diff --git a/CMakeLists.txt b/CMakeLists.txt index e097e7820c..813ad77f6e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -241,6 +241,15 @@ if(BUILD_TESTING) add_test(NAME pad_timeline COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/tools/tests/test_pad_timeline.py) set_tests_properties(pad_timeline PROPERTIES TIMEOUT 20) + set(check_compile_modes_source "${CMAKE_CURRENT_SOURCE_DIR}/tools/tests/test_check_compile_modes.py") + set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${check_compile_modes_source}") + file(STRINGS "${check_compile_modes_source}" check_compile_modes_cases REGEX "^ def test_") + foreach(test_case IN LISTS check_compile_modes_cases) + string(REGEX REPLACE "^ def (test_[A-Za-z0-9_]+).*" "\\1" test_case "${test_case}") + add_test(NAME check_compile_modes_${test_case} COMMAND ${Python3_EXECUTABLE} + "${CMAKE_CURRENT_SOURCE_DIR}/tools/tests/test_check_compile_modes.py" CheckCompileModeTests.${test_case}) + set_tests_properties(check_compile_modes_${test_case} PROPERTIES TIMEOUT 30) + endforeach() add_test(NAME trace_digest COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/tools/tests/test_trace_digest.py) add_test(NAME conventions_bom_shebang COMMAND ${Python3_EXECUTABLE} @@ -249,15 +258,23 @@ if(BUILD_TESTING) add_test(NAME env_reference COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/tools/tests/test_env_reference.py) set_tests_properties(env_reference PROPERTIES TIMEOUT 20) - add_test(NAME conventions_env_reference COMMAND ${Python3_EXECUTABLE} - ${CMAKE_CURRENT_SOURCE_DIR}/tools/tests/test_check_conventions_env_reference.py) - set_tests_properties(conventions_env_reference PROPERTIES TIMEOUT 60) + set(env_reference_test_source "${CMAKE_CURRENT_SOURCE_DIR}/tools/tests/test_check_conventions_env_reference.py") + set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${env_reference_test_source}") + file(STRINGS "${env_reference_test_source}" env_reference_cases REGEX "^ def test_") + foreach(test_case IN LISTS env_reference_cases) + string(REGEX REPLACE "^ def (test_[A-Za-z0-9_]+).*" "\\1" test_case "${test_case}") + add_test(NAME conventions_env_reference_${test_case} COMMAND ${Python3_EXECUTABLE} + "${CMAKE_CURRENT_SOURCE_DIR}/tools/tests/test_check_conventions_env_reference.py" "EnvReferenceDiffTests.${test_case}") + set_tests_properties(conventions_env_reference_${test_case} PROPERTIES TIMEOUT 30) + endforeach() add_test(NAME conventions_body_bom COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/tools/tests/test_check_conventions_body_bom.py) add_test(NAME conventions_blob_reads COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/tools/tests/test_check_conventions_blob_reads.py) add_test(NAME conventions_agent_files COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/tools/tests/test_check_conventions_agent_files.py) + add_test(NAME conventions_alignment COMMAND ${Python3_EXECUTABLE} + ${CMAKE_CURRENT_SOURCE_DIR}/tools/tests/test_check_conventions_alignment.py) add_test(NAME conventions_pr_template COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/tools/tests/test_check_conventions_pr_template.py) add_test(NAME check_compile COMMAND ${Python3_EXECUTABLE} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 01783ee784..d96b4d4c11 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -3,6 +3,7 @@ ## Code - Follow the [coding conventions](docs/dev/CONVENTIONS.md): naming, no comments except [technical debt](docs/dev/TechnicalDebt.md), Conventional Commits. +- **Every exported PS5 function with `APS5_VABI` must have exactly one declaration in a header reachable through the library's `.hpp`. Duplicate declarations in headers, `.cpp` files and tests are forbidden. This is checked by the Python test [`public_headers`](core/libs/tests/test_public_headers.py).** - Every function either does exactly what it is supposed to or throws. Unimplemented exports call `NotImplemented_nid_no_patch(__func__)` (see [libSceAudioIn](core/libs/prx/libSceAudioIn/Export.cpp)). - Pull requests that add or change shader instruction semantics say where they come from: measured on hardware (which GPU and what was checked, e.g. with the [hardware oracle](docs/dev/HW_ORACLE.md)) or the exact source (ISA section, LLVM, ACO or Mesa file). Reviewers check the semantics on hardware. Cases the source doesn't settle throw, and behaviour not verified on hardware is recorded in [technical debt](docs/dev/TechnicalDebt.md). - An export's signature or behaviour taken from a title's call sites or from a library's disassembly follows [reading titles and libraries](docs/dev/REVERSE_ENGINEERING.md): a call site settles the arguments, not what the library does. @@ -11,6 +12,7 @@ - Implement the general behaviour of a function, not what one title happens to need. - Don't add replacements for modules that titles ship themselves in `sce_module/`, `sce_modules/` or `prx/`: engine or middleware modules (Cohtml, FMOD, GOG Galaxy) and SDK libraries that only wrap other system libraries. The relinker converts and loads the title's own module, and a host library with the same name is left out of `DT_NEEDED`. Only system libraries, which reach the kernel or the hardware, are reimplemented in [core/libs/prx](core/libs/prx). A host copy may still exist for a wrapped library that some dumps lack entirely, like libSceNpCppWebApi: the title's own module wins whenever one is shipped, so it is only ever consulted by titles that ship nothing. - Avoid non-standard extensions (`__attribute__`, etc.) where standard C++ is enough. Helper symbols that must not become NIDs use the `_nid_no_patch` or `_nid_no_patch_cut` suffix. +- `alignas` takes at most 8192: MinGW GCC, the Windows compiler, rejects static objects aligned above it. A larger block is aligned at run time inside a bigger buffer. - The relinker uses only the C++20 standard library. - Third-party code is added as a submodule under `3rdparty/` and built from source, not found on the system. With `ANYPS5_USE_SYSTEM_DEPS=ON` the packages packaged by the distributions (SDL2, freetype, Vulkan-Headers, SPIRV-Headers, glslang and SPIRV-Tools) come from the system instead; that resolution lives in [cmake/SystemDeps.cmake](cmake/SystemDeps.cmake) and the default build never reads the system. - Don't add tests that only check that a symbol is exported: a missing export already fails at startup. diff --git a/core/libs/CMakeLists.txt b/core/libs/CMakeLists.txt index 99b9a9dbdf..4b0b29ad32 100644 --- a/core/libs/CMakeLists.txt +++ b/core/libs/CMakeLists.txt @@ -289,6 +289,25 @@ if(BUILD_TESTING) find_package(Python3 QUIET COMPONENTS Interpreter) if(Python3_Interpreter_FOUND) + set(public_header_compiler_args) + if(APPLE) + foreach(architecture IN LISTS CMAKE_OSX_ARCHITECTURES) + list(APPEND public_header_compiler_args --compiler-arg=-arch "--compiler-arg=${architecture}") + endforeach() + if(CMAKE_OSX_SYSROOT) + list(APPEND public_header_compiler_args --compiler-arg=-isysroot "--compiler-arg=${CMAKE_OSX_SYSROOT}") + endif() + endif() + set(public_header_manifest "${CMAKE_CURRENT_BINARY_DIR}/public_headers.json") + add_test(NAME public_headers COMMAND ${Python3_EXECUTABLE} + ${CMAKE_CURRENT_SOURCE_DIR}/tests/test_public_headers.py --audit-only --manifest "${public_header_manifest}") + set_tests_properties(public_headers PROPERTIES TIMEOUT 30 RUN_SERIAL TRUE FIXTURES_SETUP public_headers_manifest) + foreach(batch RANGE 0 63) + add_test(NAME public_headers_compile_${batch} COMMAND ${Python3_EXECUTABLE} + ${CMAKE_CURRENT_SOURCE_DIR}/tests/test_public_headers.py --compiler ${CMAKE_CXX_COMPILER} ${public_header_compiler_args} + --manifest "${public_header_manifest}" --batch-index ${batch} --batch-count 64) + set_tests_properties(public_headers_compile_${batch} PROPERTIES TIMEOUT 30 FIXTURES_REQUIRED public_headers_manifest) + endforeach() add_test(NAME nid_gnu_hash COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/nid/tests/test_gnu_hash.py $) add_test(NAME nid_elf_duplicates COMMAND ${Python3_EXECUTABLE} @@ -362,14 +381,42 @@ if(BUILD_TESTING) target_link_libraries(guest_kernel_sys_pthread_tests PRIVATE libkernel_sys libkernel libc) configure_windows_unwind(guest_kernel_sys_pthread_tests) add_test(NAME guest_kernel_sys_pthread COMMAND guest_kernel_sys_pthread_tests) + add_test_executable(guest_kernel_sys_constants_tests tests/GuestKernelSysConstants.cpp) + target_include_directories(guest_kernel_sys_constants_tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) + target_link_libraries(guest_kernel_sys_constants_tests PRIVATE libkernel_sys libkernel libc) + configure_windows_unwind(guest_kernel_sys_constants_tests) + add_test(NAME guest_kernel_sys_constants COMMAND guest_kernel_sys_constants_tests) + set_tests_properties(guest_kernel_sys_constants PROPERTIES TIMEOUT 20) if(Python3_Interpreter_FOUND) add_test(NAME nid_verneed COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/nid/tests/test_verneed.py $) endif() if(WIN32) - set_tests_properties(guest_kernel_sys guest_kernel_sys_thread_defaults guest_kernel_sys_barrier guest_kernel_sys_pthread PROPERTIES ENVIRONMENT_MODIFICATION + set_tests_properties(guest_kernel_sys guest_kernel_sys_thread_defaults guest_kernel_sys_barrier guest_kernel_sys_pthread guest_kernel_sys_constants PROPERTIES ENVIRONMENT_MODIFICATION "PATH=path_list_prepend:$") endif() + add_test_executable(guest_kernel_sys_threads_tests tests/GuestKernelSysThreads.cpp + nid/src/NidCompute.cpp nid/src/Sha1.cpp) + target_include_directories(guest_kernel_sys_threads_tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/nid/include) + target_link_libraries(guest_kernel_sys_threads_tests PRIVATE ${CMAKE_DL_LIBS}) + add_custom_target(guest_kernel_sys_threads_libraries DEPENDS + ${PATCHED_DIR}/libkernel_sys.prx ${PATCHED_DIR}/libkernel.prx ${LIBC_PATCHED}) + add_dependencies(guest_kernel_sys_threads_tests guest_kernel_sys_threads_libraries) + configure_windows_unwind(guest_kernel_sys_threads_tests) + if(MINGW) + target_compile_options(guest_kernel_sys_threads_tests PRIVATE -fasynchronous-unwind-tables) + target_link_options(guest_kernel_sys_threads_tests PRIVATE -static -static-libgcc -static-libstdc++) + endif() + if(CMAKE_SYSTEM_NAME STREQUAL "Linux") + add_test(NAME guest_kernel_sys_threads_main_late_load COMMAND guest_kernel_sys_threads_tests ${UNPATCHED_DIR} unpatched main_late_load) + add_test(NAME guest_kernel_sys_threads_main_late_load_patched COMMAND guest_kernel_sys_threads_tests ${PATCHED_DIR} patched main_late_load) + set_tests_properties(guest_kernel_sys_threads_main_late_load guest_kernel_sys_threads_main_late_load_patched PROPERTIES TIMEOUT 20) + endif() + foreach(case IN ITEMS main) + add_test(NAME guest_kernel_sys_threads_${case} COMMAND guest_kernel_sys_threads_tests ${UNPATCHED_DIR} unpatched ${case}) + add_test(NAME guest_kernel_sys_threads_${case}_patched COMMAND guest_kernel_sys_threads_tests ${PATCHED_DIR} patched ${case}) + set_tests_properties(guest_kernel_sys_threads_${case} guest_kernel_sys_threads_${case}_patched PROPERTIES TIMEOUT 20) + endforeach() add_test_executable(guest_gnm_neo_packets_tests tests/GuestGnmNeoPackets.cpp) target_include_directories(guest_gnm_neo_packets_tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) @@ -855,6 +902,18 @@ if(BUILD_TESTING) endif() add_test(NAME MemoryPoolTest COMMAND MemoryPoolTest) + add_test_executable(guest_kernel_sys_swapcontext_tests tests/GuestKernelSysSwapcontext.cpp) + target_include_directories(guest_kernel_sys_swapcontext_tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) + target_compile_options(guest_kernel_sys_swapcontext_tests PRIVATE -fno-omit-frame-pointer) + target_link_libraries(guest_kernel_sys_swapcontext_tests PRIVATE libkernel_sys libSceLibcInternal libkernel libc) + configure_windows_unwind(guest_kernel_sys_swapcontext_tests) + add_test(NAME guest_kernel_sys_swapcontext COMMAND guest_kernel_sys_swapcontext_tests) + set_tests_properties(guest_kernel_sys_swapcontext PROPERTIES TIMEOUT 20) + if(WIN32) + set_tests_properties(guest_kernel_sys_swapcontext PROPERTIES ENVIRONMENT_MODIFICATION + "PATH=path_list_prepend:$") + endif() + add_test_executable(guest_acm_tests tests/GuestAcm.cpp) target_include_directories(guest_acm_tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) target_link_libraries(guest_acm_tests PRIVATE libSceAcm libc) diff --git a/core/libs/nid/tests/test_elf_duplicates.py b/core/libs/nid/tests/test_elf_duplicates.py index 504cf33bdc..25f9853da1 100644 --- a/core/libs/nid/tests/test_elf_duplicates.py +++ b/core/libs/nid/tests/test_elf_duplicates.py @@ -4,7 +4,7 @@ import sys import unittest from pathlib import Path -from test_symbol_versions import build_image, patch, read_dynsym, IMPORTS, NID_NAME, SHN_UNDEF, STT_FUNC +from test_symbol_versions import build_image, patch, read_dynsym, IMPORTS, NID_NAME, SHN_UNDEF, STT_FUNC, PATCHER def nid(name): @@ -21,6 +21,7 @@ def image(names, addresses=None): return bytes(build_image(entries, False)) +@unittest.skipUnless(PATCHER is not None and PATCHER.is_file(), "nid_patcher executable required") class ElfDuplicateTests(unittest.TestCase): def test_exports_patched_to_one_name_are_rejected(self): cases = ( @@ -65,5 +66,4 @@ class ElfDuplicateTests(unittest.TestCase): if __name__ == "__main__": - PATCHER = Path(sys.argv.pop(1)).resolve() unittest.main() diff --git a/core/libs/nid/tests/test_elf_layout.py b/core/libs/nid/tests/test_elf_layout.py index 703ac46db3..d4060852f6 100644 --- a/core/libs/nid/tests/test_elf_layout.py +++ b/core/libs/nid/tests/test_elf_layout.py @@ -3,9 +3,10 @@ import sys import unittest from pathlib import Path -from test_symbol_versions import build_image, symbols, patch, SHOFF +from test_symbol_versions import build_image, symbols, patch, SHOFF, PATCHER +@unittest.skipUnless(PATCHER is not None and PATCHER.is_file(), "nid_patcher executable required") class ElfLayoutTests(unittest.TestCase): def test_declared_layout_must_match_supported_tables(self): changes = ((5, "B", 2), (0x3a, "H", 32), @@ -44,5 +45,4 @@ class ElfLayoutTests(unittest.TestCase): if __name__ == "__main__": - PATCHER = Path(sys.argv.pop(1)).resolve() unittest.main() diff --git a/core/libs/nid/tests/test_gnu_hash.py b/core/libs/nid/tests/test_gnu_hash.py index 2e46a70f32..c1ddde43d4 100644 --- a/core/libs/nid/tests/test_gnu_hash.py +++ b/core/libs/nid/tests/test_gnu_hash.py @@ -3,7 +3,7 @@ import sys import unittest from pathlib import Path -from test_symbol_versions import build_image, symbols, patch, HASH_OFFSET, SHOFF, read_dynsym, gnu_hash, sections +from test_symbol_versions import build_image, symbols, patch, HASH_OFFSET, SHOFF, read_dynsym, gnu_hash, sections, PATCHER def sysv_hash(name): @@ -31,6 +31,7 @@ def sysv_lookup(image, name): return None +@unittest.skipUnless(PATCHER is not None and PATCHER.is_file(), "nid_patcher executable required") class GnuHashTests(unittest.TestCase): def image(self, buckets=4, bloom=1, shift=6, symoffset=3): image = build_image(symbols(False), False) @@ -95,6 +96,7 @@ class GnuHashTests(unittest.TestCase): self.assertEqual(struct.unpack_from(" 1: + patcher = Path(sys.argv[1]).resolve() + else: + patcher = PATCHER or find_patcher() + if patcher is None: + print("nid_patcher executable required") + sys.exit(0) with tempfile.TemporaryDirectory(prefix="anyps5-macho-nid-a\u00e7\u00e3o-\u65e5\u672c-") as directory: check_shrinking(patcher, directory) check_growing(patcher, directory) diff --git a/core/libs/nid/tests/test_native_paths.py b/core/libs/nid/tests/test_native_paths.py index ccfd9e6b8c..4b5c12193a 100644 --- a/core/libs/nid/tests/test_native_paths.py +++ b/core/libs/nid/tests/test_native_paths.py @@ -5,16 +5,14 @@ import tempfile import unittest from pathlib import Path -from test_macho_nids import build_dylib, exports_of, nid +from test_macho_nids import build_dylib, exports_of, nid, PATCHER try: import resource except ImportError: resource = None -PATCHER = Path(sys.argv.pop(1)).resolve() - - +@unittest.skipUnless(PATCHER is not None and PATCHER.is_file(), "nid_patcher executable required") class NativePathTests(unittest.TestCase): def invoke(self, *arguments): return subprocess.run([str(PATCHER), "libtest", *map(str, arguments)], diff --git a/core/libs/nid/tests/test_pe_references.py b/core/libs/nid/tests/test_pe_references.py index 2e6eed7f40..ae26b4c724 100644 --- a/core/libs/nid/tests/test_pe_references.py +++ b/core/libs/nid/tests/test_pe_references.py @@ -5,7 +5,7 @@ import tempfile import unittest from pathlib import Path -from test_macho_nids import build_dylib, exports_of, nid +from test_macho_nids import build_dylib, exports_of, nid, PATCHER def reference(*, headers=False, address=0x2000, ordinal=0): @@ -100,6 +100,7 @@ def forwarding_exports(image, bits): return string(table[4]), names, targets, addresses, (export_rva, export_size) +@unittest.skipUnless(PATCHER is not None and PATCHER.is_file(), "nid_patcher executable required") class ReferenceTests(unittest.TestCase): def patch_with_reference(self, data): with tempfile.TemporaryDirectory() as tmp: @@ -135,6 +136,7 @@ class ReferenceTests(unittest.TestCase): self.assertEqual(image, original) +@unittest.skipUnless(PATCHER is not None and PATCHER.is_file(), "nid_patcher executable required") class ForwardingExportTests(unittest.TestCase): def patch(self, image): with tempfile.TemporaryDirectory() as temporary: @@ -242,5 +244,4 @@ class ForwardingExportTests(unittest.TestCase): if __name__ == "__main__": - PATCHER = Path(sys.argv.pop(1)).resolve() unittest.main() diff --git a/core/libs/nid/tests/test_shared_strings.py b/core/libs/nid/tests/test_shared_strings.py index 3bfb64125b..0d4325d8cc 100644 --- a/core/libs/nid/tests/test_shared_strings.py +++ b/core/libs/nid/tests/test_shared_strings.py @@ -3,9 +3,10 @@ import sys import unittest from pathlib import Path -from test_symbol_versions import build_image, symbols, patch, SHOFF, DYNSYM_OFFSET, read_dynsym, sections, DEFINITIONS +from test_symbol_versions import build_image, symbols, patch, SHOFF, DYNSYM_OFFSET, read_dynsym, sections, DEFINITIONS, PATCHER +@unittest.skipUnless(PATCHER is not None and PATCHER.is_file(), "nid_patcher executable required") class SharedStringTests(unittest.TestCase): def test_dynamic_names_keep_original_string_when_export_shares_offset(self): for tag in (1, 14, 15, 29): @@ -54,5 +55,4 @@ class SharedStringTests(unittest.TestCase): if __name__ == "__main__": - PATCHER = Path(sys.argv.pop(1)).resolve() unittest.main() diff --git a/core/libs/nid/tests/test_symbol_versions.py b/core/libs/nid/tests/test_symbol_versions.py index b824a374c6..c9e9adc43f 100644 --- a/core/libs/nid/tests/test_symbol_versions.py +++ b/core/libs/nid/tests/test_symbol_versions.py @@ -1,3 +1,4 @@ +import os import re import struct import subprocess @@ -198,8 +199,36 @@ def test_unversioned_library_is_still_patched(patcher): assert len({entry[0] for entry in after if entry[0]}) == len([entry for entry in after if entry[0]]) +def find_patcher(): + for index, argument in enumerate(sys.argv[1:], 1): + candidate = Path(argument) + if candidate.stem == "nid_patcher" and candidate.is_file(): + sys.argv.pop(index) + return candidate.resolve() + env = os.environ.get("ANYPS5_NID_PATCHER") or os.environ.get("NID_PATCHER") + if env and Path(env).is_file(): + return Path(env).resolve() + repo_root = Path(__file__).resolve().parents[4] + for candidate in ( + repo_root / "build" / "core" / "libs" / "nid_patcher.exe", + repo_root / "build" / "core" / "libs" / "nid_patcher", + ): + if candidate.is_file(): + return candidate + return None + + +PATCHER = find_patcher() + + def main(): - patcher = Path(sys.argv[1]).resolve() + if len(sys.argv) > 1: + patcher = Path(sys.argv[1]).resolve() + else: + patcher = PATCHER or find_patcher() + if patcher is None: + print("nid_patcher executable required") + sys.exit(0) test_versioned_library_is_rejected(patcher) test_unversioned_library_is_still_patched(patcher) print("NID patcher symbol version tests passed") diff --git a/core/libs/nid/tests/test_verneed.py b/core/libs/nid/tests/test_verneed.py index 58ebc02c6b..79dd7a7789 100644 --- a/core/libs/nid/tests/test_verneed.py +++ b/core/libs/nid/tests/test_verneed.py @@ -3,7 +3,7 @@ import sys import unittest from pathlib import Path -from test_symbol_versions import build_image, symbols, patch, SHOFF, DYNSTR_OFFSET, sections +from test_symbol_versions import build_image, symbols, patch, SHOFF, DYNSTR_OFFSET, sections, PATCHER VERNEED = 0x580 @@ -22,6 +22,7 @@ def image(*, auxiliary=16, count=1, size=32, version=1, auxnext=0, nextrecord=0) return data +@unittest.skipUnless(PATCHER is not None and PATCHER.is_file(), "nid_patcher executable required") class VersionRequirementsTests(unittest.TestCase): def test_auxiliary_record_cannot_leave_declared_section(self): self.reject(image(auxiliary=32)) @@ -72,5 +73,4 @@ class VersionRequirementsTests(unittest.TestCase): if __name__ == "__main__": - PATCHER = Path(sys.argv.pop(1)).resolve() unittest.main() diff --git a/core/libs/prx/libSceAbstractLocal/libSceAbstractLocal.hpp b/core/libs/prx/libSceAbstractLocal/libSceAbstractLocal.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceAbstractLocal/libSceAbstractLocal.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceAbstractStorage/libSceAbstractStorage.hpp b/core/libs/prx/libSceAbstractStorage/libSceAbstractStorage.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceAbstractStorage/libSceAbstractStorage.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceAbstractTcs/libSceAbstractTcs.hpp b/core/libs/prx/libSceAbstractTcs/libSceAbstractTcs.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceAbstractTcs/libSceAbstractTcs.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceAbstractTwitter/libSceAbstractTwitter.hpp b/core/libs/prx/libSceAbstractTwitter/libSceAbstractTwitter.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceAbstractTwitter/libSceAbstractTwitter.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceAbstractYoutube/libSceAbstractYoutube.hpp b/core/libs/prx/libSceAbstractYoutube/libSceAbstractYoutube.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceAbstractYoutube/libSceAbstractYoutube.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceAc3Enc/Export.cpp b/core/libs/prx/libSceAc3Enc/Export.cpp index 4ee193119b..13a2ad92a5 100644 --- a/core/libs/prx/libSceAc3Enc/Export.cpp +++ b/core/libs/prx/libSceAc3Enc/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceAc3Enc/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceAc3Enc/include/Api.hpp b/core/libs/prx/libSceAc3Enc/include/Api.hpp new file mode 100644 index 0000000000..02d6fc4467 --- /dev/null +++ b/core/libs/prx/libSceAc3Enc/include/Api.hpp @@ -0,0 +1,15 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceAc3EncCreateEncoder(); +int APS5_VABI sceAc3EncDeleteEncoder(); +int APS5_VABI sceAc3EncEncode(); +int APS5_VABI sceAc3EncEncodeAsync(); +int APS5_VABI sceAc3EncFlush(); +int APS5_VABI sceAc3EncIsEncoding(); +int APS5_VABI sceAc3EncWaitEncode(); + +} diff --git a/core/libs/prx/libSceAc3Enc/libSceAc3Enc.hpp b/core/libs/prx/libSceAc3Enc/libSceAc3Enc.hpp new file mode 100644 index 0000000000..7addfec629 --- /dev/null +++ b/core/libs/prx/libSceAc3Enc/libSceAc3Enc.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceAc3Enc/include/Api.hpp" diff --git a/core/libs/prx/libSceAcm/Export.cpp b/core/libs/prx/libSceAcm/Export.cpp index 914d474f0b..ddbe893628 100644 --- a/core/libs/prx/libSceAcm/Export.cpp +++ b/core/libs/prx/libSceAcm/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceAcm/include/Api.hpp" #include #include #include @@ -217,7 +218,6 @@ int APS5_VABI sceAcm_IFFT() { return 0; } - int APS5_VABI sceAcmBatchJobNotification() { NotImplemented_nid_no_patch(__func__); return 0; diff --git a/core/libs/prx/libSceAcm/include/Api.hpp b/core/libs/prx/libSceAcm/include/Api.hpp new file mode 100644 index 0000000000..c4da065395 --- /dev/null +++ b/core/libs/prx/libSceAcm/include/Api.hpp @@ -0,0 +1,20 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceAcmBatchStartBuffer(AcmContextId context, const void* batchCommands, size_t batchSize, AcmBatchError* batchError, AcmBatchId* batch); +int APS5_VABI sceAcmBatchStartBuffers(AcmContextId context, uint32_t batchInfoCount, const AcmBatchInfo* const batch_info[], AcmBatchError* batchError, AcmBatchId* batch); +int APS5_VABI sceAcmBatchWait(AcmContextId context, AcmBatchId batch, uint32_t timeout); +int APS5_VABI sceAcmContextCreate(AcmContextId* context); +int APS5_VABI sceAcmContextDestroy(AcmContextId context); +int APS5_VABI sceAcm_ConvReverb_SharedInput(AcmBatchInfo* batch, std::uint32_t mode, AcmReverbInput* input, std::uint32_t outputCount, const AcmReverbFilter* const* filters, const float* gains, const AcmReverbOutput* const* outputs); +int APS5_VABI sceAcm_FFT(AcmBatchInfo* batch, std::int32_t transformSize, std::uint32_t transformCount, std::int32_t inputFormat, const void* const* inputs, std::int32_t outputFormat, void* const* outputs, std::int32_t flags); +int APS5_VABI sceAcm_Panner(AcmBatchInfo* batch, std::uint32_t sourceCount, const void* const* sources, std::uint32_t sourceMode, std::uint32_t outputMode, std::uint32_t channelCount, const void* const* sourceParameters, const void* const* sourceMatrices, const void* const* inputChannels, void* const* outputChannels); +int APS5_VABI sceAcmBatchJobPriority(AcmBatchInfo* batch, std::uint32_t priority); +int APS5_VABI sceAcm_ConvReverb_SharedIr(); +int APS5_VABI sceAcm_IFFT(); +int APS5_VABI sceAcmBatchJobNotification(); + +} diff --git a/core/libs/prx/libSceAcm/libSceAcm.hpp b/core/libs/prx/libSceAcm/libSceAcm.hpp new file mode 100644 index 0000000000..a8b95eefbf --- /dev/null +++ b/core/libs/prx/libSceAcm/libSceAcm.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceAcm/include/Api.hpp" diff --git a/core/libs/prx/libSceAgc/Acb/include/Control.hpp b/core/libs/prx/libSceAgc/Acb/include/Control.hpp index c22dc4e61e..e1862076c3 100644 --- a/core/libs/prx/libSceAgc/Acb/include/Control.hpp +++ b/core/libs/prx/libSceAgc/Acb/include/Control.hpp @@ -1,4 +1,26 @@ #ifndef CORE_LIBS_PRX_LIBSCEAGC_ACB_INCLUDE_CONTROL_HPP #define CORE_LIBS_PRX_LIBSCEAGC_ACB_INCLUDE_CONTROL_HPP +#include "SceTypes.hpp" +#include "SceShaders.hpp" + +extern "C" { + +std::uint32_t* APS5_VABI sceAgcAcbAtomicGds_0900(CommandBuffer* buf, std::uint32_t control, std::uint32_t mode, std::uint32_t gdsOp, std::uint32_t src, std::uint16_t offset, std::uint16_t index, std::uint32_t mask, std::uint32_t data, std::uint64_t compareData, std::uint64_t extraData); +std::uint32_t* APS5_VABI sceAgcAcbJump(CommandBuffer* buf, std::uint8_t cachePolicy, const std::uint32_t* target, std::uint32_t sizeInDwords); +uint32_t APS5_VABI sceAgcAcbJumpGetSize(void); +uint32_t* APS5_VABI sceAgcAcbResetQueue(CommandBuffer* buf, uint32_t op, uint32_t value); +std::uint32_t* APS5_VABI sceAgcAcbRewind(CommandBuffer* buf, std::uint32_t initialState); +std::uint32_t APS5_VABI sceAgcAcbRewindGetSize(); +std::uint32_t* APS5_VABI sceAgcAcbWaitUntilSafeForRendering(CommandBuffer* buf, std::uint32_t videoOutHandle, std::uint32_t displayBufferIndex); +std::uint32_t* APS5_VABI sceAgcAcbSetFlip(CommandBuffer* buf, std::uint32_t videoOutHandle, std::int32_t displayBufferIndex, std::uint32_t flipMode, std::int64_t flipArg); +std::uint32_t* APS5_VABI sceAgcAcbSetWorkloadsActive(CommandBuffer* buf, std::uint32_t streamId, const std::uint32_t* workloadIds, std::uint32_t workloadCount); +std::uint32_t* APS5_VABI sceAgcAcbSetWorkloadComplete(CommandBuffer* buf, std::uint32_t streamId, std::uint32_t workloadId); +std::uint32_t* APS5_VABI sceAgcAcbSetWorkloadStreamInactive(CommandBuffer* buf, std::uint32_t streamId); +uint32_t* APS5_VABI sceAgcAcbPushMarker(CommandBuffer* buf, const char* str, uint32_t color); +uint32_t* APS5_VABI sceAgcAcbPopMarker(CommandBuffer* buf); +uint32_t* APS5_VABI sceAgcAcbSetMarker(CommandBuffer* buf, const char* str, uint32_t color); + +} + #endif diff --git a/core/libs/prx/libSceAgc/Acb/include/Dispatch.hpp b/core/libs/prx/libSceAgc/Acb/include/Dispatch.hpp index e207781ef7..0915d7aad8 100644 --- a/core/libs/prx/libSceAgc/Acb/include/Dispatch.hpp +++ b/core/libs/prx/libSceAgc/Acb/include/Dispatch.hpp @@ -1,4 +1,14 @@ #ifndef CORE_LIBS_PRX_LIBSCEAGC_ACB_INCLUDE_DISPATCH_HPP #define CORE_LIBS_PRX_LIBSCEAGC_ACB_INCLUDE_DISPATCH_HPP +#include "SceTypes.hpp" +#include "SceShaders.hpp" + +extern "C" { + +uint32_t* APS5_VABI sceAgcAcbDispatchIndirect(CommandBuffer* buf, const volatile void* indirectArgs, uint32_t modifier); +std::uint32_t APS5_VABI sceAgcAcbDispatchIndirectGetSize(); + +} + #endif diff --git a/core/libs/prx/libSceAgc/Acb/include/Memory.hpp b/core/libs/prx/libSceAgc/Acb/include/Memory.hpp index 78e8668cb0..93949715e6 100644 --- a/core/libs/prx/libSceAgc/Acb/include/Memory.hpp +++ b/core/libs/prx/libSceAgc/Acb/include/Memory.hpp @@ -1,4 +1,24 @@ #ifndef CORE_LIBS_PRX_LIBSCEAGC_ACB_INCLUDE_MEMORY_HPP #define CORE_LIBS_PRX_LIBSCEAGC_ACB_INCLUDE_MEMORY_HPP +#include "SceTypes.hpp" +#include "SceShaders.hpp" + +extern "C" { + +std::uint32_t* APS5_VABI sceAgcAcbAcquireMem(CommandBuffer* buf, std::uint32_t gcrControl, const volatile void* base, std::uint64_t sizeBytes, std::uint32_t pollCycles); +uint32_t APS5_VABI sceAgcAcbAcquireMemGetSize(void); +uint32_t* APS5_VABI sceAgcAcbCopyData(CommandBuffer* buf, uint8_t dst, uint8_t dstCachePolicy, uint64_t dstAddress, uint8_t src, uint8_t srcCachePolicy, uint64_t srcAddressOrImmediate, uint8_t itemSize, uint8_t writeConfirm); +std::uint64_t APS5_VABI sceAgcAcbCopyDataGetSize(); +std::uint32_t* APS5_VABI sceAgcAcbDmaData(CommandBuffer* buf, std::uint8_t dst, std::uint8_t dstCachePolicy, std::uint64_t dstAddress, std::uint8_t src, std::uint8_t srcCachePolicy, std::uint64_t srcAddress, std::uint32_t numBytes, std::uint8_t waitForPrevious, std::uint8_t writeConfirm); +std::uint32_t APS5_VABI sceAgcAcbDmaDataGetSize(); +std::uint32_t* APS5_VABI sceAgcAcbAtomicMem(CommandBuffer* buf, std::uint8_t atomicOp, std::uint8_t command, std::uint8_t cachePolicy, const volatile void* address, std::uint64_t srcData, std::uint64_t compareData, std::uint16_t loopInterval); +std::uint32_t APS5_VABI sceAgcAcbAtomicMemGetSize(); +std::uint32_t APS5_VABI sceAgcAcbAtomicGdsGetSize(); +std::uint32_t* APS5_VABI sceAgcAcbPrimeUtcl2(CommandBuffer* buf, const volatile void* address, std::uint32_t sizeInBytes); +std::uint32_t APS5_VABI sceAgcAcbPrimeUtcl2GetSize(); +std::uint32_t* APS5_VABI sceAgcAcbWriteData(CommandBuffer* buf, std::uint8_t dst, std::uint8_t cachePolicy, std::uint64_t address, const void* data, std::uint32_t numDwords, std::uint8_t increment, std::uint8_t writeConfirm); + +} + #endif diff --git a/core/libs/prx/libSceAgc/Acb/include/Sync.hpp b/core/libs/prx/libSceAgc/Acb/include/Sync.hpp index ca3084b8b8..fb7a826139 100644 --- a/core/libs/prx/libSceAgc/Acb/include/Sync.hpp +++ b/core/libs/prx/libSceAgc/Acb/include/Sync.hpp @@ -1,4 +1,20 @@ #ifndef CORE_LIBS_PRX_LIBSCEAGC_ACB_INCLUDE_SYNC_HPP #define CORE_LIBS_PRX_LIBSCEAGC_ACB_INCLUDE_SYNC_HPP +#include "SceTypes.hpp" +#include "SceShaders.hpp" + +extern "C" { + +uint32_t* APS5_VABI sceAgcAcbCondExec(CommandBuffer* buf, const volatile uint32_t* address, uint32_t numDwords); +uint32_t APS5_VABI sceAgcAcbCondExecGetSize(void); +std::uint32_t* APS5_VABI sceAgcAcbWaitRegMem(CommandBuffer* buf, std::uint8_t size, std::uint8_t compareFunction, std::uint8_t cachePolicy, const volatile void* address, std::uint64_t reference, std::uint64_t mask, std::uint32_t pollCycles); +std::uint64_t APS5_VABI sceAgcAcbWaitOnAddressGetSize(std::uint8_t size); +std::uint32_t* APS5_VABI sceAgcAcbEventWrite(CommandBuffer* buf, std::uint8_t eventType, const volatile void* address); +std::uint64_t APS5_VABI sceAgcAcbEventWriteGetSize(std::uint8_t eventType); +std::uint32_t APS5_VABI sceAgcAcbQueueEndOfShaderActionGetSize(); +std::uint32_t* APS5_VABI sceAgcAcbMemSemaphore(CommandBuffer* buf, const volatile void* address, std::uint8_t waitForMailbox, std::uint8_t signalType, std::uint8_t operation); + +} + #endif diff --git a/core/libs/prx/libSceAgc/Cb/include/Branch.hpp b/core/libs/prx/libSceAgc/Cb/include/Branch.hpp index 5c74f02461..855d78d8ee 100644 --- a/core/libs/prx/libSceAgc/Cb/include/Branch.hpp +++ b/core/libs/prx/libSceAgc/Cb/include/Branch.hpp @@ -1,4 +1,16 @@ #ifndef CORE_LIBS_PRX_LIBSCEAGC_CB_INCLUDE_BRANCH_HPP #define CORE_LIBS_PRX_LIBSCEAGC_CB_INCLUDE_BRANCH_HPP +#include "SceTypes.hpp" +#include "SceShaders.hpp" + +extern "C" { + +std::uint32_t* APS5_VABI sceAgcCbBranch(CommandBuffer* buf, std::uint8_t mode, std::uint8_t compareFunction, const volatile std::uint64_t* compareAddress, std::uint64_t mask, std::uint64_t reference, std::uint8_t cachePolicy1, const volatile std::uint32_t* buffer1, std::uint32_t sizeInDwords1, std::uint8_t cachePolicy2, const volatile std::uint32_t* buffer2, std::uint32_t sizeInDwords2); +std::uint32_t APS5_VABI sceAgcCbBranchGetSize(); +std::uint32_t* APS5_VABI sceAgcCbCondWrite(CommandBuffer* buf, std::uint32_t compareFunction, std::uint32_t writeSpace, const volatile void* writeAddress, std::uint32_t writeData, const volatile void* pollAddress, std::uint32_t reference, std::uint32_t mask); +std::uint32_t APS5_VABI sceAgcCbCondWriteGetSize(); + +} + #endif diff --git a/core/libs/prx/libSceAgc/Cb/include/Dispatch.hpp b/core/libs/prx/libSceAgc/Cb/include/Dispatch.hpp index 5881aaf5a9..9f741d7e2e 100644 --- a/core/libs/prx/libSceAgc/Cb/include/Dispatch.hpp +++ b/core/libs/prx/libSceAgc/Cb/include/Dispatch.hpp @@ -1,4 +1,14 @@ #ifndef CORE_LIBS_PRX_LIBSCEAGC_CB_INCLUDE_DISPATCH_HPP #define CORE_LIBS_PRX_LIBSCEAGC_CB_INCLUDE_DISPATCH_HPP +#include "SceTypes.hpp" +#include "SceShaders.hpp" + +extern "C" { + +std::uint32_t* APS5_VABI sceAgcCbDispatch(CommandBuffer* buf, std::uint32_t threadGroupX, std::uint32_t threadGroupY, std::uint32_t threadGroupZ, std::uint32_t modifier); +uint32_t APS5_VABI sceAgcCbDispatchGetSize(void); + +} + #endif diff --git a/core/libs/prx/libSceAgc/Cb/include/Registers.hpp b/core/libs/prx/libSceAgc/Cb/include/Registers.hpp index e5634b8ad6..d41e1beb42 100644 --- a/core/libs/prx/libSceAgc/Cb/include/Registers.hpp +++ b/core/libs/prx/libSceAgc/Cb/include/Registers.hpp @@ -1,4 +1,20 @@ #ifndef CORE_LIBS_PRX_LIBSCEAGC_CB_INCLUDE_REGISTERS_HPP #define CORE_LIBS_PRX_LIBSCEAGC_CB_INCLUDE_REGISTERS_HPP +#include "SceTypes.hpp" +#include "SceShaders.hpp" + +extern "C" { + +std::uint32_t* APS5_VABI sceAgcCbSetUcRegisterRangeDirect(CommandBuffer* buf, std::uint32_t offset, const std::uint32_t* values, std::uint32_t numValues); +std::uint32_t* APS5_VABI sceAgcCbSetShRegisterRangeDirect(CommandBuffer* buf, std::uint32_t offset, const std::uint32_t* values, std::uint32_t numValues); +uint32_t APS5_VABI sceAgcCbSetShRegisterRangeDirectGetSize(uint32_t numValues); +std::uint32_t APS5_VABI sceAgcCbSetUcRegisterRangeDirectGetSize(std::uint32_t numValues); +std::uint32_t* APS5_VABI sceAgcCbSetShRegistersDirect(CommandBuffer* buf, const volatile ShaderRegister* regs, std::uint32_t numRegs); +std::uint32_t APS5_VABI sceAgcCbSetShRegistersDirectGetSize(std::uint32_t numRegs); +std::uint32_t* APS5_VABI sceAgcCbSetUcRegistersDirect(CommandBuffer* buf, const volatile ShaderRegister* regs, std::uint32_t numRegs); +std::uint32_t APS5_VABI sceAgcCbSetUcRegistersDirectGetSize(std::uint32_t numRegs); + +} + #endif diff --git a/core/libs/prx/libSceAgc/Cb/include/Sync.hpp b/core/libs/prx/libSceAgc/Cb/include/Sync.hpp index a070c6a5fc..d3be5f9083 100644 --- a/core/libs/prx/libSceAgc/Cb/include/Sync.hpp +++ b/core/libs/prx/libSceAgc/Cb/include/Sync.hpp @@ -4,10 +4,19 @@ #include "SceTypes.hpp" #include -struct CommandBuffer; - extern "C" { std::uint32_t* APS5_VABI sceAgcCbMemSemaphore(CommandBuffer* buf, const volatile void* address, std::uint32_t operation, std::uint32_t modifier, std::uint32_t value); } +#include "SceShaders.hpp" + +extern "C" { + +std::uint32_t* APS5_VABI sceAgcCbNop_nid_postfix(CommandBuffer* buf, std::uint32_t sizeInDwords); +uint32_t APS5_VABI sceAgcCbNopGetSize(uint32_t sizeInDwords); +std::uint32_t APS5_VABI sceAgcCbQueueEndOfPipeActionGetSize(); +std::uint32_t* APS5_VABI sceAgcCbReleaseMem(CommandBuffer* buf, std::uint8_t action, std::uint16_t gcrControl, std::uint8_t dst, std::uint8_t cachePolicy, const volatile Label* address, std::uint8_t dataSelect, std::uint64_t data, std::uint16_t gdsOffset, std::uint16_t gdsSize, std::uint8_t interrupt, std::uint32_t interruptContextId); + +} + #endif diff --git a/core/libs/prx/libSceAgc/Command/src/Packet.cpp b/core/libs/prx/libSceAgc/Command/src/Packet.cpp index be43fb7028..13036e5d12 100644 --- a/core/libs/prx/libSceAgc/Command/src/Packet.cpp +++ b/core/libs/prx/libSceAgc/Command/src/Packet.cpp @@ -115,17 +115,23 @@ std::uint32_t* WriteRegisters(CommandBuffer* buffer, std::uint32_t opcode, const Require(buffer != nullptr, function, "null command buffer"); return buffer->cursor_up; } - CheckAddress(reinterpret_cast(registers), 4, function); + CheckAddress(reinterpret_cast(registers), 1, function); + const auto* bytes = reinterpret_cast(const_cast(registers)); + const auto entryAt = [&](std::uint32_t index) { + ShaderRegister entry; + std::memcpy(&entry, bytes + static_cast(index) * sizeof(ShaderRegister), sizeof(entry)); + return entry; + }; std::vector snapshot; if (snapshotAll) { snapshot.reserve(count); for (std::uint32_t i = 0; i < count; ++i) { - snapshot.push_back({registers[i].offset, registers[i].value}); + snapshot.push_back(entryAt(i)); CheckBits(snapshot.back().offset, 0xffffu, function); } } - const auto offsetAt = [&](std::uint32_t index) { return snapshotAll ? snapshot[index].offset : registers[index].offset; }; - const auto valueAt = [&](std::uint32_t index) { return snapshotAll ? snapshot[index].value : registers[index].value; }; + const auto offsetAt = [&](std::uint32_t index) { return snapshotAll ? snapshot[index].offset : entryAt(index).offset; }; + const auto valueAt = [&](std::uint32_t index) { return snapshotAll ? snapshot[index].value : entryAt(index).value; }; std::uint32_t* first = nullptr; std::uint32_t index = 0; while (index < count) { diff --git a/core/libs/prx/libSceAgc/DcbDraw/include/DrawIndexed.hpp b/core/libs/prx/libSceAgc/DcbDraw/include/DrawIndexed.hpp index e134de925d..1eede737f2 100644 --- a/core/libs/prx/libSceAgc/DcbDraw/include/DrawIndexed.hpp +++ b/core/libs/prx/libSceAgc/DcbDraw/include/DrawIndexed.hpp @@ -1,4 +1,24 @@ #ifndef CORE_LIBS_PRX_LIBSCEAGC_DCBDRAW_INCLUDE_DRAWINDEXED_HPP #define CORE_LIBS_PRX_LIBSCEAGC_DCBDRAW_INCLUDE_DRAWINDEXED_HPP +#include "SceTypes.hpp" +#include "SceShaders.hpp" + +extern "C" { + +std::uint32_t* APS5_VABI sceAgcDcbDrawIndex(CommandBuffer* buf, std::uint32_t indexCount, const volatile void* indexAddress, std::uint64_t modifier); +std::uint32_t APS5_VABI sceAgcDcbDrawIndexGetSize(); +std::uint32_t* APS5_VABI sceAgcDcbDrawIndexAuto(CommandBuffer* buf, std::uint32_t indexCount, std::uint64_t modifier); +std::uint32_t APS5_VABI sceAgcDcbDrawIndexAutoGetSize(); +std::uint32_t* APS5_VABI sceAgcDcbDrawIndexOffset(CommandBuffer* buf, std::uint32_t indexOffset, std::uint32_t indexCount, std::uint64_t modifier); +uint32_t APS5_VABI sceAgcDcbDrawIndexOffsetGetSize(void); +uint32_t* APS5_VABI sceAgcDcbDrawIndexIndirect(CommandBuffer* buf, uint32_t dataOffsetInBytes, uint64_t modifier); +std::uint32_t APS5_VABI sceAgcDcbDrawIndexIndirectGetSize(); +uint32_t* APS5_VABI sceAgcDcbDrawIndexIndirectMulti(CommandBuffer* buf, uint32_t dataOffsetInBytes, uint32_t countIndirect, uint32_t maxCountOrCount, const volatile void* countAddr, uint32_t strideInBytes, uint64_t modifier); +std::uint32_t APS5_VABI sceAgcDcbDrawIndexIndirectMultiGetSize(); +uint32_t* APS5_VABI sceAgcDcbDrawIndexMultiInstanced(CommandBuffer* buf, uint32_t indexCount, const volatile void* indexAddr, const volatile void* objectIds, uint32_t instanceCount, uint64_t modifier); +uint32_t APS5_VABI sceAgcDcbDrawIndexMultiInstancedGetSize(void); + +} + #endif diff --git a/core/libs/prx/libSceAgc/DcbDraw/include/DrawNonIndexed.hpp b/core/libs/prx/libSceAgc/DcbDraw/include/DrawNonIndexed.hpp index 19705ed1f2..5ee0a26dc5 100644 --- a/core/libs/prx/libSceAgc/DcbDraw/include/DrawNonIndexed.hpp +++ b/core/libs/prx/libSceAgc/DcbDraw/include/DrawNonIndexed.hpp @@ -1,4 +1,16 @@ #ifndef CORE_LIBS_PRX_LIBSCEAGC_DCBDRAW_INCLUDE_DRAWNONINDEXED_HPP #define CORE_LIBS_PRX_LIBSCEAGC_DCBDRAW_INCLUDE_DRAWNONINDEXED_HPP +#include "SceTypes.hpp" +#include "SceShaders.hpp" + +extern "C" { + +std::uint32_t* APS5_VABI sceAgcDcbDrawIndirect(CommandBuffer* buf, std::uint32_t dataOffsetInBytes, std::uint64_t modifier); +std::uint32_t APS5_VABI sceAgcDcbDrawIndirectGetSize(); +std::uint32_t* APS5_VABI sceAgcDcbDrawIndirectMulti(CommandBuffer* buf, std::uint32_t dataOffsetInBytes, std::uint32_t countIndirect, std::uint32_t maxCountOrCount, const volatile void* countAddress, std::uint32_t strideInBytes, std::uint64_t modifier); +std::uint32_t APS5_VABI sceAgcDcbDrawIndirectMultiGetSize(); + +} + #endif diff --git a/core/libs/prx/libSceAgc/DcbDraw/include/IndexBuffer.hpp b/core/libs/prx/libSceAgc/DcbDraw/include/IndexBuffer.hpp index b90a2a40d6..652629217a 100644 --- a/core/libs/prx/libSceAgc/DcbDraw/include/IndexBuffer.hpp +++ b/core/libs/prx/libSceAgc/DcbDraw/include/IndexBuffer.hpp @@ -1,4 +1,21 @@ #ifndef CORE_LIBS_PRX_LIBSCEAGC_DCBDRAW_INCLUDE_INDEXBUFFER_HPP #define CORE_LIBS_PRX_LIBSCEAGC_DCBDRAW_INCLUDE_INDEXBUFFER_HPP +#include "SceTypes.hpp" +#include "SceShaders.hpp" + +extern "C" { + +std::uint32_t* APS5_VABI sceAgcDcbSetIndexBuffer(CommandBuffer* buf, std::uint64_t indexAddress); +std::uint32_t APS5_VABI sceAgcDcbSetIndexBufferGetSize(); +std::uint32_t* APS5_VABI sceAgcDcbSetIndexCount(CommandBuffer* buf, std::uint32_t indexCount); +std::uint32_t APS5_VABI sceAgcDcbSetIndexCountGetSize(); +std::uint32_t* APS5_VABI sceAgcDcbSetIndexSize(CommandBuffer* buf, std::uint8_t indexSize, std::uint8_t cachePolicy); +std::uint32_t APS5_VABI sceAgcDcbSetIndexSizeGetSize(); +std::uint32_t* APS5_VABI sceAgcDcbSetIndexSize_0600(CommandBuffer* buf, std::uint8_t indexSize, std::uint8_t cachePolicy, std::uint8_t perInstanceObjectId); +std::uint32_t* APS5_VABI sceAgcDcbSetIndexIndirectArgs(CommandBuffer* buf, std::uint64_t attributeAddress, std::uint32_t attributeIndex); +std::uint32_t APS5_VABI sceAgcDcbSetIndexIndirectArgsGetSize(); + +} + #endif diff --git a/core/libs/prx/libSceAgc/DcbDraw/include/Instancing.hpp b/core/libs/prx/libSceAgc/DcbDraw/include/Instancing.hpp index b67b2b5bac..8f74423854 100644 --- a/core/libs/prx/libSceAgc/DcbDraw/include/Instancing.hpp +++ b/core/libs/prx/libSceAgc/DcbDraw/include/Instancing.hpp @@ -1,4 +1,15 @@ #ifndef CORE_LIBS_PRX_LIBSCEAGC_DCBDRAW_INCLUDE_INSTANCING_HPP #define CORE_LIBS_PRX_LIBSCEAGC_DCBDRAW_INCLUDE_INSTANCING_HPP +#include "SceTypes.hpp" +#include "SceShaders.hpp" + +extern "C" { + +std::uint32_t* APS5_VABI sceAgcDcbSetNumInstances(CommandBuffer* buf, std::uint32_t numInstances); +std::uint32_t APS5_VABI sceAgcDcbSetNumInstancesGetSize(); +uint32_t* APS5_VABI sceAgcDcbSetBaseIndirectArgs(CommandBuffer* buf, uint32_t shaderType, const volatile void* indirectBaseAddr); + +} + #endif diff --git a/core/libs/prx/libSceAgc/DcbDraw/include/Stats.hpp b/core/libs/prx/libSceAgc/DcbDraw/include/Stats.hpp index a2bd44d8bc..de4d9fcf72 100644 --- a/core/libs/prx/libSceAgc/DcbDraw/include/Stats.hpp +++ b/core/libs/prx/libSceAgc/DcbDraw/include/Stats.hpp @@ -1,4 +1,15 @@ #ifndef CORE_LIBS_PRX_LIBSCEAGC_DCBDRAW_INCLUDE_STATS_HPP #define CORE_LIBS_PRX_LIBSCEAGC_DCBDRAW_INCLUDE_STATS_HPP +#include "SceTypes.hpp" +#include "SceShaders.hpp" + +extern "C" { + +std::uint32_t* APS5_VABI sceAgcDcbGetLodStats(CommandBuffer* buf, std::uint8_t cachePolicy, const volatile void* buffer, std::uint32_t bufferSizeInBytes, std::uint32_t resetCount, std::uint8_t forceReset, std::uint8_t reportAndReset, std::uint32_t reportingIntervalIn100kClocks); +std::uint32_t APS5_VABI sceAgcDcbBeginOcclusionQueryGetSize(std::int32_t queryType); +std::uint32_t APS5_VABI sceAgcDcbEndOcclusionQueryGetSize(); + +} + #endif diff --git a/core/libs/prx/libSceAgc/DcbFlow/include/Control.hpp b/core/libs/prx/libSceAgc/DcbFlow/include/Control.hpp index 6ded533662..2890339f5b 100644 --- a/core/libs/prx/libSceAgc/DcbFlow/include/Control.hpp +++ b/core/libs/prx/libSceAgc/DcbFlow/include/Control.hpp @@ -9,4 +9,18 @@ std::uint32_t* APS5_VABI sceAgcDcbAtomicGds(CommandBuffer* buf, std::uint32_t co std::uint32_t* APS5_VABI sceAgcDcbAtomicGds_0900(CommandBuffer* buf, std::uint32_t control, std::uint32_t mode, std::uint32_t gdsOp, std::uint32_t src, std::uint16_t offset, std::uint16_t index, std::uint32_t mask, std::uint32_t data, std::uint64_t compareData, std::uint64_t extraData); } +#include "SceShaders.hpp" + +extern "C" { + +uint32_t* APS5_VABI sceAgcDcbJump(CommandBuffer* buf, uint8_t mode, uint8_t cachePolicy, const uint32_t* target, uint32_t sizeInDwords); +std::uint32_t APS5_VABI sceAgcDcbJumpGetSize(); +std::uint32_t* APS5_VABI sceAgcDcbResetQueue(CommandBuffer* buf, std::uint32_t op, std::uint32_t state); +std::uint32_t* APS5_VABI sceAgcDcbClearState(CommandBuffer* buf, std::uint32_t command); +uint32_t* APS5_VABI sceAgcDcbRewind(CommandBuffer* buf, uint32_t initialState); +uint32_t APS5_VABI sceAgcDcbRewindGetSize(void); +uint32_t* APS5_VABI sceAgcDcbWaitUntilSafeForRendering(CommandBuffer* buf, uint32_t videoOutHandle, uint32_t displayBufferIndex); + +} + #endif diff --git a/core/libs/prx/libSceAgc/DcbFlow/include/Dispatch.hpp b/core/libs/prx/libSceAgc/DcbFlow/include/Dispatch.hpp index 025f84ad5c..4266a8cf60 100644 --- a/core/libs/prx/libSceAgc/DcbFlow/include/Dispatch.hpp +++ b/core/libs/prx/libSceAgc/DcbFlow/include/Dispatch.hpp @@ -1,4 +1,14 @@ #ifndef CORE_LIBS_PRX_LIBSCEAGC_DCBFLOW_INCLUDE_DISPATCH_HPP #define CORE_LIBS_PRX_LIBSCEAGC_DCBFLOW_INCLUDE_DISPATCH_HPP +#include "SceTypes.hpp" +#include "SceShaders.hpp" + +extern "C" { + +uint32_t* APS5_VABI sceAgcDcbDispatchIndirect(CommandBuffer* buf, uint32_t dataOffsetInBytes, uint32_t flags); +std::uint32_t APS5_VABI sceAgcDcbDispatchIndirectGetSize(); + +} + #endif diff --git a/core/libs/prx/libSceAgc/DcbFlow/include/Memory.hpp b/core/libs/prx/libSceAgc/DcbFlow/include/Memory.hpp index f089c9a83e..e9202cd6b5 100644 --- a/core/libs/prx/libSceAgc/DcbFlow/include/Memory.hpp +++ b/core/libs/prx/libSceAgc/DcbFlow/include/Memory.hpp @@ -9,4 +9,20 @@ std::uint32_t* APS5_VABI sceAgcDcbAcquireMem(CommandBuffer* buf, std::uint8_t en std::uint32_t APS5_VABI sceAgcDcbAtomicGdsGetSize(); } +#include "SceShaders.hpp" + +extern "C" { + +uint32_t APS5_VABI sceAgcDcbAcquireMemGetSize(void); +uint32_t* APS5_VABI sceAgcDcbCopyData(CommandBuffer* buf, uint8_t dst, uint8_t dstCachePolicy, uint64_t dstAddress, uint8_t src, uint8_t srcCachePolicy, uint64_t srcAddressOrImmediate, uint8_t itemSize, uint8_t writeConfirm); +std::uint64_t APS5_VABI sceAgcDcbCopyDataGetSize(); +std::uint32_t* APS5_VABI sceAgcDcbDmaData(CommandBuffer* buf, std::uint8_t engine, std::uint8_t dst, std::uint8_t dstCachePolicy, std::uint64_t dstAddress, std::uint8_t src, std::uint8_t srcCachePolicy, std::uint64_t srcAddress, std::uint32_t numBytes, std::uint8_t waitForPrevious, std::uint8_t writeConfirm, std::uint8_t blockEngine); +std::uint32_t APS5_VABI sceAgcDcbDmaDataGetSize(); +std::uint32_t* APS5_VABI sceAgcDcbAtomicMem(CommandBuffer* buf, std::uint8_t atomicOp, std::uint8_t command, std::uint8_t cachePolicy, const volatile void* address, std::uint64_t srcData, std::uint64_t compareData, std::uint16_t loopInterval); +std::uint32_t APS5_VABI sceAgcDcbAtomicMemGetSize(); +std::uint32_t* APS5_VABI sceAgcDcbWriteData(CommandBuffer* buf, std::uint8_t dst, std::uint8_t cachePolicy, std::uint64_t address, const void* data, std::uint32_t numDwords, std::uint8_t increment, std::uint8_t writeConfirm); +uint32_t APS5_VABI sceAgcDcbWriteDataGetSize(uint32_t numDwords); + +} + #endif diff --git a/core/libs/prx/libSceAgc/DcbFlow/include/Sync.hpp b/core/libs/prx/libSceAgc/DcbFlow/include/Sync.hpp index 6cad00334a..fa07f43e62 100644 --- a/core/libs/prx/libSceAgc/DcbFlow/include/Sync.hpp +++ b/core/libs/prx/libSceAgc/DcbFlow/include/Sync.hpp @@ -1,5 +1,21 @@ #ifndef CORE_LIBS_PRX_LIBSCEAGC_DCBFLOW_INCLUDE_SYNC_HPP #define CORE_LIBS_PRX_LIBSCEAGC_DCBFLOW_INCLUDE_SYNC_HPP +#include "SceTypes.hpp" +#include "SceShaders.hpp" + +extern "C" { + +uint32_t* APS5_VABI sceAgcDcbCondExec(CommandBuffer* buf, const volatile uint32_t* address, uint32_t numDwords); +uint32_t APS5_VABI sceAgcDcbCondExecGetSize(void); +std::uint32_t* APS5_VABI sceAgcDcbWaitRegMem(CommandBuffer* buf, std::uint8_t size, std::uint8_t compareFunction, std::uint8_t operation, std::uint8_t cachePolicy, const volatile void* address, std::uint64_t reference, std::uint64_t mask, std::uint32_t pollCycles); +uint32_t APS5_VABI sceAgcDcbWaitOnAddressGetSize(uint32_t size); +std::uint32_t* APS5_VABI sceAgcDcbEventWrite(CommandBuffer* buf, std::uint8_t eventType, const volatile void* address); +std::uint64_t APS5_VABI sceAgcDcbEventWriteGetSize(std::uint8_t eventType); +std::uint32_t* APS5_VABI sceAgcDcbStallCommandBufferParser(CommandBuffer* buf); +std::uint32_t APS5_VABI sceAgcDcbStallCommandBufferParserGetSize(); +std::uint32_t* APS5_VABI sceAgcDcbMemSemaphore(CommandBuffer* buf, const volatile void* address, std::uint8_t waitForMailbox, std::uint8_t signalType, std::uint8_t operation); + +} #endif diff --git a/core/libs/prx/libSceAgc/DcbState/include/ContextState.hpp b/core/libs/prx/libSceAgc/DcbState/include/ContextState.hpp index 99d37d3c6a..19d2e85ba7 100644 --- a/core/libs/prx/libSceAgc/DcbState/include/ContextState.hpp +++ b/core/libs/prx/libSceAgc/DcbState/include/ContextState.hpp @@ -4,8 +4,6 @@ #include "SceTypes.hpp" #include -struct CommandBuffer; - extern "C" { uint32_t* APS5_VABI sceAgcDcbContextStateOp(CommandBuffer* buf, uint32_t operation); @@ -14,4 +12,15 @@ uint64_t APS5_VABI sceAgcDcbContextStateOpGetSize(uint32_t operation); } +#include "SceShaders.hpp" + +extern "C" { + +std::uint32_t APS5_VABI sceAgcDcbSetBaseDispatchIndirectArgsGetSize(); +std::uint32_t APS5_VABI sceAgcDcbSetBaseDrawIndirectArgsGetSize(); +std::uint32_t APS5_VABI sceAgcDcbQueueEndOfShaderActionGetSize(); +std::uint32_t APS5_VABI sceAgcDcbGetLodStatsGetSize(); + +} + #endif diff --git a/core/libs/prx/libSceAgc/DcbState/include/Display.hpp b/core/libs/prx/libSceAgc/DcbState/include/Display.hpp index 74fb8caf0d..e6868d17f4 100644 --- a/core/libs/prx/libSceAgc/DcbState/include/Display.hpp +++ b/core/libs/prx/libSceAgc/DcbState/include/Display.hpp @@ -1,4 +1,15 @@ #ifndef CORE_LIBS_PRX_LIBSCEAGC_DCBSTATE_INCLUDE_DISPLAY_HPP #define CORE_LIBS_PRX_LIBSCEAGC_DCBSTATE_INCLUDE_DISPLAY_HPP +#include "SceTypes.hpp" +#include "SceShaders.hpp" + +extern "C" { + +uint32_t* APS5_VABI sceAgcDcbSetFlip(CommandBuffer* buf, uint32_t videoOutHandle, int32_t displayBufferIndex, uint32_t flipMode, int64_t flipArg); +uint32_t* APS5_VABI sceAgcDcbPrimeUtcl2(CommandBuffer* buf, const volatile void* address, uint32_t sizeInBytes); +std::uint32_t APS5_VABI sceAgcDcbPrimeUtcl2GetSize(); + +} + #endif diff --git a/core/libs/prx/libSceAgc/DcbState/include/Init.hpp b/core/libs/prx/libSceAgc/DcbState/include/Init.hpp index de641fea3d..8e278b3fc3 100644 --- a/core/libs/prx/libSceAgc/DcbState/include/Init.hpp +++ b/core/libs/prx/libSceAgc/DcbState/include/Init.hpp @@ -1,4 +1,14 @@ #ifndef CORE_LIBS_PRX_LIBSCEAGC_DCBSTATE_INCLUDE_INIT_HPP #define CORE_LIBS_PRX_LIBSCEAGC_DCBSTATE_INCLUDE_INIT_HPP +#include "SceTypes.hpp" +#include "SceShaders.hpp" + +extern "C" { + +int APS5_VABI sceAgcInit(std::uint32_t version); +int APS5_VABI sceAgcInit_0090(std::uint32_t* state, std::uint32_t version); + +} + #endif diff --git a/core/libs/prx/libSceAgc/DcbState/include/Marker.hpp b/core/libs/prx/libSceAgc/DcbState/include/Marker.hpp index 688c0a80b2..bb626aa02e 100644 --- a/core/libs/prx/libSceAgc/DcbState/include/Marker.hpp +++ b/core/libs/prx/libSceAgc/DcbState/include/Marker.hpp @@ -12,4 +12,14 @@ std::uint32_t* Pop(CommandBuffer* buf, const char* function); } +#include "SceShaders.hpp" + +extern "C" { + +uint32_t* APS5_VABI sceAgcDcbSetMarker(CommandBuffer* buf, const char* str, uint32_t color); +uint32_t* APS5_VABI sceAgcDcbPopMarker(CommandBuffer* buf); +uint32_t* APS5_VABI sceAgcDcbPushMarker(CommandBuffer* buf, const char* str, uint32_t color); + +} + #endif diff --git a/core/libs/prx/libSceAgc/DcbState/include/Predication.hpp b/core/libs/prx/libSceAgc/DcbState/include/Predication.hpp index 65f64a14eb..5d56b7066a 100644 --- a/core/libs/prx/libSceAgc/DcbState/include/Predication.hpp +++ b/core/libs/prx/libSceAgc/DcbState/include/Predication.hpp @@ -1,4 +1,16 @@ #ifndef CORE_LIBS_PRX_LIBSCEAGC_DCBSTATE_INCLUDE_PREDICATION_HPP #define CORE_LIBS_PRX_LIBSCEAGC_DCBSTATE_INCLUDE_PREDICATION_HPP +#include "SceTypes.hpp" +#include "SceShaders.hpp" + +extern "C" { + +uint32_t* APS5_VABI sceAgcDcbSetPredication(CommandBuffer* buf, uint8_t condition, uint8_t op, uint8_t waitOp, const volatile void* address, uint32_t countInDwords); +std::uint32_t APS5_VABI sceAgcDcbSetZPassPredicationEnableGetSize(); +std::uint32_t APS5_VABI sceAgcDcbSetPredicationDisableGetSize(); +std::uint32_t APS5_VABI sceAgcDcbSetBoolPredicationEnableGetSize(); + +} + #endif diff --git a/core/libs/prx/libSceAgc/DcbState/include/Registers.hpp b/core/libs/prx/libSceAgc/DcbState/include/Registers.hpp index b7beea1499..015d0ed7b2 100644 --- a/core/libs/prx/libSceAgc/DcbState/include/Registers.hpp +++ b/core/libs/prx/libSceAgc/DcbState/include/Registers.hpp @@ -1,4 +1,26 @@ #ifndef CORE_LIBS_PRX_LIBSCEAGC_DCBSTATE_INCLUDE_REGISTERS_HPP #define CORE_LIBS_PRX_LIBSCEAGC_DCBSTATE_INCLUDE_REGISTERS_HPP +#include "SceTypes.hpp" +#include "SceShaders.hpp" + +extern "C" { + +std::uint32_t* APS5_VABI sceAgcDcbSetCfRegisterDirect(CommandBuffer* buf, ShaderRegister reg); +std::uint32_t* APS5_VABI sceAgcDcbSetCfRegisterRangeDirect(CommandBuffer* buf, std::uint32_t offset, const std::uint32_t* values, std::uint32_t numValues); +uint32_t* APS5_VABI sceAgcDcbSetCxRegisterDirect(CommandBuffer* buf, ShaderRegister reg); +uint32_t APS5_VABI sceAgcDcbSetCxRegisterDirectGetSize(void); +std::uint32_t* APS5_VABI sceAgcDcbSetCxRegistersIndirect(CommandBuffer* buf, const volatile ShaderRegister* regs, std::uint32_t numRegs); +std::uint32_t APS5_VABI sceAgcDcbSetCxRegistersIndirectGetSize(std::uint32_t numRegs); +uint32_t* APS5_VABI sceAgcDcbSetShRegisterDirect(CommandBuffer* buf, ShaderRegister reg); +std::uint32_t APS5_VABI sceAgcDcbSetShRegisterDirectGetSize(); +std::uint32_t* APS5_VABI sceAgcDcbSetShRegistersIndirect(CommandBuffer* buf, const volatile ShaderRegister* regs, std::uint32_t numRegs); +std::uint32_t APS5_VABI sceAgcDcbSetShRegistersIndirectGetSize(std::uint32_t numRegs); +uint32_t* APS5_VABI sceAgcDcbSetUcRegisterDirect(CommandBuffer* buf, ShaderRegister reg); +std::uint32_t APS5_VABI sceAgcDcbSetUcRegisterDirectGetSize(); +std::uint32_t* APS5_VABI sceAgcDcbSetUcRegistersIndirect(CommandBuffer* buf, const volatile ShaderRegister* regs, std::uint32_t numRegs); +std::uint32_t APS5_VABI sceAgcDcbSetUcRegistersIndirectGetSize(std::uint32_t numRegs); + +} + #endif diff --git a/core/libs/prx/libSceAgc/DcbState/include/Workload.hpp b/core/libs/prx/libSceAgc/DcbState/include/Workload.hpp index 3d5d6cac71..562ab7678f 100644 --- a/core/libs/prx/libSceAgc/DcbState/include/Workload.hpp +++ b/core/libs/prx/libSceAgc/DcbState/include/Workload.hpp @@ -1,4 +1,15 @@ #ifndef CORE_LIBS_PRX_LIBSCEAGC_DCBSTATE_INCLUDE_WORKLOAD_HPP #define CORE_LIBS_PRX_LIBSCEAGC_DCBSTATE_INCLUDE_WORKLOAD_HPP +#include "SceTypes.hpp" +#include "SceShaders.hpp" + +extern "C" { + +uint32_t* APS5_VABI sceAgcDcbSetWorkloadComplete(CommandBuffer* buf, uint32_t streamId, uint32_t workloadId); +uint32_t* APS5_VABI sceAgcDcbSetWorkloadsActive(CommandBuffer* buf, uint32_t streamId, const uint32_t* workloadIds, uint32_t workloadCount); +uint32_t* APS5_VABI sceAgcDcbSetWorkloadStreamInactive(CommandBuffer* buf, uint32_t streamId); + +} + #endif diff --git a/core/libs/prx/libSceAgc/Export.cpp b/core/libs/prx/libSceAgc/Export.cpp index 8e933ec1cf..3bab548078 100644 --- a/core/libs/prx/libSceAgc/Export.cpp +++ b/core/libs/prx/libSceAgc/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceAgc/include/Agc.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceAgc/Misc/include/Debug.hpp b/core/libs/prx/libSceAgc/Misc/include/Debug.hpp index 58286eb85c..6647ed5d6a 100644 --- a/core/libs/prx/libSceAgc/Misc/include/Debug.hpp +++ b/core/libs/prx/libSceAgc/Misc/include/Debug.hpp @@ -1,4 +1,15 @@ #ifndef CORE_LIBS_PRX_LIBSCEAGC_MISC_INCLUDE_DEBUG_HPP #define CORE_LIBS_PRX_LIBSCEAGC_MISC_INCLUDE_DEBUG_HPP +#include "SceTypes.hpp" +#include "SceShaders.hpp" + +extern "C" { + +int APS5_VABI sceAgcDebugRaiseException(std::uint32_t exceptionId); +int APS5_VABI sceAgcSetShaderInstrumentation(std::uint32_t flags); +std::uint32_t APS5_VABI sceAgcGetShaderInstrumentation(); + +} + #endif diff --git a/core/libs/prx/libSceAgc/Misc/include/PacketInfo.hpp b/core/libs/prx/libSceAgc/Misc/include/PacketInfo.hpp index 04a3d07eb6..29d7253eee 100644 --- a/core/libs/prx/libSceAgc/Misc/include/PacketInfo.hpp +++ b/core/libs/prx/libSceAgc/Misc/include/PacketInfo.hpp @@ -14,4 +14,14 @@ int APS5_VABI sceAgcGetDataPacketPayloadAddress(uint32_t** addr, uint32_t* cmd, int APS5_VABI sceAgcGetDataPacketPayloadAddress_0090(uint32_t** addr, uint32_t* cmd, int type); } +#include "SceShaders.hpp" + +extern "C" { + +uint32_t APS5_VABI sceAgcGetPacketSize(uint32_t* packet); +int APS5_VABI sceAgcGetDataPacketPayloadRange(SceAgcMemoryRange* range, uint32_t* cmd, int type); +int APS5_VABI sceAgcDcbGetSystemSoftwareVersion(uint32_t* destination, const uint32_t* packet); + +} + #endif diff --git a/core/libs/prx/libSceAgc/Misc/include/Platform.hpp b/core/libs/prx/libSceAgc/Misc/include/Platform.hpp index fd07f976ab..37e71bb0bd 100644 --- a/core/libs/prx/libSceAgc/Misc/include/Platform.hpp +++ b/core/libs/prx/libSceAgc/Misc/include/Platform.hpp @@ -1,4 +1,13 @@ #ifndef CORE_LIBS_PRX_LIBSCEAGC_MISC_INCLUDE_PLATFORM_HPP #define CORE_LIBS_PRX_LIBSCEAGC_MISC_INCLUDE_PLATFORM_HPP +#include "SceTypes.hpp" +#include "SceShaders.hpp" + +extern "C" { + +int APS5_VABI sceAgcGetIsTrinityMode(bool* isTrinityMode); + +} + #endif diff --git a/core/libs/prx/libSceAgc/Misc/include/RegisterDefaults.hpp b/core/libs/prx/libSceAgc/Misc/include/RegisterDefaults.hpp index c7eb4fea76..f8934d9fb0 100644 --- a/core/libs/prx/libSceAgc/Misc/include/RegisterDefaults.hpp +++ b/core/libs/prx/libSceAgc/Misc/include/RegisterDefaults.hpp @@ -4,6 +4,18 @@ #include extern "C" { -int APS5_VABI sceAgcGetDefaultCxStateFlat(void* out_state, std::uint32_t size); +int APS5_VABI sceAgcGetDefaultCxStateFlat(void* outState, std::uint32_t size); } + +#include "SceShaders.hpp" + +extern "C" { + +void* APS5_VABI sceAgcGetRegisterDefaults(); +void* APS5_VABI sceAgcGetRegisterDefaultsInternal(); +void* APS5_VABI sceAgcGetRegisterDefaults2(std::uint32_t version); +void* APS5_VABI sceAgcGetRegisterDefaults2Internal(std::uint32_t version); + +} + #endif diff --git a/core/libs/prx/libSceAgc/Misc/include/Semaphore.hpp b/core/libs/prx/libSceAgc/Misc/include/Semaphore.hpp index 834dcdd962..3f0602453c 100644 --- a/core/libs/prx/libSceAgc/Misc/include/Semaphore.hpp +++ b/core/libs/prx/libSceAgc/Misc/include/Semaphore.hpp @@ -1,4 +1,14 @@ #ifndef CORE_LIBS_PRX_LIBSCEAGC_MISC_INCLUDE_SEMAPHORE_HPP #define CORE_LIBS_PRX_LIBSCEAGC_MISC_INCLUDE_SEMAPHORE_HPP +#include "SceTypes.hpp" +#include "SceShaders.hpp" + +extern "C" { + +int APS5_VABI sceAgcSetAmmSemaphoreMemory(void* memory, std::uint64_t sizeInBytes); +int APS5_VABI sceAgcGetSemaphoreLabel(std::uint32_t index, void** label); + +} + #endif diff --git a/core/libs/prx/libSceAgc/Misc/include/ShaderFusion.hpp b/core/libs/prx/libSceAgc/Misc/include/ShaderFusion.hpp index 0927dc9e51..d90e4d427e 100644 --- a/core/libs/prx/libSceAgc/Misc/include/ShaderFusion.hpp +++ b/core/libs/prx/libSceAgc/Misc/include/ShaderFusion.hpp @@ -10,7 +10,16 @@ struct SizeAlign { std::size_t m_align; }; -extern "C" int APS5_VABI sceAgcFuseShaderHalves_0200(Shader* fused_result, const Shader* front, const Shader* back, void* scratch_mem); +extern "C" int APS5_VABI sceAgcFuseShaderHalves_0200(Shader* fusedResult, const Shader* front, const Shader* back, void* scratchMem); extern "C" int APS5_VABI sceAgcGetFusedShaderSize_0080(SizeAlign* dst, const Shader* front, const Shader* back); +#include "SceShaders.hpp" + +extern "C" { + +int APS5_VABI sceAgcFuseShaderHalves_nid_postfix(Shader* fusedResult, const Shader* front, const Shader* back, void* scratchMem); +int APS5_VABI sceAgcUpdateInterpolantMapping_0100(ShaderRegister* regs, const Shader* vs, const Shader* ps); + +} + #endif diff --git a/core/libs/prx/libSceAgc/Misc/include/Suspend.hpp b/core/libs/prx/libSceAgc/Misc/include/Suspend.hpp index 25b2dd5bf7..295d3761ce 100644 --- a/core/libs/prx/libSceAgc/Misc/include/Suspend.hpp +++ b/core/libs/prx/libSceAgc/Misc/include/Suspend.hpp @@ -1,4 +1,14 @@ #ifndef CORE_LIBS_PRX_LIBSCEAGC_MISC_INCLUDE_SUSPEND_HPP #define CORE_LIBS_PRX_LIBSCEAGC_MISC_INCLUDE_SUSPEND_HPP +#include "SceTypes.hpp" +#include "SceShaders.hpp" + +extern "C" { + +int APS5_VABI sceAgcSuspendPoint(void); +int APS5_VABI sceAgcSetSubmitMode(std::uint32_t mode); + +} + #endif diff --git a/core/libs/prx/libSceAgc/Patch/include/Branch.hpp b/core/libs/prx/libSceAgc/Patch/include/Branch.hpp index f4b7c44624..2e13cbeab4 100644 --- a/core/libs/prx/libSceAgc/Patch/include/Branch.hpp +++ b/core/libs/prx/libSceAgc/Patch/include/Branch.hpp @@ -1,4 +1,17 @@ #ifndef CORE_LIBS_PRX_LIBSCEAGC_PATCH_INCLUDE_BRANCH_HPP #define CORE_LIBS_PRX_LIBSCEAGC_PATCH_INCLUDE_BRANCH_HPP +#include "SceTypes.hpp" +#include "SceShaders.hpp" + +extern "C" { + +int APS5_VABI sceAgcBranchPatchSetCompareAddress(std::uint32_t* cmd, const volatile std::uint64_t* compareAddress); +int APS5_VABI sceAgcBranchPatchSetThenTarget(std::uint32_t* cmd, const volatile std::uint32_t* target, std::uint32_t sizeInDwords); +int APS5_VABI sceAgcBranchPatchSetElseTarget(std::uint32_t* cmd, const volatile std::uint32_t* target, std::uint32_t sizeInDwords); +int APS5_VABI sceAgcBranchPatchSetThenTarget_0300(std::uint32_t* cmd, std::uint8_t cachePolicy, const volatile std::uint32_t* target, std::uint32_t sizeInDwords); +int APS5_VABI sceAgcBranchPatchSetElseTarget_0300(std::uint32_t* cmd, std::uint8_t cachePolicy, const volatile std::uint32_t* target, std::uint32_t sizeInDwords); + +} + #endif diff --git a/core/libs/prx/libSceAgc/Patch/include/CondExec.hpp b/core/libs/prx/libSceAgc/Patch/include/CondExec.hpp index 8d81efe673..6db4bcedb9 100644 --- a/core/libs/prx/libSceAgc/Patch/include/CondExec.hpp +++ b/core/libs/prx/libSceAgc/Patch/include/CondExec.hpp @@ -1,4 +1,16 @@ #ifndef CORE_LIBS_PRX_LIBSCEAGC_PATCH_INCLUDE_CONDEXEC_HPP #define CORE_LIBS_PRX_LIBSCEAGC_PATCH_INCLUDE_CONDEXEC_HPP +#include "SceTypes.hpp" +#include "SceShaders.hpp" + +extern "C" { + +int APS5_VABI sceAgcCondExecPatchSetCommandAddress(uint32_t* cmd, const volatile uint32_t* command); +int APS5_VABI sceAgcCondExecPatchSetEnd(uint32_t* cmd, const volatile uint32_t* buffer); +int APS5_VABI sceAgcAsyncCondExecPatchSetCommandAddress(std::uint32_t* cmd, const volatile std::uint32_t* command); +int APS5_VABI sceAgcAsyncCondExecPatchSetEnd(std::uint32_t* cmd, const volatile std::uint32_t* buffer); + +} + #endif diff --git a/core/libs/prx/libSceAgc/Patch/include/Dma.hpp b/core/libs/prx/libSceAgc/Patch/include/Dma.hpp index d28d24df89..50dfc239b6 100644 --- a/core/libs/prx/libSceAgc/Patch/include/Dma.hpp +++ b/core/libs/prx/libSceAgc/Patch/include/Dma.hpp @@ -1,4 +1,14 @@ #ifndef CORE_LIBS_PRX_LIBSCEAGC_PATCH_INCLUDE_DMA_HPP #define CORE_LIBS_PRX_LIBSCEAGC_PATCH_INCLUDE_DMA_HPP +#include "SceTypes.hpp" +#include "SceShaders.hpp" + +extern "C" { + +int APS5_VABI sceAgcDmaDataPatchSetDstAddressOrOffset(std::uint32_t* cmd, std::uint64_t address); +int APS5_VABI sceAgcDmaDataPatchSetSrcAddressOrOffsetOrImmediate(std::uint32_t* cmd, std::uint64_t address); + +} + #endif diff --git a/core/libs/prx/libSceAgc/Patch/include/IndirectRegisters.hpp b/core/libs/prx/libSceAgc/Patch/include/IndirectRegisters.hpp index 72863129b7..9de388c582 100644 --- a/core/libs/prx/libSceAgc/Patch/include/IndirectRegisters.hpp +++ b/core/libs/prx/libSceAgc/Patch/include/IndirectRegisters.hpp @@ -1,4 +1,21 @@ #ifndef CORE_LIBS_PRX_LIBSCEAGC_PATCH_INCLUDE_INDIRECTREGISTERS_HPP #define CORE_LIBS_PRX_LIBSCEAGC_PATCH_INCLUDE_INDIRECTREGISTERS_HPP +#include "SceTypes.hpp" +#include "SceShaders.hpp" + +extern "C" { + +int APS5_VABI sceAgcSetCxRegIndirectPatchAddRegisters(std::uint32_t* cmd, std::uint32_t numRegs); +int APS5_VABI sceAgcSetCxRegIndirectPatchSetAddress(std::uint32_t* cmd, const volatile ShaderRegister* regs); +int APS5_VABI sceAgcSetCxRegIndirectPatchSetNumRegisters(std::uint32_t* cmd, std::uint32_t numRegs); +int APS5_VABI sceAgcSetShRegIndirectPatchAddRegisters(std::uint32_t* cmd, std::uint32_t numRegs); +int APS5_VABI sceAgcSetShRegIndirectPatchSetAddress(std::uint32_t* cmd, const volatile ShaderRegister* regs); +int APS5_VABI sceAgcSetShRegIndirectPatchSetNumRegisters(std::uint32_t* cmd, std::uint32_t numRegs); +int APS5_VABI sceAgcSetUcRegIndirectPatchAddRegisters(std::uint32_t* cmd, std::uint32_t numRegs); +int APS5_VABI sceAgcSetUcRegIndirectPatchSetAddress(std::uint32_t* cmd, const volatile ShaderRegister* regs); +int APS5_VABI sceAgcSetUcRegIndirectPatchSetNumRegisters(std::uint32_t* cmd, std::uint32_t numRegs); + +} + #endif diff --git a/core/libs/prx/libSceAgc/Patch/include/Jump.hpp b/core/libs/prx/libSceAgc/Patch/include/Jump.hpp index b5820f260d..1d6ba6899e 100644 --- a/core/libs/prx/libSceAgc/Patch/include/Jump.hpp +++ b/core/libs/prx/libSceAgc/Patch/include/Jump.hpp @@ -1,4 +1,14 @@ #ifndef CORE_LIBS_PRX_LIBSCEAGC_PATCH_INCLUDE_JUMP_HPP #define CORE_LIBS_PRX_LIBSCEAGC_PATCH_INCLUDE_JUMP_HPP +#include "SceTypes.hpp" +#include "SceShaders.hpp" + +extern "C" { + +int APS5_VABI sceAgcJumpPatchSetTarget(uint32_t* cmd, const volatile uint32_t* target, uint32_t sizeInDwords); +int APS5_VABI sceAgcJumpPatchSetTarget_0300(uint32_t* cmd, uint64_t cachePolicy, const volatile uint32_t* target, uint32_t sizeInDwords); + +} + #endif diff --git a/core/libs/prx/libSceAgc/Patch/include/Nop.hpp b/core/libs/prx/libSceAgc/Patch/include/Nop.hpp index 9958a2cbc6..390c3de34c 100644 --- a/core/libs/prx/libSceAgc/Patch/include/Nop.hpp +++ b/core/libs/prx/libSceAgc/Patch/include/Nop.hpp @@ -1,4 +1,13 @@ #ifndef CORE_LIBS_PRX_LIBSCEAGC_PATCH_INCLUDE_NOP_HPP #define CORE_LIBS_PRX_LIBSCEAGC_PATCH_INCLUDE_NOP_HPP +#include "SceTypes.hpp" +#include "SceShaders.hpp" + +extern "C" { + +std::uint32_t* APS5_VABI sceAgcSetNop(CommandBuffer* buf, std::uint32_t sizeDw); + +} + #endif diff --git a/core/libs/prx/libSceAgc/Patch/include/QueueEndOfPipeAction.hpp b/core/libs/prx/libSceAgc/Patch/include/QueueEndOfPipeAction.hpp index eb06c3a58d..7c7d61b7cc 100644 --- a/core/libs/prx/libSceAgc/Patch/include/QueueEndOfPipeAction.hpp +++ b/core/libs/prx/libSceAgc/Patch/include/QueueEndOfPipeAction.hpp @@ -1,4 +1,16 @@ #ifndef CORE_LIBS_PRX_LIBSCEAGC_PATCH_INCLUDE_QUEUEENDOFPIPEACTION_HPP #define CORE_LIBS_PRX_LIBSCEAGC_PATCH_INCLUDE_QUEUEENDOFPIPEACTION_HPP +#include "SceTypes.hpp" +#include "SceShaders.hpp" + +extern "C" { + +int APS5_VABI sceAgcQueueEndOfPipeActionPatchAddress(std::uint32_t* cmd, const volatile Label* address); +int APS5_VABI sceAgcQueueEndOfPipeActionPatchData(uint32_t* cmd, uint64_t data); +int APS5_VABI sceAgcQueueEndOfPipeActionPatchGcrCntl(std::uint32_t* cmd, std::uint16_t gcrControl); +int APS5_VABI sceAgcQueueEndOfPipeActionPatchType(std::uint32_t* cmd, std::uint8_t action); + +} + #endif diff --git a/core/libs/prx/libSceAgc/Patch/include/Rewind.hpp b/core/libs/prx/libSceAgc/Patch/include/Rewind.hpp index 52e1bc2625..9752bd43da 100644 --- a/core/libs/prx/libSceAgc/Patch/include/Rewind.hpp +++ b/core/libs/prx/libSceAgc/Patch/include/Rewind.hpp @@ -1,4 +1,14 @@ #ifndef CORE_LIBS_PRX_LIBSCEAGC_PATCH_INCLUDE_REWIND_HPP #define CORE_LIBS_PRX_LIBSCEAGC_PATCH_INCLUDE_REWIND_HPP +#include "SceTypes.hpp" +#include "SceShaders.hpp" + +extern "C" { + +int APS5_VABI sceAgcRewindPatchSetRewindState(uint32_t* cmd, uint8_t state); +int APS5_VABI sceAgcAsyncRewindPatchSetRewindState(std::uint32_t* cmd, std::uint8_t state); + +} + #endif diff --git a/core/libs/prx/libSceAgc/Patch/include/WaitRegMem.hpp b/core/libs/prx/libSceAgc/Patch/include/WaitRegMem.hpp index 8e14191a5e..0bdd3d5fd6 100644 --- a/core/libs/prx/libSceAgc/Patch/include/WaitRegMem.hpp +++ b/core/libs/prx/libSceAgc/Patch/include/WaitRegMem.hpp @@ -1,4 +1,22 @@ #ifndef CORE_LIBS_PRX_LIBSCEAGC_PATCH_INCLUDE_WAITREGMEM_HPP #define CORE_LIBS_PRX_LIBSCEAGC_PATCH_INCLUDE_WAITREGMEM_HPP +#include "SceTypes.hpp" +#include "SceShaders.hpp" + +extern "C" { + +int APS5_VABI sceAgcWaitRegMemPatchAddress(std::uint32_t* cmd, const volatile void* address); +int APS5_VABI sceAgcWaitRegMemPatchReference(std::uint32_t* cmd, std::uint32_t reference); +int APS5_VABI sceAgcWaitRegMemPatchMask(std::uint32_t* cmd, std::uint32_t mask); +int APS5_VABI sceAgcWaitRegMemPatchCompareFunction(std::uint32_t* cmd, std::uint8_t compareFunction); +int APS5_VABI sceAgcWriteDataPatchSetAddressOrOffset(std::uint32_t* cmd, std::uint64_t address); +int APS5_VABI sceAgcAsyncWriteDataPatchSetAddressOrOffset(std::uint32_t* cmd, std::uint64_t address); +int APS5_VABI sceAgcWriteDataPatchSetDst(std::uint32_t* cmd, std::uint8_t dst); +int APS5_VABI sceAgcAsyncWriteDataPatchSetDst(std::uint32_t* cmd, std::uint8_t dst); +int APS5_VABI sceAgcWriteDataPatchSetCachePolicy(std::uint32_t* cmd, std::uint8_t cachePolicy); +int APS5_VABI sceAgcAsyncWriteDataPatchSetCachePolicy(std::uint32_t* cmd, std::uint8_t cachePolicy); + +} + #endif diff --git a/core/libs/prx/libSceAgc/Predication/include/Predication.hpp b/core/libs/prx/libSceAgc/Predication/include/Predication.hpp index 7ae84c8a76..cad10cd236 100644 --- a/core/libs/prx/libSceAgc/Predication/include/Predication.hpp +++ b/core/libs/prx/libSceAgc/Predication/include/Predication.hpp @@ -1,4 +1,14 @@ #ifndef CORE_LIBS_PRX_LIBSCEAGC_PREDICATION_INCLUDE_PREDICATION_HPP #define CORE_LIBS_PRX_LIBSCEAGC_PREDICATION_INCLUDE_PREDICATION_HPP +#include "SceTypes.hpp" +#include "SceShaders.hpp" + +extern "C" { + +int APS5_VABI sceAgcSetPacketPredication(uint32_t* packet, uint32_t predication); +int APS5_VABI sceAgcSetRangePredication(uint32_t* start, const volatile uint32_t* end, uint32_t predication); + +} + #endif diff --git a/core/libs/prx/libSceAgc/Shader/include/CreateShader.hpp b/core/libs/prx/libSceAgc/Shader/include/CreateShader.hpp index 68117f4735..044d288596 100644 --- a/core/libs/prx/libSceAgc/Shader/include/CreateShader.hpp +++ b/core/libs/prx/libSceAgc/Shader/include/CreateShader.hpp @@ -1,4 +1,13 @@ #ifndef CORE_LIBS_PRX_LIBSCEAGC_SHADER_INCLUDE_CREATESHADER_HPP #define CORE_LIBS_PRX_LIBSCEAGC_SHADER_INCLUDE_CREATESHADER_HPP +#include "SceTypes.hpp" +#include "SceShaders.hpp" + +extern "C" { + +int APS5_VABI sceAgcCreateShader(Shader** dst, void* header, const volatile void* code); + +} + #endif diff --git a/core/libs/prx/libSceAgc/Shader/include/GsOversubscription.hpp b/core/libs/prx/libSceAgc/Shader/include/GsOversubscription.hpp new file mode 100644 index 0000000000..b454416920 --- /dev/null +++ b/core/libs/prx/libSceAgc/Shader/include/GsOversubscription.hpp @@ -0,0 +1,10 @@ +#pragma once + +#include "SceTypes.hpp" +#include "SceShaders.hpp" + +extern "C" { + +int APS5_VABI sceAgcGetGsOversubscription(ShaderRegister* regs, const Shader* gs, std::uint32_t budget, float factor); + +} diff --git a/core/libs/prx/libSceAgc/Shader/include/GsPrimPayload.hpp b/core/libs/prx/libSceAgc/Shader/include/GsPrimPayload.hpp new file mode 100644 index 0000000000..d72b485767 --- /dev/null +++ b/core/libs/prx/libSceAgc/Shader/include/GsPrimPayload.hpp @@ -0,0 +1,10 @@ +#pragma once + +#include "SceTypes.hpp" +#include "SceShaders.hpp" + +extern "C" { + +int APS5_VABI sceAgcGetGsPrimPayload(std::uint32_t* payload, const Shader* gs); + +} diff --git a/core/libs/prx/libSceAgc/Shader/include/InterpolantMapping.hpp b/core/libs/prx/libSceAgc/Shader/include/InterpolantMapping.hpp index 91ffb9eeb8..7085d35fe0 100644 --- a/core/libs/prx/libSceAgc/Shader/include/InterpolantMapping.hpp +++ b/core/libs/prx/libSceAgc/Shader/include/InterpolantMapping.hpp @@ -1,4 +1,17 @@ #ifndef CORE_LIBS_PRX_LIBSCEAGC_SHADER_INCLUDE_INTERPOLANTMAPPING_HPP #define CORE_LIBS_PRX_LIBSCEAGC_SHADER_INCLUDE_INTERPOLANTMAPPING_HPP +#include "SceTypes.hpp" +#include "SceShaders.hpp" + +extern "C" { + +int APS5_VABI sceAgcCreateInterpolantMapping_0100(ShaderRegister* regs, const Shader* gs, const Shader* ps); +int APS5_VABI sceAgcCreateInterpolantMapping_10000(ShaderRegister* regs, const Shader* gs, const Shader* ps); +int APS5_VABI sceAgcUpdateInterpolantMapping_10000(ShaderRegister* regs, const Shader* gs, const Shader* ps); +int APS5_VABI sceAgcCreateInterpolantMapping_nid_postfix(ShaderRegister* regs, const Shader* gs, const Shader* ps); +int APS5_VABI sceAgcUpdateInterpolantMapping_nid_postfix(ShaderRegister* regs, const Shader* gs, const Shader* ps); + +} + #endif diff --git a/core/libs/prx/libSceAgc/Shader/include/LinkShaders.hpp b/core/libs/prx/libSceAgc/Shader/include/LinkShaders.hpp new file mode 100644 index 0000000000..99d9e328a3 --- /dev/null +++ b/core/libs/prx/libSceAgc/Shader/include/LinkShaders.hpp @@ -0,0 +1,10 @@ +#pragma once + +#include "SceTypes.hpp" +#include "SceShaders.hpp" + +extern "C" { + +int APS5_VABI sceAgcLinkShaders(ShaderRegister* context, ShaderRegister* primitive, const void* reserved, const Shader* vertex, const Shader* pixel, std::uint32_t primitiveType); + +} diff --git a/core/libs/prx/libSceAgc/Shader/include/PrimState.hpp b/core/libs/prx/libSceAgc/Shader/include/PrimState.hpp index 1dda27a825..090a9a78e6 100644 --- a/core/libs/prx/libSceAgc/Shader/include/PrimState.hpp +++ b/core/libs/prx/libSceAgc/Shader/include/PrimState.hpp @@ -1,4 +1,14 @@ #ifndef CORE_LIBS_PRX_LIBSCEAGC_SHADER_INCLUDE_PRIMSTATE_HPP #define CORE_LIBS_PRX_LIBSCEAGC_SHADER_INCLUDE_PRIMSTATE_HPP +#include "SceTypes.hpp" +#include "SceShaders.hpp" + +extern "C" { + +int APS5_VABI sceAgcCreatePrimState(ShaderRegister* cxRegs, ShaderRegister* ucRegs, const Shader* hs, const Shader* gs, std::uint32_t primType); +int APS5_VABI sceAgcUpdatePrimState(ShaderRegister* cxRegs, ShaderRegister* ucRegs, std::uint32_t primType); + +} + #endif diff --git a/core/libs/prx/libSceAgc/Shader/src/GsOversubscription.cpp b/core/libs/prx/libSceAgc/Shader/src/GsOversubscription.cpp index 029ec1c099..79209401f3 100644 --- a/core/libs/prx/libSceAgc/Shader/src/GsOversubscription.cpp +++ b/core/libs/prx/libSceAgc/Shader/src/GsOversubscription.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceAgc/Shader/include/GsOversubscription.hpp" #include #include #include diff --git a/core/libs/prx/libSceAgc/Shader/src/GsPrimPayload.cpp b/core/libs/prx/libSceAgc/Shader/src/GsPrimPayload.cpp index 722ade98c6..2815c5a02b 100644 --- a/core/libs/prx/libSceAgc/Shader/src/GsPrimPayload.cpp +++ b/core/libs/prx/libSceAgc/Shader/src/GsPrimPayload.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceAgc/Shader/include/GsPrimPayload.hpp" #include #include #include diff --git a/core/libs/prx/libSceAgc/Shader/src/LinkShaders.cpp b/core/libs/prx/libSceAgc/Shader/src/LinkShaders.cpp index 59a43354c8..8b6a8ff132 100644 --- a/core/libs/prx/libSceAgc/Shader/src/LinkShaders.cpp +++ b/core/libs/prx/libSceAgc/Shader/src/LinkShaders.cpp @@ -1,3 +1,6 @@ +#include "prx/libSceAgc/Shader/include/PrimState.hpp" +#include "prx/libSceAgc/Shader/include/LinkShaders.hpp" +#include "prx/libSceAgc/Shader/include/InterpolantMapping.hpp" #include "SceShaders.hpp" #include "prx/libSceAgcDriver/Execution/include/ShaderPreparationScope.hpp" #include "prx/libSceAgcDriver/Execution/include/Driver.hpp" @@ -6,9 +9,6 @@ #include #include -extern "C" int APS5_VABI sceAgcCreatePrimState(ShaderRegister*, ShaderRegister*, const Shader*, const Shader*, std::uint32_t); -extern "C" int APS5_VABI sceAgcCreateInterpolantMapping_0100(ShaderRegister*, const Shader*, const Shader*); - extern "C" int APS5_VABI sceAgcLinkShaders(ShaderRegister* context, ShaderRegister* primitive, const void* reserved, const Shader* vertex, const Shader* pixel, std::uint32_t primitiveType) { using namespace ShaderRegs; diff --git a/core/libs/prx/libSceAgc/Unimplemented.cpp b/core/libs/prx/libSceAgc/Unimplemented.cpp index 487d737193..919f2d8b77 100644 --- a/core/libs/prx/libSceAgc/Unimplemented.cpp +++ b/core/libs/prx/libSceAgc/Unimplemented.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceAgc/include/Agc.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceAgc/include/Agc.hpp b/core/libs/prx/libSceAgc/include/Agc.hpp new file mode 100644 index 0000000000..e600558de3 --- /dev/null +++ b/core/libs/prx/libSceAgc/include/Agc.hpp @@ -0,0 +1,19 @@ +#pragma once + +#include "SceTypes.hpp" +#include "SceShaders.hpp" + +extern "C" { + +int APS5_VABI sceAgcSuspendPointAndCheckStatus(void); +std::uint32_t* APS5_VABI sceAgcAcbPushMarkerSpan(CommandBuffer* buffer, const char* text, std::uint32_t length, std::uint32_t color); +std::uint32_t* APS5_VABI sceAgcAcbSetMarkerSpan(CommandBuffer* buffer, const char* text, std::uint32_t length, std::uint32_t color); +int APS5_VABI sceAgcAcquireMemSetEngine(std::uint32_t* packet, std::uint8_t engine); +std::uint32_t* APS5_VABI sceAgcDcbPushMarkerSpan(CommandBuffer* buffer, const char* text, std::uint32_t length, std::uint32_t color); +std::uint32_t* APS5_VABI sceAgcDcbSetMarkerSpan(CommandBuffer* buffer, const char* text, std::uint32_t length, std::uint32_t color); +int APS5_VABI sceAgcSetSemaphoreMemory(void* memory, std::uint64_t size); +std::uint32_t* APS5_VABI sceAgcCbMemsetExclusive(CommandBuffer* buffer, void* destination, const void* pattern, std::uint64_t size); + +int APS5_VABI sceAgcAcbInitializeDefaultHardwareState(); + +} diff --git a/core/libs/prx/libSceAgc/libSceAgc.hpp b/core/libs/prx/libSceAgc/libSceAgc.hpp new file mode 100644 index 0000000000..407e5b809c --- /dev/null +++ b/core/libs/prx/libSceAgc/libSceAgc.hpp @@ -0,0 +1,51 @@ +#pragma once + +#include "prx/libSceAgc/Acb/include/Control.hpp" +#include "prx/libSceAgc/Acb/include/Dispatch.hpp" +#include "prx/libSceAgc/Acb/include/Memory.hpp" +#include "prx/libSceAgc/Acb/include/Sync.hpp" +#include "prx/libSceAgc/Cb/include/Branch.hpp" +#include "prx/libSceAgc/Cb/include/Dispatch.hpp" +#include "prx/libSceAgc/Cb/include/Registers.hpp" +#include "prx/libSceAgc/Cb/include/Sync.hpp" +#include "prx/libSceAgc/DcbDraw/include/DrawIndexed.hpp" +#include "prx/libSceAgc/DcbDraw/include/DrawNonIndexed.hpp" +#include "prx/libSceAgc/DcbDraw/include/IndexBuffer.hpp" +#include "prx/libSceAgc/DcbDraw/include/Instancing.hpp" +#include "prx/libSceAgc/DcbDraw/include/Stats.hpp" +#include "prx/libSceAgc/DcbFlow/include/Control.hpp" +#include "prx/libSceAgc/DcbFlow/include/Dispatch.hpp" +#include "prx/libSceAgc/DcbFlow/include/Memory.hpp" +#include "prx/libSceAgc/DcbFlow/include/Sync.hpp" +#include "prx/libSceAgc/DcbState/include/ContextState.hpp" +#include "prx/libSceAgc/DcbState/include/Display.hpp" +#include "prx/libSceAgc/DcbState/include/Init.hpp" +#include "prx/libSceAgc/DcbState/include/Marker.hpp" +#include "prx/libSceAgc/DcbState/include/Predication.hpp" +#include "prx/libSceAgc/DcbState/include/Registers.hpp" +#include "prx/libSceAgc/DcbState/include/Workload.hpp" +#include "prx/libSceAgc/include/Agc.hpp" +#include "prx/libSceAgc/Misc/include/Debug.hpp" +#include "prx/libSceAgc/Misc/include/PacketInfo.hpp" +#include "prx/libSceAgc/Misc/include/Platform.hpp" +#include "prx/libSceAgc/Misc/include/RegisterDefaults.hpp" +#include "prx/libSceAgc/Misc/include/Semaphore.hpp" +#include "prx/libSceAgc/Misc/include/ShaderFusion.hpp" +#include "prx/libSceAgc/Misc/include/StaticBuffer.hpp" +#include "prx/libSceAgc/Misc/include/Suspend.hpp" +#include "prx/libSceAgc/Patch/include/Branch.hpp" +#include "prx/libSceAgc/Patch/include/CondExec.hpp" +#include "prx/libSceAgc/Patch/include/Dma.hpp" +#include "prx/libSceAgc/Patch/include/IndirectRegisters.hpp" +#include "prx/libSceAgc/Patch/include/Jump.hpp" +#include "prx/libSceAgc/Patch/include/Nop.hpp" +#include "prx/libSceAgc/Patch/include/QueueEndOfPipeAction.hpp" +#include "prx/libSceAgc/Patch/include/Rewind.hpp" +#include "prx/libSceAgc/Patch/include/WaitRegMem.hpp" +#include "prx/libSceAgc/Predication/include/Predication.hpp" +#include "prx/libSceAgc/Shader/include/CreateShader.hpp" +#include "prx/libSceAgc/Shader/include/GsOversubscription.hpp" +#include "prx/libSceAgc/Shader/include/GsPrimPayload.hpp" +#include "prx/libSceAgc/Shader/include/InterpolantMapping.hpp" +#include "prx/libSceAgc/Shader/include/LinkShaders.hpp" +#include "prx/libSceAgc/Shader/include/PrimState.hpp" diff --git a/core/libs/prx/libSceAgc/tests/AtomicGdsSize.cpp b/core/libs/prx/libSceAgc/tests/AtomicGdsSize.cpp index bbc5416bd3..3315cd1312 100644 --- a/core/libs/prx/libSceAgc/tests/AtomicGdsSize.cpp +++ b/core/libs/prx/libSceAgc/tests/AtomicGdsSize.cpp @@ -1,14 +1,11 @@ +#include "prx/libSceAgc/Acb/include/Memory.hpp" +#include "prx/libSceAgc/Acb/include/Control.hpp" #include "prx/libSceAgc/Command/include/Packet.hpp" #include #include #include -extern "C" std::uint32_t APS5_VABI sceAgcAcbAtomicGdsGetSize(); -extern "C" std::uint32_t* APS5_VABI sceAgcAcbAtomicGds_0900(CommandBuffer* buf, std::uint32_t control, std::uint32_t mode, - std::uint32_t gdsOp, std::uint32_t src, std::uint16_t offset, std::uint16_t index, std::uint32_t mask, - std::uint32_t data, std::uint64_t compareData, std::uint64_t extraData); - int main() { constexpr std::uint32_t expectedSize = 11u * sizeof(std::uint32_t); if (sceAgcAcbAtomicGdsGetSize() != expectedSize) { diff --git a/core/libs/prx/libSceAgc/tests/BranchPatch.cpp b/core/libs/prx/libSceAgc/tests/BranchPatch.cpp index 58afe9b1c9..24c0f213b0 100644 --- a/core/libs/prx/libSceAgc/tests/BranchPatch.cpp +++ b/core/libs/prx/libSceAgc/tests/BranchPatch.cpp @@ -1,3 +1,5 @@ +#include "prx/libSceAgc/Patch/include/Branch.hpp" +#include "prx/libSceAgc/Cb/include/Branch.hpp" #include "prx/libSceAgc/Command/include/Packet.hpp" #include @@ -7,16 +9,6 @@ #include #include -extern "C" { -std::uint32_t* APS5_VABI sceAgcCbBranch(CommandBuffer*, std::uint8_t, std::uint8_t, const volatile std::uint64_t*, std::uint64_t, std::uint64_t, std::uint8_t, const volatile std::uint32_t*, std::uint32_t, std::uint8_t, const volatile std::uint32_t*, std::uint32_t); -std::uint32_t APS5_VABI sceAgcCbBranchGetSize(); -int APS5_VABI sceAgcBranchPatchSetCompareAddress(std::uint32_t*, const volatile std::uint64_t*); -int APS5_VABI sceAgcBranchPatchSetThenTarget(std::uint32_t*, const volatile std::uint32_t*, std::uint32_t); -int APS5_VABI sceAgcBranchPatchSetElseTarget(std::uint32_t*, const volatile std::uint32_t*, std::uint32_t); -int APS5_VABI sceAgcBranchPatchSetThenTarget_0300(std::uint32_t*, std::uint8_t, const volatile std::uint32_t*, std::uint32_t); -int APS5_VABI sceAgcBranchPatchSetElseTarget_0300(std::uint32_t*, std::uint8_t, const volatile std::uint32_t*, std::uint32_t); -} - namespace { void check(bool condition, const char* message) { diff --git a/core/libs/prx/libSceAgc/tests/CbCondWrite.cpp b/core/libs/prx/libSceAgc/tests/CbCondWrite.cpp index 69186e10ba..f08ab6e67b 100644 --- a/core/libs/prx/libSceAgc/tests/CbCondWrite.cpp +++ b/core/libs/prx/libSceAgc/tests/CbCondWrite.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceAgc/Cb/include/Branch.hpp" #include "prx/libSceAgc/Command/include/Packet.hpp" #include @@ -5,11 +6,6 @@ #include #include -extern "C" { -std::uint32_t* APS5_VABI sceAgcCbCondWrite(CommandBuffer*, std::uint32_t, std::uint32_t, const volatile void*, std::uint32_t, const volatile void*, std::uint32_t, std::uint32_t); -std::uint32_t APS5_VABI sceAgcCbCondWriteGetSize(); -} - namespace { constexpr std::uint32_t Sentinel = 0xabcdef01u; diff --git a/core/libs/prx/libSceAgc/tests/Commands.cpp b/core/libs/prx/libSceAgc/tests/Commands.cpp index bcda442f6b..a9ec29ed76 100644 --- a/core/libs/prx/libSceAgc/tests/Commands.cpp +++ b/core/libs/prx/libSceAgc/tests/Commands.cpp @@ -1,3 +1,23 @@ +#include "prx/libSceAgc/include/Agc.hpp" +#include "prx/libSceAgcDriver/Resource/include/Registration.hpp" +#include "prx/libSceAgc/Patch/include/WaitRegMem.hpp" +#include "prx/libSceAgc/Patch/include/Nop.hpp" +#include "prx/libSceAgc/Misc/include/Suspend.hpp" +#include "prx/libSceAgc/Misc/include/RegisterDefaults.hpp" +#include "prx/libSceAgc/Misc/include/PacketInfo.hpp" +#include "prx/libSceAgc/Misc/include/Debug.hpp" +#include "prx/libSceAgc/DcbState/include/Workload.hpp" +#include "prx/libSceAgc/DcbState/include/Marker.hpp" +#include "prx/libSceAgc/DcbState/include/Init.hpp" +#include "prx/libSceAgc/DcbState/include/Display.hpp" +#include "prx/libSceAgc/DcbState/include/ContextState.hpp" +#include "prx/libSceAgc/DcbFlow/include/Sync.hpp" +#include "prx/libSceAgc/DcbFlow/include/Control.hpp" +#include "prx/libSceAgc/DcbDraw/include/Instancing.hpp" +#include "prx/libSceAgc/DcbDraw/include/IndexBuffer.hpp" +#include "prx/libSceAgc/DcbDraw/include/DrawIndexed.hpp" +#include "prx/libSceAgc/Cb/include/Registers.hpp" +#include "prx/libSceAgc/Acb/include/Control.hpp" #include "prx/libSceAgc/Command/include/Packet.hpp" #include "prx/libSceAgc/Command/include/Memory.hpp" #include "prx/libSceAgc/Command/include/RegisterDefaults.hpp" @@ -10,57 +30,6 @@ #include #include -extern "C" std::uint32_t* APS5_VABI sceAgcDcbEventWrite(CommandBuffer* buf, std::uint8_t eventType, const volatile void* address); -extern "C" std::uint64_t APS5_VABI sceAgcDcbEventWriteGetSize(std::uint8_t eventType); -extern "C" std::uint32_t* APS5_VABI sceAgcDcbResetQueue(CommandBuffer* buf, std::uint32_t op, std::uint32_t state); -extern "C" std::uint32_t* APS5_VABI sceAgcDcbClearState(CommandBuffer* buf, std::uint32_t command); -extern "C" std::uint32_t* APS5_VABI sceAgcDcbSetFlip(CommandBuffer* buf, std::uint32_t handle, std::int32_t index, std::uint32_t mode, std::int64_t argument); -extern "C" std::uint32_t* APS5_VABI sceAgcAcbWaitUntilSafeForRendering(CommandBuffer* buf, std::uint32_t handle, std::uint32_t index); -extern "C" std::uint32_t* APS5_VABI sceAgcAcbSetFlip(CommandBuffer* buf, std::uint32_t handle, std::int32_t index, std::uint32_t mode, std::int64_t argument); -extern "C" int APS5_VABI sceAgcSuspendPoint(); -extern "C" int APS5_VABI sceAgcInit(std::uint32_t version); -extern "C" void* APS5_VABI sceAgcGetRegisterDefaults(); -extern "C" void* APS5_VABI sceAgcGetRegisterDefaults2(std::uint32_t version); -extern "C" void* APS5_VABI sceAgcGetRegisterDefaultsInternal(); -extern "C" void* APS5_VABI sceAgcGetRegisterDefaults2Internal(std::uint32_t version); -extern "C" int APS5_VABI sceAgcGetDefaultCxStateFlat(void* out_state, std::uint32_t size); -extern "C" int APS5_VABI sceAgcInit_0090(std::uint32_t* state, std::uint32_t version); -extern "C" std::uint32_t* APS5_VABI sceAgcDcbDrawIndexAuto(CommandBuffer* buf, std::uint32_t indexCount, std::uint64_t modifier); -extern "C" std::uint32_t* APS5_VABI sceAgcDcbDrawIndexIndirect(CommandBuffer* buf, std::uint32_t dataOffsetInBytes, std::uint64_t modifier); -extern "C" std::uint32_t* APS5_VABI sceAgcDcbDrawIndexIndirectMulti(CommandBuffer* buf, std::uint32_t dataOffsetInBytes, std::uint32_t countIndirect, std::uint32_t maxCountOrCount, const volatile void* countAddress, std::uint32_t strideInBytes, std::uint64_t modifier); -extern "C" int APS5_VABI sceAgcWaitRegMemPatchAddress(std::uint32_t* cmd, const volatile void* address); -extern "C" int APS5_VABI sceAgcWaitRegMemPatchCompareFunction(std::uint32_t* cmd, std::uint8_t compareFunction); -extern "C" int APS5_VABI sceAgcWaitRegMemPatchReference(std::uint32_t* cmd, std::uint32_t reference); -extern "C" int APS5_VABI sceAgcWaitRegMemPatchMask(std::uint32_t* cmd, std::uint32_t mask); -extern "C" int APS5_VABI sceAgcGetDataPacketPayloadAddress_0090(std::uint32_t** addr, std::uint32_t* cmd, int type); -extern "C" std::uint32_t* APS5_VABI sceAgcCbSetShRegisterRangeDirect(CommandBuffer* buf, std::uint32_t offset, const std::uint32_t* values, std::uint32_t numValues); -extern "C" std::uint32_t* APS5_VABI sceAgcDcbContextStateOp_0100(CommandBuffer* buf, std::uint32_t operation); -extern "C" std::uint32_t* APS5_VABI sceAgcDcbPushMarker(CommandBuffer* buf, const char* str, std::uint32_t color); -extern "C" std::uint32_t* APS5_VABI sceAgcDcbPopMarker(CommandBuffer* buf); -extern "C" std::uint32_t* APS5_VABI sceAgcDcbSetWorkloadComplete(CommandBuffer* buf, std::uint32_t stream_id, std::uint32_t workload_id); -extern "C" int APS5_VABI sceAgcDriverRegisterWorkloadStream(std::uint32_t stream_id, const void* stream); -extern "C" int APS5_VABI sceAgcDriverUnregisterWorkloadStream(std::uint32_t stream_id); -extern "C" std::uint32_t* APS5_VABI sceAgcDcbSetWorkloadsActive(CommandBuffer* buf, std::uint32_t stream_id, const std::uint32_t* workload_ids, std::uint32_t workload_count); -extern "C" std::uint32_t* APS5_VABI sceAgcDcbSetWorkloadStreamInactive(CommandBuffer* buf, std::uint32_t streamId); -extern "C" std::uint32_t* APS5_VABI sceAgcAcbSetWorkloadsActive(CommandBuffer* buf, std::uint32_t streamId, const std::uint32_t* workloadIds, std::uint32_t workloadCount); -extern "C" std::uint32_t* APS5_VABI sceAgcAcbSetWorkloadComplete(CommandBuffer* buf, std::uint32_t streamId, std::uint32_t workloadId); -extern "C" std::uint32_t* APS5_VABI sceAgcAcbSetWorkloadStreamInactive(CommandBuffer* buf, std::uint32_t streamId); -extern "C" std::uint32_t* APS5_VABI sceAgcDcbSetMarker(CommandBuffer* buf, const char* str, std::uint32_t color); -extern "C" std::uint32_t* APS5_VABI sceAgcAcbPushMarker(CommandBuffer* buf, const char* str, std::uint32_t color); -extern "C" std::uint32_t* APS5_VABI sceAgcAcbPopMarker(CommandBuffer* buf); -extern "C" std::uint32_t* APS5_VABI sceAgcAcbPushMarkerSpan(CommandBuffer* buf, const char* str, std::uint32_t length, std::uint32_t color); -extern "C" std::uint32_t* APS5_VABI sceAgcAcbSetMarkerSpan(CommandBuffer* buf, const char* str, std::uint32_t length, std::uint32_t color); -extern "C" std::uint32_t* APS5_VABI sceAgcDcbPushMarkerSpan(CommandBuffer* buf, const char* str, std::uint32_t length, std::uint32_t color); -extern "C" std::uint32_t* APS5_VABI sceAgcDcbSetMarkerSpan(CommandBuffer* buf, const char* str, std::uint32_t length, std::uint32_t color); -extern "C" std::uint32_t* APS5_VABI sceAgcAcbSetMarker(CommandBuffer* buf, const char* str, std::uint32_t color); -extern "C" std::uint32_t* APS5_VABI sceAgcDcbSetIndexBuffer(CommandBuffer* buf, std::uint64_t indexAddress); -extern "C" std::uint32_t* APS5_VABI sceAgcDcbSetIndexIndirectArgs(CommandBuffer* buf, std::uint64_t attributeAddress, std::uint32_t attributeIndex); -extern "C" std::uint32_t APS5_VABI sceAgcDcbSetIndexIndirectArgsGetSize(); -extern "C" std::uint32_t* APS5_VABI sceAgcDcbSetBaseIndirectArgs(CommandBuffer* buf, std::uint32_t shaderType, const volatile void* indirectBaseAddr); -extern "C" std::uint32_t* APS5_VABI sceAgcSetNop(CommandBuffer* buf, std::uint32_t sizeDw); -extern "C" int APS5_VABI sceAgcDebugRaiseException(std::uint32_t exceptionId); -extern "C" std::uint32_t* APS5_VABI sceAgcAcbAtomicGds_0900(CommandBuffer* buf, std::uint32_t control, std::uint32_t mode, std::uint32_t gdsOp, std::uint32_t src, std::uint16_t offset, std::uint16_t index, std::uint32_t mask, std::uint32_t data, std::uint64_t compareData, std::uint64_t extraData); - namespace { void check(bool condition, const char* message) { diff --git a/core/libs/prx/libSceAgc/tests/CondExecPatch.cpp b/core/libs/prx/libSceAgc/tests/CondExecPatch.cpp index 762f40b1a7..b5939e0c46 100644 --- a/core/libs/prx/libSceAgc/tests/CondExecPatch.cpp +++ b/core/libs/prx/libSceAgc/tests/CondExecPatch.cpp @@ -1,3 +1,6 @@ +#include "prx/libSceAgc/Patch/include/CondExec.hpp" +#include "prx/libSceAgc/DcbFlow/include/Sync.hpp" +#include "prx/libSceAgc/Acb/include/Sync.hpp" #include "prx/libSceAgc/Command/include/Packet.hpp" #include @@ -7,15 +10,6 @@ #include #include -extern "C" { -std::uint32_t* APS5_VABI sceAgcDcbCondExec(CommandBuffer*, const volatile std::uint32_t*, std::uint32_t); -std::uint32_t* APS5_VABI sceAgcAcbCondExec(CommandBuffer*, const volatile std::uint32_t*, std::uint32_t); -int APS5_VABI sceAgcCondExecPatchSetCommandAddress(std::uint32_t*, const volatile std::uint32_t*); -int APS5_VABI sceAgcCondExecPatchSetEnd(std::uint32_t*, const volatile std::uint32_t*); -int APS5_VABI sceAgcAsyncCondExecPatchSetCommandAddress(std::uint32_t*, const volatile std::uint32_t*); -int APS5_VABI sceAgcAsyncCondExecPatchSetEnd(std::uint32_t*, const volatile std::uint32_t*); -} - namespace { constexpr std::uint32_t Sentinel = 0xabcdef01u; diff --git a/core/libs/prx/libSceAgc/tests/ContextStateSize.cpp b/core/libs/prx/libSceAgc/tests/ContextStateSize.cpp index 3de0a5eda6..6d2e583e47 100644 --- a/core/libs/prx/libSceAgc/tests/ContextStateSize.cpp +++ b/core/libs/prx/libSceAgc/tests/ContextStateSize.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceAgc/DcbState/include/ContextState.hpp" #include "SceTypes.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libc/include/Shutdown.hpp" @@ -7,10 +8,6 @@ #include #include -extern "C" std::uint64_t APS5_VABI sceAgcDcbContextStateOpGetSize(std::uint32_t operation); -extern "C" std::uint32_t* APS5_VABI sceAgcDcbContextStateOp(CommandBuffer* buf, std::uint32_t operation); -extern "C" std::uint32_t* APS5_VABI sceAgcDcbContextStateOp_0100(CommandBuffer* buf, std::uint32_t operation); - namespace { void check(bool condition, const char* message) { diff --git a/core/libs/prx/libSceAgc/tests/DmaData.cpp b/core/libs/prx/libSceAgc/tests/DmaData.cpp index 77c80988f2..880035d394 100644 --- a/core/libs/prx/libSceAgc/tests/DmaData.cpp +++ b/core/libs/prx/libSceAgc/tests/DmaData.cpp @@ -1,3 +1,5 @@ +#include "prx/libSceAgc/DcbFlow/include/Memory.hpp" +#include "prx/libSceAgc/Acb/include/Memory.hpp" #include "prx/libSceAgc/Command/include/Packet.hpp" #include @@ -7,13 +9,6 @@ #include #include -extern "C" { -std::uint32_t* APS5_VABI sceAgcAcbDmaData(CommandBuffer*, std::uint8_t, std::uint8_t, std::uint64_t, std::uint8_t, std::uint8_t, std::uint64_t, std::uint32_t, std::uint8_t, std::uint8_t); -std::uint32_t APS5_VABI sceAgcAcbDmaDataGetSize(); -std::uint32_t* APS5_VABI sceAgcDcbDmaData(CommandBuffer*, std::uint8_t, std::uint8_t, std::uint8_t, std::uint64_t, std::uint8_t, std::uint8_t, std::uint64_t, std::uint32_t, std::uint8_t, std::uint8_t, std::uint8_t); -std::uint32_t APS5_VABI sceAgcDcbDmaDataGetSize(); -} - namespace { constexpr std::uint32_t Sentinel = 0xabcdef01u; diff --git a/core/libs/prx/libSceAgc/tests/EndOfShaderActionSize.cpp b/core/libs/prx/libSceAgc/tests/EndOfShaderActionSize.cpp index cf78ada4a3..5421cb5733 100644 --- a/core/libs/prx/libSceAgc/tests/EndOfShaderActionSize.cpp +++ b/core/libs/prx/libSceAgc/tests/EndOfShaderActionSize.cpp @@ -1,3 +1,8 @@ +#include "prx/libSceAgc/DcbState/include/ContextState.hpp" +#include "prx/libSceAgc/DcbFlow/include/Memory.hpp" +#include "prx/libSceAgc/DcbFlow/include/Control.hpp" +#include "prx/libSceAgc/Cb/include/Sync.hpp" +#include "prx/libSceAgc/Acb/include/Sync.hpp" #include "prx/libSceAgc/Command/include/Packet.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libc/include/Shutdown.hpp" @@ -8,15 +13,6 @@ #include #include -extern "C" { -std::uint32_t APS5_VABI sceAgcDcbQueueEndOfShaderActionGetSize(); -std::uint32_t APS5_VABI sceAgcAcbQueueEndOfShaderActionGetSize(); -std::uint32_t* APS5_VABI sceAgcCbReleaseMem(CommandBuffer*, std::uint8_t, std::uint16_t, std::uint8_t, std::uint8_t, const volatile Label*, std::uint8_t, std::uint64_t, std::uint16_t, std::uint16_t, std::uint8_t, std::uint32_t); -std::uint32_t APS5_VABI sceAgcDcbAtomicGdsGetSize(); -std::uint32_t* APS5_VABI sceAgcDcbAtomicGds_0900(CommandBuffer*, std::uint32_t, std::uint32_t, std::uint32_t, std::uint32_t, std::uint16_t, std::uint16_t, std::uint32_t, std::uint32_t, std::uint64_t, std::uint64_t); -std::uint32_t* APS5_VABI sceAgcDcbAtomicGds(CommandBuffer*, std::uint32_t, std::uint32_t, std::uint32_t, std::uint32_t, std::uint16_t, std::uint16_t, std::uint32_t, std::uint32_t, std::uint64_t, std::uint64_t); -} - namespace { void check(bool condition, const char* message) { diff --git a/core/libs/prx/libSceAgc/tests/GsOversubscription.cpp b/core/libs/prx/libSceAgc/tests/GsOversubscription.cpp index 7c312c879d..3666a2d338 100644 --- a/core/libs/prx/libSceAgc/tests/GsOversubscription.cpp +++ b/core/libs/prx/libSceAgc/tests/GsOversubscription.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceAgc/Shader/include/GsOversubscription.hpp" #include "SceShaders.hpp" #include "prx/libc/include/Shutdown.hpp" #include "prx/libc/include/general/VabiMacros.hpp" @@ -11,8 +12,6 @@ #include #include -extern "C" int APS5_VABI sceAgcGetGsOversubscription(ShaderRegister* regs, const Shader* gs, std::uint32_t budget, float factor); - namespace { using Registers = std::array; diff --git a/core/libs/prx/libSceAgc/tests/GsPrimPayload.cpp b/core/libs/prx/libSceAgc/tests/GsPrimPayload.cpp index 60f3d29b77..396311e9ee 100644 --- a/core/libs/prx/libSceAgc/tests/GsPrimPayload.cpp +++ b/core/libs/prx/libSceAgc/tests/GsPrimPayload.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceAgc/Shader/include/GsPrimPayload.hpp" #include "SceShaders.hpp" #include "prx/libc/include/Shutdown.hpp" #include "prx/libc/include/general/VabiMacros.hpp" @@ -9,8 +10,6 @@ #include #include -extern "C" int APS5_VABI sceAgcGetGsPrimPayload(std::uint32_t* payload, const Shader* gs); - namespace { constexpr std::uint32_t Sentinel = 0xccccccccu; diff --git a/core/libs/prx/libSceAgc/tests/InstrumentationQuerySize.cpp b/core/libs/prx/libSceAgc/tests/InstrumentationQuerySize.cpp index 7f75026d39..66e572d0b6 100644 --- a/core/libs/prx/libSceAgc/tests/InstrumentationQuerySize.cpp +++ b/core/libs/prx/libSceAgc/tests/InstrumentationQuerySize.cpp @@ -1,3 +1,5 @@ +#include "prx/libSceAgc/Misc/include/Debug.hpp" +#include "prx/libSceAgc/DcbDraw/include/Stats.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libc/include/Shutdown.hpp" @@ -5,13 +7,6 @@ #include #include -extern "C" { -int APS5_VABI sceAgcSetShaderInstrumentation(std::uint32_t); -std::uint32_t APS5_VABI sceAgcGetShaderInstrumentation(); -std::uint32_t APS5_VABI sceAgcDcbBeginOcclusionQueryGetSize(std::int32_t); -std::uint32_t APS5_VABI sceAgcDcbEndOcclusionQueryGetSize(); -} - namespace { void check(bool condition, const char* message) { diff --git a/core/libs/prx/libSceAgc/tests/InterpolantMapping.cpp b/core/libs/prx/libSceAgc/tests/InterpolantMapping.cpp index 1b38f7df08..2fbd372623 100644 --- a/core/libs/prx/libSceAgc/tests/InterpolantMapping.cpp +++ b/core/libs/prx/libSceAgc/tests/InterpolantMapping.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceAgc/Shader/include/InterpolantMapping.hpp" #include "SceShaders.hpp" #include "prx/libc/include/Shutdown.hpp" #include "prx/libc/include/general/VabiMacros.hpp" @@ -11,12 +12,6 @@ #include #include -extern "C" int APS5_VABI sceAgcCreateInterpolantMapping_0100(ShaderRegister* regs, const Shader* gs, const Shader* ps); -extern "C" int APS5_VABI sceAgcCreateInterpolantMapping_10000(ShaderRegister* regs, const Shader* gs, const Shader* ps); -extern "C" int APS5_VABI sceAgcUpdateInterpolantMapping_10000(ShaderRegister* regs, const Shader* gs, const Shader* ps); -extern "C" int APS5_VABI sceAgcCreateInterpolantMapping_nid_postfix(ShaderRegister* regs, const Shader* gs, const Shader* ps); -extern "C" int APS5_VABI sceAgcUpdateInterpolantMapping_nid_postfix(ShaderRegister* regs, const Shader* gs, const Shader* ps); - namespace { using Registers = std::array; diff --git a/core/libs/prx/libSceAgc/tests/PacketInfo.cpp b/core/libs/prx/libSceAgc/tests/PacketInfo.cpp index 5e95906b5a..9054c828ba 100644 --- a/core/libs/prx/libSceAgc/tests/PacketInfo.cpp +++ b/core/libs/prx/libSceAgc/tests/PacketInfo.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceAgc/Misc/include/PacketInfo.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libc/include/Shutdown.hpp" @@ -7,8 +8,6 @@ #include #include -extern "C" std::uint32_t APS5_VABI sceAgcGetPacketSize(std::uint32_t* packet); - namespace { void check(bool condition, const char* message) { diff --git a/core/libs/prx/libSceAgc/tests/PayloadRange.cpp b/core/libs/prx/libSceAgc/tests/PayloadRange.cpp index f920eb0384..d070135e43 100644 --- a/core/libs/prx/libSceAgc/tests/PayloadRange.cpp +++ b/core/libs/prx/libSceAgc/tests/PayloadRange.cpp @@ -8,10 +8,6 @@ #include #include -extern "C" int APS5_VABI sceAgcGetDataPacketPayloadRange(SceAgcMemoryRange* range, std::uint32_t* cmd, int type); -extern "C" int APS5_VABI sceAgcGetDataPacketPayloadAddress(std::uint32_t** addr, std::uint32_t* cmd, int type); -extern "C" int APS5_VABI sceAgcGetDataPacketPayloadAddress_0090(std::uint32_t** addr, std::uint32_t* cmd, int type); - namespace { void check(bool condition, const char* message) { diff --git a/core/libs/prx/libSceAgc/tests/Platform.cpp b/core/libs/prx/libSceAgc/tests/Platform.cpp index daa0634cf3..5ed2b2aea1 100644 --- a/core/libs/prx/libSceAgc/tests/Platform.cpp +++ b/core/libs/prx/libSceAgc/tests/Platform.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceAgc/Misc/include/Platform.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libc/include/Shutdown.hpp" @@ -5,8 +6,6 @@ #include #include -extern "C" int APS5_VABI sceAgcGetIsTrinityMode(bool* isTrinityMode); - namespace { void check(bool condition, const char* message) { diff --git a/core/libs/prx/libSceAgc/tests/Predication.cpp b/core/libs/prx/libSceAgc/tests/Predication.cpp index 32a6619ed5..7d9511f10f 100644 --- a/core/libs/prx/libSceAgc/tests/Predication.cpp +++ b/core/libs/prx/libSceAgc/tests/Predication.cpp @@ -1,3 +1,6 @@ +#include "prx/libSceAgc/Predication/include/Predication.hpp" +#include "prx/libSceAgc/DcbState/include/Predication.hpp" +#include "prx/libSceAgc/DcbDraw/include/IndexBuffer.hpp" #include "prx/libSceAgc/Command/include/Packet.hpp" #include @@ -5,17 +8,6 @@ #include #include -extern "C" { -std::uint32_t* APS5_VABI sceAgcDcbSetPredication(CommandBuffer*, std::uint8_t, std::uint8_t, std::uint8_t, const volatile void*, std::uint32_t); -std::uint32_t APS5_VABI sceAgcDcbSetZPassPredicationEnableGetSize(); -std::uint32_t APS5_VABI sceAgcDcbSetPredicationDisableGetSize(); -std::uint32_t APS5_VABI sceAgcDcbSetBoolPredicationEnableGetSize(); -std::uint32_t* APS5_VABI sceAgcDcbSetIndexCount(CommandBuffer*, std::uint32_t); -std::uint32_t* APS5_VABI sceAgcDcbSetIndexBuffer(CommandBuffer*, std::uint64_t); -int APS5_VABI sceAgcSetPacketPredication(std::uint32_t*, std::uint32_t); -int APS5_VABI sceAgcSetRangePredication(std::uint32_t*, const volatile std::uint32_t*, std::uint32_t); -} - namespace { void check(bool condition, const char* message) { diff --git a/core/libs/prx/libSceAgc/tests/PrimeUtcl2.cpp b/core/libs/prx/libSceAgc/tests/PrimeUtcl2.cpp index b1e702d246..4e7791491c 100644 --- a/core/libs/prx/libSceAgc/tests/PrimeUtcl2.cpp +++ b/core/libs/prx/libSceAgc/tests/PrimeUtcl2.cpp @@ -1,3 +1,5 @@ +#include "prx/libSceAgc/DcbState/include/Display.hpp" +#include "prx/libSceAgc/Acb/include/Memory.hpp" #include "prx/libSceAgc/Command/include/Packet.hpp" #include @@ -7,13 +9,6 @@ #include #include -extern "C" { -std::uint32_t* APS5_VABI sceAgcAcbPrimeUtcl2(CommandBuffer*, const volatile void*, std::uint32_t); -std::uint32_t APS5_VABI sceAgcAcbPrimeUtcl2GetSize(); -std::uint32_t* APS5_VABI sceAgcDcbPrimeUtcl2(CommandBuffer*, const volatile void*, std::uint32_t); -std::uint32_t APS5_VABI sceAgcDcbPrimeUtcl2GetSize(); -} - namespace { constexpr std::uint32_t Sentinel = 0xabcdef01u; diff --git a/core/libs/prx/libSceAgc/tests/RegisterCommands.cpp b/core/libs/prx/libSceAgc/tests/RegisterCommands.cpp index 5e6be0c709..4c52d26b8a 100644 --- a/core/libs/prx/libSceAgc/tests/RegisterCommands.cpp +++ b/core/libs/prx/libSceAgc/tests/RegisterCommands.cpp @@ -1,39 +1,14 @@ +#include "prx/libSceAgc/Patch/include/IndirectRegisters.hpp" +#include "prx/libSceAgc/DcbState/include/Registers.hpp" +#include "prx/libSceAgc/Cb/include/Registers.hpp" #include "prx/libSceAgc/Command/include/Packet.hpp" #include #include #include +#include #include -extern "C" { -std::uint32_t* APS5_VABI sceAgcDcbSetCfRegisterDirect(CommandBuffer*, ShaderRegister); -std::uint32_t* APS5_VABI sceAgcDcbSetCfRegisterRangeDirect(CommandBuffer*, std::uint32_t, const std::uint32_t*, std::uint32_t); -std::uint32_t* APS5_VABI sceAgcCbSetShRegisterRangeDirect(CommandBuffer*, std::uint32_t, const std::uint32_t*, std::uint32_t); -std::uint32_t* APS5_VABI sceAgcCbSetUcRegisterRangeDirect(CommandBuffer*, std::uint32_t, const std::uint32_t*, std::uint32_t); -std::uint32_t* APS5_VABI sceAgcDcbSetCxRegisterDirect(CommandBuffer*, ShaderRegister); -std::uint32_t* APS5_VABI sceAgcDcbSetShRegisterDirect(CommandBuffer*, ShaderRegister); -std::uint32_t* APS5_VABI sceAgcDcbSetUcRegisterDirect(CommandBuffer*, ShaderRegister); -std::uint32_t APS5_VABI sceAgcDcbSetCxRegisterDirectGetSize(); -std::uint32_t APS5_VABI sceAgcDcbSetShRegisterDirectGetSize(); -std::uint32_t APS5_VABI sceAgcDcbSetUcRegisterDirectGetSize(); -std::uint32_t* APS5_VABI sceAgcDcbSetCxRegistersIndirect(CommandBuffer*, const volatile ShaderRegister*, std::uint32_t); -std::uint32_t* APS5_VABI sceAgcDcbSetShRegistersIndirect(CommandBuffer*, const volatile ShaderRegister*, std::uint32_t); -std::uint32_t* APS5_VABI sceAgcDcbSetUcRegistersIndirect(CommandBuffer*, const volatile ShaderRegister*, std::uint32_t); -std::uint32_t APS5_VABI sceAgcDcbSetCxRegistersIndirectGetSize(std::uint32_t); -std::uint32_t APS5_VABI sceAgcDcbSetShRegistersIndirectGetSize(std::uint32_t); -std::uint32_t APS5_VABI sceAgcDcbSetUcRegistersIndirectGetSize(std::uint32_t); -int APS5_VABI sceAgcSetCxRegIndirectPatchSetNumRegisters(std::uint32_t*, std::uint32_t); -int APS5_VABI sceAgcSetShRegIndirectPatchSetNumRegisters(std::uint32_t*, std::uint32_t); -int APS5_VABI sceAgcSetUcRegIndirectPatchSetNumRegisters(std::uint32_t*, std::uint32_t); -int APS5_VABI sceAgcSetCxRegIndirectPatchSetAddress(std::uint32_t*, const volatile ShaderRegister*); -int APS5_VABI sceAgcSetShRegIndirectPatchSetAddress(std::uint32_t*, const volatile ShaderRegister*); -int APS5_VABI sceAgcSetUcRegIndirectPatchSetAddress(std::uint32_t*, const volatile ShaderRegister*); -std::uint32_t* APS5_VABI sceAgcCbSetShRegistersDirect(CommandBuffer*, const volatile ShaderRegister*, std::uint32_t); -std::uint32_t* APS5_VABI sceAgcCbSetUcRegistersDirect(CommandBuffer*, const volatile ShaderRegister*, std::uint32_t); -std::uint32_t APS5_VABI sceAgcCbSetShRegistersDirectGetSize(std::uint32_t); -std::uint32_t APS5_VABI sceAgcCbSetUcRegistersDirectGetSize(std::uint32_t); -} - namespace { void check(bool condition, const char* message) { @@ -125,6 +100,26 @@ void testRangeFromAnyByte() { } } +void testListFromAnyByte() { + const std::array writers{sceAgcCbSetShRegistersDirect, sceAgcCbSetUcRegistersDirect}; + const std::array opcodes{0x7600u, 0x7900u}; + const std::array registers{{{0x10u, 0x11223344u}, {0x11u, 0x55667788u}, {0x30u, 0x99aabbccu}}}; + for (std::size_t i = 0; i < writers.size(); ++i) { + for (const std::size_t offset : {1u, 2u, 3u, 5u}) { + alignas(16) std::array bytes{}; + std::memcpy(bytes.data() + offset, registers.data(), sizeof(registers)); + Storage storage; + storage.words.fill(0xabcdef01u); + const auto* list = reinterpret_cast(bytes.data() + offset); + auto* packet = writers[i](&storage.buffer, list, static_cast(registers.size())); + const std::array expected{0xc0020000u | opcodes[i], 0x10u, 0x11223344u, 0x55667788u, 0xc0010000u | opcodes[i], 0x30u, 0x99aabbccu}; + check(packet == storage.words.data() && storage.buffer.cursor_up == packet + expected.size(), "unaligned register list allocation mismatch"); + check(std::equal(expected.begin(), expected.end(), packet), "unaligned register list was not read byte for byte"); + check(packet[expected.size()] == 0xabcdef01u, "unaligned register list overwrote the following word"); + } + } +} + void testIndirect() { const std::array writers{sceAgcDcbSetCxRegistersIndirect, sceAgcDcbSetShRegistersIndirect, sceAgcDcbSetUcRegistersIndirect}; const std::array sizes{sceAgcDcbSetCxRegistersIndirectGetSize, sceAgcDcbSetShRegistersIndirectGetSize, sceAgcDcbSetUcRegistersIndirectGetSize}; @@ -239,6 +234,7 @@ int main() { testDirect(); testConfig(); testRangeFromAnyByte(); + testListFromAnyByte(); testIndirect(); testIndirectPlaceholder(); testDirectList(); diff --git a/core/libs/prx/libSceAgc/tests/Semaphore.cpp b/core/libs/prx/libSceAgc/tests/Semaphore.cpp index 4ab4f08a83..3d4ff1c16d 100644 --- a/core/libs/prx/libSceAgc/tests/Semaphore.cpp +++ b/core/libs/prx/libSceAgc/tests/Semaphore.cpp @@ -1,3 +1,8 @@ +#include "prx/libSceAgc/include/Agc.hpp" +#include "prx/libSceAgc/Misc/include/Semaphore.hpp" +#include "prx/libSceAgc/DcbFlow/include/Sync.hpp" +#include "prx/libSceAgc/Cb/include/Sync.hpp" +#include "prx/libSceAgc/Acb/include/Sync.hpp" #include "prx/libSceAgc/Command/include/Packet.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libc/include/Shutdown.hpp" @@ -12,13 +17,6 @@ #include #include -extern "C" int APS5_VABI sceAgcSetAmmSemaphoreMemory(void* memory, std::uint64_t sizeInBytes); -extern "C" int APS5_VABI sceAgcSetSemaphoreMemory(void* memory, std::uint64_t sizeInBytes); -extern "C" int APS5_VABI sceAgcGetSemaphoreLabel(std::uint32_t index, void** label); -extern "C" std::uint32_t* APS5_VABI sceAgcCbMemSemaphore(CommandBuffer* buf, const volatile void* address, std::uint32_t operation, std::uint32_t modifier, std::uint32_t value); -extern "C" std::uint32_t* APS5_VABI sceAgcAcbMemSemaphore(CommandBuffer* buf, const volatile void* address, std::uint8_t waitForMailbox, std::uint8_t signalType, std::uint8_t operation); -extern "C" std::uint32_t* APS5_VABI sceAgcDcbMemSemaphore(CommandBuffer* buf, const volatile void* address, std::uint8_t waitForMailbox, std::uint8_t signalType, std::uint8_t operation); - namespace { constexpr std::uint64_t blockBytes = 0x4000u; diff --git a/core/libs/prx/libSceAgc/tests/ShaderHelpers.cpp b/core/libs/prx/libSceAgc/tests/ShaderHelpers.cpp index 46f7c3c8e8..6c842de199 100644 --- a/core/libs/prx/libSceAgc/tests/ShaderHelpers.cpp +++ b/core/libs/prx/libSceAgc/tests/ShaderHelpers.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceAgc/Shader/include/LinkShaders.hpp" #include "SceShaders.hpp" #include "prx/libSceAgc/Shader/include/PrimState.hpp" #include "prx/libSceAgc/Shader/include/InterpolantMapping.hpp" @@ -11,10 +12,6 @@ #include #include -extern "C" int APS5_VABI sceAgcLinkShaders(ShaderRegister*, ShaderRegister*, const void*, const Shader*, const Shader*, std::uint32_t); -extern "C" int APS5_VABI sceAgcCreatePrimState(ShaderRegister*, ShaderRegister*, const Shader*, const Shader*, std::uint32_t); -extern "C" int APS5_VABI sceAgcCreateInterpolantMapping_0100(ShaderRegister*, const Shader*, const Shader*); - namespace { std::array preparedContext; std::array preparedPrimitive; diff --git a/core/libs/prx/libSceAgc/tests/WriteDataPatch.cpp b/core/libs/prx/libSceAgc/tests/WriteDataPatch.cpp index 5f543c8707..a8307962a4 100644 --- a/core/libs/prx/libSceAgc/tests/WriteDataPatch.cpp +++ b/core/libs/prx/libSceAgc/tests/WriteDataPatch.cpp @@ -1,3 +1,6 @@ +#include "prx/libSceAgc/Patch/include/WaitRegMem.hpp" +#include "prx/libSceAgc/DcbFlow/include/Memory.hpp" +#include "prx/libSceAgc/Acb/include/Memory.hpp" #include "prx/libSceAgc/Command/include/Packet.hpp" #include @@ -7,17 +10,6 @@ #include #include -extern "C" { -std::uint32_t* APS5_VABI sceAgcDcbWriteData(CommandBuffer*, std::uint8_t, std::uint8_t, std::uint64_t, const void*, std::uint32_t, std::uint8_t, std::uint8_t); -std::uint32_t* APS5_VABI sceAgcAcbWriteData(CommandBuffer*, std::uint8_t, std::uint8_t, std::uint64_t, const void*, std::uint32_t, std::uint8_t, std::uint8_t); -int APS5_VABI sceAgcWriteDataPatchSetAddressOrOffset(std::uint32_t*, std::uint64_t); -int APS5_VABI sceAgcAsyncWriteDataPatchSetAddressOrOffset(std::uint32_t*, std::uint64_t); -int APS5_VABI sceAgcWriteDataPatchSetDst(std::uint32_t*, std::uint8_t); -int APS5_VABI sceAgcAsyncWriteDataPatchSetDst(std::uint32_t*, std::uint8_t); -int APS5_VABI sceAgcWriteDataPatchSetCachePolicy(std::uint32_t*, std::uint8_t); -int APS5_VABI sceAgcAsyncWriteDataPatchSetCachePolicy(std::uint32_t*, std::uint8_t); -} - namespace { constexpr std::array Payload{0x11111111u, 0x22222222u, 0x33333333u}; diff --git a/core/libs/prx/libSceAgcDriver/CMakeLists.txt b/core/libs/prx/libSceAgcDriver/CMakeLists.txt index 613780e647..9d764d5052 100644 --- a/core/libs/prx/libSceAgcDriver/CMakeLists.txt +++ b/core/libs/prx/libSceAgcDriver/CMakeLists.txt @@ -805,7 +805,9 @@ if(BUILD_TESTING) set_tests_properties(agc_import_alias_shared PROPERTIES SKIP_RETURN_CODE 77 TIMEOUT 20) add_test(NAME agc_compared_shared_generations COMMAND agc_write_tracking_tests --compared-shared-generations) set_tests_properties(agc_compared_shared_generations PROPERTIES SKIP_RETURN_CODE 77 TIMEOUT 20) - set_tests_properties(agc_write_tracking agc_write_tracking_metadata_commit agc_resident_direct_remap agc_rewatched_direct_shared agc_import_alias_shared agc_compared_shared_generations PROPERTIES ENVIRONMENT_MODIFICATION + add_test(NAME agc_write_tracking_rewatch_import_pages COMMAND agc_write_tracking_tests --rewatch-import-pages) + set_tests_properties(agc_write_tracking_rewatch_import_pages PROPERTIES SKIP_RETURN_CODE 77 TIMEOUT 20) + set_tests_properties(agc_write_tracking agc_write_tracking_metadata_commit agc_resident_direct_remap agc_rewatched_direct_shared agc_import_alias_shared agc_compared_shared_generations agc_write_tracking_rewatch_import_pages PROPERTIES ENVIRONMENT_MODIFICATION "PATH=path_list_prepend:$") endif() endif() @@ -860,6 +862,15 @@ if(BUILD_TESTING) add_test(NAME agc_fragment_barycentric COMMAND agc_fragment_barycentric_tests) endif() +add_test_executable(agc_tessellation_pipeline_cache_tests EXCLUDE_FROM_ALL tests/TessellationPipelineCache.cpp) +target_include_directories(agc_tessellation_pipeline_cache_tests PRIVATE ${LIBS_INCLUDE_DIR} ${ANYPS5_VULKAN_HEADERS_INCLUDE_DIR}) +set_target_properties(agc_tessellation_pipeline_cache_tests PROPERTIES CXX_EXTENSIONS OFF) +configure_windows_unwind(agc_tessellation_pipeline_cache_tests) +if(BUILD_TESTING) + set_target_properties(agc_tessellation_pipeline_cache_tests PROPERTIES EXCLUDE_FROM_ALL OFF) + add_test(NAME agc_tessellation_pipeline_cache COMMAND agc_tessellation_pipeline_cache_tests) +endif() + add_test_executable(agc_float32_flush_control_tests EXCLUDE_FROM_ALL tests/Float32FlushControl.cpp) target_include_directories(agc_float32_flush_control_tests PRIVATE ${LIBS_INCLUDE_DIR} ${ANYPS5_VULKAN_HEADERS_INCLUDE_DIR}) set_target_properties(agc_float32_flush_control_tests PROPERTIES CXX_EXTENSIONS OFF) @@ -1572,6 +1583,8 @@ if(BUILD_TESTING) endif() add_test(NAME agc_import_watch COMMAND agc_driver_recorder_tests --import-watch-only) set_tests_properties(agc_import_watch PROPERTIES SKIP_RETURN_CODE 77) + add_test(NAME agc_import_settle_initial_dcc COMMAND agc_driver_recorder_tests --settle-initial-dcc-only) + set_tests_properties(agc_import_settle_initial_dcc PROPERTIES SKIP_RETURN_CODE 77 TIMEOUT 30) if(WIN32) add_test(NAME agc_import_watch_other_family COMMAND agc_driver_recorder_tests --import-watch-other-family-only) set_tests_properties(agc_import_watch_other_family PROPERTIES SKIP_RETURN_CODE 77) @@ -1589,7 +1602,7 @@ if(BUILD_TESTING) add_test(NAME agc_import_settle_retire COMMAND agc_driver_recorder_tests --settle-retire-only) add_test(NAME agc_import_settle_storage_image COMMAND agc_driver_recorder_tests --settle-storage-image-only) set_tests_properties(agc_import_settle_deferred agc_import_settle_deferred_other_family agc_import_settle_first_use agc_import_settle_earlier_import agc_import_settle_retire agc_import_settle_storage_image PROPERTIES SKIP_RETURN_CODE 77 TIMEOUT 60) - set_tests_properties(agc_import_watch agc_import_watch_other_family agc_import_settle_deferred agc_import_settle_deferred_other_family agc_import_settle_first_use agc_import_settle_earlier_import agc_import_settle_retire agc_import_settle_storage_image PROPERTIES ENVIRONMENT_MODIFICATION + set_tests_properties(agc_import_watch agc_import_watch_other_family agc_import_settle_deferred agc_import_settle_deferred_other_family agc_import_settle_first_use agc_import_settle_earlier_import agc_import_settle_retire agc_import_settle_storage_image agc_import_settle_initial_dcc PROPERTIES ENVIRONMENT_MODIFICATION "PATH=path_list_prepend:$") endif() if(WIN32) @@ -2474,12 +2487,14 @@ if(BUILD_TESTING) set_tests_properties(agc_shader_srt_read_patching PROPERTIES ENVIRONMENT "ANYPS5_NO_SHADER_CACHE=1" WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}") add_test(NAME agc_shader_table_snapshot_reuse COMMAND agc_shader_memory_tests --table-snapshot-reuse) set_tests_properties(agc_shader_table_snapshot_reuse PROPERTIES ENVIRONMENT "ANYPS5_NO_SHADER_CACHE=1" WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}") + add_test(NAME agc_shader_table_snapshot_reuse_unmasked COMMAND agc_shader_memory_tests --table-snapshot-reuse) + set_tests_properties(agc_shader_table_snapshot_reuse_unmasked PROPERTIES ENVIRONMENT "ANYPS5_NO_SHADER_CACHE=1;APS5_NO_MASKED_RESULT_MEMO=1" WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}") add_test(NAME agc_driver_image_table_vouched_lookups COMMAND agc_driver_image_table_cache_bounds_tests --vouched-lookups) set_tests_properties(agc_driver_image_table_vouched_lookups PROPERTIES ENVIRONMENT "ANYPS5_NO_SHADER_CACHE=1;APS5_WRITE_WATCH_IMPORTS=watch" SKIP_RETURN_CODE 77 WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" TIMEOUT 60) add_test(NAME agc_driver_image_table_vouch_queued_draws COMMAND agc_driver_image_table_cache_bounds_tests --queued-draws) set_tests_properties(agc_driver_image_table_vouch_queued_draws PROPERTIES ENVIRONMENT "ANYPS5_NO_SHADER_CACHE=1" SKIP_RETURN_CODE 77 WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" TIMEOUT 60) if(WIN32) - set_tests_properties(agc_shader_table_snapshot_reuse agc_driver_image_table_vouched_lookups agc_driver_image_table_vouch_queued_draws PROPERTIES ENVIRONMENT_MODIFICATION "PATH=path_list_prepend:$") + set_tests_properties(agc_shader_table_snapshot_reuse agc_shader_table_snapshot_reuse_unmasked agc_driver_image_table_vouched_lookups agc_driver_image_table_vouch_queued_draws PROPERTIES ENVIRONMENT_MODIFICATION "PATH=path_list_prepend:$") endif() add_test(NAME agc_shader_type_zero_image_materialization COMMAND agc_shader_memory_tests --type-zero-image-materialization) set_tests_properties(agc_shader_type_zero_image_materialization PROPERTIES ENVIRONMENT "ANYPS5_NO_SHADER_CACHE=1" WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}") @@ -2756,6 +2771,12 @@ if(BUILD_TESTING) "PATH=path_list_prepend:$") endif() + add_test(NAME agc_address_copy_cap COMMAND agc_driver_graphics_tests --address-copy-cap) + add_test(NAME agc_address_copy_cap_remembered COMMAND agc_driver_graphics_tests --address-copy-cap-remembered) + set_tests_properties(agc_address_copy_cap agc_address_copy_cap_remembered PROPERTIES TIMEOUT 30) + if(WIN32) + set_tests_properties(agc_address_copy_cap agc_address_copy_cap_remembered PROPERTIES ENVIRONMENT_MODIFICATION "PATH=path_list_prepend:$") + endif() add_test(NAME agc_driver_emulated_color_compare_srgb_decode COMMAND agc_driver_emulated_color_compare_tests) set_tests_properties(agc_driver_emulated_color_compare_srgb_decode PROPERTIES ENVIRONMENT "ANYPS5_NO_SHADER_CACHE=1;APS5_SRGB_SHADER_DECODE=1" @@ -3118,7 +3139,7 @@ if(BUILD_TESTING) set_tests_properties(agc_driver_array_layer_target_cpu PROPERTIES ENVIRONMENT_MODIFICATION "PATH=path_list_prepend:$") endif() - foreach(preparedMode IN ITEMS indirect uncached debug debug_failure deferred deferred_undecodable registered_workgroup registered_workgroup_sync abi_deferred_compute abi_deferred_pixel abi_deferred_stages abi_deferred_rectangle abi_deferred_undecodable_state abi_deferred_registration_failure abi_deferred_vertex_inputs abi_deferred_rectangle_pairs lazy lazy_sync) + foreach(preparedMode IN ITEMS indirect uncached debug debug_failure deferred deferred_undecodable registered_workgroup registered_workgroup_sync dispatch_ahead_prewarm abi_deferred_compute abi_deferred_pixel abi_deferred_stages abi_deferred_rectangle abi_deferred_undecodable_state abi_deferred_registration_failure abi_deferred_vertex_inputs abi_deferred_rectangle_pairs lazy lazy_sync) set(preparedTest "agc_driver_prepared_shaders_${preparedMode}") if(preparedMode MATCHES "^abi_deferred_") string(REPLACE "_" "-" preparedArgument ${preparedMode}) @@ -3133,6 +3154,8 @@ if(BUILD_TESTING) add_test(NAME ${preparedTest} COMMAND agc_driver_prepared_shaders_tests --lazy) elseif(preparedMode STREQUAL "registered_workgroup" OR preparedMode STREQUAL "registered_workgroup_sync") add_test(NAME ${preparedTest} COMMAND agc_driver_prepared_shaders_tests --registered-workgroup) + elseif(preparedMode STREQUAL "dispatch_ahead_prewarm") + add_test(NAME ${preparedTest} COMMAND agc_driver_prepared_shaders_tests --dispatch-ahead-prewarm) elseif(preparedMode STREQUAL "debug_failure") add_test(NAME ${preparedTest} COMMAND agc_driver_prepared_shaders_tests --fail-before-registration) set_tests_properties(${preparedTest} PROPERTIES WILL_FAIL TRUE TIMEOUT 30) @@ -3420,7 +3443,8 @@ if(BUILD_TESTING) endif() endforeach() - if(WIN32) + option(ANYPS5_RUN_QUARANTINED_FRAME_REPLAY "Build and register agc_driver_frame_replay on Windows" OFF) + if(WIN32 AND ANYPS5_RUN_QUARANTINED_FRAME_REPLAY) add_test_executable(agc_driver_frame_replay_tests tests/FrameReplay.cpp Execution/src/FrameCapture.cpp) target_include_directories(agc_driver_frame_replay_tests PRIVATE ${LIBS_INCLUDE_DIR}) target_link_libraries(agc_driver_frame_replay_tests PRIVATE libSceAgc libSceAgcDriver libkernel libc libzstd_static) diff --git a/core/libs/prx/libSceAgcDriver/Execution/include/Driver/Diagnostics.hpp b/core/libs/prx/libSceAgcDriver/Execution/include/Driver/Diagnostics.hpp index 39bb6c35c9..86505f5a7b 100644 --- a/core/libs/prx/libSceAgcDriver/Execution/include/Driver/Diagnostics.hpp +++ b/core/libs/prx/libSceAgcDriver/Execution/include/Driver/Diagnostics.hpp @@ -10,7 +10,7 @@ namespace AgcDriver::DriverDetail { double TraceMs(); -std::uint64_t SkippedShader(); +bool SkippedShader(std::uint64_t address); class RefusedDraw final : public std::runtime_error { public: diff --git a/core/libs/prx/libSceAgcDriver/Execution/include/Driver/Draw/DrawPipeline.hpp b/core/libs/prx/libSceAgcDriver/Execution/include/Driver/Draw/DrawPipeline.hpp index 50844922e8..f2bc4960a5 100644 --- a/core/libs/prx/libSceAgcDriver/Execution/include/Driver/Draw/DrawPipeline.hpp +++ b/core/libs/prx/libSceAgcDriver/Execution/include/Driver/Draw/DrawPipeline.hpp @@ -55,6 +55,7 @@ public: std::uint64_t DecodeDrains() const { return decodeDrains.load(std::memory_order_relaxed); } std::optional PendingLabel(std::uint64_t address, std::size_t bytes); static bool HeldReads(std::uint64_t address, std::size_t bytes); + static std::uint64_t HeldReadQueries(); void ReleaseRunningReads(); static bool MetadataPassesPipelined(); diff --git a/core/libs/prx/libSceAgcDriver/Execution/include/PerformanceTrace.hpp b/core/libs/prx/libSceAgcDriver/Execution/include/PerformanceTrace.hpp index e683bc7695..49858aaa31 100644 --- a/core/libs/prx/libSceAgcDriver/Execution/include/PerformanceTrace.hpp +++ b/core/libs/prx/libSceAgcDriver/Execution/include/PerformanceTrace.hpp @@ -451,18 +451,30 @@ public: static void AppendString(std::string& output, std::string_view text) { output += '"'; - for (const char character : text) { + std::size_t index = 0; + while (index < text.size()) { + const char character = text[index]; const auto byte = static_cast(character); if (character == '"' || character == '\\') { output += '\\'; output += character; - } else if (byte < 0x20 || byte >= 0x7f) { + } else if (byte >= 0x80) { + if (const auto length = utf8SequenceLength(text, index); length != 0) { + output.append(text.substr(index, length)); + index += length; + continue; + } + char escaped[8]; + std::snprintf(escaped, sizeof escaped, "\\u%04x", static_cast(byte)); + output += escaped; + } else if (byte < 0x20 || byte == 0x7f) { char escaped[8]; std::snprintf(escaped, sizeof escaped, "\\u%04x", static_cast(byte)); output += escaped; } else { output += character; } + ++index; } output += '"'; } @@ -697,6 +709,34 @@ public: } private: + static std::size_t utf8SequenceLength(std::string_view text, std::size_t index) { + const auto lead = static_cast(text[index]); + std::size_t length = 0; + unsigned char low = 0x80; + unsigned char high = 0xbf; + if (lead >= 0xc2 && lead <= 0xdf) { + length = 2; + } else if (lead >= 0xe0 && lead <= 0xef) { + length = 3; + if (lead == 0xe0) low = 0xa0; + if (lead == 0xed) high = 0x9f; + } else if (lead >= 0xf0 && lead <= 0xf4) { + length = 4; + if (lead == 0xf0) low = 0x90; + if (lead == 0xf4) high = 0x8f; + } else { + return 0; + } + if (text.size() - index < length) return 0; + for (std::size_t offset = 1; offset < length; ++offset) { + const auto next = static_cast(text[index + offset]); + if (next < low || next > high) return 0; + low = 0x80; + high = 0xbf; + } + return length; + } + static void AppendMachine(std::string& output, const TraceSummary& summary) { if (summary.host) { output += ",\"cpu\":"; diff --git a/core/libs/prx/libSceAgcDriver/Execution/include/PresentMode.hpp b/core/libs/prx/libSceAgcDriver/Execution/include/PresentMode.hpp index cb448bbc44..17510d198b 100644 --- a/core/libs/prx/libSceAgcDriver/Execution/include/PresentMode.hpp +++ b/core/libs/prx/libSceAgcDriver/Execution/include/PresentMode.hpp @@ -3,6 +3,8 @@ #include #include +#include +#include #include #include #include @@ -22,6 +24,11 @@ inline VkPresentModeKHR SelectPresentMode(const char* requested, std::span SelectPresentQueue(std::uint32_t familyQueues, std::uint32_t queuesTaken) { + if (queuesTaken >= familyQueues) return std::nullopt; + return queuesTaken; +} + } #endif diff --git a/core/libs/prx/libSceAgcDriver/Execution/include/SwapchainImages.hpp b/core/libs/prx/libSceAgcDriver/Execution/include/SwapchainImages.hpp new file mode 100644 index 0000000000..b3411ca19b --- /dev/null +++ b/core/libs/prx/libSceAgcDriver/Execution/include/SwapchainImages.hpp @@ -0,0 +1,17 @@ +#ifndef CORE_LIBS_PRX_LIBSCEAGCDRIVER_EXECUTION_INCLUDE_SWAPCHAINIMAGES_HPP +#define CORE_LIBS_PRX_LIBSCEAGCDRIVER_EXECUTION_INCLUDE_SWAPCHAINIMAGES_HPP + +#include +#include +#include + +namespace AgcDriver { + +inline std::uint32_t SwapchainImageCount(const VkSurfaceCapabilitiesKHR& surface) { + const std::uint32_t count = std::max(surface.minImageCount, 3u); + return surface.maxImageCount != 0 ? std::min(count, surface.maxImageCount) : count; +} + +} + +#endif diff --git a/core/libs/prx/libSceAgcDriver/Execution/include/TessellationPipelineCache.hpp b/core/libs/prx/libSceAgcDriver/Execution/include/TessellationPipelineCache.hpp new file mode 100644 index 0000000000..7605cd2c68 --- /dev/null +++ b/core/libs/prx/libSceAgcDriver/Execution/include/TessellationPipelineCache.hpp @@ -0,0 +1,14 @@ +#ifndef CORE_LIBS_PRX_LIBSCEAGCDRIVER_EXECUTION_INCLUDE_TESSELLATIONPIPELINECACHE_HPP +#define CORE_LIBS_PRX_LIBSCEAGCDRIVER_EXECUTION_INCLUDE_TESSELLATIONPIPELINECACHE_HPP + +#include + +namespace AgcDriver { + +inline bool TessellationPipelineCacheUsable(VkDriverId driver) { + return driver != VK_DRIVER_ID_MOLTENVK; +} + +} + +#endif diff --git a/core/libs/prx/libSceAgcDriver/Execution/include/VulkanDevice.hpp b/core/libs/prx/libSceAgcDriver/Execution/include/VulkanDevice.hpp index 8dbf80c316..1c7d1a1350 100644 --- a/core/libs/prx/libSceAgcDriver/Execution/include/VulkanDevice.hpp +++ b/core/libs/prx/libSceAgcDriver/Execution/include/VulkanDevice.hpp @@ -45,9 +45,11 @@ struct DeviceQueuePlan { bool sparseBinding = false; std::uint32_t sparseFamily = VK_QUEUE_FAMILY_IGNORED; std::uint32_t sparseIndex = 0; + bool present = false; + std::uint32_t presentIndex = 0; }; -DeviceQueuePlan PlanDeviceQueues(std::span families, std::uint32_t family, bool settles, bool sparseBinding); +DeviceQueuePlan PlanDeviceQueues(std::span families, std::uint32_t family, bool settles, bool sparseBinding, bool presents); class VulkanDevice { public: @@ -58,6 +60,8 @@ public: // Builds the pipeline of a journaled compute result ahead of its first dispatch (the journal // replay's hook, on its threads): false when the device already holds a pipeline for the module. bool ReplayComputePipeline(const ShaderRecompiler::RecompileResult& shader, bool pushConstants); + bool HasComputePipeline(const ShaderRecompiler::RecompileResult& shader) const; + void PrebuildComputePipeline(const ShaderRecompiler::RecompileResult& shader, std::uint64_t programAddress = 0); // Starts the journal replay if the device has not (a headless device starts it at its first // draw or dispatch) and joins it (tests; the teardown joins it anyway). void WaitForPipelineJournalReplay(); @@ -226,7 +230,7 @@ public: bool ProvokingVertexLast() const; bool GraphicsPipelineLibraries() const; // A presentation is a few steps so the presenter holds GuestMemory::GpuMutex only while it - // touches the queue. Presentations are slots (FlipInFlight() + 1, each with its own command + // touches the main queue. Presentations are slots (FlipInFlight() + 1, each with its own command // buffer, fence, kept resident image and dump buffer): RetirePresents(keep) (no mutex) retires // the slots whose fence signaled, oldest first, and waits for the oldest ones until at most // `keep` are in flight (the only CPU wait of the flip path; it returns the time spent waiting); @@ -235,7 +239,9 @@ public: // PresentClear/PresentDisplayBuffer record and submit the frame into the next slot (under the // mutex; the blit follows the frame's batches in queue order, so the displayed image is always // complete) and return whether one was submitted; QueuePresent hands the image to the swapchain - // (under the mutex). FinishPresent = RetirePresents(0): the render fence wait of the + // (on the device's presentation queue under that queue's mutex, with the GPU mutex released, + // when the presentation family had a free queue; otherwise on the main queue under the GPU + // mutex). FinishPresent = RetirePresents(0): the render fence wait of the // synchronous paths (APS5_FLIP_INFLIGHT=0, APS5_SYNC_FLIP, PresentPixels). AcquireImage returns // false when the swapchain is out of date (the frame is dropped; the next Resize recreates it); // a present without a prior AcquireImage acquires itself, one whose slot is in flight waits for @@ -258,6 +264,7 @@ public: bool PresentDisplayBuffer(const DisplayBuffer& buffer); double FinishPresent(); void QueuePresent(); + bool PresentsOnOwnQueue() const; // At the flip packet (under the mutex): the recorder's submissions so far and, under // APS5_PROFILE_DRAW, how many in flight have not signaled (the frame record's batches_at_flip). void FlipBatches(std::uint64_t& submissions, std::uint64_t& unsignaled) const; diff --git a/core/libs/prx/libSceAgcDriver/Execution/src/Driver/Diagnostics.cpp b/core/libs/prx/libSceAgcDriver/Execution/src/Driver/Diagnostics.cpp index b94858e431..ca92adc259 100644 --- a/core/libs/prx/libSceAgcDriver/Execution/src/Driver/Diagnostics.cpp +++ b/core/libs/prx/libSceAgcDriver/Execution/src/Driver/Diagnostics.cpp @@ -1,11 +1,19 @@ #include "prx/libSceAgcDriver/Execution/include/Driver/Driver.hpp" #include "prx/libSceAgcDriver/Execution/include/Driver/Diagnostics.hpp" +#include +#include +#include +#include #include #include +#include +#include #include +#include #include #include #include +#include namespace AgcDriver::DriverDetail { @@ -14,9 +22,65 @@ double TraceMs() { return std::chrono::duration(std::chrono::steady_clock::now() - origin).count(); } -std::uint64_t SkippedShader() { - static const std::uint64_t skipped = [] { const char* text = std::getenv("APS5_SKIP_SHADER"); return text ? std::strtoull(text, nullptr, 16) : 0ull; }(); - return skipped; +namespace { + +constexpr std::size_t MaxSkippedShaders = 256; +std::array, MaxSkippedShaders> skippedShaders{}; +std::atomic skippedShaderCount{0}; + +std::optional programAddress(std::string_view word) { + if (word.starts_with("0x") || word.starts_with("0X")) word.remove_prefix(2); + std::uint64_t address = 0; + const auto [end, error] = std::from_chars(word.data(), word.data() + word.size(), address, 16); + if (word.empty() || error != std::errc{} || end != word.data() + word.size()) return std::nullopt; + return address; +} + +void ReloadSkippedShaders(const char* path) { + static std::mutex reload; + static std::filesystem::file_time_type seen{}; + const std::unique_lock lock(reload, std::try_to_lock); + if (!lock.owns_lock()) return; + std::error_code error; + const auto stamp = std::filesystem::last_write_time(path, error); + if (error || stamp == seen) return; + seen = stamp; + std::ifstream file(path); + std::size_t count = 0; + skippedShaderCount.store(0, std::memory_order_release); + for (std::string word; count < MaxSkippedShaders && file >> word;) { + if (word.starts_with('#')) { + std::getline(file, word); + continue; + } + const auto address = programAddress(word); + if (!address) { + std::fprintf(stderr, "[skip-shader] ignoring '%s' in %s: not a hexadecimal program address\n", word.c_str(), path); + continue; + } + if (*address != 0) skippedShaders[count++].store(*address, std::memory_order_relaxed); + } + skippedShaderCount.store(count, std::memory_order_release); + std::fprintf(stderr, "[skip-shader] %zu programs listed in %s\n", count, path); +} + +} + +bool SkippedShader(std::uint64_t address) { + static const std::uint64_t single = [] { const char* text = std::getenv("APS5_SKIP_SHADER"); return text ? std::strtoull(text, nullptr, 16) : 0ull; }(); + static const char* const file = std::getenv("APS5_SKIP_SHADER_FILE"); + if (address == 0) return false; + if (address == single) return true; + if (file == nullptr) return false; + static std::atomic nextCheck{0}; + const auto now = std::chrono::steady_clock::now().time_since_epoch(); + auto due = nextCheck.load(std::memory_order_relaxed); + if (now.count() >= due && nextCheck.compare_exchange_strong(due, std::chrono::duration_cast(now + std::chrono::milliseconds(500)).count(), std::memory_order_relaxed)) ReloadSkippedShaders(file); + const auto count = skippedShaderCount.load(std::memory_order_acquire); + for (std::size_t index = 0; index < count; ++index) { + if (skippedShaders[index].load(std::memory_order_relaxed) == address) return true; + } + return false; } bool SkipRefusedDraws() { diff --git a/core/libs/prx/libSceAgcDriver/Execution/src/Driver/Dispatch/Dispatch.cpp b/core/libs/prx/libSceAgcDriver/Execution/src/Driver/Dispatch/Dispatch.cpp index 8110338e83..528da65d87 100644 --- a/core/libs/prx/libSceAgcDriver/Execution/src/Driver/Dispatch/Dispatch.cpp +++ b/core/libs/prx/libSceAgcDriver/Execution/src/Driver/Dispatch/Dispatch.cpp @@ -66,7 +66,7 @@ bool Driver::pipelineDispatch() { void Driver::dispatch(QueueState& queue, std::span packet, const Submission& submission, std::uint64_t indirectArguments) { PerformanceTimer timing("Driver.Dispatch"); const auto address = (static_cast(readRegister(queue.shader, 0x20c)) << 8u) | (static_cast(readRegister(queue.shader, 0x20d) & 0xffu) << 40u); - if (address == SkippedShader() && address != 0) return; + if (SkippedShader(address)) return; auto registeredShader = RegisteredProgram(*submission.shaders, address, {0}); if (!registeredShader) registeredShader = ReadRawShader(address); const auto& snapshot = *registeredShader; @@ -414,6 +414,11 @@ void Driver::dispatch(QueueState& queue, std::span packet, parked.resolvedAt = std::chrono::steady_clock::now(); ++groupStats.resolved; if (cached) ++groupStats.resolvedHits; + if (!cached && compiledResult != nullptr && !localDevice->HasComputePipeline(*compiledResult)) { + SubmitLibraryPrebuild([localDevice, compiledResult, address] { + try { localDevice->PrebuildComputePipeline(*compiledResult, address); } catch (const std::exception&) {} + }); + } return; } if (verifyDataHits() && dataHit) verifyDataHit(snapshot, codeOffset, request, memory, address, *keepVariant, liveWords, *compiledResult); diff --git a/core/libs/prx/libSceAgcDriver/Execution/src/Driver/Dispatch/DispatchAhead.cpp b/core/libs/prx/libSceAgcDriver/Execution/src/Driver/Dispatch/DispatchAhead.cpp index 6391881462..0ebd368419 100644 --- a/core/libs/prx/libSceAgcDriver/Execution/src/Driver/Dispatch/DispatchAhead.cpp +++ b/core/libs/prx/libSceAgcDriver/Execution/src/Driver/Dispatch/DispatchAhead.cpp @@ -2,9 +2,11 @@ #include "ThreadOwned.hpp" #include "prx/libSceAgcDriver/Execution/include/Driver/Driver.hpp" #include "prx/libSceAgcDriver/Execution/include/Driver/Draw/DrawPipeline.hpp" +#include "prx/libSceAgcDriver/Execution/include/Driver/Shaders/ShaderRegistry.hpp" #include "prx/libSceAgcDriver/Execution/include/Driver/Synchronization/DeferredLabels.hpp" #include "prx/libSceAgcDriver/Execution/include/Pm4.hpp" #include "prx/libSceAgcDriver/Execution/include/VideoOutput.hpp" +#include "Optimization/ResourceProgram.hpp" #include #include #include @@ -40,7 +42,17 @@ std::uint64_t Driver::DispatchesAdoptedAhead() const { return dispatchesAdoptedAhead.load(std::memory_order_relaxed); } +namespace { + +std::size_t& PreviewedUntil() { + static thread_local std::size_t until = 0; + return until; +} + +} + void Driver::clearResolvedAhead() { + PreviewedUntil() = 0; auto& resolved = resolvedAhead(); if (resolved.empty()) return; groupCaptureStats().stale += resolved.size(); @@ -107,7 +119,8 @@ void Driver::resolveGroupAhead(const Submission& submission, const QueueState& l static const bool allQueues = std::getenv("APS5_GROUP_CAPTURE_ALL_QUEUES") != nullptr; if (!allQueues && submission.queue == 0) return; auto& resolved = resolvedAhead(); - if (resolved.contains(from) || device.Load() == nullptr) return; + const auto localDevice = device.Load(); + if (resolved.contains(from) || localDevice == nullptr) return; if (submission.queue == 0 && DrawPipeline::Depth() != 0 && DrawPipeline::Queue0().Busy()) DrawPipeline::Queue0().Drain(DrawPipeline::DrainReason::Packet, (submission.commands[from] >> 8u) & 0xffu); auto& stats = groupCaptureStats(); const auto begin = std::chrono::steady_clock::now(); @@ -126,6 +139,110 @@ void Driver::resolveGroupAhead(const Submission& submission, const QueueState& l } } resolving; const auto& commands = submission.commands; + if (submission.shaders != nullptr && from >= PreviewedUntil()) { + bool hasFurtherDispatch = false; + std::size_t limit = from < commands.size() ? from + Pm4::PacketWords(commands[from]) : commands.size(); + while (limit < commands.size()) { + const auto header = commands[limit]; + if (Pm4::FillerPacket(header)) { + ++limit; + continue; + } + const auto count = Pm4::PacketWords(header); + if (limit + count > commands.size()) break; + const auto opcode = (header >> 8u) & 0xffu; + if (header == FlipPacketHeader || header == RenderingWaitPacketHeader || opcode == 0x22 || opcode == 0x3f || opcode == 0x3c || opcode == 0x93) break; + if (opcode == 0x15 || opcode == 0x16) hasFurtherDispatch = true; + limit += count; + } + PreviewedUntil() = limit; + if (hasFurtherDispatch) { + static thread_local QueueState* previewSlot = nullptr; + auto& preview = ShaderRecompiler::ThreadOwned(previewSlot); + preview.shader = live.shader; + preview.predication = live.predication; + std::vector pendingShaders; + std::vector submittedShaders; + std::size_t scan = from; + while (scan < limit) { + const auto header = commands[scan]; + if (Pm4::FillerPacket(header)) { + ++scan; + continue; + } + const auto count = Pm4::PacketWords(header); + if (scan + count > limit) break; + const auto packet = std::span(commands).subspan(scan, count); + const auto opcode = (header >> 8u) & 0xffu; + const auto next = scan + count; + if (opcode == 0x15 || opcode == 0x16) { + if (count < (opcode == 0x15 ? 5u : 3u)) break; + if (scan > from) { + const auto low = preview.shader.find(0x20c); + const auto high = preview.shader.find(0x20d); + if (low != preview.shader.end() && high != preview.shader.end()) { + const auto address = (static_cast(low->second) << 8u) | (static_cast(high->second & 0xffu) << 40u); + if (auto registered = RegisteredProgram(*submission.shaders, address, {0}); registered != nullptr && registered->type == 0) { + bool isPending = false; + bool isEmpty = false; + { + std::lock_guard lock(registered->prepared->mutex); + isPending = registered->prepared->pending; + isEmpty = registered->prepared->entries.empty(); + } + if (isPending) { + if (std::ranges::find(pendingShaders, registered->prepared.get()) == pendingShaders.end()) { + pendingShaders.push_back(registered->prepared.get()); + } + } else if (isEmpty && std::ranges::find(submittedShaders, registered->prepared.get()) == submittedShaders.end()) { + const auto codeOffset = static_cast((address - registered->codeAddress) / sizeof(std::uint32_t)); + if (codeOffset < registered->code.size()) { + try { + auto compute = Graphics::DecodeComputeStageInfo(preview.shader, registered->header); + submittedShaders.push_back(registered->prepared.get()); + const auto rsrc2 = preview.shader.find(0x213); + const auto userCount = rsrc2 != preview.shader.end() ? ((rsrc2->second >> 1u) & 0x1fu) : 0u; + std::vector userData(userCount, 0u); + for (std::uint32_t i = 0; i < userCount; ++i) { + if (const auto reg = preview.shader.find(0x240u + i); reg != preview.shader.end()) userData[i] = reg->second; + } + const auto wave = (packet.back() & 0x8000u) != 0 ? 32u : 64u; + SubmitRegistrationPreparation([registered, localDevice, address, codeOffset, wave, compute, userData = std::move(userData), state = preview.shader]() mutable { + std::vector memory{{registered->codeAddress, std::as_bytes(std::span(registered->code))}}; + if (!registered->header.empty()) memory.push_back({registered->headerAddress, registered->header}); + ShaderRecompiler::RecompileRequest request{ + {ShaderRecompiler::ShaderStage::Compute, address, std::span(registered->code).subspan(codeOffset), registered->headerAddress, registered->header}, + {wave, 0, userData, compute, std::nullopt, std::nullopt, memory, DispatchFloatMode(*registered, state)}, + localDevice->ComputeTarget(wave), + {0, 0, 0, 128} + }; + try { static_cast(InvocationFor(*registered, codeOffset, request)); } catch (const std::exception&) {} + }, registered->prepared.get()); + } catch (const std::exception&) {} + } + } + } + } + } + Pm4::NoteDispatchRegisters(packet, preview); + } else if (Pm4::IndirectRegisterOpcode(opcode)) { + const auto found = submission.registerLists.find(scan); + if (count != 5 || found == submission.registerLists.end() || found->second.size() != static_cast(packet[4]) * 2 || !Pm4::IndirectRegistersValid(found->second)) break; + Pm4::ExecuteIndirectRegisters(packet, found->second, preview); + } else if (!Pm4::AccessesMemory(header) && opcode != 0x3c && opcode != 0x93 && opcode != 0x37 && opcode != 0x42 && opcode != 0x46 && opcode != 0x49 && opcode != 0x58) { + try { + Pm4::Execute(packet, preview); + } catch (const std::exception&) { + break; + } + } + scan = next; + } + for (auto it = pendingShaders.rbegin(); it != pendingShaders.rend(); ++it) { + PrioritizeRegistrationPreparation(**it); + } + } + } for (std::size_t cursor = from; cursor < commands.size();) { const auto header = commands[cursor]; if (Pm4::FillerPacket(header)) { @@ -141,7 +258,7 @@ void Driver::resolveGroupAhead(const Submission& submission, const QueueState& l if (opcode == 0x3c || opcode == 0x93) { if (!Pm4::WaitSatisfiedUnchecked(packet) && !WrittenByRun(packet, labels)) break; } else if (opcode == 0x15 || opcode == 0x16) { - if (resolved.contains(cursor)) break; + if (count < (opcode == 0x15 ? 5u : 3u) || resolved.contains(cursor)) break; if (opcode == 0x16) { std::uint64_t arguments = 0; try { diff --git a/core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/Draw.cpp b/core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/Draw.cpp index 477c943f72..4d85df3c00 100644 --- a/core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/Draw.cpp +++ b/core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/Draw.cpp @@ -518,7 +518,7 @@ DrawVerdict Driver::draw(QueueState& queue, std::span packe for (const auto& patch : userPatches) writablePrograms[patch.program].userData[patch.index] = patch.value; tail.programs = writesPrograms ? &writablePrograms : &decode->programs; const auto& programs = *tail.programs; - if (const auto skipped = SkippedShader(); skipped != 0 && std::any_of(programs.begin(), programs.end(), [skipped](const DrawProgram& program) { return program.binary.codeAddress == skipped; })) return drawn(); + if (std::any_of(programs.begin(), programs.end(), [](const DrawProgram& program) { return SkippedShader(program.binary.codeAddress); })) return drawn(); const bool emptyIndirectSkip = EmptyIndirectSkip(); auto& cpuIndirectPrograms = CpuIndirectPrograms(); const auto recordDraws = [&](const Pm4::DrawArguments& arguments) { return arguments.count != 0 && arguments.instances != 0 && (!drawParameters.indexed || !drawParameters.indirect->indexLimitKnown || arguments.firstVertexOrIndex < drawParameters.indexCount); }; diff --git a/core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawPipeline.cpp b/core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawPipeline.cpp index a1a5ebaab1..a34ffbd972 100644 --- a/core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawPipeline.cpp +++ b/core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawPipeline.cpp @@ -482,6 +482,10 @@ bool DrawPipeline::HeldReads(std::uint64_t address, std::size_t bytes) { return false; } +std::uint64_t DrawPipeline::HeldReadQueries() { + return heldReadQueries.load(std::memory_order_relaxed); +} + void DrawPipeline::ReleaseRunningReads() { std::lock_guard lock(mutex); if (!items.empty()) items.front().reads.clear(); diff --git a/core/libs/prx/libSceAgcDriver/Execution/src/Driver/Packets/PacketExecution.cpp b/core/libs/prx/libSceAgcDriver/Execution/src/Driver/Packets/PacketExecution.cpp index 6328766099..814ee7aadc 100644 --- a/core/libs/prx/libSceAgcDriver/Execution/src/Driver/Packets/PacketExecution.cpp +++ b/core/libs/prx/libSceAgcDriver/Execution/src/Driver/Packets/PacketExecution.cpp @@ -29,11 +29,6 @@ bool orderedFills() { return ordered; } -bool pipelineDma() { - static const bool enabled = std::getenv("APS5_PIPELINE_DMA") != nullptr; - return enabled; -} - bool keepsDrawFinisher(std::uint32_t header, std::uint32_t opcode) { if (header == FlipPacketHeader || header == RenderingWaitPacketHeader) return false; if (Pm4::DrawOpcode(opcode)) return true; @@ -65,7 +60,6 @@ bool keepsDrawPipeline(std::span packet, std::uint32_t head if (packet.size() < 7) return false; const auto destination = Pm4::DmaDestination(packet); if (destination == Pm4::DmaDestinationNowhere) return true; - if (!pipelineDma()) return false; if (destination == Pm4::DmaSelectGds) return true; const auto bytes = Pm4::DmaBytes(packet); if (bytes == 0) return true; diff --git a/core/libs/prx/libSceAgcDriver/Execution/src/Driver/Packets/PacketMemory.cpp b/core/libs/prx/libSceAgcDriver/Execution/src/Driver/Packets/PacketMemory.cpp index 5c2cc06454..7f11880db5 100644 --- a/core/libs/prx/libSceAgcDriver/Execution/src/Driver/Packets/PacketMemory.cpp +++ b/core/libs/prx/libSceAgcDriver/Execution/src/Driver/Packets/PacketMemory.cpp @@ -292,8 +292,7 @@ void Driver::dumpSampleCounters(std::uint64_t address) { } bool Driver::enqueueDmaPacket(std::span packet, std::uint32_t opcode, std::uint32_t queue, const QueueState& state) { - static const bool enabled = std::getenv("APS5_PIPELINE_DMA") != nullptr; - if (!enabled || opcode != 0x50 || queue != 0 || packet.size() < 7 || !DrawPipeline::Active() || !deferredLabels().labels.empty()) return false; + if (opcode != 0x50 || queue != 0 || packet.size() < 7 || !DrawPipeline::Active() || !deferredLabels().labels.empty()) return false; const auto source = ((packet[1] >> 29u) & 3u) | ((packet[6] >> 24u) & 4u) | ((packet[6] >> 25u) & 8u); constexpr std::size_t immediateLimit = std::size_t{16} << 20u; constexpr std::size_t gpuStoreLimit = 65536; diff --git a/core/libs/prx/libSceAgcDriver/Execution/src/Driver/Presentation.cpp b/core/libs/prx/libSceAgcDriver/Execution/src/Driver/Presentation.cpp index a2fa486528..ce28441eb1 100644 --- a/core/libs/prx/libSceAgcDriver/Execution/src/Driver/Presentation.cpp +++ b/core/libs/prx/libSceAgcDriver/Execution/src/Driver/Presentation.cpp @@ -93,6 +93,7 @@ void Driver::Present(const PresentationWindow& window, const DisplayBuffer* buff bool submitted = false; bool presentable = false; bool trailing = false; + bool queueUnlocked = false; double waitedMs = 0; { GuestMemory::TagGpuLockSite(GuestMemory::GpuLockSite::Present); @@ -141,12 +142,20 @@ void Driver::Present(const PresentationWindow& window, const DisplayBuffer* buff } if (submitted && (syncFlip || inFlight != 0)) { - presenting->QueuePresent(); - timing.Mark("queue_present"); + if (presenting->PresentsOnOwnQueue()) { + queueUnlocked = true; + } else { + presenting->QueuePresent(); + timing.Mark("queue_present"); + } trailing = !syncFlip; submitted = false; } } + if (queueUnlocked) { + presenting->QueuePresent(); + timing.Mark("queue_present"); + } if (trailing) { waitedMs += presenting->FinishPresent(); timing.Mark("render_fence_wait"); @@ -155,9 +164,13 @@ void Driver::Present(const PresentationWindow& window, const DisplayBuffer* buff waitedMs = presenting->FinishPresent(); timing.Mark("render_fence_wait"); - GuestMemory::TagGpuLockSite(GuestMemory::GpuLockSite::Present); - std::lock_guard lock(GuestMemory::GpuMutex()); - presenting->QueuePresent(); + if (presenting->PresentsOnOwnQueue()) { + presenting->QueuePresent(); + } else { + GuestMemory::TagGpuLockSite(GuestMemory::GpuLockSite::Present); + std::lock_guard lock(GuestMemory::GpuMutex()); + presenting->QueuePresent(); + } timing.Mark("queue_present"); } gpuReady(context); diff --git a/core/libs/prx/libSceAgcDriver/Execution/src/FrameRecorder.cpp b/core/libs/prx/libSceAgcDriver/Execution/src/FrameRecorder.cpp index 0b64a184c8..8d34708b90 100644 --- a/core/libs/prx/libSceAgcDriver/Execution/src/FrameRecorder.cpp +++ b/core/libs/prx/libSceAgcDriver/Execution/src/FrameRecorder.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceAgcDriver/State/include/Configuration.hpp" #include "prx/libSceAgcDriver/Execution/include/FrameRecorder.hpp" #include "prx/libSceAgcDriver/Execution/include/Driver/Driver.hpp" #include "prx/libSceAgcDriver/Execution/include/GuestMemory.hpp" @@ -25,8 +26,6 @@ #include #endif -extern "C" int APS5_VABI sceAgcDriverGetTFRing(uintptr_t* base, uint32_t* size); - namespace AgcDriver { namespace { diff --git a/core/libs/prx/libSceAgcDriver/Execution/src/GuestMemory.cpp b/core/libs/prx/libSceAgcDriver/Execution/src/GuestMemory.cpp index fe8241fcfc..982b53e003 100644 --- a/core/libs/prx/libSceAgcDriver/Execution/src/GuestMemory.cpp +++ b/core/libs/prx/libSceAgcDriver/Execution/src/GuestMemory.cpp @@ -1751,7 +1751,7 @@ void Rewatch(std::span> ranges) { if (!tracker.watched) return; bool restored = false; for (const auto& [begin, end] : ranges) { - if (end <= begin || begin < tracker.base || end - tracker.base > tracker.size || (begin - tracker.base) % WriteBlockBytes != 0 || (end - tracker.base) % WriteBlockBytes != 0) continue; + if (end <= begin || begin < tracker.base || end - tracker.base > tracker.size || (begin - tracker.base) % WritePageBytes != 0 || (end - tracker.base) % WritePageBytes != 0) continue; const auto bytes = static_cast(end - begin); if (tracker.coverage.Covers(begin, bytes)) continue; GuestArena::GuestArenaCompareWhenShared_nid_no_patch(static_cast(begin), bytes); diff --git a/core/libs/prx/libSceAgcDriver/Execution/src/Pm4.cpp b/core/libs/prx/libSceAgcDriver/Execution/src/Pm4.cpp index f742e7b945..09dda98153 100644 --- a/core/libs/prx/libSceAgcDriver/Execution/src/Pm4.cpp +++ b/core/libs/prx/libSceAgcDriver/Execution/src/Pm4.cpp @@ -1,3 +1,4 @@ +#include "prx/libkernel/include/Api.hpp" #include "prx/libSceAgcDriver/Execution/include/Pm4.hpp" #include "prx/libSceAgcDriver/Execution/include/GuestMemory.hpp" #include "prx/libc/include/General.hpp" @@ -13,8 +14,6 @@ #include #include -extern "C" void* APS5_VABI mmap_nid_postfix(void* address, std::size_t length, int protection, int flags, int descriptor, std::int64_t offset) noexcept; - namespace AgcDriver::Pm4 { std::uint64_t GdsAddress() { @@ -115,7 +114,6 @@ std::vector copySource(std::uint64_t source, std::size_t bytes, bool return data; } - bool gdsRange(std::uint64_t offset, std::size_t bytes) { return offset <= GdsBytes && bytes <= GdsBytes - offset; } diff --git a/core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp b/core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp index 70fdef29e3..a1c2eef27c 100644 --- a/core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp +++ b/core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp @@ -20,9 +20,11 @@ #include "prx/libSceAgcDriver/Execution/include/PipelineLinkOptimization.hpp" #include "prx/libSceAgcDriver/Execution/include/DrawInputsInPlace.hpp" #include "prx/libSceAgcDriver/Execution/include/SubgroupBarrier.hpp" +#include "prx/libSceAgcDriver/Execution/include/TessellationPipelineCache.hpp" #include "prx/libSceAgcDriver/Execution/include/SubgroupClock.hpp" #include "prx/libSceAgcDriver/Execution/include/ShaderDeviceProfile.hpp" #include "prx/libSceAgcDriver/Execution/include/PresentMode.hpp" +#include "prx/libSceAgcDriver/Execution/include/SwapchainImages.hpp" #include "prx/libSceAgcDriver/Execution/include/PerformanceOverlay.hpp" #include "prx/libSceAgcDriver/Execution/include/PresentationPass.hpp" #include "prx/libSceAgcDriver/Execution/include/PresentationScaler.hpp" @@ -83,7 +85,7 @@ namespace AgcDriver { -DeviceQueuePlan PlanDeviceQueues(std::span families, std::uint32_t family, bool settles, bool sparseBinding) { +DeviceQueuePlan PlanDeviceQueues(std::span families, std::uint32_t family, bool settles, bool sparseBinding, bool presents) { DeviceQueuePlan plan; const auto count = static_cast(families.size()); if (settles) { @@ -102,6 +104,13 @@ DeviceQueuePlan PlanDeviceQueues(std::span famili } } } + if (presents && family < count) { + if (const auto index = SelectPresentQueue(families[family].queueCount, plan.mainCount)) { + plan.present = true; + plan.presentIndex = *index; + plan.mainCount = *index + 1; + } + } if (!sparseBinding) return plan; const auto taken = [&](std::uint32_t index) { return plan.settle && index == plan.settleFamily ? plan.settleIndex + 1 : 0u; }; const auto binds = [&](std::uint32_t index) { return index != family && families[index].queueCount > taken(index) && (families[index].queueFlags & VK_QUEUE_SPARSE_BINDING_BIT) != 0; }; @@ -351,6 +360,7 @@ struct VulkanDevice::State { VkDriverId driverId = VK_DRIVER_ID_MAX_ENUM; std::uint32_t pixelFunctionStorageDwords = 4096u; bool individuallyFreeDescriptorSets = false; + bool tessellationPipelineCache = true; PFN_vkGetCalibratedTimestampsKHR calibratedTimestamps = nullptr; PFN_vkCmdSetCheckpointNV checkpointMarker = nullptr; PFN_vkCmdWriteBufferMarkerAMD bufferMarker = nullptr; @@ -439,6 +449,8 @@ struct VulkanDevice::State { std::uint32_t settleFamily = 0; VkCommandPool settlePool = VK_NULL_HANDLE; std::mutex settleQueueMutex; + VkQueue presentQueue = VK_NULL_HANDLE; + std::mutex presentQueueMutex; bool memoryBudget = false; bool depthRangeUnrestricted = false; bool samplerAnisotropy = false; @@ -806,7 +818,7 @@ struct VulkanDevice::State { for (std::uint32_t x = 0; x < width; ++x) std::memcpy(pixels.data() + (static_cast(y) * width + x) * 4, full.data() + (static_cast(y) * scale * slot.dumpWidth + static_cast(x) * scale) * 4, 4); } static const auto start = std::chrono::steady_clock::now(); - std::fprintf(stderr, "[gpu] frame_%03d.bmp: %ux%u display read back on the GPU at %.1f s\n", index, slot.dumpWidth, slot.dumpHeight, std::chrono::duration(std::chrono::steady_clock::now() - start).count()); + AgcDriver::ProfilePrint_nid_no_patch("[gpu] frame_%03d.bmp: %ux%u display read back on the GPU at %.1f s\n", index, slot.dumpWidth, slot.dumpHeight, std::chrono::duration(std::chrono::steady_clock::now() - start).count()); dumpWriter.Enqueue(index, width, height, 1, false, std::move(pixels)); } @@ -1275,6 +1287,7 @@ VulkanDevice::VulkanDevice(const PresentationWindow* window, bool compileOnly) : state->driverId = driver.driverID; state->individuallyFreeDescriptorSets = driver.driverID == VK_DRIVER_ID_MESA_LLVMPIPE; state->fusedExactArithmetic = driver.driverID == VK_DRIVER_ID_MOLTENVK; + state->tessellationPipelineCache = TessellationPipelineCacheUsable(driver.driverID); state->subgroupControlBarriers = SubgroupControlBarrierUsable(driver.driverID); state->workgroupScopeFences = WorkgroupScopeFenceUsable(driver.driverID); } @@ -1682,7 +1695,7 @@ VulkanDevice::VulkanDevice(const PresentationWindow* window, bool compileOnly) : queueInfo.queueFamilyIndex = family; queueInfo.queueCount = 1; queueInfo.pQueuePriorities = &priority; - const float priorities[2]{1.0f, 1.0f}; + const float priorities[3]{1.0f, 1.0f, 1.0f}; #ifdef _WIN32 const bool settles = true; #else @@ -1729,13 +1742,13 @@ VulkanDevice::VulkanDevice(const PresentationWindow* window, bool compileOnly) : // Guest shaders routinely read past descriptor ranges; robust access turns that into zeros // instead of a GPU fault that loses the device. enabled.robustBufferAccess = available.robustBufferAccess; - const auto plan = PlanDeviceQueues(queues, family, settles, available.sparseBinding == VK_TRUE); + const auto plan = PlanDeviceQueues(queues, family, settles, available.sparseBinding == VK_TRUE, window != nullptr); const bool settleQueue = plan.settle; const auto settleFamily = plan.settleFamily; const auto settleIndex = plan.settleIndex; VkDeviceQueueCreateInfo queueInfos[3]{queueInfo, {VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO}, {VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO}}; queueInfos[0].queueCount = plan.mainCount; - queueInfos[0].pQueuePriorities = plan.mainCount == 2 ? priorities : &priority; + queueInfos[0].pQueuePriorities = plan.mainCount > 1 ? priorities : &priority; deviceInfo.queueCreateInfoCount = 1; const auto addQueue = [&](std::uint32_t queueFamily, std::uint32_t index) { for (std::uint32_t info = 1; info < deviceInfo.queueCreateInfoCount; ++info) { @@ -2103,6 +2116,10 @@ VulkanDevice::VulkanDevice(const PresentationWindow* window, bool compileOnly) : } state->DeviceFunction("vkGetDeviceQueue")(state->device, family, 0, &state->queue); state->queueFamily = family; + if (plan.present) { + state->DeviceFunction("vkGetDeviceQueue")(state->device, family, plan.presentIndex, &state->presentQueue); + APS5_LOG_OUT("Presentation queue family=%u index=%u", family, plan.presentIndex); + } if (settleQueue) { state->settleFamily = settleFamily; state->DeviceFunction("vkGetDeviceQueue")(state->device, settleFamily, settleIndex, &state->settleQueue); @@ -2193,7 +2210,7 @@ VulkanDevice::VulkanDevice(const PresentationWindow* window, bool compileOnly) : require((surface.supportedUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) != 0, "surface does not support color attachment images"); VkSwapchainCreateInfoKHR swapchain{VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR}; swapchain.surface = state->surface; - swapchain.minImageCount = surface.minImageCount; + swapchain.minImageCount = AgcDriver::SwapchainImageCount(surface); swapchain.imageFormat = state->surfaceFormat; swapchain.imageColorSpace = state->surfaceColorSpace; swapchain.imageExtent = state->extent; @@ -2297,6 +2314,26 @@ bool VulkanDevice::ReplayComputePipeline(const ShaderRecompiler::RecompileResult return state->computePipelines.try_emplace(key, std::move(objects)).second; } +bool VulkanDevice::HasComputePipeline(const ShaderRecompiler::RecompileResult& shader) const { + const std::array shaders{{{ShaderRecompiler::ShaderStage::Compute, &shader, 0}}}; + const auto key = ComputePipelineKey::Of(shader, Graphics::PushConstantStages(shaders) != 0); + std::lock_guard pipelines(state->computePipelinesMutex); + return !key.identity.Empty() && (state->computePipelines.contains(key) || state->computePipelinesBuilding.contains(key)); +} + +void VulkanDevice::PrebuildComputePipeline(const ShaderRecompiler::RecompileResult& shader, std::uint64_t programAddress) { + if (shader.spirv.size() < 5 || shader.spirv[0] != 0x07230203u) return; + ShaderRecompiler::RuntimeAbi::RequireVersion(shader.runtimeAbiVersion); + const auto context = graphicsContext(); + if (context.descriptorCache == nullptr) return; + const std::array shaders{{{ShaderRecompiler::ShaderStage::Compute, &shader, 0}}}; + const auto pushStages = Graphics::PushConstantStages(shaders); + if (pushStages != 0 && state->properties.limits.maxPushConstantsSize < Graphics::ComputePushConstantBytes) return; + if (HasComputePipeline(shader)) return; + const auto layouts = Graphics::DescribeSetLayouts(context, shaders); + static_cast(computePipeline(context, shader, layouts.layouts.main, layouts.mainKey, pushStages, programAddress)); +} + bool VulkanDevice::ImportGuestMemory(const GuestAllocations::Mapped& ranges, std::uint64_t generation, bool adoptDevice) { if (adoptDevice) GuestMemory::AssertGpuLockHeld("VulkanDevice::ImportGuestMemory"); return Graphics::ImportMappedRanges(graphicsContext(), ranges, generation, adoptDevice); @@ -2332,6 +2369,8 @@ void VulkanDevice::WaitIdle() { if (!state->recorder->Idle()) Graphics::Recorder::CountSync(0, __builtin_return_address(0)); state->recorder->Sync(); } + std::unique_lock presentQueueLock(state->presentQueueMutex, std::defer_lock); + if (state->presentQueue != VK_NULL_HANDLE) presentQueueLock.lock(); check(state->DeviceFunction("vkDeviceWaitIdle")(state->device), "vkDeviceWaitIdle"); Graphics::CheckPixelFunctionLds(graphicsContext()); APS5_LOG_CHARS_OUT_DEBUG("VulkanDevice::WaitIdle complete"); @@ -3044,7 +3083,7 @@ void VulkanDevice::recreateSwapchain(std::uint32_t width, std::uint32_t height, require((surface.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_DST_BIT) != 0 && (surface.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR) != 0 && (surface.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) != 0, "resized surface capabilities are unsupported"); VkSwapchainCreateInfoKHR create{VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR}; create.surface = state->surface; - create.minImageCount = surface.minImageCount; + create.minImageCount = AgcDriver::SwapchainImageCount(surface); create.imageFormat = state->surfaceFormat; create.imageColorSpace = state->surfaceColorSpace; create.imageExtent = {width, height}; @@ -3780,13 +3819,19 @@ void VulkanDevice::QueuePresent() { present.swapchainCount = 1; present.pSwapchains = &state->swapchain; present.pImageIndices = &index; - const auto presented = state->DeviceFunction("vkQueuePresentKHR")(state->queue, &present); + std::unique_lock presentQueueLock(state->presentQueueMutex, std::defer_lock); + if (state->presentQueue != VK_NULL_HANDLE) presentQueueLock.lock(); + const auto presented = state->DeviceFunction("vkQueuePresentKHR")(state->presentQueue != VK_NULL_HANDLE ? state->presentQueue : state->queue, &present); if (presented == VK_ERROR_OUT_OF_DATE_KHR || presented == VK_SUBOPTIMAL_KHR) state->extent = {0, 0}; else check(presented, "vkQueuePresentKHR"); timing.Mark("queue_present"); APS5_LOG_OUT_DEBUG("vkQueuePresentKHR queued imageIndex=%u", index); } +bool VulkanDevice::PresentsOnOwnQueue() const { + return state->presentQueue != VK_NULL_HANDLE; +} + ShaderRecompiler::SpirvTarget VulkanDevice::ComputeTarget(std::uint32_t waveSize) const { auto target = Target(); if (waveSize == 32u && state->computeWave32) target.subgroupSize = 32u; @@ -3955,6 +4000,7 @@ Graphics::Context VulkanDevice::buildContext() const { }; context.pipelineCacheSynchronization = state->pipelineCache ? &state->pipelineCache->Synchronization() : nullptr; context.individuallyFreeDescriptorSets = state->individuallyFreeDescriptorSets; + context.tessellationPipelineCache = state->tessellationPipelineCache; context.dmaBufImport = state->dmaBufImport; context.sparseBinding = state->sparseBinding; context.sparseResidencyBuffer = state->sparseResidencyBuffer; @@ -4332,7 +4378,7 @@ struct DispatchCounters { std::array phaseTotals{}; std::uint64_t profiledDispatches = 0; IndirectHold indirectHold; - std::uint64_t cacheHits = 0, cacheMisses = 0, cacheInvalidated = 0, templateRefreshed = 0, templateSameWords = 0; + std::uint64_t cacheHits = 0, cacheMisses = 0, cacheInvalidated = 0, templateRefreshed = 0, templateSameWords = 0, templateByNumber = 0; double templateRevalidateMs = 0; std::uint64_t procLookups = 0, preBarriersRecorded = 0, preBarriersSkipped = 0; std::chrono::steady_clock::time_point cacheReport = std::chrono::steady_clock::now(); @@ -4993,6 +5039,7 @@ void VulkanDevice::recordDispatch(RecordedDispatch& record) { // after an earlier dispatch's reads of the buffers by that dispatch's trailing barrier. A // recipe compares the two 64-bit hashes first: equal hashes mean the buffers hold the words. const bool differs = record.dataRefresh == RecordedDispatch::DataRefresh::Words || resources.DataWordsHash() != record.dataWordsHash; + if (timer.profile && record.shader->program != nullptr && record.shader->program->bindings.size() != resources.BindingCount()) ++d.templateByNumber; if (differs && (record.resourceKeyMatched ? resources.refreshData(commands, *record.shader, &recorder) : resources.RefreshData(commands, *record.shader, &recorder))) { covered = 0; ++d.templateRefreshed; @@ -5506,7 +5553,7 @@ VulkanDevice::IndirectOutcome VulkanDevice::dispatch(const ShaderRecompiler::Rec } if (profile && std::chrono::steady_clock::now() - d.cacheReport > std::chrono::seconds(10)) { d.cacheReport = std::chrono::steady_clock::now(); - AgcDriver::ProfilePrint_nid_no_patch("[rescache] (cumulative): %llu hits, %llu misses, %llu invalidated, %zu entries (dispatch + draw); template hits: %llu refreshed the data buffers (revalidate %.1f ms), %llu had the same words; Find calls %llu, Touch calls %llu\n", static_cast(d.cacheHits), static_cast(d.cacheMisses), static_cast(d.cacheInvalidated), state->resourceCache.Size(), static_cast(d.templateRefreshed), d.templateRevalidateMs, static_cast(d.templateSameWords), static_cast(ResourceCache::Finds()), static_cast(ResourceCache::Touches())); + AgcDriver::ProfilePrint_nid_no_patch("[rescache] (cumulative): %llu hits, %llu misses, %llu invalidated, %zu entries (dispatch + draw); template hits: %llu refreshed the data buffers (revalidate %.1f ms), %llu had the same words, %llu paired their data bindings by number (no image table binding of their own); Find calls %llu, Touch calls %llu\n", static_cast(d.cacheHits), static_cast(d.cacheMisses), static_cast(d.cacheInvalidated), state->resourceCache.Size(), static_cast(d.templateRefreshed), d.templateRevalidateMs, static_cast(d.templateSameWords), static_cast(d.templateByNumber), static_cast(ResourceCache::Finds()), static_cast(ResourceCache::Touches())); AgcDriver::ProfilePrint_nid_no_patch("[vk] deviceProc lookups inside the device call (cumulative): %llu (%.2f per dispatch); pre-dispatch barriers recorded %llu, skipped %llu; compute pipelines created %llu (%llu under the GPU mutex)\n", static_cast(d.procLookups), d.profiledDispatches != 0 ? static_cast(d.procLookups) / static_cast(d.profiledDispatches) : 0.0, static_cast(d.preBarriersRecorded), static_cast(d.preBarriersSkipped), static_cast(computePipelinesCreated.load(std::memory_order_relaxed)), static_cast(computePipelinesCreatedLocked.load(std::memory_order_relaxed))); reportRecipes(); reportDispatchMove(); diff --git a/core/libs/prx/libSceAgcDriver/Export.cpp b/core/libs/prx/libSceAgcDriver/Export.cpp index 18cd1da5d8..fd98ebbdb5 100644 --- a/core/libs/prx/libSceAgcDriver/Export.cpp +++ b/core/libs/prx/libSceAgcDriver/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceAgcDriver/include/AgcDriver.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceAgcDriver/Graphics/include/Context.hpp b/core/libs/prx/libSceAgcDriver/Graphics/include/Context.hpp index 7e0e07d07b..dc2e00475a 100644 --- a/core/libs/prx/libSceAgcDriver/Graphics/include/Context.hpp +++ b/core/libs/prx/libSceAgcDriver/Graphics/include/Context.hpp @@ -240,6 +240,7 @@ struct Context { std::uint32_t imageTableCapacity = 0; std::uint32_t samplerTableCapacity = 0; bool individuallyFreeDescriptorSets = false; + bool tessellationPipelineCache = true; bool imageTableUpdateAfterBind = false; bool samplerTableUpdateAfterBind = false; bool geometryShader = false; diff --git a/core/libs/prx/libSceAgcDriver/Graphics/include/GuestBufferMemory.hpp b/core/libs/prx/libSceAgcDriver/Graphics/include/GuestBufferMemory.hpp index 9fe4caae06..bc6afff426 100644 --- a/core/libs/prx/libSceAgcDriver/Graphics/include/GuestBufferMemory.hpp +++ b/core/libs/prx/libSceAgcDriver/Graphics/include/GuestBufferMemory.hpp @@ -38,6 +38,7 @@ struct HostImport { // Identity for the life of this import (see HostImportSerial); 0 until first asked for. std::uint64_t serial = 0; bool unwatched = false; + bool settleOnDemand = false; bool dmaBuf = false; bool joined = false; std::shared_ptr chunk; @@ -102,6 +103,7 @@ void ReportHostImports(); // address)` in the import's buffer. const HostImport* HostImportFor(const Context& context, std::uint64_t address, std::size_t bytes, ImportRequester requester = ImportRequester::Access); const HostImport* ExistingHostImportFor(const Context& context, std::uint64_t address, std::size_t bytes); +bool WatchedAfterSettle(const Context& context, std::uint64_t address, std::size_t bytes); void SetHostImportWindow(std::uint64_t bytes); // Tests: the window of one large registered range (64 MiB) and the import budget (0: the configured one). void SetHostImportRangeWindow(std::uint64_t bytes); @@ -264,6 +266,8 @@ struct AddressCopy { std::uint64_t end; std::uint64_t committed; const char* reason; + bool heap = false; + bool overBudget = false; }; std::string AddressCopyOverflow(std::vector copies, std::uint64_t limit); diff --git a/core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp b/core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp index b3d8776df4..c140e57ec6 100644 --- a/core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp +++ b/core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp @@ -315,6 +315,7 @@ public: } // Whether RefreshData would record anything for `shader` (the per-word compare; verification). bool DataWordsDiffer(const CompiledShader& shader) const; + std::size_t BindingCount() const { return bindings.size(); } // Why the fast proof of a Revalidate left the object to the full walk (the [rescache] // revalidate line's reasons); Count: it did not. enum class FastFail : std::size_t { NoRecord, Collect, Pending, Evicted, Changed, Keys, ClearedView, StorageKeys, Depth, Replaced, Audit, Count }; diff --git a/core/libs/prx/libSceAgcDriver/Graphics/include/State.hpp b/core/libs/prx/libSceAgcDriver/Graphics/include/State.hpp index 4e7174f582..294c4bda9b 100644 --- a/core/libs/prx/libSceAgcDriver/Graphics/include/State.hpp +++ b/core/libs/prx/libSceAgcDriver/Graphics/include/State.hpp @@ -45,6 +45,7 @@ struct ColorTarget { ShaderRecompiler::ColorExportPacking packing = ShaderRecompiler::ColorExportPacking::None; // DCC metadata of a compressed target (CB_COLOR_INFO DCC_ENABLE), or 0 (see DccMetadata.hpp). std::uint64_t dccAddress = 0; + std::uint64_t chainDccAddress = 0; bool dccAlphaOnMsb = false; bool dccPipeAligned = false; std::uint64_t cmaskAddress = 0; diff --git a/core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp b/core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp index 7273cb82e3..8113221475 100644 --- a/core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp +++ b/core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp @@ -1970,20 +1970,15 @@ VkImageView DepthSurfaceView(const Context& context, const DepthTarget& target, const bool created = surface == nullptr; GuestAllocations::Lease creationLease; if (created) { - for (const auto& surface : surfaces()) { - if (!surface->active->load(std::memory_order_acquire) || !surface->samplingActive || surface->context.device != context.device) continue; - const auto bytes = target.samples == 1u ? DepthSliceBytes(target.extent, target.format == VK_FORMAT_D16_UNORM ? 2u : 4u) : MultisampledDepthBytes_nid_no_patch(target.extent, target.format == VK_FORMAT_D16_UNORM ? 2u : 4u, target.samples); - Require(target.address <= std::numeric_limits::max() - bytes && target.htileAddress <= std::numeric_limits::max() - HtileMetadataBytes(target.extent), "native depth attachment range overflows"); - for (const auto& range : surface->sampling.initial) { - Require(target.address >= range.address + range.bytes || range.address >= target.address + bytes, "native multisample depth attachment layout or metadata changed"); - if (target.stencilAddress != 0u) { - const auto stencilBytes = target.samples == 1u ? DepthSliceBytes(target.extent, 1u) : MultisampledDepthBytes_nid_no_patch(target.extent, 1u, target.samples); - Require(target.stencilAddress <= std::numeric_limits::max() - stencilBytes && (target.stencilAddress >= range.address + range.bytes || range.address >= target.stencilAddress + stencilBytes), "native multisample stencil attachment aliases a resident depth surface"); - } - if (target.htileAddress != 0u) Require(target.htileAddress >= range.address + range.bytes || range.address >= target.htileAddress + HtileMetadataBytes(target.extent), "native multisample depth attachment layout or metadata changed"); - } - } + const bool d16 = target.format == VK_FORMAT_D16_UNORM || target.format == VK_FORMAT_D16_UNORM_S8_UINT; + const auto depthBytes = target.samples == 1u ? DepthSliceBytes(target.extent, d16 ? 2u : 4u) : MultisampledDepthBytes_nid_no_patch(target.extent, d16 ? 2u : 4u, target.samples); + const auto stencilBytes = target.stencilAddress == 0u ? 0u : target.samples == 1u ? DepthSliceBytes(target.extent, 1u) : MultisampledDepthBytes_nid_no_patch(target.extent, 1u, target.samples); + const auto metadataBytes = target.htileAddress == 0u ? 0u : HtileMetadataBytes(target.extent); + Require(target.address <= std::numeric_limits::max() - depthBytes && target.stencilAddress <= std::numeric_limits::max() - stencilBytes && target.htileAddress <= std::numeric_limits::max() - metadataBytes, "native depth attachment range overflows"); lock.unlock(); + RequireNoResidentDepthRead_nid_no_patch(target.address, static_cast(depthBytes)); + if (stencilBytes != 0u) RequireNoResidentDepthRead_nid_no_patch(target.stencilAddress, static_cast(stencilBytes)); + if (metadataBytes != 0u) RequireNoResidentDepthRead_nid_no_patch(target.htileAddress, static_cast(metadataBytes)); auto sampling = target.samples == 1u ? DepthSamplingState{} : prepareDepthSampling(context, target); creationLease = target.samples == 1u || !sampling.refusal.empty() ? GuestAllocations::Lease{} : GuestAllocations::GuestAllocationsAcquireAll_nid_postfix(); lock.lock(); diff --git a/core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp b/core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp index a91fc9d2ff..0af56987c9 100644 --- a/core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp +++ b/core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp @@ -3279,7 +3279,7 @@ DrawRecipeOutcome DrawWithRecipe(const Context& context, const State& state, con timer.phase(PhaseSetup); if (state.colors[index].fmaskAddress != 0) GuardOneFragmentFmask(context, state.colors[index]); auto stored = recipe.targets[index].lock(); - if (stored == nullptr || !StorageImageCached(context, stored.get()) || !StorageImageServesKeys(*stored, state.colors[index].dccAddress)) return miss(DrawRecipeMiss::TargetGone); + if (stored == nullptr || !StorageImageCached(context, stored.get()) || !StorageImageServesKeys(*stored, SurfaceForTarget(state.colors[index]).dccAddress)) return miss(DrawRecipeMiss::TargetGone); auto resident = refreshResidentTarget(context, state, state.colors[index], outcome, profile, [&] { if (state.colors[index].arrayLastSlice != 0) stored->RefreshLayers(state.colors[index].arraySlice, 1); else stored->Refresh(); diff --git a/core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp b/core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp index 12939ea058..66c0f4a533 100644 --- a/core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp +++ b/core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp @@ -285,6 +285,7 @@ struct HostImports { bool allocationFailed = false; std::uint8_t reportNoted = 0; std::map spaceUses; + std::uint64_t budgetRefusals = 0; }; HostImports& Imports() { @@ -868,6 +869,7 @@ bool importsStale(const Context& context, const HostImports& state); constexpr std::uint64_t settleFloorBytes = 0x100000; #ifdef _WIN32 constexpr std::uint64_t settleBlockBytes = 0x10000; +constexpr std::uint64_t settlePageBytes = 0x1000; constexpr auto settlePollPeriod = std::chrono::microseconds(100); std::atomic deferredSettles{std::getenv("APS5_NO_DEFERRED_SETTLES") == nullptr}; #endif @@ -1094,8 +1096,22 @@ void reapSettleBatches(const Context& context, HostImports& state) { } } +bool comparedImportShares(const HostImports& state, std::uint64_t own, std::uint64_t begin, std::uint64_t end) { + const auto shares = [&](const HostImport& entry) { return entry.unwatched && entry.memoryBase < end && begin < entry.memoryBase + entry.pinnedBytes; }; + for (const auto& [base, entry] : state.imports) { + if (base != own && shares(entry)) return true; + } + for (const auto& [device, list] : state.parked) { + for (const auto& retired : list) { + if (shares(retired->node.mapped())) return true; + } + } + return false; +} + void rewatchSettledImports(HostImports& state) { if (state.settleReady.empty()) return; + std::vector bases; std::vector> ranges; for (const auto base : state.settleReady) { const auto settle = state.pendingSettles.find(base); @@ -1103,19 +1119,23 @@ void rewatchSettledImports(HostImports& state) { state.pendingSettles.erase(settle); const auto import = state.imports.find(base); if (import == state.imports.end() || !import->second.unwatched) continue; - const std::array, 1> span{{{base, base + import->second.bytes}}}; + const auto first = base & ~(settleBlockBytes - 1); + const auto stop = (base + import->second.bytes + settleBlockBytes - 1) & ~(settleBlockBytes - 1); + if ((first != base || stop != base + import->second.bytes) && comparedImportShares(state, base, first, stop)) continue; + const std::array, 1> span{{{first, stop}}}; if (StorageTexture::AnyLiveOverlaps(span)) { ++state.settlesKeptCompared; continue; } - ranges.push_back(span.front()); + bases.push_back(base); + ranges.emplace_back(base & ~(settlePageBytes - 1), (base + import->second.bytes + settlePageBytes - 1) & ~(settlePageBytes - 1)); } state.settleReady.clear(); if (ranges.empty()) return; GuestMemory::Rewatch(ranges); - for (const auto& [begin, end] : ranges) { - const auto import = state.imports.find(begin); - if (import == state.imports.end() || !GuestMemory::Watched(begin, static_cast(end - begin))) continue; + for (const auto base : bases) { + const auto import = state.imports.find(base); + if (import == state.imports.end() || !GuestMemory::Watched(base, static_cast(import->second.bytes))) continue; import->second.unwatched = false; ++state.settlesRewatched; } @@ -1130,6 +1150,49 @@ void settleUnwatchedImports(const Context& context, HostImports& state) { rewatchSettledImports(state); submitSettleBatch(context, state); } + +void settleImportsNow(const Context& context, HostImports& state, std::uint64_t begin, std::uint64_t end) { + if (context.settleQueue == VK_NULL_HANDLE || context.settleQueueMutex == nullptr || !GuestMemory::GpuMutex().HeldByThisThread()) return; + std::vector needed; + auto it = state.imports.lower_bound(begin); + if (it != state.imports.begin()) --it; + for (; it != state.imports.end() && it->first < end; ++it) { + auto& entry = it->second; + if (entry.base + entry.bytes <= begin || !entry.unwatched) continue; + auto settle = state.pendingSettles.find(it->first); + if (settle == state.pendingSettles.end()) { + if (!entry.settleOnDemand || !deferredSettles.load(std::memory_order_relaxed)) continue; + entry.settleOnDemand = false; + settle = state.pendingSettles.insert_or_assign(it->first, PendingSettle{}).first; + } + if (settle->second.phase == SettlePhase::Wanted) { + std::erase(state.settleWanted, it->first); + state.settleWanted.insert(state.settleWanted.begin(), it->first); + } + needed.push_back(it->first); + } + if (needed.empty()) return; + auto& deviceSettle = settleFor(context, state); + const auto wanted = [&] { + return std::any_of(needed.begin(), needed.end(), [&](std::uint64_t base) { + const auto settle = state.pendingSettles.find(base); + return settle != state.pendingSettles.end() && settle->second.phase == SettlePhase::Wanted; + }); + }; + while (wanted()) { + if (std::all_of(deviceSettle.batches.begin(), deviceSettle.batches.end(), [](const SettleBatch& batch) { return batch.busy; })) { + for (const auto& batch : deviceSettle.batches) waitSettleBatch(deviceSettle, context.device, batch); + reapSettleBatches(context, state); + } + submitSettleBatch(context, state); + } + for (const auto base : needed) { + const auto settle = state.pendingSettles.find(base); + if (settle != state.pendingSettles.end() && settle->second.phase == SettlePhase::Submitted && settle->second.device == context.device) waitSettleBatch(deviceSettle, context.device, deviceSettle.batches[settle->second.batch]); + } + reapSettleBatches(context, state); + rewatchSettledImports(state); +} #endif void decideImportWatch(const Context& context, HostImports& state) { @@ -1631,6 +1694,7 @@ const HostImport* importAllocation(const Context& context, HostImports& state, s ++counts.refused; counts.refusedBytes += lease[index]->bytes; ++counts.remembered; + ++state.budgetRefusals; return nullptr; } const auto bounds = importRunBounds(lease, address, largest, budget); @@ -1796,6 +1860,7 @@ const HostImport* importRunAt(const Context& context, HostImports& state, Import if (evict) state.evictingRefusals.insert_or_assign(std::pair{base, bytes}, EvictingRefusal{base, bytes, GuestAllocations::Mapped(run.ranges.begin(), run.ranges.end()), state.epoch, state.liveBytes, budget, room, importWindow.load(std::memory_order_relaxed), state.buildFloor, ready, readyHeld, joined}); if (stepDown && containing != run.ranges.end() && room >= (*containing)->bytes) return importAllocation(context, state, address, lease, requester, end, evict, std::min(bytes / 2, room)); if (containing != run.ranges.end() && run.ranges.size() > 1) remember((*containing)->address, (*containing)->bytes, GuestAllocations::Mapped{*containing}); + ++state.budgetRefusals; return nullptr; } for (auto it = first; it != state.imports.end() && it->first < base + bytes;) { @@ -1948,8 +2013,10 @@ const HostImport* importRunAt(const Context& context, HostImports& state, Import entry.joined = joined; entry.lastUse = ++state.useCounter; #ifdef _WIN32 - if (deferredSettles.load(std::memory_order_relaxed) && entry.alias == nullptr && state.watchPrivateImports && writable && base % settleBlockBytes == 0 && bytes % settleBlockBytes == 0) { - if (entry.unwatched) { + if (deferredSettles.load(std::memory_order_relaxed) && entry.alias == nullptr && state.watchPrivateImports && writable) { + if (base % settleBlockBytes != 0 || bytes % settleBlockBytes != 0) { + entry.settleOnDemand = entry.unwatched; + } else if (entry.unwatched) { state.pendingSettles.insert_or_assign(base, PendingSettle{}); state.settleWanted.push_back(base); } else if (settled && !GuestMemory::Watched(base, static_cast(bytes))) { @@ -2708,6 +2775,11 @@ bool importsNow(const Context& context, HostImports& state, const GuestAllocatio return context.hostImportAlignment != 0 && (importsStale(context, state) || importAllocation(context, state, address, lease, ImportRequester::Build, 0, false) != nullptr); } +const char* heapCopyReason(bool overBudget, bool watched) { + if (overBudget) return watched ? "import over the host import budget, heap mirror refused" : "import over the host import budget, heap not fully write-watched"; + return watched ? "heap mirror refused" : "heap not fully write-watched"; +} + // The mirror for a leased image range: the existing one, or a new one when none exists or the // registered Range object changed (a protection change). Null when the range cannot be mirrored. An // existing writable mirror's blocks are appended to `blocks` for the caller's one compare of every @@ -3235,7 +3307,8 @@ std::string AddressCopyOverflow(std::vector copies, std::uint64_t l std::string message = text; for (std::size_t index = 0; index < copies.size() && index < 8; ++index) { const auto& copy = copies[index]; - std::snprintf(text, sizeof(text), " 0x%llx+0x%llx (%.1f MiB committed, %s)", static_cast(copy.begin), static_cast(copy.end - copy.begin), copy.committed / 1048576.0, copy.reason); + const char* reason = copy.heap ? heapCopyReason(copy.overBudget, GuestMemory::Watched(copy.begin, copy.end - copy.begin)) : copy.reason; + std::snprintf(text, sizeof(text), " 0x%llx+0x%llx (%.1f MiB committed, %s)", static_cast(copy.begin), static_cast(copy.end - copy.begin), copy.committed / 1048576.0, reason); message += text; } return message; @@ -3716,6 +3789,22 @@ const HostImport* ExistingHostImportFor(const Context& context, std::uint64_t ad return findImport(state, address, address + bytes); } +bool WatchedAfterSettle(const Context& context, std::uint64_t address, std::size_t bytes) { +#ifdef _WIN32 + if (context.hostImportAlignment != 0 && bytes != 0 && bytes <= std::numeric_limits::max() - address && GuestMemory::GpuMutex().HeldByThisThread()) { + ensurePinWaiter(); + auto& state = Imports(); + std::lock_guard lock(state.mutex); + if (importsStale(context, state)) { + const auto lease = GuestAllocations::GuestAllocationsAcquire_nid_postfix(); + refreshImports(context, state, lease); + } + settleImportsNow(context, state, address, address + bytes); + } +#endif + return GuestMemory::Watched(address, bytes); +} + bool ImportMappedRanges(const Context& context, const GuestAllocations::Mapped& ranges, std::uint64_t generation, bool adoptDevice) { if (context.hostImportAlignment == 0) return true; ensurePinWaiter(); @@ -3925,16 +4014,24 @@ void GuestBufferMemory::AcquireRegistered() { // The import lock is taken per range: a mirror's preparation may wait for recorded work, which // must not happen under it. regions.reserve(lease.size()); + static const std::uint64_t copyLimit = [] { + const char* value = std::getenv("APS5_ADDRESS_COPY_MAX_MIB"); + return (value ? std::strtoull(value, nullptr, 10) : 64ull) << 20u; + }(); + const auto copyOverride = addressCopyLimitOverride.load(std::memory_order_relaxed); + const auto cap = copyOverride != 0 ? copyOverride : copyLimit; std::vector copies; std::vector> imported; const HostImport* covering = nullptr; std::uint64_t coveredBegin = 0; std::uint64_t coveredEnd = 0; + std::uint64_t copiedBytes = 0; for (const auto& range : lease) { if (!range->readable || !range->gpu) continue; validate(range->address, range->bytes); Region region{range->address, range->address + range->bytes, range->writable, {}, nullptr}; const HostImport* entry = nullptr; + bool overBudget = false; std::vector pieces; const auto limit = importMaxBytes.load(std::memory_order_relaxed); if (importable && covering != nullptr && range->address >= coveredBegin && range->address + range->bytes <= coveredEnd) { @@ -3946,7 +4043,9 @@ void GuestBufferMemory::AcquireRegistered() { } else if (importable) { auto& state = Imports(); std::lock_guard lock(state.mutex); + const auto refusals = state.budgetRefusals; entry = importAllocation(context, state, range->address, lease, ImportRequester::Build, 0, false); + overBudget = state.budgetRefusals != refusals; covering = entry; if (entry != nullptr) { coveredBegin = entry->base; @@ -4012,17 +4111,36 @@ void GuestBufferMemory::AcquireRegistered() { committed = 0; for (const auto& [first, last] : copied.backed) committed += last - first; } - const char* reason = !mirrorsEnabled() ? "mirrors disabled by APS5_NO_LEASE_MIRROR" : copied.sparse ? "unreadable pages" : !range->releasable ? "image mirror refused" : "outside the write-watched arena"; - copies.push_back({copied.begin, copied.end, committed, reason}); + if (overBudget && copiedBytes + committed > cap) { + auto& state = Imports(); + std::lock_guard lock(state.mutex); + entry = importAllocation(context, state, range->address, lease, ImportRequester::Build, 0, true); + if (entry != nullptr) { + covering = entry; + coveredBegin = entry->base; + coveredEnd = entry->base + entry->bytes; + } + static auto lastReport = std::chrono::steady_clock::now() - std::chrono::seconds(60); + if (entry != nullptr && std::chrono::steady_clock::now() - lastReport > std::chrono::seconds(10)) { + lastReport = std::chrono::steady_clock::now(); + std::fprintf(stderr, "[gpu] host import budget: 0x%llx+0x%llx imported by evicting idle imports, as copying it would pass APS5_ADDRESS_COPY_MAX_MIB\n", static_cast(range->address), static_cast(range->bytes)); + } + } + if (entry != nullptr) { + regions.pop_back(); + region.hostBacked = true; + region.direct = entry; + regions.push_back(std::move(region)); + imported.emplace_back(range->address, range->address + range->bytes); + continue; + } + copiedBytes += committed; + const char* reason = !mirrorsEnabled() ? "mirrors disabled by APS5_NO_LEASE_MIRROR" : copied.sparse ? "unreadable pages" : !range->releasable ? "image mirror refused" : nullptr; + copies.push_back({copied.begin, copied.end, committed, reason, reason == nullptr, overBudget}); } releaseImportedMirrors(context, imported); regionsSorted = sortedLookup; - static const std::uint64_t copyLimit = [] { - const char* value = std::getenv("APS5_ADDRESS_COPY_MAX_MIB"); - return (value ? std::strtoull(value, nullptr, 10) : 64ull) << 20u; - }(); - const auto limit = addressCopyLimitOverride.load(std::memory_order_relaxed); - if (const auto overflow = AddressCopyOverflow(std::move(copies), limit != 0 ? limit : copyLimit); !overflow.empty()) { + if (const auto overflow = AddressCopyOverflow(std::move(copies), cap); !overflow.empty()) { std::fprintf(stderr, "FATAL: %s\n", overflow.c_str()); std::fflush(stderr); std::abort(); @@ -4462,6 +4580,7 @@ VkBufferUsageFlags gpuCopyUsage(bool addressable) { // window takes those elements there. APS5_ATOMIC_STAGE_MAX_KIB (1024) bounds the atomic one. constexpr std::uint64_t SweptShadowMax = std::uint64_t{16} << 20u; constexpr std::uint64_t DiscreteWrittenShadowMax = std::uint64_t{8} << 20u; +constexpr std::uint64_t DiscreteSweptShadowMax = std::uint64_t{256} << 20u; bool writtenShadowEnabled() { static const bool disabled = std::getenv("APS5_NO_WRITTEN_SHADOW") != nullptr; @@ -4604,7 +4723,7 @@ bool GuestBufferMemory::stagingEligible(const Region& region, bool addressable) const auto bytes = region.end - region.begin; if (!WritesOverlap(region.begin, static_cast(bytes))) return false; if (region.atomic && atomicStagingEnabled() && bytes <= atomicStageMax()) return true; - return writtenShadowEnabled() && bytes >= writtenShadowMin() && bytes <= (region.swept ? std::max(writtenShadowMax(context.discreteGpu), SweptShadowMax) : writtenShadowMax(context.discreteGpu)); + return writtenShadowEnabled() && bytes >= writtenShadowMin() && bytes <= (region.swept ? std::max(writtenShadowMax(context.discreteGpu), context.discreteGpu ? DiscreteSweptShadowMax : SweptShadowMax) : writtenShadowMax(context.discreteGpu)); } bool GuestBufferMemory::overlayCandidate(const Region& inside, bool readOnly) const { diff --git a/core/libs/prx/libSceAgcDriver/Graphics/src/MultisampleTarget.cpp b/core/libs/prx/libSceAgcDriver/Graphics/src/MultisampleTarget.cpp index 0520466262..b4759d8ee0 100644 --- a/core/libs/prx/libSceAgcDriver/Graphics/src/MultisampleTarget.cpp +++ b/core/libs/prx/libSceAgcDriver/Graphics/src/MultisampleTarget.cpp @@ -4,6 +4,7 @@ #include "prx/libSceAgcDriver/Graphics/include/DepthSurface.hpp" #include "prx/libSceAgcDriver/Graphics/include/FirstSampleCopy.hpp" #include "prx/libSceAgcDriver/Graphics/include/BufferPool.hpp" +#include "prx/libSceAgcDriver/Graphics/include/GuestBufferMemory.hpp" #include "prx/libSceAgcDriver/Graphics/include/Pipeline.hpp" #include "prx/libSceAgcDriver/Graphics/include/Recorder.hpp" #include "prx/libSceAgcDriver/Graphics/include/Resources.hpp" @@ -500,6 +501,7 @@ public: Context context; std::shared_ptr> active = std::make_shared>(true); + std::shared_ptr> hostOnly = std::make_shared>(true); std::shared_ptr> metadataValid; ColorTarget target; VkImage image = VK_NULL_HANDLE; @@ -574,7 +576,7 @@ private: if (use.cmaskAddress != 0) dccRanges.push_back({use.cmaskAddress, use.cmaskBytes, 0}); for (auto& range : dccRanges) { GuestMemory::CheckRange(reinterpret_cast(range.address), range.bytes, 256); - Require(GuestMemory::Watched(range.address, range.bytes), "initial multisampled DCC contents require watched guest memory"); + Require(WatchedAfterSettle(context, range.address, range.bytes), "initial multisampled DCC contents require watched guest memory"); range.generation = collectBlocks(range.address, range.bytes); Require(range.generation != 0, "initial multisampled DCC contents have no write generation"); } @@ -591,7 +593,7 @@ private: fmaskRange = GuestMemory::UnchangedQuery{use.fmaskAddress, static_cast(DescribeSurface(resource).guestBytes), 0}; auto& range = *fmaskRange; GuestMemory::CheckRange(reinterpret_cast(range.address), range.bytes, 65536u); - Require(GuestMemory::Watched(range.address, range.bytes), "native FMASK contents require watched guest memory"); + Require(WatchedAfterSettle(context, range.address, range.bytes), "native FMASK contents require watched guest memory"); range.generation = GuestMemory::CollectWritesUncached(range.address, range.bytes); Require(range.generation != 0, "native FMASK contents have no write generation"); for (const auto& other : dccRanges) Require(range.address >= other.address + other.bytes || other.address >= range.address + range.bytes, "native FMASK overlaps its color or metadata planes"); @@ -631,7 +633,7 @@ private: if (fmaskRange) { Require(use.fmaskAddress == target.fmaskAddress && use.fmaskPipeBankXor == target.fmaskPipeBankXor, "native FMASK target layout changed"); const auto& range = *fmaskRange; - requireDccRange(GuestMemory::Watched(range.address, range.bytes), range, "native FMASK sampling requires watched guest memory"); + requireDccRange(WatchedAfterSettle(context, range.address, range.bytes), range, "native FMASK sampling requires watched guest memory"); GuestMemory::CollectWritesUncached(range.address, range.bytes); requireDccRange(GuestMemory::UnchangedSince(range.address, range.bytes, range.generation) || !GuestMemory::StoredOver(range.address, range.bytes, range.generation), range, "writes to a resident native FMASK are not implemented"); if (auto* recorder = Recorder::Active(); recorder != nullptr) requireDccRange(!recorder->PendingWriteOverlaps(range.address, range.bytes), range, "pending writes to a resident native FMASK are not implemented"); @@ -660,6 +662,7 @@ struct GuardedRange { std::uint32_t samples; std::shared_ptr> active; std::shared_ptr> metadataValid; + std::shared_ptr> hostOnly; bool fmask = false; }; @@ -734,7 +737,7 @@ void retireUnmapped(std::uintptr_t address, std::size_t bytes) { anyGuarded().store(!guarded().empty(), std::memory_order_release); } -void guard(const Context& context, const ColorTarget& target, const std::shared_ptr>& active, const std::shared_ptr>& metadataValid) { +void guard(const Context& context, const ColorTarget& target, const std::shared_ptr>& active, const std::shared_ptr>& metadataValid, const std::shared_ptr>& hostOnly) { auto bytes = std::max(target.bytes * target.samples, static_cast(target.extent.width) * target.extent.height * target.elementBytes * target.samples); if (MultisampledBlockLog2(target.tileMode) == 16u && target.tileMode != ColorTileMode::Standard64KB && std::has_single_bit(target.elementBytes) && std::has_single_bit(target.samples)) { const auto log2Samples = std::countr_zero(target.samples); @@ -746,11 +749,11 @@ void guard(const Context& context, const ColorTarget& target, const std::shared_ bytes = align(target.extent.width, blockWidth) * align(target.extent.height, blockHeight) * target.elementBytes * target.samples; } std::unique_lock lock(guardedMutex()); - guarded().push_back({context.device, target.address, bytes, target.samples, active}); + guarded().push_back({context.device, target.address, bytes, target.samples, active, nullptr, hostOnly}); if (target.dccAddress != 0) { - guarded().push_back({context.device, target.dccAddress, MultisampledDccBytes(target), target.samples, active, metadataValid}); - if (target.cmaskAddress != 0) guarded().push_back({context.device, target.cmaskAddress, target.cmaskBytes, target.samples, active, metadataValid}); - if (target.samples == 8u && target.fmaskAddress != 0u && target.cmaskAddress != 0u) guarded().push_back({context.device, target.fmaskAddress, DescribeSurface(fmaskResource(target)).guestBytes, target.samples, active, metadataValid}); + guarded().push_back({context.device, target.dccAddress, MultisampledDccBytes(target), target.samples, active, metadataValid, hostOnly}); + if (target.cmaskAddress != 0) guarded().push_back({context.device, target.cmaskAddress, target.cmaskBytes, target.samples, active, metadataValid, hostOnly}); + if (target.samples == 8u && target.fmaskAddress != 0u && target.cmaskAddress != 0u) guarded().push_back({context.device, target.fmaskAddress, DescribeSurface(fmaskResource(target)).guestBytes, target.samples, active, metadataValid, hostOnly}); } anyGuarded().store(true, std::memory_order_release); InstallResidentImageReadGuard_nid_no_patch(); @@ -770,6 +773,13 @@ void discardRetiredTargets() { std::erase_if(targets(), [](const auto& target) { return !target->active->load(std::memory_order_acquire); }); } +bool holdHostOnly(const MultisampleTarget& target) { + std::unique_lock lock(guardedMutex()); + if (!target.active->load(std::memory_order_acquire)) return false; + target.hostOnly->store(true, std::memory_order_release); + return true; +} + MultisampleTarget& acquire(const Context& context, const ColorTarget& requested) { discardRetiredTargets(); for (const auto& target : targets()) { @@ -780,14 +790,21 @@ MultisampleTarget& acquire(const Context& context, const ColorTarget& requested) if (recreated(target->target, use)) { { std::unique_lock lock(guardedMutex()); + if (!target->active->load(std::memory_order_acquire)) continue; std::erase_if(guarded(), [&](const auto& range) { return range.active == target->active; }); anyGuarded().store(!guarded().empty(), std::memory_order_release); } target->Recreate(use); - guard(context, use, target->active, target->metadataValid); + target->hostOnly->store(true, std::memory_order_release); + guard(context, use, target->active, target->metadataValid, target->hostOnly); target->ApplyFastClear(use); return *target; } + { + std::unique_lock lock(guardedMutex()); + if (!target->active->load(std::memory_order_acquire)) continue; + target->hostOnly->store(true, std::memory_order_release); + } if (target->fromTexture && use.cmaskAddress != 0) { target->fromTexture = false; target->cmask = MultisampledCmask(use.cmaskAddress, use.cmaskBytes); @@ -803,14 +820,14 @@ MultisampleTarget& acquire(const Context& context, const ColorTarget& requested) target->Keep(); targets().push_back(std::move(target)); auto& created = *targets().back(); - guard(context, use, created.active, created.metadataValid); + guard(context, use, created.active, created.metadataValid, created.hostOnly); if (use.cmaskFastClear && use.dccAddress == 0) created.cmask.SeedCode(CurrentUniformMetadataByte(use.cmaskAddress, static_cast(use.cmaskBytes))); created.ApplyFastClear(use); created.Keep(); return created; } -MultisampleTarget& createFilled(const Context& context, const GuestTextureResource& resource, VkFormat format, const char* access) { +MultisampleTarget& createFilled(const Context& context, const GuestTextureResource& resource, VkFormat format, const char* access, bool written) { const auto refuse = [&](const std::string& reason) { char text[192]; std::snprintf(text, sizeof(text), "AGC graphics: %s the %ux%u multisampled texture 0x%llx of %u samples, which no draw rendered to and ", access, resource.width, resource.height, static_cast(resource.baseAddress), resource.samples); @@ -877,7 +894,8 @@ MultisampleTarget& createFilled(const Context& context, const GuestTextureResour target->Keep(); targets().push_back(std::move(target)); auto& created = *targets().back(); - guard(context, use, created.active, created.metadataValid); + created.hostOnly->store(written, std::memory_order_release); + guard(context, use, created.active, created.metadataValid, created.hostOnly); created.colorFill.NoteFill(use.address, static_cast(bytes), value); created.fromTexture = true; created.htileAddress = resource.dccAddress; @@ -1177,7 +1195,7 @@ std::shared_ptr MultisampleTargetTexture(const Context& context, const } if (other == nullptr) { Require(Recorder::Active() != nullptr, "a multisampled texture is only sampled by recorded draws and dispatches"); - return createFilled(context, resource, format, "sampling").Sampled(components, viewType); + return createFilled(context, resource, format, "sampling", false).Sampled(components, viewType); } char text[320]; std::snprintf(text, sizeof(text), "AGC graphics: sampling multisampled color target 0x%llx (%ux%u, %u samples, vk format %d) as a %ux%u texture of %u samples and guest format %u (vk %d) is not implemented", static_cast(resource.baseAddress), other->target.extent.width, other->target.extent.height, other->target.samples, static_cast(other->target.format), resource.width, resource.height, resource.samples, resource.format, static_cast(format)); @@ -1200,7 +1218,7 @@ std::shared_ptr MultisampleTargetFirstSample(const Context& context, co } if (other == nullptr) { Require(Recorder::Active() != nullptr, "a multisampled texture is only sampled by recorded draws and dispatches"); - return createFilled(context, resource, format, "sampling").FirstSample(components); + return createFilled(context, resource, format, "sampling", false).FirstSample(components); } char text[320]; std::snprintf(text, sizeof(text), "AGC graphics: reading sample 0 of multisampled color target 0x%llx (%ux%u, %u samples, vk format %d) as a %ux%u texture of %u samples and guest format %u (vk %d) is not implemented", static_cast(resource.baseAddress), other->target.extent.width, other->target.extent.height, other->target.samples, static_cast(other->target.format), resource.width, resource.height, resource.samples, resource.format, static_cast(format)); @@ -1221,12 +1239,15 @@ VkImageView MultisampleTargetStorageView(const Context& context, const GuestText if (!target->active->load(std::memory_order_acquire)) continue; if (target->context.device != context.device || target->target.surfaceAddress != resource.baseAddress) continue; const auto& rendered = target->target; - if (sameStorageForm(context, rendered.format, format) && rendered.extent.width == resource.width && rendered.extent.height == resource.height && rendered.samples == resource.samples && rendered.mip == 0) return target->Storage(StorageFormatForGuest(context, resource.format)); + if (sameStorageForm(context, rendered.format, format) && rendered.extent.width == resource.width && rendered.extent.height == resource.height && rendered.samples == resource.samples && rendered.mip == 0) { + if (!holdHostOnly(*target)) continue; + return target->Storage(StorageFormatForGuest(context, resource.format)); + } other = target.get(); } if (other == nullptr) { Require(Recorder::Active() != nullptr, "a multisampled color target is only written by recorded dispatches"); - return createFilled(context, resource, format, "writing").Storage(StorageFormatForGuest(context, resource.format)); + return createFilled(context, resource, format, "writing", true).Storage(StorageFormatForGuest(context, resource.format)); } char text[320]; std::snprintf(text, sizeof(text), "AGC graphics: storage image access to multisampled color target 0x%llx (%ux%u, %u samples, vk format %d) as a %ux%u texture of %u samples and guest format %u (vk %d) is not implemented", static_cast(resource.baseAddress), other->target.extent.width, other->target.extent.height, other->target.samples, static_cast(other->target.format), resource.width, resource.height, resource.samples, resource.format, static_cast(format)); @@ -1266,10 +1287,13 @@ void ResolveMultisampleTarget(const Context& context, const ColorTarget& source, bool MultisampledColorFillAbsorbs(std::uint64_t address, std::size_t bytes, std::uint32_t pattern) { if (bytes == 0) return false; std::lock_guard lock(targetsMutex()); - return std::any_of(targets().begin(), targets().end(), [&](const auto& target) { + bool absorbed = false; + for (const auto& target : targets()) { VkClearColorValue clear{}; - return target->active->load(std::memory_order_acquire) && target->target.address == address && MultisampledColorBytes(target->target) == bytes && MultisampledFillClearColor(target->target, pattern, clear); - }); + if (!target->active->load(std::memory_order_acquire) || target->target.address != address || MultisampledColorBytes(target->target) != bytes || !MultisampledFillClearColor(target->target, pattern, clear)) continue; + absorbed = holdHostOnly(*target) || absorbed; + } + return absorbed; } void NoteColorMetadataFill(std::uint64_t address, std::size_t bytes, std::uint32_t pattern) { @@ -1327,7 +1351,7 @@ void GuardOneFragmentFmask(const Context& context, const ColorTarget& target) { const auto bytes = std::max((bits / 8u + 0xffffu) & ~0xffffull, 0x10000u); std::unique_lock lock(guardedMutex()); const bool known = std::ranges::any_of(guarded(), [&](const auto& range) { return range.fmask && range.device == context.device && range.address == target.fmaskAddress && range.bytes == bytes; }); - if (!known) guarded().push_back({context.device, target.fmaskAddress, bytes, target.coverageSamples, std::make_shared>(true), nullptr, true}); + if (!known) guarded().push_back({context.device, target.fmaskAddress, bytes, target.coverageSamples, std::make_shared>(true), nullptr, std::make_shared>(true), true}); anyGuarded().store(true, std::memory_order_release); lock.unlock(); InstallResidentImageReadGuard_nid_no_patch(); @@ -1340,9 +1364,8 @@ void RequireNoMultisampleTarget(std::uint64_t address, std::size_t bytes, const void RequireNoMultisampleColorTarget(std::uint64_t address, std::size_t bytes, const char* access) { if (bytes == 0 || !anyGuarded().load(std::memory_order_acquire)) return; - std::shared_lock lock(guardedMutex()); - for (const auto& range : guarded()) { - if (address >= range.address + range.bytes || range.address >= address + bytes) continue; + const auto overlaps = [&](const GuardedRange& range) { return address < range.address + range.bytes && range.address < address + bytes; }; + const auto refuse = [&](const GuardedRange& range) { char text[256]; if (range.fmask) { std::snprintf(text, sizeof(text), "AGC graphics: %s of 0x%llx+0x%zx overlaps the FMASK 0x%llx+0x%llx of a one-fragment color target of %u samples drawn on the host, which does not write it: guest access to it is not implemented", access, static_cast(address), bytes, static_cast(range.address), static_cast(range.bytes), range.samples); @@ -1350,7 +1373,27 @@ void RequireNoMultisampleColorTarget(std::uint64_t address, std::size_t bytes, c } std::snprintf(text, sizeof(text), "AGC graphics: %s of 0x%llx+0x%zx overlaps multisampled color target 0x%llx+0x%llx (%u samples), whose samples are only on the host: guest access to it is not implemented", access, static_cast(address), bytes, static_cast(range.address), static_cast(range.bytes), range.samples); throw std::runtime_error(text); + }; + { + std::shared_lock lock(guardedMutex()); + bool retirable = false; + for (const auto& range : guarded()) { + if (!overlaps(range)) continue; + if (range.hostOnly->load(std::memory_order_acquire)) refuse(range); + retirable = true; + } + if (!retirable) return; } + std::unique_lock lock(guardedMutex()); + std::vector>> retired; + for (const auto& range : guarded()) { + if (!overlaps(range)) continue; + if (range.hostOnly->load(std::memory_order_acquire)) refuse(range); + retired.push_back(range.active); + } + for (const auto& active : retired) active->store(false, std::memory_order_release); + std::erase_if(guarded(), [&](const auto& range) { return std::find(retired.begin(), retired.end(), range.active) != retired.end(); }); + anyGuarded().store(!guarded().empty(), std::memory_order_release); } } diff --git a/core/libs/prx/libSceAgcDriver/Graphics/src/Pipeline.cpp b/core/libs/prx/libSceAgcDriver/Graphics/src/Pipeline.cpp index fcad4ff7bf..8ce59dade1 100644 --- a/core/libs/prx/libSceAgcDriver/Graphics/src/Pipeline.cpp +++ b/core/libs/prx/libSceAgcDriver/Graphics/src/Pipeline.cpp @@ -321,7 +321,7 @@ void appendKey(std::vector& key, const TValue& value) { bool libraryKeys(PipelineLibraryKeys& keys, const Context& context, const State& state, const VertexInputLayout& input, const PipelineSetLayouts& resources, std::span shaders) { using Stage = ShaderRecompiler::ShaderStage; - if (!context.graphicsPipelineLibrary || context.pipelineExecutableInfo || state.depthBiasPerFace || state.rectList || BarycentricPatches(state, shaders) || SplitsAlternateAlpha(state) || std::ranges::any_of(shaders, [](const CompiledShader& shader) { return shader.program != nullptr && shader.program->functionLdsBuffer; }) || FragmentInterlock(shaders)) return false; + if (!context.graphicsPipelineLibrary || context.pipelineExecutableInfo || (state.stages.tessellation && !context.tessellationPipelineCache) || state.depthBiasPerFace || state.rectList || BarycentricPatches(state, shaders) || SplitsAlternateAlpha(state) || std::ranges::any_of(shaders, [](const CompiledShader& shader) { return shader.program != nullptr && shader.program->functionLdsBuffer; }) || FragmentInterlock(shaders)) return false; keys = {}; for (const auto& shader : shaders) { const auto identity = shader.program->Identity(); @@ -723,20 +723,21 @@ Pipeline::Pipeline(const Context& context, const State& state, const VertexInput prebuilt = true; return; } + const VkPipelineCache pipelineCache = state.stages.tessellation && !context.tessellationPipelineCache ? VK_NULL_HANDLE : context.pipelineCache; if (libraries) pipeline = LinkPipelineFromLibraries(context, pipelineInfo, rendering, layoutInfo, keys, &optimized, false, _modules); else { auto pipelineCacheLock = context.LockPipelineCacheForUse(); - Check(context.Function("vkCreateGraphicsPipelines")(context.device, context.pipelineCache, 1, &pipelineInfo, nullptr, &pipeline), "vkCreateGraphicsPipelines"); + Check(context.Function("vkCreateGraphicsPipelines")(context.device, pipelineCache, 1, &pipelineInfo, nullptr, &pipeline), "vkCreateGraphicsPipelines"); } if (alternateAlpha) { blend.pAttachments = secondChannels.data(); auto pipelineCacheLock = context.LockPipelineCacheForUse(); - Check(context.Function("vkCreateGraphicsPipelines")(context.device, context.pipelineCache, 1, &pipelineInfo, nullptr, &secondChannel), "vkCreateGraphicsPipelines"); + Check(context.Function("vkCreateGraphicsPipelines")(context.device, pipelineCache, 1, &pipelineInfo, nullptr, &secondChannel), "vkCreateGraphicsPipelines"); } if (state.depthBiasPerFace) { raster.cullMode = VK_CULL_MODE_FRONT_BIT; auto pipelineCacheLock = context.LockPipelineCacheForUse(); - Check(context.Function("vkCreateGraphicsPipelines")(context.device, context.pipelineCache, 1, &pipelineInfo, nullptr, &backFaces), "vkCreateGraphicsPipelines"); + Check(context.Function("vkCreateGraphicsPipelines")(context.device, pipelineCache, 1, &pipelineInfo, nullptr, &backFaces), "vkCreateGraphicsPipelines"); } for (const auto module : _modules) context.Function("vkDestroyShaderModule")(context.device, module, nullptr); _modules.clear(); diff --git a/core/libs/prx/libSceAgcDriver/Graphics/src/PipelineJournal.cpp b/core/libs/prx/libSceAgcDriver/Graphics/src/PipelineJournal.cpp index 7eba2c79ac..9e2f8a97ce 100644 --- a/core/libs/prx/libSceAgcDriver/Graphics/src/PipelineJournal.cpp +++ b/core/libs/prx/libSceAgcDriver/Graphics/src/PipelineJournal.cpp @@ -38,7 +38,7 @@ static_assert(sizeof(VkStencilOpState) == 28, "VkStencilOpState changed: update static_assert(sizeof(VkVertexInputBindingDescription) == 12, "VkVertexInputBindingDescription changed: update the recipe codec"); static_assert(sizeof(VkVertexInputAttributeDescription) == 16, "VkVertexInputAttributeDescription changed: update the recipe codec"); #if defined(__linux__) && defined(__x86_64__) && defined(__GLIBCXX__) -static_assert(sizeof(State) == 832, "State changed: update CanonicalPipelineState and the recipe codec"); +static_assert(sizeof(State) == 840, "State changed: update CanonicalPipelineState and the recipe codec"); static_assert(sizeof(ShaderStages) == 112, "ShaderStages changed: update the recipe codec"); static_assert(sizeof(ShaderRecompiler::MeshConfiguration) == 40, "MeshConfiguration changed: update the recipe codec"); static_assert(sizeof(ShaderRecompiler::TessellationConfiguration) == 40, "TessellationConfiguration changed: update the recipe codec"); @@ -1346,6 +1346,9 @@ public: private: void run() { +#ifdef _WIN32 + if (!SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL)) std::fprintf(stderr, "[pipeline-journal] replay thread priority not lowered (error %lu)\n", GetLastError()); +#endif std::call_once(loadOnce, [&] { try { auto journal = Journal::Instance().Load(); diff --git a/core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp b/core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp index 84bc841971..f73b2c2b0e 100644 --- a/core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp +++ b/core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp @@ -2445,7 +2445,7 @@ void ShaderResources::buildComplete() { for (auto element = first; element < last; ++element) { const auto index = binding.imageAllocations[element]; if (binding.layout.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER) images.push_back({samplers[index]->Handle(), VK_NULL_HANDLE, VK_IMAGE_LAYOUT_UNDEFINED}); - else if (binding.layout.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) images.push_back({VK_NULL_HANDLE, storageAtomic[index] ? storageTextures[index]->AtomicView(storageMips[index], storageFirstLayer[index]) : storageTextures[index]->StorageView(storageMips[index], storageFirstLayer[index]), VK_IMAGE_LAYOUT_GENERAL}); + else if (binding.layout.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) images.push_back({VK_NULL_HANDLE, storageAtomic64[index] ? storageTextures[index]->Atomic64View(storageMips[index], storageFirstLayer[index]) : storageAtomic[index] ? storageTextures[index]->AtomicView(storageMips[index], storageFirstLayer[index]) : storageTextures[index]->StorageView(storageMips[index], storageFirstLayer[index]), VK_IMAGE_LAYOUT_GENERAL}); else images.push_back({VK_NULL_HANDLE, textureFirstLayer[index] ? textures[index]->FirstLayerView() : textures[index]->View(), textures[index]->Layout()}); } if (recorded) runs.emplace_back(write.dstArrayElement, write.descriptorCount); @@ -4384,7 +4384,8 @@ std::size_t ShaderResources::addGuestBuffer(std::span words Require(!written || !overlap(address, size, indexAddress, indexBytes), "writable shader buffer aliases the index buffer"); written = written || allWritten; const std::uint64_t recordBytes = descriptor.Stride() != 0 ? descriptor.Stride() : extent; - const bool swept = read && dispatchThreads != 0 && recordBytes != 0 && dispatchThreads * recordBytes * 2u >= byteSize; + constexpr std::uint64_t WidestBufferStoreBytes = 16; + const bool swept = (read || (context.discreteGpu && descriptor.Stride() > WidestBufferStoreBytes)) && dispatchThreads != 0 && recordBytes != 0 && dispatchThreads * recordBytes * 2u >= byteSize; if (written) guestMemory.AddWritable(address, size, atomic, swept); else { guestMemory.AddReadable(address, size); @@ -4492,12 +4493,11 @@ std::uint64_t ShaderResources::DataWordsHash(const CompiledShader& shader) { bool ShaderResources::DataWordsDiffer(const CompiledShader& shader) const { Require(shader.program != nullptr, "missing compiled shader"); const auto& program = *shader.program; - if (program.bindings.size() != bindings.size()) return true; - for (std::size_t index = 0; index < program.bindings.size(); ++index) { - const auto& binding = program.bindings[index]; + for (const auto& binding : program.bindings) { if (!DataRole(binding.role)) continue; - if (bindings[index].allocations.size() != 1) return true; - const auto& allocation = allocations[bindings[index].allocations.front()]; + const auto held = std::ranges::find_if(bindings, [&](const Binding& candidate) { return candidate.layout.binding == binding.binding; }); + if (held == bindings.end() || held->allocations.size() != 1) return true; + const auto& allocation = allocations[held->allocations.front()]; if (allocation.dataWords.size() != binding.guestDescriptor.size() || !std::equal(allocation.dataWords.begin(), allocation.dataWords.end(), binding.guestDescriptor.begin())) return true; } return false; @@ -4512,23 +4512,23 @@ bool ShaderResources::RefreshData(VkCommandBuffer commands, const CompiledShader bool ShaderResources::refreshData(VkCommandBuffer commands, const CompiledShader& shader, Recorder* recorder) { Require(shader.program != nullptr, "missing compiled shader"); const auto& program = *shader.program; - Require(program.bindings.size() == bindings.size(), "template bindings disagree with the shader"); bool recorded = false; // One [gputime] range of class TemplateDataRefresh around the updates, begun at the first one // (a refresh that finds every word equal records nothing and times nothing). auto timing = Recorder::NoTiming; std::uint64_t refreshedBytes = 0; - for (std::size_t index = 0; index < program.bindings.size(); ++index) { - const auto& binding = program.bindings[index]; + for (const auto& binding : program.bindings) { if (!DataRole(binding.role)) continue; - Require(bindings[index].allocations.size() == 1, "data binding without its buffer"); - auto& allocation = allocations[bindings[index].allocations.front()]; + const auto held = std::ranges::find_if(bindings, [&](const Binding& candidate) { return candidate.layout.binding == binding.binding; }); + Require(held != bindings.end(), "template bindings disagree with the shader"); + Require(held->allocations.size() == 1, "data binding without its buffer"); + auto& allocation = allocations[held->allocations.front()]; const auto size = binding.guestDescriptor.size() * sizeof(std::uint32_t); Require(allocation.buffer != nullptr && !allocation.guest && allocation.size == size && size <= MaxRefreshBytes, "template data buffer cannot take the dispatch's words"); if (allocation.dataWords.size() == binding.guestDescriptor.size() && std::equal(allocation.dataWords.begin(), allocation.dataWords.end(), binding.guestDescriptor.begin())) continue; if (binding.role == ShaderRecompiler::DescriptorRole::ShaderData) ValidateRuntimeResources(shader, binding.guestDescriptor); if (recorder != nullptr && timing == Recorder::NoTiming) timing = recorder->BeginGpuTiming(Recorder::CommandClass::TemplateDataRefresh); - writeDataWords(commands, bindings[index].allocations.front(), binding.guestDescriptor); + writeDataWords(commands, held->allocations.front(), binding.guestDescriptor); allocation.dataWords.assign(binding.guestDescriptor.begin(), binding.guestDescriptor.end()); refreshedBytes += size; recorded = true; @@ -5227,7 +5227,7 @@ void ShaderResources::resolveImageTables() { storageFirstLayer.push_back(firstLayer); storageWritten.push_back(true); storageAtomic.push_back(element < binding.imageAtomic.size() && binding.imageAtomic[element]); - storageAtomic64.push_back(false); + storageAtomic64.push_back(element < binding.imageAtomic64.size() && binding.imageAtomic64[element]); describedRanges.push_back({"storage", resource.baseAddress, guestBytes, resource.width, resource.height, resource.format, static_cast(resource.tileMode), resource.dccAddress, true}); bindings[storageBinding].imageAllocations[absolute] = storageTextures.size() - 1u; continue; diff --git a/core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp b/core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp index de94232f92..da78c29b18 100644 --- a/core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp +++ b/core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp @@ -1912,7 +1912,7 @@ GuestTextureResource SurfaceForTarget(const ColorTarget& color) { surface.dstSelY = 5; surface.dstSelZ = 6; surface.dstSelW = 7; - surface.dccAddress = color.dccAddress; + surface.dccAddress = color.dccAddress != 0 ? color.dccAddress : color.chainDccAddress; surface.dccAlphaOnMsb = color.dccAlphaOnMsb; surface.dccPipeAligned = color.dccPipeAligned; return surface; @@ -2081,9 +2081,10 @@ ColorTarget DecodeColorBuffer(const Registers& cx, std::uint32_t slot, bool allo Require(color.fmaskAddress != 0, "a compressed one-fragment color target without an FMASK address is unsupported"); } if ((info & 0x10000000u) != 0) { + const auto dccHigh = find(cx, 0x3a8 + slot); + const auto dccBase = ((dccHigh == cx.end() ? 0ull : static_cast(dccHigh->second & 0xffu)) << 40u) | (static_cast(read(cx, 0x325 + stride)) << 8u); if (maxMip == 0) { - const auto dccHigh = find(cx, 0x3a8 + slot); - color.dccAddress = ((dccHigh == cx.end() ? 0ull : static_cast(dccHigh->second & 0xffu)) << 40u) | (static_cast(read(cx, 0x325 + stride)) << 8u); + color.dccAddress = dccBase; color.dccAlphaOnMsb = DccAlphaOnMsb(color.format, swap); color.dccPipeAligned = ((attrib3 >> 30u) & 1u) != 0; if (color.samples > 1) { @@ -2091,11 +2092,15 @@ ColorTarget DecodeColorBuffer(const Registers& cx, std::uint32_t slot, bool allo color.dccControl = read(cx, 0x31e + stride); if (!allowMultisampleDcc) Require((color.dccControl & 0x3ff80u) == 0, "multisampled DCC color transforms or lossy modes are not implemented"); } + } else if (!volume && color.arrayLastSlice == 0 && slice == 0) { + color.chainDccAddress = dccBase; + color.dccAlphaOnMsb = DccAlphaOnMsb(color.format, swap); + color.dccPipeAligned = ((attrib3 >> 30u) & 1u) != 0; } else { static bool reported = false; if (!reported) { reported = true; - std::fprintf(stderr, "[gpu] DCC keys of mipmapped color targets are ignored\n"); + std::fprintf(stderr, "[gpu] DCC keys of mipmapped array and 3D color targets are ignored\n"); } } } diff --git a/core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp b/core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp index d8394b6c5e..5db5738ced 100644 --- a/core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp +++ b/core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp @@ -3914,6 +3914,18 @@ void waitForIdlePublish(const char* reason) { bool StorageTexture::FlushPending(std::uint64_t address, std::size_t bytes, const StorageTexture* except, const char* reason, PublishScope scope, bool* published, bool waited) { static_cast(FlushDepthPlanes(address, bytes)); if (published != nullptr) *published = false; + const auto nothingToStore = [&] { + auto& pending = Pending(); + if (pending.flushingCount.load(std::memory_order_acquire) != 0) return false; + if (!pending.textures.SurelyClear(address, bytes)) { + std::lock_guard lock(pending.mutex); + const auto* exempt = refreshing; + if (pending.textures.MayOverlap(address, bytes) && std::any_of(pending.textures.begin(), pending.textures.end(), [&](const StorageTexture* texture) { return texture != except && texture != exempt && texture->overlaps(address, bytes) && texture->pendingUnitInside(address, bytes); })) return false; + if (pending.flushingCount.load(std::memory_order_acquire) != 0) return false; + } + return scope == PublishScope::None || !AnyShadowedOverlaps(address, bytes); + }; + if (nothingToStore()) return false; if (AgcDriver::DriverDetail::DrawPipeline::HeldReads(address, bytes)) { queuedReadHeld.fetch_add(1, std::memory_order_relaxed); return false; diff --git a/core/libs/prx/libSceAgcDriver/Resource/include/Lifecycle.hpp b/core/libs/prx/libSceAgcDriver/Resource/include/Lifecycle.hpp index d2485e8727..8d49017a87 100644 --- a/core/libs/prx/libSceAgcDriver/Resource/include/Lifecycle.hpp +++ b/core/libs/prx/libSceAgcDriver/Resource/include/Lifecycle.hpp @@ -1,4 +1,13 @@ #ifndef CORE_LIBS_PRX_LIBSCEAGCDRIVER_RESOURCE_INCLUDE_LIFECYCLE_HPP #define CORE_LIBS_PRX_LIBSCEAGCDRIVER_RESOURCE_INCLUDE_LIFECYCLE_HPP +#include "SceTypes.hpp" + +extern "C" { + +uint32_t APS5_VABI sceAgcDriverInitResourceRegistration(void); +uint32_t APS5_VABI sceAgcDriverQueryResourceRegistrationUserMemoryRequirements(uint64_t* sizeInBytes); + +} + #endif diff --git a/core/libs/prx/libSceAgcDriver/Resource/include/Registration.hpp b/core/libs/prx/libSceAgcDriver/Resource/include/Registration.hpp index d30f27839a..6cbdcce863 100644 --- a/core/libs/prx/libSceAgcDriver/Resource/include/Registration.hpp +++ b/core/libs/prx/libSceAgcDriver/Resource/include/Registration.hpp @@ -5,4 +5,33 @@ extern "C" bool AgcDriverWorkloadStreamRegistered_nid_postfix(std::uint32_t streamId); +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceAgcDriverRegisterOwner(uint32_t* ownerHandle, const char* name); +int APS5_VABI sceAgcDriverRegisterResource(uint32_t* resourceHandle, uint32_t ownerHandle, const void* memory, size_t size, const char* name, uint32_t type, uint64_t userData); +int APS5_VABI sceAgcDriverRegisterMultipleResources(uint32_t* resourceHandle, uint32_t ownerHandle, const void* resources, uint32_t resourceCount); +int APS5_VABI sceAgcDriverRegisterWorkloadStream(uint32_t streamId, const void* stream); +int APS5_VABI sceAgcDriverUnregisterOwnerAndResources(uint32_t ownerHandle); +int APS5_VABI sceAgcDriverUnregisterResource(uint32_t resourceHandle); +int APS5_VABI sceAgcDriverRegisterGdsResource(uint32_t* resourceHandle, uint32_t ownerHandle, uint32_t gdsOffset, uint32_t gdsSize, const char* name, uint32_t type, uint64_t userData); +int APS5_VABI sceAgcDriverUnregisterAllResourcesForOwner(uint32_t ownerHandle); +int APS5_VABI sceAgcDriverUnregisterWorkloadStream(uint32_t streamId); +int APS5_VABI sceAgcDriverGetDefaultOwner(uint32_t* ownerHandle); +int APS5_VABI sceAgcDriverGetResourceRegistrationMaxNameLength(uint32_t* maxLength); +int APS5_VABI sceAgcDriverGetOwnerName(uint32_t ownerHandle, const char** name); +int APS5_VABI sceAgcDriverGetResourceName(uint32_t resourceHandle, const char** name); +int APS5_VABI sceAgcDriverGetResourceType(uint32_t resourceHandle, uint32_t* type); +int APS5_VABI sceAgcDriverGetResourceUserData(uint32_t resourceHandle, uint64_t* userData); +int APS5_VABI sceAgcDriverSetResourceUserData(uint32_t resourceHandle, uint64_t userData); +int APS5_VABI sceAgcDriverGetResourceBaseAddressAndSizeInBytes(uint32_t resourceHandle, void** memory, size_t* size); +int APS5_VABI sceAgcDriverGetResourceShaderGuid(uint32_t resourceHandle, void* guid); +int APS5_VABI sceAgcDriverFindResourcesPublic(const void* callback, void* userData); +int APS5_VABI sceAgcDriverRegisterOwnerForSystem(); +int APS5_VABI sceAgcDriverInitResourceRegistrationInterface(); +int APS5_VABI sceAgcDriverSetResourceRegistrationInfo(); + +} + #endif diff --git a/core/libs/prx/libSceAgcDriver/State/include/Configuration.hpp b/core/libs/prx/libSceAgcDriver/State/include/Configuration.hpp index aadd076ce7..54c8fc2cca 100644 --- a/core/libs/prx/libSceAgcDriver/State/include/Configuration.hpp +++ b/core/libs/prx/libSceAgcDriver/State/include/Configuration.hpp @@ -1,4 +1,14 @@ #ifndef CORE_LIBS_PRX_LIBSCEAGCDRIVER_STATE_INCLUDE_CONFIGURATION_HPP #define CORE_LIBS_PRX_LIBSCEAGCDRIVER_STATE_INCLUDE_CONFIGURATION_HPP +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceAgcDriverSetHsOffchipParam(uint64_t value0, uint64_t value1, uint64_t value2); +int APS5_VABI sceAgcDriverSetTFRing(const volatile void* base, uint32_t size); +int APS5_VABI sceAgcDriverGetTFRing(uintptr_t* base, uint32_t* size); + +} + #endif diff --git a/core/libs/prx/libSceAgcDriver/State/include/Status.hpp b/core/libs/prx/libSceAgcDriver/State/include/Status.hpp index d7184e323f..822d5016ab 100644 --- a/core/libs/prx/libSceAgcDriver/State/include/Status.hpp +++ b/core/libs/prx/libSceAgcDriver/State/include/Status.hpp @@ -1,4 +1,17 @@ #ifndef CORE_LIBS_PRX_LIBSCEAGCDRIVER_STATE_INCLUDE_STATUS_HPP #define CORE_LIBS_PRX_LIBSCEAGCDRIVER_STATE_INCLUDE_STATUS_HPP +#include "SceTypes.hpp" + +extern "C" { + +bool APS5_VABI sceAgcDriverIsCaptureInProgress(void); +bool APS5_VABI sceAgcDriverIsTraceInProgress(void); +bool APS5_VABI sceAgcDriverIsSubmitValidationEnabled(void); +int APS5_VABI sceAgcDriverRequestCaptureStart(const char* path); +int APS5_VABI sceAgcDriverRequestCaptureStop(); +int APS5_VABI sceAgcDriverTriggerCapture(); + +} + #endif diff --git a/core/libs/prx/libSceAgcDriver/Submit/include/Acb.hpp b/core/libs/prx/libSceAgcDriver/Submit/include/Acb.hpp index d6d7244c58..d39b6ce6e9 100644 --- a/core/libs/prx/libSceAgcDriver/Submit/include/Acb.hpp +++ b/core/libs/prx/libSceAgcDriver/Submit/include/Acb.hpp @@ -4,6 +4,6 @@ #include "SceTypes.hpp" extern "C" int APS5_VABI sceAgcDriverSubmitAcb(std::uint32_t queue, const Packet* packet); -extern "C" int APS5_VABI sceAgcDriverSubmitMultiAcbs(std::uint32_t queue, std::uint32_t* const* acbs, const std::uint32_t* sizes_in_dwords, std::uint32_t count); +extern "C" int APS5_VABI sceAgcDriverSubmitMultiAcbs(std::uint32_t queue, std::uint32_t* const* acbs, const std::uint32_t* sizesInDwords, std::uint32_t count); #endif diff --git a/core/libs/prx/libSceAgcDriver/Submit/include/CommandBuffer.hpp b/core/libs/prx/libSceAgcDriver/Submit/include/CommandBuffer.hpp index 52fb4cb31d..bf355fbe65 100644 --- a/core/libs/prx/libSceAgcDriver/Submit/include/CommandBuffer.hpp +++ b/core/libs/prx/libSceAgcDriver/Submit/include/CommandBuffer.hpp @@ -4,12 +4,10 @@ #include "SceTypes.hpp" #include -struct Packet; - extern "C" { -int APS5_VABI sceAgcDriverSubmitCommandBuffer(void* queue_context, const Packet* packet); -int APS5_VABI sceAgcDriverSubmitMultiCommandBuffers(void* queue_context, uint32_t* const* command_buffers, const uint32_t* sizes_in_dwords, uint32_t count); +int APS5_VABI sceAgcDriverSubmitCommandBuffer(void* queueContext, const Packet* packet); +int APS5_VABI sceAgcDriverSubmitMultiCommandBuffers(void* queueContext, uint32_t* const* commandBuffers, const uint32_t* sizesInDwords, uint32_t count); } diff --git a/core/libs/prx/libSceAgcDriver/Submit/include/Dcb.hpp b/core/libs/prx/libSceAgcDriver/Submit/include/Dcb.hpp index 9e8fe9fdf7..78cfda269b 100644 --- a/core/libs/prx/libSceAgcDriver/Submit/include/Dcb.hpp +++ b/core/libs/prx/libSceAgcDriver/Submit/include/Dcb.hpp @@ -18,4 +18,15 @@ extern "C" int APS5_VABI sceAgcDriverAgrSubmitDcb(const Packet* packet); extern "C" int APS5_VABI sceAgcDriverSubmitMultiDcbs(std::uint32_t* const* dcbGpuAddrs, const std::uint32_t* dcbSizesInDwords, std::uint32_t count); extern "C" int APS5_VABI sceAgcDriverAgrSubmitMultiDcbs(std::uint32_t* const* dcbGpuAddrs, const std::uint32_t* dcbSizesInDwords, std::uint32_t count); +extern "C" { + +std::uint32_t APS5_VABI sceAgcDriverGetSetWorkloadsActivePacketSize(); +std::uint32_t APS5_VABI sceAgcDriverGetSetWorkloadCompletePacketSize(); +std::uint32_t APS5_VABI sceAgcDriverGetSetWorkloadStreamInactivePacketSize(); +std::uint32_t APS5_VABI sceAgcDriverNopDataGetPacketSize(std::uint32_t bytes); +std::uint32_t APS5_VABI sceAgcDriverUserDataGetPacketSize(std::uint32_t bytes); +std::uint32_t APS5_VABI sceAgcDriverWaitUntilSafeForRendering(std::uint32_t** command, std::uint32_t capacity, std::uint32_t mode, std::uint32_t handle, int index); + +} + #endif diff --git a/core/libs/prx/libSceAgcDriver/Unimplemented.cpp b/core/libs/prx/libSceAgcDriver/Unimplemented.cpp index dd330964bc..f361aacbe8 100644 --- a/core/libs/prx/libSceAgcDriver/Unimplemented.cpp +++ b/core/libs/prx/libSceAgcDriver/Unimplemented.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceAgcDriver/include/AgcDriver.hpp" #include #include #include @@ -68,7 +69,6 @@ int APS5_VABI sceAgcDriverNopDataWritePacket(void* destination, uint32_t address return data == nullptr || bytes == 0 ? 2 : static_cast(totalBytes / 4); } - int APS5_VABI sceAgcDriverSetValidationDisabled() { return DEBUG_UNAVAILABLE; } diff --git a/core/libs/prx/libSceAgcDriver/include/AgcDriver.hpp b/core/libs/prx/libSceAgcDriver/include/AgcDriver.hpp new file mode 100644 index 0000000000..6c6e8fea9b --- /dev/null +++ b/core/libs/prx/libSceAgcDriver/include/AgcDriver.hpp @@ -0,0 +1,85 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceAgcDriverAcquireRazorACQ(void); +int APS5_VABI sceAgcDriverCreateQueue(void); +int APS5_VABI sceAgcDriverCwsrResumeAcq(void); +int APS5_VABI sceAgcDriverCwsrSuspendAcq(void); +int APS5_VABI sceAgcDriverDebugHardwareStatus(void); +int APS5_VABI sceAgcDriverDestroyQueue(void); +int APS5_VABI sceAgcDriverGetPaDebugInterfaceVersion(void); +int APS5_VABI sceAgcDriverGetRegShadowInfo(void); +int APS5_VABI sceAgcDriverGetRegShadowInfoAgr(void); +int APS5_VABI sceAgcDriverGetReservedDmemForAgc(void); +int APS5_VABI sceAgcDriverGetWorkloadStreamInfo(void); +int APS5_VABI sceAgcDriverIDHSSubmit(void); +int APS5_VABI sceAgcDriverModuleRegistration(void); +int APS5_VABI sceAgcDriverNotifyDefaultStates(void); +int APS5_VABI sceAgcDriverPassInfoDownward(void); +int APS5_VABI sceAgcDriverPatchClearState(void); +int APS5_VABI sceAgcDriverSetFlip(void); +int APS5_VABI sceAgcDriverSetHsOffchipParamDirect(void); +int APS5_VABI sceAgcDriverSetWorkloadComplete(void); +int APS5_VABI sceAgcDriverSetWorkloadsActive(void); +int APS5_VABI sceAgcDriverSetupAsyncGraphics(void); +int APS5_VABI sceAgcDriverSetupRegisterShadow(void); +int APS5_VABI sceAgcDriverSubmitMultiCommandBuffersDirect(void); +int APS5_VABI sceAgcDriverSubmitToHDRScopesACQ(void); +int APS5_VABI sceAgcDriverSubmitToRazorACQ(void); +int APS5_VABI sceAgcDriverSuspendPointSubmit(void); +int APS5_VABI sceAgcDriverSuspendPointSubmitDirect(void); +int APS5_VABI sceAgcDriverSysEnableSubmitDone45Exception(void); +int APS5_VABI sceAgcDriverSysGetClientNumber(void); +int APS5_VABI sceAgcDriverSysIsGameClosed(void); +int APS5_VABI sceAgcDriverTmpInitIdhs(void); +int APS5_VABI sceAgcDriverUserDataWritePacket(void); +int APS5_VABI sceAgcDriverUserDataWritePopMarker(void); +int APS5_VABI sceAgcDriverUserDataWritePushMarker(void); +int APS5_VABI sceAgcDriverUserDataWriteSetMarker(void); +int APS5_VABI sceAgcDriverGetShaderDebuggingStatus(); +int APS5_VABI sceAgcDriverRegisterDefaultOwner(uint32_t owner); +int APS5_VABI sceAgcDriverSetValidationErrorOutputFrequency(uint32_t frequency); +int APS5_VABI sceAgcDriverSetSubmitValidationMode(uint32_t mode); +int APS5_VABI sceAgcDriverGetSubmitValidationConfig(void* config); +int APS5_VABI sceAgcDriverGetSubmitValidationMode(uint32_t* mode); +int APS5_VABI sceAgcDriverSetSubmitValidationConfig(const void* config); +int APS5_VABI sceAgcDriverGetHsOffchipParam(uint16_t* first, uint16_t* second); +int APS5_VABI sceAgcDriverNopDataWritePacket(void* destination, uint32_t address, const void* data, uint32_t bytes); +int APS5_VABI sceAgcDriverSetValidationDisabled(); +int APS5_VABI sceAgcDriverGetCaptureConfig(); +int APS5_VABI sceAgcDriverSetCaptureConfig(); +int APS5_VABI sceAgcDriverGetGpuPrintfWorkArea(); +int APS5_VABI sceAgcDriverSetGpuPrintfEnabled(); +int APS5_VABI sceAgcDriverDbgReadRegister(); +int APS5_VABI sceAgcDriverDbgWriteRegister(); +int APS5_VABI sceAgcDriverGetGpuRefClks(); +int APS5_VABI sceAgcDriverIsSuspendPointInFlight(); +int APS5_VABI sceAgcDriverIsPaDebug(); +int APS5_VABI sceAgcDriverGetExceptionStatus(); +int APS5_VABI sceAgcDriverGetTraceInitiator(); +int APS5_VABI sceAgcDriverRegisterGpuResetCallbacks(); +int APS5_VABI sceAgcDriverUnregisterGpuResetCallbacks(); +int APS5_VABI sceAgdResetGpu(); +int APS5_VABI sceAgcDriverSysSubmitFlipHandleProxy(); +int APS5_VABI sceAgcDriverUserDataImmediateWrite(); +int APS5_VABI sceAgcDriverUserDataImmediateWritePacket(); +int APS5_VABI sceAgcDriverGetCoredumpMode(uint32_t* mode); +int APS5_VABI sceAgcDriverAllocateToolMemoryForGpuReset(uint64_t, uint64_t, uint64_t, void* range); +int APS5_VABI sceAgcDriverGetAllocatedToolMemoryForGpuReset(uint64_t, void* range); +int APS5_VABI sceAgcDriverAcquireHDRScopesACQ(); +void* APS5_VABI sceAgcDriverGetCoredumpAddress(); +int APS5_VABI sceAgcDriverHp3dLockEnd(); +int APS5_VABI sceAgcDriverHp3dLockStart(); +int APS5_VABI sceAgcDriverIsEsvmProcess(); +int APS5_VABI sceAgcDriverReleaseHDRScopesACQ(); +int APS5_VABI sceAgcDriverSetTargetRingForDiag(); +int APS5_VABI sceAgcDriverSetValueToSharedGds(); +int APS5_VABI sceAgcDriverSetWorkloadStreamInactive(); +int APS5_VABI sceAgcDriverSubmitReprojectionAcb(); +int APS5_VABI sceAgcDriverSuspendPointSubmitCdbg(); +int APS5_VABI sceAgcDriverSysGetGfxAppGpuResetStatus(); + +} diff --git a/core/libs/prx/libSceAgcDriver/libSceAgcDriver.hpp b/core/libs/prx/libSceAgcDriver/libSceAgcDriver.hpp new file mode 100644 index 0000000000..342610270a --- /dev/null +++ b/core/libs/prx/libSceAgcDriver/libSceAgcDriver.hpp @@ -0,0 +1,12 @@ +#pragma once + +#include "prx/libSceAgcDriver/Eq/include/Event.hpp" +#include "prx/libSceAgcDriver/Eq/include/Query.hpp" +#include "prx/libSceAgcDriver/include/AgcDriver.hpp" +#include "prx/libSceAgcDriver/Resource/include/Lifecycle.hpp" +#include "prx/libSceAgcDriver/Resource/include/Registration.hpp" +#include "prx/libSceAgcDriver/State/include/Configuration.hpp" +#include "prx/libSceAgcDriver/State/include/Status.hpp" +#include "prx/libSceAgcDriver/Submit/include/Acb.hpp" +#include "prx/libSceAgcDriver/Submit/include/CommandBuffer.hpp" +#include "prx/libSceAgcDriver/Submit/include/Dcb.hpp" diff --git a/core/libs/prx/libSceAgcDriver/tests/BdaResources.cpp b/core/libs/prx/libSceAgcDriver/tests/BdaResources.cpp index c2c44c6aed..dfc860ca61 100644 --- a/core/libs/prx/libSceAgcDriver/tests/BdaResources.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/BdaResources.cpp @@ -3430,6 +3430,137 @@ void RunHeapMirrorRunUnwatchTests(const Context& context, const BdaTestAccess& a std::cout << "an address-based build refreshes the unwatched heap of a run in full and its watched neighbour by its writes\n"; } +void RunAddressCopyCapTests(const Context& context, const BdaTestAccess& access, bool remembered) { + constexpr std::size_t block = 65536; + constexpr std::size_t heapBytes = 32 * block; + constexpr std::size_t idleBytes = 16 * block; + constexpr std::size_t busyBytes = block; +#ifdef _WIN32 + if (!GuestArena::GuestArenaAvailable_nid_postfix() || !GuestArena::GuestArenaWriteWatched_nid_postfix()) { + std::cout << "guest arena unavailable or not write-watched: the address copy cap not tested\n"; + return; + } +#else + if (!GuestWriteWatch::GuestWriteWatchAvailable_nid_postfix()) { + std::cout << "write watch unavailable: the address copy cap not tested\n"; + return; + } +#endif + struct Piece { + void* pointer = nullptr; + void* mapping = nullptr; + std::size_t allocated = 0; + std::size_t bytes = 0; + }; + std::array pieces{}; + const std::array, 4> sizes{{{heapBytes + block, heapBytes}, {heapBytes + block, idleBytes}, {busyBytes + block, busyBytes}, {busyBytes + block, busyBytes}}}; + for (std::size_t index = 0; index < pieces.size(); ++index) { + auto& piece = pieces[index]; + piece.allocated = sizes[index].first; + piece.bytes = sizes[index].second; +#ifdef _WIN32 + piece.pointer = GuestArena::GuestArenaAllocate_nid_postfix(piece.allocated, block); + Require(piece.pointer != nullptr, "cannot allocate the address copy cap ranges in the guest arena"); + GuestArena::GuestArenaCommit_nid_postfix(piece.pointer, piece.allocated, PAGE_READWRITE, piece.allocated); + piece.mapping = piece.pointer; +#else + piece.mapping = mmap(nullptr, piece.allocated + block, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + Require(piece.mapping != MAP_FAILED, "cannot map the address copy cap ranges"); + piece.pointer = reinterpret_cast((reinterpret_cast(piece.mapping) + block - 1) & ~std::uintptr_t{block - 1}); +#endif + std::memset(piece.pointer, 0x5a, piece.allocated); + } + if (pieces[1].pointer < pieces[0].pointer) { + std::swap(pieces[0].pointer, pieces[1].pointer); + std::swap(pieces[0].mapping, pieces[1].mapping); + } + const auto heap = reinterpret_cast(pieces[0].pointer); + const auto idle = reinterpret_cast(pieces[1].pointer); + const auto busy = reinterpret_cast(pieces[2].pointer); + Require(heap < idle, "the idle range does not follow the heap in the registry"); +#ifndef _WIN32 + GuestWriteWatch::GuestWriteWatchRegister_nid_postfix(pieces[0].pointer, heapBytes); +#endif + const auto registry = [&](bool add) { + auto* mutation = GuestAllocations::GuestAllocationsBegin_nid_postfix(); + for (std::size_t index = 0; index < 3; ++index) { + if (add) GuestAllocations::GuestAllocationsAdd_nid_postfix(mutation, pieces[index].pointer, pieces[index].bytes, true, false, true); + else GuestAllocations::GuestAllocationsRemove_nid_postfix(mutation, pieces[index].pointer); + } + GuestAllocations::GuestAllocationsEnd_nid_postfix(mutation); + }; + const auto unrelated = [&](bool add) { + auto* mutation = GuestAllocations::GuestAllocationsBegin_nid_postfix(); + if (add) GuestAllocations::GuestAllocationsAdd_nid_postfix(mutation, pieces[3].pointer, pieces[3].bytes, true, false, false); + else GuestAllocations::GuestAllocationsRemove_nid_postfix(mutation, pieces[3].pointer); + GuestAllocations::GuestAllocationsEnd_nid_postfix(mutation); + }; + registry(true); +#ifdef _WIN32 + AgcDriver::GuestMemory::Unwatch(idle, idleBytes); + AgcDriver::GuestMemory::Unwatch(busy, busyBytes); +#endif + auto importing = context; + importing.hostImportAlignment = block; + SetHostImportBudget(heapBytes + idleBytes + busyBytes - block); + Require(HostImportFor(importing, idle, 64) != nullptr && HostImportFor(importing, busy, 64) != nullptr, "the idle and busy ranges were not imported"); + Require(HostImportLiveBytes() == idleBytes + busyBytes && !HostImportCovers(importing, heap, heapBytes), "the imports before the build are not the idle and busy ranges"); + Require(AgcDriver::GuestMemory::Watched(heap, heapBytes), "the heap is not write-watched"); + const auto before = MirrorCounters(); + const auto builds = [] { return HostImportCounters().requesters[static_cast(ImportRequester::Build)]; }; + const auto unwatch = [&] { + AgcDriver::GuestMemory::Unwatch(heap + heapBytes / 2, block); + Require(AgcDriver::GuestMemory::Watched(heap, heapBytes / 2) && !AgcDriver::GuestMemory::Watched(heap, heapBytes), "the heap is not partly outside the write watch"); + }; + if (remembered) { + unwatch(); + SetAddressCopyLimit(2 * heapBytes); + { + GuestBufferMemory leased(importing); + leased.AcquireRegistered(); + leased.Upload(true); + Require(MirrorCounters().heapMirrors == before.heapMirrors && !HostImportCovers(importing, heap, heapBytes), "the first build did not copy the heap whose import the budget refused"); + leased.WriteBack(); + } + SetAddressCopyLimit(0); + unrelated(true); + } + for (int use = 0; use < 300; ++use) Require(HostImportFor(importing, busy, 64) != nullptr, "the busy range lost its import"); + if (!remembered) unwatch(); + const auto refused = builds(); + { + GuestBufferMemory leased(importing); + leased.AcquireRegistered(); + leased.Upload(true); + const bool imported = HostImportCovers(importing, heap, heapBytes); + Require(imported || (!remembered && MirrorCounters().heapMirrors == before.heapMirrors + 1), "the heap is neither imported nor mirrored"); + const auto ranges = leased.AddressRanges(); + const auto found = std::find_if(ranges.begin(), ranges.end(), [&](const auto& range) { return range.begin == heap; }); + Require(found != ranges.end() && found->deviceAddress != 0u, "the heap is missing from the BDA table"); + Require(imported || access.addressBytes(found->deviceAddress)[heapBytes / 2 + 3] == std::byte{0x5a}, "the heap mirror does not hold the guest bytes"); + leased.WriteBack(); + } + Require(!remembered || builds().remembered == refused.remembered + 1, "the build under the copy cap was not answered from the refusal the first build remembered"); + SetHostImportBudget(0); + if (remembered) unrelated(false); + registry(false); + ClearImageMirrors(importing.device); + ClearHostImports(importing.device); + ClearSnapshotCopies(importing.device); +#ifndef _WIN32 + GuestWriteWatch::GuestWriteWatchUnregister_nid_postfix(pieces[0].pointer, heapBytes); +#endif + for (const auto& piece : pieces) { +#ifdef _WIN32 + GuestArena::GuestArenaReset_nid_postfix(piece.pointer, piece.allocated); + GuestArena::GuestArenaRelease_nid_postfix(piece.pointer, piece.allocated); +#else + munmap(piece.mapping, piece.allocated + block); +#endif + } + std::cout << (remembered ? "an address-based build answered from a remembered budget refusal evicts instead of copying a partly unwatched heap past the cap\n" : "an address-based build serves a partly unwatched heap whose import is over the budget\n"); +} + void hostWriteWatchExclusionTests() { #ifdef _WIN32 std::vector host(64, 0x31); @@ -3854,5 +3985,10 @@ void RunBdaResourceTests(const Context& context, const BdaTestAccess& access) { Require(AddressCopyOverflow({{0x1000, 0x3000, 0x2000, "uncommitted pages"}}, 0x2000).empty(), "copies within the limit were refused"); const auto copies = AddressCopyOverflow({{0x1000, 0x2000, 0x1000, "not mirrored"}, {0x10000, 0x30000, 0x18000, "uncommitted pages"}}, 0x2000); Require(!copies.empty() && copies.find("0x10000+0x20000 (0.1 MiB committed, uncommitted pages)") < copies.find("0x1000+0x1000"), "the copy limit does not name the largest copy first"); + AgcDriver::GuestMemory::Unwatch(0x10000, 0x20000); + AgcDriver::GuestMemory::Unwatch(0x40000, 0x10000); + Require(!AgcDriver::GuestMemory::Watched(0x10000, 0x20000), "the unregistered heap copy range is write-watched"); + const auto heapCopies = AddressCopyOverflow({{0x10000, 0x30000, 0x18000, nullptr, true, true}, {0x40000, 0x50000, 0x10000, nullptr, true, false}}, 0x2000); + Require(heapCopies.find("0x10000+0x20000 (0.1 MiB committed, import over the host import budget, heap not fully write-watched)") != std::string::npos && heapCopies.find("0x40000+0x10000 (0.1 MiB committed, heap not fully write-watched)") != std::string::npos, "the copy limit does not name a copied heap's reason"); ClearSnapshotCopies(context.device); } diff --git a/core/libs/prx/libSceAgcDriver/tests/BdaTests.hpp b/core/libs/prx/libSceAgcDriver/tests/BdaTests.hpp index 49cd994d6e..7479c1f4b1 100644 --- a/core/libs/prx/libSceAgcDriver/tests/BdaTests.hpp +++ b/core/libs/prx/libSceAgcDriver/tests/BdaTests.hpp @@ -21,6 +21,7 @@ void RunHeapMirrorUnwatchTests(const AgcDriver::Graphics::Context& context, cons void RunSparseHeapMirrorUnwatchTests(const AgcDriver::Graphics::Context& context, const BdaTestAccess& access); void RunSparseHeapMirrorBudgetTests(const AgcDriver::Graphics::Context& context, const BdaTestAccess& access); void RunHeapMirrorRunUnwatchTests(const AgcDriver::Graphics::Context& context, const BdaTestAccess& access); +void RunAddressCopyCapTests(const AgcDriver::Graphics::Context& context, const BdaTestAccess& access, bool remembered); void RunGuestAllocationTests(); void RunGuestLeaseWaitTests(); void RunUnmappedGapTests(); diff --git a/core/libs/prx/libSceAgcDriver/tests/DenormalFlushElimination.cpp b/core/libs/prx/libSceAgcDriver/tests/DenormalFlushElimination.cpp index cc952f5ea9..5dd5cfc4ba 100644 --- a/core/libs/prx/libSceAgcDriver/tests/DenormalFlushElimination.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/DenormalFlushElimination.cpp @@ -110,7 +110,8 @@ std::vector Recompiled(std::span code) { request.target.maxWorkgroupSharedMemoryBytes = 49152; request.layout = {0, 0, 0, 128}; request.useCache = false; - const auto& words = Recompile(request).spirv.Words(); + const auto result = Recompile(request); + const auto& words = result.spirv.Words(); return {words.begin(), words.end()}; } diff --git a/core/libs/prx/libSceAgcDriver/tests/Flip.cpp b/core/libs/prx/libSceAgcDriver/tests/Flip.cpp index 9e89fdd61c..849703ad95 100644 --- a/core/libs/prx/libSceAgcDriver/tests/Flip.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/Flip.cpp @@ -1,5 +1,6 @@ #include "prx/libSceAgcDriver/Execution/include/Driver.hpp" #include "prx/libSceAgcDriver/Execution/include/PresentMode.hpp" +#include "prx/libSceAgcDriver/Execution/include/SwapchainImages.hpp" #include "prx/libc/include/Shutdown.hpp" #include "prx/libSceAgcDriver/Execution/include/VideoOutput.hpp" #include "prx/libSceAgcDriver/Submit/include/Dcb.hpp" @@ -406,6 +407,19 @@ void testReset(bool compute) { void testPresentMode() { using AgcDriver::SelectPresentMode; + VkSurfaceCapabilitiesKHR surface{}; + surface.minImageCount = 2; + surface.maxImageCount = 8; + check(AgcDriver::SwapchainImageCount(surface) == 3, "the swapchain has no image beyond the surface minimum"); + surface.minImageCount = 3; + check(AgcDriver::SwapchainImageCount(surface) == 3, "a three-image surface minimum gained an image"); + surface.minImageCount = 5; + check(AgcDriver::SwapchainImageCount(surface) == 5, "the swapchain does not follow a larger surface minimum"); + surface.minImageCount = 2; + surface.maxImageCount = 2; + check(AgcDriver::SwapchainImageCount(surface) == 2, "the swapchain exceeds the surface maximum"); + surface.maxImageCount = 0; + check(AgcDriver::SwapchainImageCount(surface) == 3, "an unlimited surface maximum capped the swapchain"); const std::array wayland{VK_PRESENT_MODE_FIFO_KHR, VK_PRESENT_MODE_IMMEDIATE_KHR}; const std::array all{VK_PRESENT_MODE_IMMEDIATE_KHR, VK_PRESENT_MODE_MAILBOX_KHR, VK_PRESENT_MODE_FIFO_KHR}; check(SelectPresentMode(nullptr, wayland) == VK_PRESENT_MODE_FIFO_KHR, "the default present mode is not FIFO"); @@ -421,6 +435,11 @@ void testPresentMode() { check(expectFailure([&] { SelectPresentMode("", all); }).find("must be fifo, fifo_latest_ready, mailbox or immediate") != std::string::npos, "an empty present mode name was accepted"); const std::array none{}; check(expectFailure([&] { SelectPresentMode(nullptr, none); }).find("does not support") != std::string::npos, "FIFO was selected on a surface without it"); + using AgcDriver::SelectPresentQueue; + check(SelectPresentQueue(16, 2) == 2u, "the presentation queue does not follow the main and settle queues"); + check(SelectPresentQueue(16, 1) == 1u, "the presentation queue does not follow the main queue alone"); + check(!SelectPresentQueue(2, 2).has_value(), "a presentation queue was taken from a family without a free queue"); + check(!SelectPresentQueue(1, 1).has_value(), "a presentation queue was taken from a family with one queue"); } int main(int argc, char** argv) { diff --git a/core/libs/prx/libSceAgcDriver/tests/FrameReplay.cpp b/core/libs/prx/libSceAgcDriver/tests/FrameReplay.cpp index 56d6b1c40d..dc652cddfe 100644 --- a/core/libs/prx/libSceAgcDriver/tests/FrameReplay.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/FrameReplay.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceAgc/DcbFlow/include/Memory.hpp" #include "prx/libSceAgcDriver/Execution/include/Driver.hpp" #include "prx/libSceAgcDriver/Execution/include/FrameCapture.hpp" #include "prx/libSceAgcDriver/Execution/include/VideoOutput.hpp" @@ -21,11 +22,6 @@ #include #endif -extern "C" { -std::uint32_t* APS5_VABI sceAgcDcbWriteData(CommandBuffer*, std::uint8_t, std::uint8_t, std::uint64_t, const void*, std::uint32_t, std::uint8_t, std::uint8_t); -std::uint32_t* APS5_VABI sceAgcDcbDmaData(CommandBuffer*, std::uint8_t, std::uint8_t, std::uint8_t, std::uint64_t, std::uint8_t, std::uint8_t, std::uint64_t, std::uint32_t, std::uint8_t, std::uint8_t, std::uint8_t); -} - namespace { using AgcDriver::FrameCallKind; diff --git a/core/libs/prx/libSceAgcDriver/tests/Graphics.cpp b/core/libs/prx/libSceAgcDriver/tests/Graphics.cpp index 7afcaac27e..2595184b0c 100644 --- a/core/libs/prx/libSceAgcDriver/tests/Graphics.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/Graphics.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "BdaTests.hpp" #include "GraphicsTests.hpp" #include "prx/libSceAgcDriver/Execution/include/GuestMemory.hpp" @@ -64,8 +65,6 @@ #include #include -extern "C" std::terminate_handler APS5_VABI _ZSt13set_terminatePFvvE_nid_postfix(std::terminate_handler handler); - namespace { using AgcDriver::Graphics::Require; @@ -3135,6 +3134,13 @@ void metadataPassTests() { auto mipmapped = queue; mipmapped.context[0x3b0] |= 1u << 28u; expectFailure([&] { DecodeColorMetadataPass(mipmapped); }, "mipmapped DCC"); + const auto chain = AgcDriver::Graphics::DecodeColorBuffer(mipmapped.context, 0); + const auto chainSurface = AgcDriver::Graphics::SurfaceForTarget(chain); + Require(chain.dccAddress == 0 && chainSurface.mipCount == 2 && chainSurface.dccAddress == keysAddress, "the surface of a mipmapped DCC color target lost its keys"); + auto mipmappedArray = mipmapped; + mipmappedArray.context[0x3b8] |= 1u; + mipmappedArray.context[0x31b] = 1u << 13u; + Require(AgcDriver::Graphics::SurfaceForTarget(AgcDriver::Graphics::DecodeColorBuffer(mipmappedArray.context, 0)).dccAddress == 0, "a mipmapped DCC array color target took keys whose layers are not modeled"); const AgcDriver::Graphics::Context context{}; const auto texels = [&](std::uint32_t value) { for (std::size_t offset = 0; offset < colorMemory.size(); offset += 4) { @@ -5980,6 +5986,7 @@ void descriptorPoolResetFailureTest() { }); cache.Free(allocation); _ZSt13set_terminatePFvvE_nid_postfix(previous); + } void pushConstantTests() { @@ -7138,6 +7145,41 @@ void misalignedShaderDataTests() { Require(mock.live == 0, "misaligned shader data resources leaked Vulkan objects"); } +void imageTableTemplateRefreshTests() { + namespace Abi = ShaderRecompiler::ImageTableAbi; + mock = MockVulkan{}; + auto context = mockContext(); + context.imageTableCapacity = 2; + context.limits.maxDescriptorSetSampledImages = 2; + context.limits.maxPerStageDescriptorSampledImages = 2; + const auto commands = reinterpret_cast(std::uintptr_t{1}); + { + ShaderRecompiler::RecompileResult compute; + auto map = makeBinding(Role::ImageTableMap, static_cast(ShaderRecompiler::RuntimeAbi::Binding::ImageTableMap), 1, std::vector(Abi::HeaderWords)); + map.guestDescriptor[Abi::HeaderVersion] = Abi::Version; + map.guestDescriptor[Abi::HeaderElementFaults] = Abi::HeaderWords; + map.guestDescriptor[Abi::HeaderSamplerFaults] = Abi::HeaderWords; + compute.bindings.push_back(map); + auto images = makeBinding(Role::ImageTable, ShaderRecompiler::RuntimeAbi::ImageTableBinding, 0, {}); + images.kind = Kind::SampledImage; + compute.bindings.push_back(images); + compute.bindings.push_back(makeBinding(Role::ShaderData, 1, 1, ShaderDataWords({0x11, 0x22}))); + compute.shaderDataDwords = ShaderRecompiler::RuntimeAbi::ShaderDataDwords; + auto live = compute; + live.bindings[2].guestDescriptor = ShaderDataWords({0x33, 0x44}); + const AgcDriver::Graphics::CompiledShader shader{ShaderRecompiler::ShaderStage::Compute, &compute, 0}; + const AgcDriver::Graphics::CompiledShader liveShader{ShaderRecompiler::ShaderStage::Compute, &live, 0}; + AgcDriver::Graphics::ShaderResources resources(context, shader); + const auto data = findWrite(1).buffers.at(0).buffer; + Require(!resources.DataWordsDiffer(shader), "a template's own words differ from the shader that built it"); + Require(resources.DataWordsDiffer(liveShader), "a template with an image table missed the dispatch's new words"); + Require(resources.RefreshData(commands, liveShader), "a refresh of a template with an image table recorded nothing"); + Require(sameBytes(bufferBytes(data), live.bindings[2].guestDescriptor.data(), 3u * sizeof(std::uint32_t)), "a refresh of a template with an image table did not write the dispatch's words"); + Require(!resources.DataWordsDiffer(liveShader), "the refreshed template's words are not the dispatch's"); + } + Require(mock.live == 0, "image table template refresh resources leaked Vulkan objects"); +} + struct ModuleShape { bool fragment = false; std::optional fragmentMode; @@ -8076,6 +8118,38 @@ void pipelineLibraryClearWaitsForBuildTests() { Require(mock.live == 0, "clearing during a library build leaked Vulkan objects"); } +void tessellationPipelineLibraryCacheTests() { + using namespace AgcDriver::Graphics; + for (const auto shared : {true, false}) { + mock = MockVulkan{}; + auto context = mockContext(); + context.graphicsPipelineLibrary = true; + context.tessellationShader = true; + context.tessellationPipelineCache = shared; + context.limits.maxTessellationPatchSize = 32; + context.limits.maxPushConstantsSize = 256; + context.limits.framebufferNoAttachmentsSampleCounts = VK_SAMPLE_COUNT_1_BIT; + State state{}; + state.stages.path = ShaderPath::Tessellation; + state.stages.tessellation = ShaderRecompiler::TessellationConfiguration{3, 3, 2, 1, 4, 128, 16, false}; + ShaderRecompiler::RecompileResult vertex, control, evaluation, fragment; + vertex.spirv = makeModule({}); + control.spirv = makeModule({}); + evaluation.spirv = makeModule({}); + fragment.spirv = makeModule({.fragment = true}); + vertex.variantId = 201; + control.variantId = 202; + evaluation.variantId = 203; + fragment.variantId = 204; + const std::array shaders{{{ShaderRecompiler::ShaderStage::Vertex, &vertex, 0}, {ShaderRecompiler::ShaderStage::TessellationControl, &control, 0}, {ShaderRecompiler::ShaderStage::TessellationEvaluation, &evaluation, 0}, {ShaderRecompiler::ShaderStage::Fragment, &fragment, PipelinePushSlotBytes}}}; + std::array mainKey{31}; + const PipelineSetLayouts resources{makeHandle(), VK_NULL_HANDLE, false, mainKey, {}}; + Require(Pipeline::Prebuild(context, state, VertexInputLayout{}, resources, shaders) == shared, shared ? "tessellation pipelines skipped graphics pipeline libraries with a shared pipeline cache" : "tessellation pipelines without the pipeline cache were built from graphics pipeline libraries"); + ClearPipelineLibraries(context.device); + Require(mock.live == 0, "tessellation pipeline library tests leaked Vulkan objects"); + } +} + void framebufferOwnerTests() { using namespace AgcDriver::Graphics; mock = MockVulkan{}; @@ -10962,7 +11036,6 @@ void validationTests() { } } - } bool recompilesDebugBranch(std::uint32_t opcode) { @@ -11918,6 +11991,32 @@ int main(int argc, char** argv) { Require(mock.live == 0, "the heap mirror run unwatch test leaked Vulkan objects"); return 0; } + if (argc == 2 && (std::string_view(argv[1]) == "--address-copy-cap" || std::string_view(argv[1]) == "--address-copy-cap-remembered")) { +#ifdef _WIN32 + _putenv_s("APS5_ADDRESS_COPY_MAX_MIB", "1"); +#else + setenv("APS5_ADDRESS_COPY_MAX_MIB", "1", 1); +#endif + { + mock = MockVulkan{}; + auto context = mockContext(); + context.bufferDeviceAddress = true; + context.limits.maxStorageBufferRange = 1u << 27; + RunAddressCopyCapTests(context, { + [](VkBuffer buffer) -> std::span { return mockBufferMemory(buffer); }, + {}, + [](VkDeviceAddress address) { + const auto offset = address - 0x100000000000ULL; + const auto buffer = reinterpret_cast(offset / 0x10000); + return mockBufferMemory(buffer).subspan(offset % 0x10000); + }, + {}, + {} + }, std::string_view(argv[1]) == "--address-copy-cap-remembered"); + } + Require(mock.live == 0, "the address copy cap test leaked Vulkan objects"); + return 0; + } if (argc == 2 && std::string_view(argv[1]) == "--address-space-teardown") { addressSpaceTeardownTests(); std::cout << "address-space device teardown releases cached guest allocations\n"; @@ -12045,6 +12144,7 @@ int main(int argc, char** argv) { retainedPixelStageTests(); pipelineLibrarySetTests(); pipelineLibraryClearWaitsForBuildTests(); + tessellationPipelineLibraryCacheTests(); framebufferOwnerTests(); hdrComponentSwapTests(); depthMaintenanceTests(); @@ -12137,6 +12237,7 @@ int main(int argc, char** argv) { samplerTableDeviceLimitTests(); tableUpdateAfterBindTests(); misalignedShaderDataTests(); + imageTableTemplateRefreshTests(); debugBranchTests(); hostImportBudgetTests(); textureCacheBudgetTests(); diff --git a/core/libs/prx/libSceAgcDriver/tests/NopDataWritePacket.cpp b/core/libs/prx/libSceAgcDriver/tests/NopDataWritePacket.cpp index 587bc082bc..6be7c6011a 100644 --- a/core/libs/prx/libSceAgcDriver/tests/NopDataWritePacket.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/NopDataWritePacket.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceAgcDriver/include/AgcDriver.hpp" #include "SceTypes.hpp" #include #include @@ -5,8 +6,6 @@ #include #include -extern "C" int APS5_VABI sceAgcDriverNopDataWritePacket(void* destination, uint32_t address, const void* data, uint32_t bytes); - int main() { std::array storage; storage.fill(std::byte{0xaa}); @@ -34,5 +33,18 @@ int main() { std::memcpy(&address, storage.data() + 8, sizeof(address)); if (zeroBytesWords != 2 || header != 0xc0001000U || address != 0x01020304U) return 7; if (storage[12] != std::byte{0xaa}) return 8; + + for (std::uint32_t len = 1; len <= 4; ++len) { + storage.fill(std::byte{0xaa}); + const auto lenWords = sceAgcDriverNopDataWritePacket(storage.data() + 4, 0xaabbccddU, data.data(), len); + std::memcpy(&header, storage.data() + 4, sizeof(header)); + std::memcpy(&address, storage.data() + 8, sizeof(address)); + if (lenWords != 3 || header != 0xc0011000U || address != 0xaabbccddU) return 9 + static_cast(len); + if (!std::equal(data.begin(), data.begin() + len, storage.begin() + 12)) return 14 + static_cast(len); + for (std::size_t pad = 12 + len; pad < 16; ++pad) { + if (storage[pad] != std::byte{0}) return 19 + static_cast(len); + } + if (storage[3] != std::byte{0xaa} || storage[16] != std::byte{0xaa}) return 24 + static_cast(len); + } return 0; } diff --git a/core/libs/prx/libSceAgcDriver/tests/PerformanceTrace.cpp b/core/libs/prx/libSceAgcDriver/tests/PerformanceTrace.cpp index efad88d641..a6272db6c6 100644 --- a/core/libs/prx/libSceAgcDriver/tests/PerformanceTrace.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/PerformanceTrace.cpp @@ -134,6 +134,20 @@ void EscapeStrings() { Check(output == "\"a\\\"b\\\\c\\u000a\\u00e9\"", "string escaping is not valid JSON"); } +void Utf8Strings() { + std::string output; + TraceFormat::AppendString(output, "Ghost of Y\xc5\x8dtei \xe2\x84\xa2 \xf0\x9f\x8e\xae"); + Check(output == "\"Ghost of Y\xc5\x8dtei \xe2\x84\xa2 \xf0\x9f\x8e\xae\"", "a UTF-8 title was not written as its own characters"); + output.clear(); + TraceFormat::AppendString(output, "\xc0\xaf\xed\xa0\x80\xf4\x90\x80\x80\xe2\x84\x7f\xc5"); + Check(output == "\"\\u00c0\\u00af\\u00ed\\u00a0\\u0080\\u00f4\\u0090\\u0080\\u0080\\u00e2\\u0084\\u007f\\u00c5\"", "a byte outside a valid UTF-8 sequence was not escaped"); + AgcDriver::TraceSummary summary; + summary.title = AgcDriver::TraceTitle{"PPSA26344", "Ghost of Y\xc5\x8dtei", "01.000.000"}; + const auto origin = Clock::now(); + const std::vector presents{origin, origin + milliseconds(16)}; + Check(TraceFormat::Summary(summary, {}, presents).find("\"title\":\"Ghost of Y\xc5\x8dtei\"") != std::string::npos, "the summary line did not keep a UTF-8 title"); +} + void EventsShape() { const auto origin = Clock::now(); const std::vector slices{ @@ -576,6 +590,7 @@ int main() { FullBufferEvents(); FoldShortSlices(); EscapeStrings(); + Utf8Strings(); EventsShape(); BatchIds(); SummaryFields(); diff --git a/core/libs/prx/libSceAgcDriver/tests/Pm4.cpp b/core/libs/prx/libSceAgcDriver/tests/Pm4.cpp index a7ea1d923b..a95329f86d 100644 --- a/core/libs/prx/libSceAgcDriver/tests/Pm4.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/Pm4.cpp @@ -1,3 +1,4 @@ +#include "prx/libkernel/include/Api.hpp" #include "prx/libSceAgcDriver/Execution/include/Pm4.hpp" #include "prx/libSceAgcDriver/Execution/include/GuestMemory.hpp" #include "prx/libSceAgcDriver/Execution/include/Driver.hpp" @@ -40,8 +41,6 @@ #include #endif -extern "C" int APS5_VABI sceKernelAvailableFlexibleMemorySize(size_t* size); - namespace { void check(bool condition, const char* reason) { diff --git a/core/libs/prx/libSceAgcDriver/tests/Pm4Replay.cpp b/core/libs/prx/libSceAgcDriver/tests/Pm4Replay.cpp index 8668696b41..7359bc4598 100644 --- a/core/libs/prx/libSceAgcDriver/tests/Pm4Replay.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/Pm4Replay.cpp @@ -1,3 +1,10 @@ +#include "prx/libSceAgc/Patch/include/Rewind.hpp" +#include "prx/libSceAgc/DcbFlow/include/Sync.hpp" +#include "prx/libSceAgc/DcbFlow/include/Memory.hpp" +#include "prx/libSceAgc/Cb/include/Sync.hpp" +#include "prx/libSceAgc/Acb/include/Sync.hpp" +#include "prx/libSceAgc/Acb/include/Memory.hpp" +#include "prx/libSceAgc/Acb/include/Control.hpp" #include "../tools/Pm4Analysis.hpp" #include "prx/libSceAgcDriver/Execution/include/Driver.hpp" #include "prx/libSceAgcDriver/Execution/include/Driver/Synchronization/LabelStores.hpp" @@ -21,18 +28,6 @@ #include #include -extern "C" { -std::uint32_t* APS5_VABI sceAgcDcbWriteData(CommandBuffer*, std::uint8_t, std::uint8_t, std::uint64_t, const void*, std::uint32_t, std::uint8_t, std::uint8_t); -std::uint32_t* APS5_VABI sceAgcAcbWriteData(CommandBuffer*, std::uint8_t, std::uint8_t, std::uint64_t, const void*, std::uint32_t, std::uint8_t, std::uint8_t); -std::uint32_t* APS5_VABI sceAgcDcbWaitRegMem(CommandBuffer*, std::uint8_t, std::uint8_t, std::uint8_t, std::uint8_t, const volatile void*, std::uint64_t, std::uint64_t, std::uint32_t); -std::uint32_t* APS5_VABI sceAgcAcbWaitRegMem(CommandBuffer*, std::uint8_t, std::uint8_t, std::uint8_t, const volatile void*, std::uint64_t, std::uint64_t, std::uint32_t); -std::uint32_t* APS5_VABI sceAgcCbReleaseMem(CommandBuffer*, std::uint8_t, std::uint16_t, std::uint8_t, std::uint8_t, const volatile Label*, std::uint8_t, std::uint64_t, std::uint16_t, std::uint16_t, std::uint8_t, std::uint32_t); -std::uint32_t* APS5_VABI sceAgcDcbDmaData(CommandBuffer*, std::uint8_t, std::uint8_t, std::uint8_t, std::uint64_t, std::uint8_t, std::uint8_t, std::uint64_t, std::uint32_t, std::uint8_t, std::uint8_t, std::uint8_t); -std::uint32_t* APS5_VABI sceAgcDcbCondExec(CommandBuffer*, const volatile std::uint32_t*, std::uint32_t); -std::uint32_t* APS5_VABI sceAgcAcbRewind(CommandBuffer*, std::uint32_t); -int APS5_VABI sceAgcAsyncRewindPatchSetRewindState(std::uint32_t*, std::uint8_t); -} - namespace { using AgcDriver::CapturedSubmission; diff --git a/core/libs/prx/libSceAgcDriver/tests/Recorder.cpp b/core/libs/prx/libSceAgcDriver/tests/Recorder.cpp index a86232068f..f46ae835ce 100644 --- a/core/libs/prx/libSceAgcDriver/tests/Recorder.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/Recorder.cpp @@ -1,3 +1,4 @@ +#include "prx/libkernel/include/Api.hpp" #include "prx/libSceAgc/Command/include/Packet.hpp" #include "prx/libSceAgcDriver/Execution/include/PipelineLinkOptimization.hpp" #include "Triangle_frag_spv.h" @@ -79,14 +80,6 @@ namespace { -extern "C" { -int APS5_VABI sceKernelAllocateDirectMemory(std::int64_t, std::int64_t, std::size_t, std::size_t, int, std::int64_t*); -int APS5_VABI sceKernelMapDirectMemory(void**, std::size_t, int, int, std::int64_t, std::size_t); -int APS5_VABI sceKernelReleaseDirectMemory(std::int64_t, std::size_t); -int APS5_VABI sceKernelMunmap(void*, std::size_t); -int APS5_VABI sceKernelMprotect(const void*, std::size_t, int); -} - using namespace AgcDriver::Graphics; using AgcDriver::GuestMemory::GpuMutex; @@ -1331,7 +1324,7 @@ void directCompletionLabelTests(Recorder& recorder) { std::int64_t physical = -1; ~Release() { recorder.Sync(); - if (mapping != nullptr) sceKernelMunmap(mapping, size); + if (mapping != nullptr) sceKernelMunmap(reinterpret_cast(mapping), size); if (physical >= 0) sceKernelReleaseDirectMemory(physical, size); } } release{recorder}; @@ -2518,6 +2511,297 @@ bool settleStorageImageTests(const Device& device) { std::cout << "a settled import under a storage image tests passed\n"; return true; } + +bool settleInitialDccTests(const Device& device) { + using namespace AgcDriver::GuestMemory; + const auto& base = device.GetContext(); + constexpr std::size_t unit = 65536; + constexpr std::size_t tail = 0x4000; + if ((base.limits.framebufferColorSampleCounts & VK_SAMPLE_COUNT_4_BIT) == 0 || !device.Graphics() || base.hostImportAlignment == 0 || base.hostImportAlignment > tail || base.settleQueue == VK_NULL_HANDLE || !WriteWatched()) { + std::cout << "4x color targets, graphics, host imports within 16 KiB, a settle queue or write watching unavailable: an initial multisampled DCC import over a pending settle not tested\n"; + return false; + } + { + std::lock_guard gpu(GpuMutex()); + PrepareImportWatch(base); + if (!settledImportsWatchPrivate(base)) { + std::cout << "this device compares every Windows import: an initial multisampled DCC import over a pending settle not tested\n"; + return false; + } + } + std::cout << "write watch: Windows private imports stay watched after a settle read; imports under 1 MiB wait for a deferred settle\n"; + for (const std::size_t count : {256u, 257u, 1025u}) { + const auto bytes = count * unit; + auto* block = static_cast(AllocateWatched(bytes, unit)); + Require(block != nullptr, "(m) cannot allocate adjacent pending imports"); + const auto address = reinterpret_cast(block); + struct Release { + const Context& context; + std::uint8_t* block; + std::size_t bytes; + std::size_t registered = 0; + ~Release() { + { + GuestAllocations::Mutation mutation; + for (std::size_t index = 0; index < registered; ++index) mutation.Remove(block + index * unit); + } + HostImportFor(context, reinterpret_cast(block), unit); + SetHostImportWindow(0); + ReleaseWatched(block, bytes); + } + } release{base, block, bytes}; + std::memset(block, 0x11, bytes); + SetHostImportWindow(unit); + { + GuestAllocations::Mutation mutation; + for (std::size_t index = 0; index < count; ++index) { + mutation.Add(block + index * unit, unit, true, true, true); + ++release.registered; + } + } + for (std::size_t index = 0; index < count; ++index) { + const auto at = address + index * unit; + const auto* import = HostImportFor(base, at, unit); + Require(import != nullptr && import->base == at && import->bytes == unit && import->unwatched, + "(m) an adjacent 64 KiB import did not start with its settle pending"); + } + { + std::lock_guard gpu(GpuMutex()); + Require(!Watched(address, bytes), "(m) adjacent pending imports were already watched"); + const auto before = HostImportSettles(); + Require(WatchedAfterSettle(base, address, bytes), + "(m) one synchronous settle left part of " + std::to_string(count) + " adjacent imports unwatched"); + const auto after = HostImportSettles(); + BumpCollectEpoch(); + const auto collected = CollectWrites(address, bytes); + Require(collected != 0, "(m) adjacent settled imports were not collected"); + static_cast(block)[bytes - 1] = 0x22; + CollectWritesUncached(address, bytes); + Require(!UnchangedSince(address, bytes, collected), "(m) a CPU write after the final import settled was missed"); + std::cout << "(m) " << count << " adjacent pending imports settled: " << after.submitted - before.submitted << " reads submitted\n"; + } + } + TextureDetiler detiler(base); + auto context = base; + context.detiler = &detiler; + Recorder recorder(context); + recorder.Activate(); + enum class Case { Pending, PartialBlock, ComparedNeighbour, DeferredOff, UnwatchedKeys, PendingFmask, PendingFmaskAlone }; + const auto run = [&](Case kind, std::uint32_t height) { + const bool fmaskAlone = kind == Case::PendingFmaskAlone; + const bool eightSamples = kind == Case::PendingFmask || fmaskAlone; + if (eightSamples && (!base.storageImageMultisample || (base.limits.framebufferColorSampleCounts & VK_SAMPLE_COUNT_8_BIT) == 0)) { + std::cout << "(m) 8x color or multisampled storage images unavailable: an initial FMASK import over a pending settle not tested\n"; + return; + } + const bool partial = kind == Case::PartialBlock || kind == Case::ComparedNeighbour; + ColorTarget target{}; + target.extent = {128, height}; + target.surfaceExtent = target.extent; + target.format = VK_FORMAT_R8G8B8A8_UNORM; + target.elementBytes = 4; + target.samples = eightSamples ? 8 : 4; + target.tileMode = ColorTileMode::RenderTarget; + target.dccPipeAligned = true; + const auto colorBytes = static_cast(MultisampledColorBytes(target)); + const auto dccBytes = MultisampledDccBytes(target); + const auto importBytes = colorBytes + (partial ? tail : unit); + const auto reserved = (importBytes + unit - 1) & ~(unit - 1); + const auto fmaskBytes = static_cast(target.extent.width) * target.extent.height * 4u; + const auto fmaskReserved = (fmaskBytes + unit - 1) & ~(unit - 1); + const auto regionBytes = unit + reserved + unit + (kind == Case::UnwatchedKeys ? unit : eightSamples ? fmaskReserved + unit : 0); + auto* region = static_cast(AllocateWatched(regionBytes, unit)); + void* block = region != nullptr ? region + unit : nullptr; + void* keys = region != nullptr && kind == Case::UnwatchedKeys ? region + unit + reserved + unit : nullptr; + void* fmask = region != nullptr && eightSamples ? region + unit + reserved + unit : nullptr; + const auto destBytes = static_cast(target.extent.width) * target.extent.height * 4u; + void* dest = VirtualAlloc(nullptr, destBytes, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); + Require(block != nullptr && dest != nullptr && (kind != Case::UnwatchedKeys || keys != nullptr) && (!eightSamples || fmask != nullptr), "(m) cannot allocate the target"); + const auto address = reinterpret_cast(block); + const auto neighbour = address + importBytes + tail; + const auto describe = [](const HostImport* found, std::uint64_t at, std::size_t bytes) { + char text[256]; + if (found == nullptr) std::snprintf(text, sizeof(text), ": no import of 0x%llx+0x%zx, watched %d", static_cast(at), bytes, Watched(at, bytes) ? 1 : 0); + else std::snprintf(text, sizeof(text), ": import 0x%llx+0x%llx, unwatched %d, settled on demand %d, for 0x%llx+0x%zx, watched %d", static_cast(found->base), static_cast(found->bytes), found->unwatched ? 1 : 0, found->settleOnDemand ? 1 : 0, static_cast(at), bytes, Watched(at, bytes) ? 1 : 0); + return std::string(text); + }; + struct Release { + const Context& context; + Recorder& recorder; + void* region; + std::size_t regionBytes; + void* block; + void* keys; + void* fmask; + void* dest; + std::size_t reserved; + std::uint64_t neighbour; + ~Release() { + { + std::lock_guard gpu(GpuMutex()); + recorder.Sync(); + ClearMultisampleTargets(context.device); + ClearCachedTextures(context.device); + recorder.FlushDeferredReleases(); + } + { + GuestAllocations::Mutation mutation; + mutation.Remove(block); + mutation.Remove(dest); + if (keys != nullptr) mutation.Remove(keys); + if (fmask != nullptr) mutation.Remove(fmask); + if (neighbour < reinterpret_cast(block) + reserved) mutation.Remove(reinterpret_cast(neighbour)); + } + HostImportFor(context, reinterpret_cast(block), 16); + SetHostImportDeferredSettles(true); + ReleaseWatched(region, regionBytes); + VirtualFree(dest, 0, MEM_RELEASE); + } + } release{context, recorder, region, regionBytes, block, keys, fmask, dest, reserved, kind == Case::ComparedNeighbour ? neighbour : std::numeric_limits::max()}; + target.address = address; + target.surfaceAddress = address; + target.bytes = colorBytes; + target.dccAddress = kind == Case::UnwatchedKeys ? reinterpret_cast(keys) : address + colorBytes; + std::memset(block, 0, importBytes); + std::memset(reinterpret_cast(target.dccAddress), 0xc0, dccBytes); + std::memset(dest, 0x5a, destBytes); + if (fmask != nullptr) { + target.cmaskAddress = target.dccAddress + ((dccBytes + 4095) & ~std::size_t{4095}); + target.cmaskBytes = CmaskBytes(target.extent.width, target.extent.height); + target.cmaskFastClear = true; + target.fmaskAddress = reinterpret_cast(fmask); + Require(target.cmaskAddress + target.cmaskBytes <= address + importBytes, "(m) the CMASK does not fit the target's import"); + std::memset(reinterpret_cast(target.cmaskAddress), 0xcc, static_cast(target.cmaskBytes)); + std::memset(fmask, 0x11, fmaskBytes); + } + { + GuestAllocations::Mutation mutation; + mutation.Add(block, importBytes, true, true, true); + mutation.Add(dest, destBytes, true, true, true); + if (keys != nullptr) mutation.Add(keys, unit, true, true, true); + if (fmask != nullptr) mutation.Add(fmask, fmaskBytes, true, true, true); + if (kind == Case::ComparedNeighbour) mutation.Add(reinterpret_cast(neighbour), reserved - (importBytes + tail), true, true, true); + } + if (kind == Case::UnwatchedKeys) Unwatch(target.dccAddress, dccBytes); + if (kind == Case::DeferredOff) SetHostImportDeferredSettles(false); + if (kind == Case::ComparedNeighbour) { + const auto* other = HostImportFor(context, neighbour, reserved - (importBytes + tail)); + Require(other != nullptr && other->unwatched && !Watched(neighbour, reserved - (importBytes + tail)), "(m) the import sharing the target's last 64 KiB block was not compared" + describe(other, neighbour, reserved - (importBytes + tail))); + } + if (fmask != nullptr && !fmaskAlone) { + const auto* fmaskImport = HostImportFor(context, target.fmaskAddress, fmaskBytes); + Require(fmaskImport != nullptr && fmaskImport->base == target.fmaskAddress && fmaskImport->bytes == fmaskBytes && fmaskImport->unwatched && !Watched(target.fmaskAddress, fmaskBytes), "(m) the FMASK's import was not compared at first" + describe(fmaskImport, target.fmaskAddress, fmaskBytes)); + } + const auto* import = HostImportFor(context, address, importBytes); + Require(import != nullptr && import->base == address && import->bytes == importBytes && import->unwatched && !Watched(address, importBytes), "(m) the target's import of " + std::to_string(importBytes) + " bytes was not compared at first" + describe(import, address, importBytes)); + HostImportSettleCounts quiet{}; + if (fmaskAlone) { + { + std::lock_guard gpu(GpuMutex()); + const auto start = HostImportSettles(); + Require(WatchedAfterSettle(context, address, importBytes), "(m) the target's import did not settle before the FMASK's import" + describe(ExistingHostImportFor(context, address, importBytes), address, importBytes)); + const auto settledTarget = HostImportSettles(); + Require(settledTarget.submitted > start.submitted && settledTarget.rewatched > start.rewatched, "(m) the target's import returned to the write watch without a settle read"); + } + const std::array, 3> planes{{{address, colorBytes}, {target.dccAddress, dccBytes}, {target.cmaskAddress, static_cast(target.cmaskBytes)}}}; + for (const auto& [at, bytes] : planes) { + const auto* covering = ExistingHostImportFor(context, at, bytes); + Require(Watched(at, bytes) && (covering == nullptr || !covering->unwatched), "(m) a color, DCC or CMASK plane is not watched before the FMASK's import" + describe(covering, at, bytes)); + } + quiet = HostImportSettles(); + const auto* fmaskImport = HostImportFor(context, target.fmaskAddress, fmaskBytes); + Require(fmaskImport != nullptr && fmaskImport->base == target.fmaskAddress && fmaskImport->bytes == fmaskBytes && fmaskImport->unwatched && !fmaskImport->settleOnDemand && !Watched(target.fmaskAddress, fmaskBytes), "(m) the FMASK's import is not compared with its deferred settle wanted" + describe(fmaskImport, target.fmaskAddress, fmaskBytes)); + } + std::unique_lock gpu(GpuMutex()); + if (partial) { + for (int round = 0; round < 20; ++round) { + gpu.unlock(); + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + gpu.lock(); + HostImportFor(context, address, importBytes); + } + Require(!Watched(address, importBytes), "(m) a deferred settle returned an import that is not a whole number of 64 KiB blocks to the write watch"); + } + const auto before = HostImportSettles(); + Require(!fmaskAlone || before.submitted == quiet.submitted, "(m) a settle read was submitted between the FMASK's import and the target's first use"); + std::string refusal; + try { + Require(MultisampleTargetView(context, target) != VK_NULL_HANDLE, "(m) the multisampled DCC target has no view"); + } catch (const std::exception& error) { + refusal = error.what(); + } + const auto after = HostImportSettles(); + const auto* settled = ExistingHostImportFor(context, address, importBytes); + const char* name = kind == Case::Pending ? "a pending settle" : kind == Case::PartialBlock ? "an import of whole and partial 64 KiB blocks" : kind == Case::ComparedNeighbour ? "a compared import in its last 64 KiB block" : kind == Case::DeferredOff ? "deferred settles off" : kind == Case::UnwatchedKeys ? "explicitly unwatched DCC keys" : kind == Case::PendingFmask ? "an eight-sample target whose color and FMASK imports both have pending settles" : "an eight-sample target whose FMASK alone has a pending settle"; + std::cout << "(m) initial DCC over " << name << " (import " << importBytes << " bytes): " << (refusal.empty() ? "accepted" : refusal) << "; " << after.submitted - before.submitted << " settle reads submitted, " << after.rewatched - before.rewatched << " back in the write watch\n"; + if (kind == Case::ComparedNeighbour || kind == Case::DeferredOff || kind == Case::UnwatchedKeys) { + Require(refusal.find("initial multisampled DCC contents require watched guest memory") != std::string::npos, std::string("(m) an initial multisampled DCC import over ") + name + " was not refused: " + refusal); + Require(kind == Case::UnwatchedKeys || !Watched(address, importBytes), std::string("(m) ") + name + " returned the target's import to the write watch"); + Require(kind != Case::UnwatchedKeys || (Watched(address, importBytes) && !Watched(target.dccAddress, dccBytes)), "(m) the refusal over explicitly unwatched DCC keys did not come from the keys" + describe(settled, address, importBytes)); + return; + } + Require(refusal.empty(), std::string("(m) an initial multisampled DCC import over ") + name + " was refused: " + refusal); + Require(!fmaskAlone || (after.submitted - before.submitted == 1 && after.rewatched - before.rewatched == 1), "(m) the first use over a pending FMASK settle alone submitted " + std::to_string(after.submitted - before.submitted) + " settle reads, not the FMASK's alone"); + Require(after.submitted > before.submitted && after.rewatched > before.rewatched && Watched(address, importBytes) && settled != nullptr && !settled->unwatched, std::string("(m) the initial DCC import over ") + name + " did not settle the import and return it to the write watch"); + if (fmask != nullptr) { + const auto* settledFmask = ExistingHostImportFor(context, target.fmaskAddress, fmaskBytes); + Require(Watched(target.fmaskAddress, fmaskBytes) && settledFmask != nullptr && !settledFmask->unwatched, "(m) the FMASK's import did not settle back into the write watch" + describe(settledFmask, target.fmaskAddress, fmaskBytes)); + } + ColorTarget destination{}; + destination.address = reinterpret_cast(dest); + destination.surfaceAddress = destination.address; + destination.extent = target.extent; + destination.surfaceExtent = target.extent; + destination.format = VK_FORMAT_R8G8B8A8_UNORM; + destination.elementBytes = 4; + destination.bytes = destBytes; + destination.samples = 1; + destination.tileMode = ColorTileMode::RenderTarget; + RunColorMetadataPass(context, {ColorMetadataPass::Mode::Resolve, {destination}, target}); + recorder.Submit(); + device.WaitQueue(); + recorder.Sync(); + std::vector resolved(destBytes / 4); + AgcDriver::GuestMemory::Read(destination.address, std::as_writable_bytes(std::span(resolved))); + Require(std::ranges::all_of(resolved, [](std::uint32_t word) { return word == 0xffffffffu; }), std::string("(m) the target made over ") + name + " did not start from its DCC fast clear"); + BumpCollectEpoch(); + if (fmask != nullptr) { + const auto collectedFmask = CollectWrites(target.fmaskAddress, fmaskBytes); + Require(collectedFmask != 0, "(m) the settled FMASK import is not collected"); + static_cast(fmask)[0] = 0x22; + std::string fmaskReuse; + try { + MultisampleTargetView(context, target); + } catch (const std::exception& error) { + fmaskReuse = error.what(); + } + Require(fmaskReuse.find("writes to a resident native FMASK are not implemented") != std::string::npos, "(m) the resident target missed the CPU store to its FMASK: " + fmaskReuse); + return; + } + const auto collected = CollectWrites(address, importBytes); + Require(collected != 0, "(m) the settled import is not collected"); + static_cast(block)[importBytes - 1] = 0x77; + static_cast(block)[colorBytes] = 0x00; + CollectWritesUncached(address, importBytes); + Require(!UnchangedSince(address + importBytes - 1, 1, collected) && !UnchangedSince(address + colorBytes, 1, collected), "(m) a CPU store after the initial DCC import was missed"); + std::string reuse; + try { + MultisampleTargetView(context, target); + } catch (const std::exception& error) { + reuse = error.what(); + } + Require(reuse.find("writes to a resident multisampled DCC target or its metadata are not implemented") != std::string::npos, "(m) the resident target missed the CPU store to its DCC keys: " + reuse); + }; + run(Case::Pending, 128); + run(Case::PartialBlock, 384); + run(Case::ComparedNeighbour, 384); + run(Case::DeferredOff, 128); + run(Case::UnwatchedKeys, 128); + run(Case::PendingFmask, 128); + run(Case::PendingFmaskAlone, 128); + std::cout << "initial multisampled DCC over a pending settle tests passed\n"; + return true; +} #endif void remappedImportTests(const Device& device) { @@ -2694,8 +2978,8 @@ void secondMappingImportTests(const Device& device) { void* alias = nullptr; std::int64_t physical = -1; ~Release() { - if (alias != nullptr) sceKernelMunmap(alias, page); - if (mapping != nullptr) sceKernelMunmap(mapping, bytes); + if (alias != nullptr) sceKernelMunmap(reinterpret_cast(alias), page); + if (mapping != nullptr) sceKernelMunmap(reinterpret_cast(mapping), bytes); if (physical >= 0) sceKernelReleaseDirectMemory(physical, bytes); } } release; @@ -2766,7 +3050,7 @@ int reimportBench(const Device& device) { void* mapping = nullptr; std::int64_t physical = -1; ~Release() { - if (mapping != nullptr) sceKernelMunmap(mapping, bytes); + if (mapping != nullptr) sceKernelMunmap(reinterpret_cast(mapping), bytes); if (physical >= 0) sceKernelReleaseDirectMemory(physical, bytes); } }; @@ -2916,8 +3200,8 @@ int hostImportCutTests(const Device& device) { std::size_t holeBytes = 0; ~Backing() { auto* memory = static_cast(mapping); - if (memory != nullptr && hole != 0) sceKernelMunmap(memory, hole); - if (memory != nullptr && hole + holeBytes < bytes) sceKernelMunmap(memory + hole + holeBytes, bytes - hole - holeBytes); + if (memory != nullptr && hole != 0) sceKernelMunmap(reinterpret_cast(memory), hole); + if (memory != nullptr && hole + holeBytes < bytes) sceKernelMunmap(reinterpret_cast(memory + hole + holeBytes), bytes - hole - holeBytes); if (physical >= 0) sceKernelReleaseDirectMemory(physical, bytes); } }; @@ -2946,7 +3230,7 @@ int hostImportCutTests(const Device& device) { auto* cut = memory + test.offset; gpu.unlock(); if (test.unmap) { - Require(sceKernelMunmap(cut, test.length) == 0, name + ": the unmap failed"); + Require(sceKernelMunmap(reinterpret_cast(cut), test.length) == 0, name + ": the unmap failed"); backing.hole = test.offset; backing.holeBytes = test.length; } else { @@ -2996,7 +3280,7 @@ int hostImportCutTests(const Device& device) { Require(whole != nullptr && whole->base == address && whole->bytes == bytes && whole->alias == nullptr && !whole->unwatched, name + ": the range was not imported whole, settled and watched"); gpu.unlock(); Require(sceKernelMprotect(memory, run, 0x03) == 0, name + ": the protection of the head failed"); - Require(sceKernelMunmap(memory + run, bytes - run) == 0, name + ": the unmap of the kept side failed"); + Require(sceKernelMunmap(reinterpret_cast(memory + run), bytes - run) == 0, name + ": the unmap of the kept side failed"); backing.hole = run; backing.holeBytes = bytes - run; void* again = memory + run; @@ -3430,7 +3714,7 @@ bool readWrittenStagingTests(const Device& device, Recorder& recorder) { std::cout << "host imports unavailable: read and written staging not tested\n"; return false; } - constexpr std::size_t bytes = 16u << 20u; + constexpr std::size_t bytes = 40u << 20u; #ifdef _WIN32 void* block = VirtualAlloc(nullptr, bytes, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); #else @@ -3463,9 +3747,8 @@ bool readWrittenStagingTests(const Device& device, Recorder& recorder) { Require(boundInPlace(address + 4096, 4u << 20u, false) != context.discreteGpu, context.discreteGpu ? "a written-only 4 MiB element was bound in place on a discrete GPU" : "a written-only 4 MiB element was staged past the written window"); Require(boundInPlace(address + 4096, 12u << 20u, false), "a written-only 12 MiB element was staged past the discrete written window"); Require(!boundInPlace(address + 4096, 4u << 20u, true), "a read and written 4 MiB element was bound in place"); - const auto buildInPlace = [&](std::uint64_t dispatchThreads, bool read, std::uint32_t stride, std::uint32_t extent) { + const auto buildInPlace = [&](std::uint64_t dispatchThreads, bool read, std::uint32_t stride, std::uint32_t extent, std::uint32_t elementBytes = 12u << 20u) { const auto element = address + 4096; - constexpr std::uint32_t elementBytes = 12u << 20u; const std::uint32_t records = stride != 0 ? elementBytes / stride : elementBytes; ShaderRecompiler::RecompileResult program; ShaderRecompiler::DescriptorBinding binding; @@ -3490,7 +3773,12 @@ bool readWrittenStagingTests(const Device& device, Recorder& recorder) { Require(!buildInPlace((12u << 20u) / 16u, true, 16, 0), "a dispatch sweeping a read and written 12 MiB element bound it in place"); Require(buildInPlace(1024, true, 16, 0), "a dispatch touching 16 KiB of a read and written 12 MiB element staged all of it"); Require(buildInPlace(0, true, 16, 0), "a dispatch of unknown size staged a read and written 12 MiB element"); - Require(buildInPlace((12u << 20u) / 16u, false, 16, 0), "a dispatch sweeping a written-only 12 MiB element staged it"); + Require(buildInPlace((12u << 20u) / 32u, false, 32, 0) != context.discreteGpu, context.discreteGpu ? "a dispatch sweeping a written-only 12 MiB element of 32-byte records bound it in place on a discrete GPU" : "a dispatch sweeping a written-only 12 MiB element of 32-byte records staged it on a GPU without separate VRAM"); + Require(buildInPlace((12u << 20u) / 16u, false, 16, 0), "a dispatch sweeping a written-only 12 MiB element of 16-byte records, which its stores write contiguously, staged it"); + Require(buildInPlace(1024, false, 32, 0), "a dispatch touching 32 KiB of a written-only 12 MiB element staged all of it"); + Require(buildInPlace((12u << 20u) / 32u, false, 0, 32), "a dispatch writing a written-only 12 MiB raw element staged it"); + Require(buildInPlace(204800, false, 160, 0, 204800u * 160u) != context.discreteGpu, context.discreteGpu ? "a dispatch sweeping a written-only 31.25 MiB element of 160-byte records bound it in place on a discrete GPU" : "a dispatch sweeping a written-only 31.25 MiB element of 160-byte records staged it on a GPU without separate VRAM"); + Require(buildInPlace(204800, true, 160, 0, 204800u * 160u) != context.discreteGpu, context.discreteGpu ? "a dispatch sweeping a read and written 31.25 MiB element bound it in place on a discrete GPU" : "a dispatch sweeping a read and written 31.25 MiB element staged it past the 16 MiB cap on a GPU without separate VRAM"); Require(!buildInPlace((12u << 20u) / 32u, true, 0, 32), "a dispatch sweeping a read and written 12 MiB raw element bound it in place"); Require(buildInPlace(1024, true, 0, 32), "a dispatch touching 32 KiB of a read and written 12 MiB raw element staged all of it"); Require(buildInPlace((12u << 20u) / 32u, true, 0, 0), "a raw element without an access extent was staged"); @@ -6944,7 +7232,6 @@ void refreshProofTests(const Device& device, Recorder& recorder) { recorder.Sync(); } - void unchangedCpuStampTests(const Device& device, Recorder& recorder) { const auto& base = device.GetContext(); constexpr std::uint32_t side = 256; @@ -7094,7 +7381,7 @@ void keptUnitSettleTests(const Device& device, Recorder& recorder) { return; } if (direct) { - if (block != nullptr) sceKernelMunmap(block, surfaceBytes); + if (block != nullptr) sceKernelMunmap(reinterpret_cast(block), surfaceBytes); if (physical >= 0) sceKernelReleaseDirectMemory(physical, surfaceBytes); return; } @@ -10979,6 +11266,14 @@ int main(int argc, char** argv) { importWatchTests(device); return 0; } + if (argc == 2 && std::string_view(argv[1]) == "--settle-initial-dcc-only") { +#ifdef _WIN32 + return settleInitialDccTests(device) ? 0 : 77; +#else + std::cout << "skipped, the device has no deferred settle of host imports: imports under 1 MiB wait for one only on Windows\n"; + return 77; +#endif + } #ifdef _WIN32 if (argc == 2 && std::string_view(argv[1]) == "--host-import-lifetime-other-family-only") { if (device.GetContext().settleFamily == device.GetContext().queueFamily) { diff --git a/core/libs/prx/libSceAgcDriver/tests/RedundantValueElimination.cpp b/core/libs/prx/libSceAgcDriver/tests/RedundantValueElimination.cpp index 8dfde5e87e..202aa559ae 100644 --- a/core/libs/prx/libSceAgcDriver/tests/RedundantValueElimination.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/RedundantValueElimination.cpp @@ -209,7 +209,8 @@ std::vector Recompiled(std::span code) { request.target.maxWorkgroupSharedMemoryBytes = 49152; request.layout = {0, 0, 0, 128}; request.useCache = false; - const auto& words = Recompile(request).spirv.Words(); + const auto result = Recompile(request); + const auto& words = result.spirv.Words(); return {words.begin(), words.end()}; } diff --git a/core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp b/core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp index 4d7e4dc551..0037bdb37f 100644 --- a/core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp @@ -406,6 +406,36 @@ void verifyFrontendPair() { } } +void verifySpecializedModuleRelease() { + using namespace ShaderRecompiler; + const std::array color{0x3f800000u}; + const std::vector code{0xbf800003u, 0x7e000200u, 0xf800180fu, 0u, 0xbf810000u}; + auto pixel = FrontendRequest(code, color); + pixel.shader.stage = ShaderStage::Fragment; + pixel.context.compute.reset(); + pixel.context.pixel = ShaderPixelStageInfo{}; + pixel.context.pixel->wave32 = true; + pixel.context.pixel->targetOutputMode[0] = 9u; + pixel.context.waveSize = 32u; + pixel.useCache = true; + SharedSpirv::Weak released; + std::uint64_t specializationId = 0; + std::vector words; + { + const auto first = Recompile(pixel); + require(first.specializationId != 0u, "specialized module release: the pixel fixture was not specialized"); + released = first.spirv.Weaken(); + specializationId = first.specializationId; + words = first.spirv.Copy(); + } + require(released.Expired(), "specialized module release: the module caches kept the words of a module no result uses"); + const auto again = Recompile(pixel); + require(again.specializationId == specializationId, "specialized module release: a module built again from its key got another specialization ID"); + require(std::ranges::equal(again.spirv.Words(), words), "specialized module release: a module built again from its key has other words"); + const auto shared = Recompile(pixel); + require(shared.spirv.data() == again.spirv.data(), "specialized module release: a second result of a live module copied its words"); +} + ShaderRecompiler::RecompileRequest LayoutPairRequest(std::span code, std::span userData, bool registration, std::uint32_t wordLimit) { using namespace ShaderRecompiler; auto request = FrontendRequest(code, userData); @@ -2339,7 +2369,10 @@ void verifyTableSnapshotReuse() { const auto otherBuffer = CompileTable(request); std::copy(outputV.begin(), outputV.end(), guest.srt.begin() + 12); const auto resolvedShared = ResourceMaterializer::TableReuse(); - require(otherBuffer.result != compiled.result && otherBuffer.result->variantId == compiled.result->variantId && resolvedShared.resolutionsShared - resolvedBefore.resolutionsShared == 1u && resolvedShared.resolutions == resolvedBefore.resolutions && TableMap(*otherBuffer.result) == map && TableBinding(*otherBuffer.result, DescriptorRole::ImageTable)->guestDescriptor == images->guestDescriptor, "table snapshot reuse: a result for another buffer did not reuse the unchanged table's resolution"); + const bool resolves = std::getenv("APS5_NO_MASKED_RESULT_MEMO") != nullptr || std::getenv("APS5_VERIFY_MASKED_RESULT_MEMO") != nullptr; + require(otherBuffer.result != compiled.result && otherBuffer.result->variantId == compiled.result->variantId && resolvedShared.resolutionsShared - resolvedBefore.resolutionsShared == (resolves ? 1u : 0u) && resolvedShared.resolutions == resolvedBefore.resolutions && TableMap(*otherBuffer.result) == map && TableBinding(*otherBuffer.result, DescriptorRole::ImageTable)->guestDescriptor == images->guestDescriptor, "table snapshot reuse: a result for another buffer did not reuse the unchanged table's resolution"); + const auto* otherBuffers = TableBinding(*otherBuffer.result, DescriptorRole::GuestBuffers); + require(otherBuffers != nullptr && std::search(otherBuffers->guestDescriptor.begin(), otherBuffers->guestDescriptor.end(), otherOutputV.begin(), otherOutputV.end()) != otherBuffers->guestDescriptor.end(), "table snapshot reuse: a result for another buffer does not hold that buffer's descriptor"); const auto storedWord = heap[5u * 8u]; heap[5u * 8u] = heap[6u * 8u]; const auto restoredMap = map; @@ -3364,6 +3397,19 @@ void verifyImageTableRegistration() { const auto* atomicTable = TableBinding(*atomic.result, DescriptorRole::ImageStorageTable); require((atomicFault & Abi::PoisonFlag) == 0u && atomicTable != nullptr && atomicTable->count != 0u && atomicTable->imageAtomic.size() == atomicTable->count && std::all_of(atomicTable->imageWritten.begin(), atomicTable->imageWritten.end(), [](bool written) { return written; }) && std::all_of(atomicTable->imageAtomic.begin(), atomicTable->imageAtomic.end(), [](bool atomic) { return atomic; }), "image table registration: the image_atomic_add table was not bound as atomic storage elements"); require(TableBinding(*atomic.result, DescriptorRole::ImageTable) == nullptr || TableBinding(*atomic.result, DescriptorRole::ImageTable)->count == 0u, "image table registration: an atomic-only table bound sampled elements"); + auto atomic64Code = storeCode; + atomic64Code[8] = 0xf0440308u; + guest.heap[0] = TableT(texture.bytes.data(), TableFormat32_32UInt, TableType2D); + static constexpr std::array int64ImageCapabilities{29u, spv::CapabilityInt64, spv::CapabilityPhysicalStorageBufferAddresses, spv::CapabilityStorageBuffer8BitAccess, spv::CapabilityInt64ImageEXT}; + auto atomic64Request = TableRequest(atomic64Code, userData); + atomic64Request.target.supportedCapabilities = int64ImageCapabilities; + const auto atomic64 = CompileTable(atomic64Request); + const auto& atomic64Plan = *atomic64.capture->plan; + require(atomic64Plan.info.images.size() == 1u && atomic64Plan.info.images[0].table == 0u && atomic64Plan.info.images[0].tableOperation == TableOperation::Supported, "image table registration: a table T# feeding image_atomic64_add was not a supported table operation"); + const auto& atomic64Map = TableMap(*atomic64.result); + const auto atomic64Fault = atomic64Map[Abi::TableHeader(0) + Abi::TableFault]; + const auto* atomic64Table = TableBinding(*atomic64.result, DescriptorRole::ImageStorageTable); + require((atomic64Fault & Abi::PoisonFlag) == 0u && atomic64Table != nullptr && atomic64Table->count != 0u && atomic64Table->imageAtomic64.size() == atomic64Table->count && std::all_of(atomic64Table->imageAtomic64.begin(), atomic64Table->imageAtomic64.end(), [](bool atomic) { return atomic; }), "image table registration: the image_atomic64_add table was not bound as 64-bit atomic storage elements"); const std::array, 2> unsupportedStores{{{0xf0240f08u, "image_store_mip"}, {0xf0280f08u, "image_store_pck"}}}; for (const auto& [instruction, name] : unsupportedStores) { auto code = storeCode; @@ -3794,7 +3840,7 @@ void verifySelectedRecordDirectOperations() { require(word0 == 0xf0440308u || (TableBinding(*compiled.result, DescriptorRole::ImageTable) == nullptr && compiled.result->imageTableFaults == 0u && TableCovered(compiled.regions, &heap[2], sizeof(heap[2]))), (what + " through a T# whose record the CPU evaluates was not bound from its record").c_str()); const auto wholeCode = WithImageOperation(TableWholeCode, word0, false); const auto whole = GetResourcePlan(TableRequest(wholeCode, userData)); - require(whole->info.images.size() == 1u && whole->info.images[0].table == 0u && whole->info.images[0].tableOperation == (word0 == 0xf0200f08u || word0 == 0xf0440108u ? TableOperation::Supported : TableOperation::Unsupported), (what + " through a T# keyed per lane left the image table or has the wrong table operation").c_str()); + require(whole->info.images.size() == 1u && whole->info.images[0].table == 0u && whole->info.images[0].tableOperation == (word0 == 0xf0200f08u || word0 == 0xf0440108u || word0 == 0xf0440308u ? TableOperation::Supported : TableOperation::Unsupported), (what + " through a T# keyed per lane left the image table or has the wrong table operation").c_str()); } const auto mixedCode = WithImageOperation(TableSrtKeyCode, 0xf0200f08u, true); const auto mixed = GetResourcePlan(TableRequest(mixedCode, userData)); @@ -8530,6 +8576,7 @@ int main(int argc, char** argv) { verifyTargetFeatureKey(); verifyImageTableKeys(); verifyImageTables(); + verifySpecializedModuleRelease(); verifyImageTableRegistration(); verifyScalarAddressRule(); verifyPointerImageTable(); diff --git a/core/libs/prx/libSceAgcDriver/tests/SharedWrites.cpp b/core/libs/prx/libSceAgcDriver/tests/SharedWrites.cpp index f1fe06c422..496fb288c5 100644 --- a/core/libs/prx/libSceAgcDriver/tests/SharedWrites.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/SharedWrites.cpp @@ -1,3 +1,4 @@ +#include "prx/libkernel/include/Api.hpp" #include "prx/libSceAgcDriver/Execution/include/GuestMemory.hpp" #include "prx/libc/include/GuestWriteWatch.hpp" #include "prx/libc/include/GuestArena.hpp" @@ -17,14 +18,6 @@ #include #endif -extern "C" { -int APS5_VABI sceKernelAllocateDirectMemory(std::int64_t, std::int64_t, std::size_t, std::size_t, int, std::int64_t*); -int APS5_VABI sceKernelMapDirectMemory(void**, std::size_t, int, int, std::int64_t, std::size_t); -int APS5_VABI sceKernelReleaseDirectMemory(std::int64_t, std::size_t); -int APS5_VABI sceKernelMunmap(void*, std::size_t); -int APS5_VABI sceKernelMprotect(const void*, std::size_t, int); -} - namespace { using namespace AgcDriver::GuestMemory; void require(bool condition, const char* reason) { if (!condition) throw std::runtime_error(reason); } @@ -36,13 +29,14 @@ struct Mapping { require(sceKernelAllocateDirectMemory(0, 0x10000000000ll, size, 65536, 3, &physical) == 0, "allocate direct memory failed"); if (sceKernelMapDirectMemory(&data, size, 3, 0, physical, 65536) != 0) { sceKernelReleaseDirectMemory(physical, size); + throw std::runtime_error("map direct memory failed"); } } Mapping(const Mapping&) = delete; Mapping& operator=(const Mapping&) = delete; ~Mapping() { - if (data != nullptr) sceKernelMunmap(data, size); + if (data != nullptr) sceKernelMunmap(reinterpret_cast(data), size); if (physical >= 0) sceKernelReleaseDirectMemory(physical, size); } std::uint64_t Address() const { return reinterpret_cast(data); } @@ -180,7 +174,7 @@ void partialCollect() { require(collect(alias, 0, mapping.size, 4, true) == std::vector{page, page * 2}, "writes to two pages were not reported apart"); require(collect(mapping.data, 0, mapping.size, 4, true) == std::vector{page, page * 2}, "writes to two pages were not reported for their own view"); require(collect(mapping.data, 0, mapping.size, 4, false).empty() && collect(alias, 0, mapping.size, 4, false).empty(), "page tracking did not settle"); - require(sceKernelMunmap(alias, mapping.size) == 0, "partial collect alias unmap failed"); + require(sceKernelMunmap(reinterpret_cast(alias), mapping.size) == 0, "partial collect alias unmap failed"); #endif std::cout << "Partial shared write collection tests passed\n"; } @@ -253,14 +247,14 @@ void run() { require(std::memcmp(replacement.data, across.data() + part, part) == 0, "physical alias did not see the write"); require(std::all_of(static_cast(originalAlias), static_cast(originalAlias) + part, [](auto x) { return x == std::byte{29}; }), "replaced virtual range wrote the old backing"); #ifndef _WIN32 - require(sceKernelMunmap(middle, part) == 0, "partial unmap failed"); + require(sceKernelMunmap(reinterpret_cast(middle), part) == 0, "partial unmap failed"); const auto saved = bytes[0]; across[0] = std::byte{99}; require(!GuestArena::GuestArenaWriteSharedBacking_nid_no_patch(mapping.Address(), across.data(), across.size()), "writer accepted an unmapped gap"); require(bytes[0] == saved, "failed shared write changed its prefix"); #endif require(sceKernelMapDirectMemory(&middle, part, 3, 0x10, mapping.physical + part, part) == 0, "original backing restore failed"); - require(sceKernelMunmap(originalAlias, part) == 0, "alias unmap failed"); + require(sceKernelMunmap(reinterpret_cast(originalAlias), part) == 0, "alias unmap failed"); } std::vector threads; for (unsigned i = 0; i < 8; ++i) threads.emplace_back([&, i] { diff --git a/core/libs/prx/libSceAgcDriver/tests/SpirvModule.cpp b/core/libs/prx/libSceAgcDriver/tests/SpirvModule.cpp index 05d848cdf2..956897cb51 100644 --- a/core/libs/prx/libSceAgcDriver/tests/SpirvModule.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/SpirvModule.cpp @@ -460,6 +460,20 @@ void testInternedSpirvSharesEqualWords() { check(edited[6] == spv::CapabilityFloat64 && first[6] == spv::CapabilityShader && again.data() == first.data(), "a write to one holder of interned SPIR-V changed the others"); } +void testInternedSpirvReleasesUnusedWords() { + const std::vector words{spv::MagicNumber, 0x00010400u, 0u, 7u, 0u, (2u << 16u) | spv::OpCapability, spv::CapabilityGeometry}; + SharedSpirv::Weak released; + { + const auto first = InternSpirv(words); + const auto second = InternSpirv(words); + check(first.data() == second.data(), "two equal specialized modules kept separate copies of their words"); + released = first.Weaken(); + } + check(released.Expired(), "the SPIR-V interning table kept words no holder uses"); + const auto again = InternSpirv(words); + check(std::ranges::equal(again.Words(), words) && released.Lock().empty(), "SPIR-V interned again after its release changed its words"); +} + int main() { testFoldingLeavesNoDeadBlocksOrConstants(); testIdsBeyondTheBoundAreRejected(); @@ -477,6 +491,7 @@ int main() { testEmittedWordsAreStable(); testBlockBallotsOfOnePredicateShareOneBallot(); testInternedSpirvSharesEqualWords(); + testInternedSpirvReleasesUnusedWords(); if (failures != 0) { std::fprintf(stderr, "%d check(s) failed\n", failures); return 1; diff --git a/core/libs/prx/libSceAgcDriver/tests/Submit.cpp b/core/libs/prx/libSceAgcDriver/tests/Submit.cpp index d97862941b..d2e874a808 100644 --- a/core/libs/prx/libSceAgcDriver/tests/Submit.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/Submit.cpp @@ -1,3 +1,4 @@ +#include "prx/libkernel/include/Api.hpp" #include "prx/libSceAgcDriver/Execution/include/Driver.hpp" #include "execution/VulkanTestDevice.hpp" #include "prx/libSceAgcDriver/Execution/include/QueueState.hpp" @@ -31,9 +32,6 @@ #include #endif -extern "C" int APS5_VABI sceKernelCreateEqueue(KernelEqueue* eq, const char* name); -extern "C" int APS5_VABI sceKernelDeleteEqueue(KernelEqueue eq); - static_assert(sizeof(Packet) == 16); static_assert(offsetof(Packet, addr) == 0); static_assert(offsetof(Packet, dw_num) == 8); @@ -593,8 +591,7 @@ void testSmallCopyBehindPendingSource() { waitFor(&copied, 1, "the label after a small copy behind a pending source never landed"); AgcDriverWaitIdle_nid_postfix(); check(std::equal(destination, destination + smallWords, produced), "a small copy did not see the GPU copy into its source before it"); - if (std::getenv("APS5_COPY_SYNC") != nullptr) check(AgcDriver::DriverDetail::copiesBehindPendingSources.load() == before, "a small copy that has to wait for a completion store over its source went through the GPU copy"); - else check(AgcDriver::DriverDetail::copiesBehindPendingSources.load() == before + 1, "a small copy whose source the GPU still stores into was not recorded on the GPU"); + check(AgcDriver::DriverDetail::copiesBehindPendingSources.load() == before, "a small copy queued behind the pipeline write into its source was recorded inline"); std::fill(destination, destination + smallWords, 0u); const auto settled = AgcDriver::DriverDetail::copiesBehindPendingSources.load(); submit(0, commands(memoryCopy(destination, produced, smallBytes), writeData(&settledCopied, 1))); diff --git a/core/libs/prx/libSceAgcDriver/tests/TessellationFactorRing.cpp b/core/libs/prx/libSceAgcDriver/tests/TessellationFactorRing.cpp index f302a0d119..c6bbb71920 100644 --- a/core/libs/prx/libSceAgcDriver/tests/TessellationFactorRing.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/TessellationFactorRing.cpp @@ -1,14 +1,10 @@ +#include "prx/libSceAgcDriver/State/include/Configuration.hpp" #include "SceTypes.hpp" #include #include #include #include -extern "C" { -int APS5_VABI sceAgcDriverSetTFRing(const volatile void* base, uint32_t size); -int APS5_VABI sceAgcDriverGetTFRing(uintptr_t* base, uint32_t* size); -} - namespace { constexpr uint32_t Canary = 0xa5a5a5a5; diff --git a/core/libs/prx/libSceAgcDriver/tests/TessellationPipelineCache.cpp b/core/libs/prx/libSceAgcDriver/tests/TessellationPipelineCache.cpp new file mode 100644 index 0000000000..6c922e0bc9 --- /dev/null +++ b/core/libs/prx/libSceAgcDriver/tests/TessellationPipelineCache.cpp @@ -0,0 +1,31 @@ +#include "prx/libSceAgcDriver/Execution/include/TessellationPipelineCache.hpp" +#include + +namespace { + +struct Case { + VkDriverId driver; + bool usable; +}; + +constexpr Case Cases[]{ + {VK_DRIVER_ID_MOLTENVK, false}, + {VK_DRIVER_ID_MESA_RADV, true}, + {VK_DRIVER_ID_MESA_LLVMPIPE, true}, + {VK_DRIVER_ID_NVIDIA_PROPRIETARY, true}, + {VK_DRIVER_ID_AMD_PROPRIETARY, true}, + {VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS, true}, +}; + +} + +int main() { + int failures = 0; + for (const auto& item : Cases) { + if (AgcDriver::TessellationPipelineCacheUsable(item.driver) != item.usable) { + std::fprintf(stderr, "driver %d: expected tessellation pipelines %s the pipeline cache\n", static_cast(item.driver), item.usable ? "to use" : "not to use"); + ++failures; + } + } + return failures == 0 ? 0 : 1; +} diff --git a/core/libs/prx/libSceAgcDriver/tests/UnsupportedDiagnostics.cpp b/core/libs/prx/libSceAgcDriver/tests/UnsupportedDiagnostics.cpp index db2f77f1ec..3217dc0eb1 100644 --- a/core/libs/prx/libSceAgcDriver/tests/UnsupportedDiagnostics.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/UnsupportedDiagnostics.cpp @@ -1,8 +1,6 @@ +#include "prx/libSceAgcDriver/include/AgcDriver.hpp" #include "SceTypes.hpp" -extern "C" void* APS5_VABI sceAgcDriverGetCoredumpAddress(); -extern "C" int APS5_VABI sceAgcDriverSetTargetRingForDiag(); - int main() { if (sceAgcDriverGetCoredumpAddress() != nullptr) return 1; if (sceAgcDriverSetTargetRingForDiag() != static_cast(0x8A6D0001)) return 2; diff --git a/core/libs/prx/libSceAgcDriver/tests/WriteTracking.cpp b/core/libs/prx/libSceAgcDriver/tests/WriteTracking.cpp index af8efbc48e..f2fdcc6fdc 100644 --- a/core/libs/prx/libSceAgcDriver/tests/WriteTracking.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/WriteTracking.cpp @@ -36,6 +36,7 @@ constexpr std::size_t Block = 65536; #ifdef _WIN32 constexpr wchar_t HostHoleMode[] = L"--host-hole"; constexpr wchar_t ResidentRemapMode[] = L"--resident-direct-remap"; +constexpr wchar_t RewatchImportPagesMode[] = L"--rewatch-import-pages"; constexpr wchar_t RewatchedSharedMode[] = L"--rewatched-direct-shared"; constexpr wchar_t ImportAliasSharedMode[] = L"--import-alias-shared"; constexpr wchar_t SharedGenerationsMode[] = L"--compared-shared-generations"; @@ -712,13 +713,18 @@ void CheckRewatch() { const auto unwatched = UnwatchSerial(); Require(!Watched(imported, Block) && UntrackedHint(imported, Block) != 0, "the unwatched block does not read as untracked"); bytes[Block + 8] = 0x22; + const std::array, 1> unaligned{{{imported + 1, imported + Block}}}; + Rewatch(unaligned); + Require(!Watched(imported + 4096, Block - 4096) && UnwatchSerial() == unwatched, "a range that is not whole pages returned to the write watch"); const std::array, 1> partial{{{imported + 4096, imported + Block}}}; Rewatch(partial); - Require(!Watched(imported, Block) && UnwatchSerial() == unwatched, "part of a block returned to the write watch"); + Require(Watched(imported + 4096, Block - 4096) && !Watched(imported, 4096) && !Watched(imported, Block), "rewatching part of a block did not return exactly its pages to the write watch"); + const auto partly = UnwatchSerial(); + Require(partly != unwatched, "rewatching part of a block did not invalidate what was cached while it was unwatched"); const std::array, 1> first{{{imported, imported + Block}}}; Rewatch(first); Require(Watched(imported, Block) && !Watched(imported + Block, Block), "rewatching did not return exactly its block to the write watch"); - Require(UnwatchSerial() != unwatched, "rewatching did not invalidate what was cached while the block was unwatched"); + Require(UnwatchSerial() != partly, "rewatching did not invalidate what was cached while the block was unwatched"); Require(UntrackedHint(imported, Block) == 0, "a rewatched block still reads as untracked"); Require(!UnchangedSince(imported, Block, before) && StoredOver(imported, Block, before), "a block returned to the write watch reads as unchanged since before it left"); Require(!UnchangedSinceCollected(imported, Block, before), "a CPU store made while the block was unwatched reads as no CPU store"); @@ -740,6 +746,125 @@ void CheckRewatch() { GuestArena::GuestArenaRelease_nid_postfix(memory, 4 * Block); } +using RewatchSpan = std::array, 1>; + +RewatchSpan BlockSpan(std::uint64_t address, std::size_t bytes) { + return {{{address & ~std::uint64_t{Block - 1}, (address + bytes + Block - 1) & ~std::uint64_t{Block - 1}}}}; +} + +RewatchSpan PageSpan(std::uint64_t address, std::size_t bytes) { + return {{{address & ~std::uint64_t{4095}, (address + bytes + 4095) & ~std::uint64_t{4095}}}}; +} + +void PrintPageState(const char* page, const void* address) { + MEMORY_BASIC_INFORMATION info{}; + Require(VirtualQuery(address, &info, sizeof(info)) == sizeof(info), "cannot query a page next to an import"); + std::cout << page << ": State 0x" << std::hex << info.State << " Type 0x" << info.Type << " Protect 0x" << info.Protect << std::dec << '\n'; +} + +struct ImportFixture { + std::uint8_t* memory; + std::size_t reserved; + ImportFixture(std::size_t reservedBytes, std::size_t committed) : memory(static_cast(GuestArena::GuestArenaAllocate_nid_postfix(reservedBytes, Block))), reserved(reservedBytes) { + Require(memory != nullptr, "cannot reserve an import fixture"); + GuestArena::GuestArenaCommit_nid_postfix(memory, committed, PAGE_READWRITE, committed); + std::memset(memory, 0x11, committed); + BumpCollectEpoch(); + Require(CollectWrites(Base(), committed) != 0, "an import fixture was not collected"); + } + ImportFixture(const ImportFixture&) = delete; + ImportFixture& operator=(const ImportFixture&) = delete; + ~ImportFixture() { + GuestArena::GuestArenaReset_nid_postfix(memory, reserved); + GuestArena::GuestArenaRelease_nid_postfix(memory, reserved); + } + std::uint64_t Base() const { + return reinterpret_cast(memory); + } +}; + +void UnwatchImport(std::uint64_t address, std::size_t bytes) { + Require(ImportWatched(address, bytes, [] { return true; }, false) && !Watched(address, bytes), "an import that leaves the watch stayed watched"); +} + +void RequireRewatchedStores(std::uint64_t address, std::size_t bytes) { + BumpCollectEpoch(); + const auto collected = CollectWrites(address, bytes); + Require(collected != 0 && UnchangedSince(address, bytes, collected), "a rewatched import is not collected"); + *reinterpret_cast(address + bytes - 1) = 0x22; + CollectWritesUncached(address, bytes); + Require(!UnchangedSince(address + bytes - 1, 1, collected), "a CPU store into a rewatched import's last page was missed"); +} + +void CheckRewatchWholeBlockImport() { + constexpr std::size_t bytes = 4 * Block; + ImportFixture fixture(6 * Block, 6 * Block); + const auto import = fixture.Base() + Block; + const auto before = CollectWrites(fixture.Base(), 6 * Block); + UnwatchImport(import, bytes); + Require(PageSpan(import, bytes) == BlockSpan(import, bytes), "a whole-block import has a page span unlike its block span"); + Rewatch(PageSpan(import, bytes)); + Require(Watched(import, bytes), "a settled whole-block import did not return to the write watch"); + Require(!UnchangedSince(import, bytes, before) && UnchangedSince(fixture.Base(), Block, before) && UnchangedSince(import + bytes, Block, before), "rewatching a whole-block import did not stamp exactly its blocks"); + RequireRewatchedStores(import, bytes); +} + +void CheckRewatchImportTail() { + constexpr std::size_t bytes = 0xc4000; + ImportFixture fixture(13 * Block, bytes); + const auto import = fixture.Base(); + UnwatchImport(import, bytes); + PrintPageState("page past a 0xc4000-byte import", fixture.memory + bytes); + const auto unwatched = UnwatchSerial(); + Rewatch(BlockSpan(import, bytes)); + Require(!Watched(import, bytes) && UnwatchSerial() == unwatched, "the 64 KiB span past the import's committed pages returned to the write watch"); + Rewatch(PageSpan(import, bytes)); + Require(Watched(import, bytes), "a settled import whose size is not a whole block did not return to the write watch"); + Require(Watched(import + 12 * Block, bytes - 12 * Block) && !Watched(import, bytes + 1) && !Watched(import + bytes - 1, 2) && !Watched(import + bytes, 4096), "rewatching an import ending inside a block did not return exactly its pages"); + Require(UnwatchSerial() != unwatched && UntrackedHint(import, bytes) == 0, "a rewatched import still reads as unwatched"); + RequireRewatchedStores(import, bytes); +} + +void CheckRewatchUnalignedImport() { + constexpr std::size_t offset = 0x1000; + constexpr std::size_t bytes = 0xc4000; + constexpr std::size_t committed = 0xc8000; + ImportFixture fixture(13 * Block, committed); + const auto import = fixture.Base() + offset; + UnwatchImport(import, bytes); + PrintPageState("page past an import at block offset 0x1000", fixture.memory + committed); + Rewatch(BlockSpan(import, bytes)); + Require(!Watched(import, bytes), "the 64 KiB span past the committed pages around an import returned to the write watch"); + Rewatch(PageSpan(import, bytes)); + Require(Watched(import, bytes), "a settled import that does not start on a block did not return to the write watch"); + Require(!Watched(fixture.Base(), offset) && !Watched(import + bytes, 4096), "rewatching an import returned pages outside it"); + RequireRewatchedStores(import, bytes); +} + +void CheckRewatchImportBesideUnwatchedImport() { + constexpr std::size_t bytes = 0xc4000; + constexpr std::size_t otherBytes = 0x1c000; + ImportFixture fixture(14 * Block, 14 * Block); + const auto import = fixture.Base(); + const auto other = import + bytes; + UnwatchImport(import, bytes); + UnwatchImport(other, otherBytes); + Rewatch(PageSpan(import, bytes)); + Require(Watched(import, bytes), "an import sharing its last block with another unwatched import did not return to the write watch"); + Require(!Watched(other, 4096) && !Watched(import + 13 * Block - 4096, 4096) && !Watched(other + otherBytes - 4096, 4096), "rewatching an import returned another unwatched import's pages in its last block"); + Require(UntrackedHint(other, otherBytes) != 0, "an unwatched import beside a rewatched one does not read as untracked"); + RequireRewatchedStores(import, bytes); + Rewatch(PageSpan(other, otherBytes)); + Require(Watched(import, bytes + otherBytes), "rewatching the second import did not return both to the write watch"); +} + +void CheckRewatchImportPages() { + CheckRewatchWholeBlockImport(); + CheckRewatchImportTail(); + CheckRewatchUnalignedImport(); + CheckRewatchImportBesideUnwatchedImport(); +} + void CheckRewatchedDirectMemoryComparedWhenShared() { constexpr std::size_t bytes = 2 * Block; auto* memory = static_cast(GuestArena::GuestArenaAllocate_nid_postfix(2 * bytes, Block)); @@ -1773,6 +1898,10 @@ int main() { CheckResidentDirectMappingReuse(); return 0; } + if (std::wstring_view(GetCommandLineW()).ends_with(RewatchImportPagesMode)) { + CheckRewatchImportPages(); + return 0; + } if (std::wstring_view(GetCommandLineW()).ends_with(RewatchedSharedMode)) { CheckRewatchedDirectMemoryComparedWhenShared(); CheckImportedDirectMemoryComparedWhenShared(); diff --git a/core/libs/prx/libSceAgcDriver/tests/WriteWatchCoverage.cpp b/core/libs/prx/libSceAgcDriver/tests/WriteWatchCoverage.cpp index 62e56cfe52..121205b1a2 100644 --- a/core/libs/prx/libSceAgcDriver/tests/WriteWatchCoverage.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/WriteWatchCoverage.cpp @@ -99,6 +99,17 @@ int main() { coverage.Exclude(base + block, block, 43); require(coverage.Restore(base + block - page, 2 * page, 42), "a newer boundary page was not restored"); require(coverage.Covers(base + block - page, page) && !coverage.Covers(base + block, page), "a stale boundary mapping erased a newer neighbouring exclusion"); + constexpr std::size_t tail = 0xc4000; + coverage.Initialize(base, 14 * block); + coverage.Exclude(base, tail, 50); + require(coverage.Restore(base, tail, 51), "an import ending inside a block did not restore its pages"); + require(coverage.Covers(base, tail) && coverage.Covers(base + 12 * block, tail - 12 * block), "an import ending inside a block is not watched"); + require(!coverage.Covers(base, tail + 1) && !coverage.Covers(base + tail - 1, 2) && !coverage.Covers(base + tail, page) && !coverage.Covers(base, 13 * block), "a range past an import ending inside a block is watched"); + require(coverage.Covers(base + tail - page, page) && !coverage.Covers(base + 13 * block - page, page) && coverage.Covers(base + 13 * block, block), "an import ending inside a block changed the pages after it"); + coverage.Initialize(base, 14 * block); + coverage.Exclude(base + page, tail, 60); + require(coverage.Restore(base + page, tail, 61) && coverage.Covers(base + page, tail), "an import starting and ending inside blocks is not watched"); + require(!coverage.Covers(base, page) && !coverage.Covers(base, tail) && !coverage.Covers(base + page + tail, page) && !coverage.Covers(base + page, tail + 1), "an import starting and ending inside blocks watched pages outside it"); std::cout << "write watch coverage passed\n"; return 0; } catch (const std::exception& error) { diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/DccKeysFirstWrite.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/DccKeysFirstWrite.cpp index 6faa64b11e..5dc96d71c0 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/DccKeysFirstWrite.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/DccKeysFirstWrite.cpp @@ -1,4 +1,5 @@ #include "prx/libSceAgcDriver/Execution/include/GuestMemory.hpp" +#include "prx/libSceAgcDriver/Execution/include/QueueState.hpp" #include "prx/libSceAgcDriver/Execution/include/VulkanDevice.hpp" #include "prx/libSceAgcDriver/Graphics/include/ColorTargetLayout.hpp" #include "prx/libSceAgcDriver/Graphics/include/DccMetadata.hpp" @@ -7,7 +8,9 @@ #include "prx/libSceAgcDriver/Graphics/include/GuestTextureResource.hpp" #include "prx/libSceAgcDriver/Graphics/include/Recorder.hpp" #include "prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp" +#include "prx/libSceAgcDriver/Graphics/include/State.hpp" #include "prx/libSceAgcDriver/Graphics/include/Texture.hpp" +#include "prx/libSceAgcDriver/Graphics/include/TextureTiling.hpp" #include "prx/libc/include/GuestAllocations.hpp" #include "prx/libc/include/GuestArena.hpp" #include "prx/libc/include/GuestWriteWatch.hpp" @@ -826,6 +829,45 @@ void RunSharedImport(AgcDriver::VulkanDevice& device, std::uint8_t* block) { } +void RunMipmappedTarget(AgcDriver::VulkanDevice& device, std::uint8_t* block) { +#ifndef _WIN32 + constexpr std::uint32_t ChainSide = 64; + constexpr std::uint32_t ChainLevels = 7; + auto* texels = block; + auto* keys = block + KeysOffset; + const auto surface = AddressOf(texels); + const auto meta = AddressOf(keys); + std::memset(texels, 0x55, SurfaceBytes); + std::memset(keys, 0x00, KeyBytes); + AgcDriver::GuestMemory::BumpCollectEpoch(); + AgcDriver::Registers cx; + cx[0x318] = static_cast(surface >> 8u); + cx[0x390] = static_cast(surface >> 40u); + cx[0x31b] = 0; + cx[0x31c] = 0x10028028u; + cx[0x31d] = 0; + cx[0x3b0] = ((ChainLevels - 1u) << 28u) | ((ChainSide - 1u) << 14u) | (ChainSide - 1u); + cx[0x3b8] = 0x9000000u | (TileRenderTarget64KB << 14u) | (1u << 30u); + cx[0x325] = static_cast(meta >> 8u); + cx[0x3a8] = static_cast(meta >> 40u); + const auto color = AgcDriver::Graphics::DecodeColorBuffer(cx, 0); + const auto resource = AgcDriver::Graphics::SurfaceForTarget(color); + Require(color.mipCount == ChainLevels && color.dccAddress == 0 && resource.dccAddress == meta, "the resident surface of a mipmapped DCC color target has no keys"); + const auto bytes = AgcDriver::Graphics::DescribeSurface(resource).guestBytes; + Require(bytes <= SurfaceBytes, "the mip chain does not fit the test surface"); + std::lock_guard gpu(AgcDriver::GuestMemory::GpuMutex()); + const auto context = AgcDriver::VulkanDeviceTestAccess::ContextOf(device); + const auto image = AgcDriver::Graphics::CachedStorageSurface(context, resource); + Require(image->UploadedKeys() == DccKeys::Clear0000, "the resident image of a 0000-cleared mipmapped target was not cleared from its keys"); + image->MarkDirty(); + Require(AgcDriver::Graphics::CurrentDccKeys(meta, bytes) == DccKeys::Uncompressed, "the first write into a mipmapped DCC target left its keys cleared"); + Require(AgcDriver::Graphics::TextureClearKeys(resource, bytes) == DccKeys::Uncompressed, "a sampled view of a rendered mipmapped DCC target still reads its clear"); +#else + static_cast(device); + static_cast(block); +#endif +} + int main() { try { #ifdef _WIN32 @@ -866,6 +908,9 @@ int main() { std::optional uniform; uniform.emplace(false); RunUniformKeysBehindKernel(*device, uniform->Data()); + std::optional chain; + chain.emplace(false); + RunMipmappedTarget(*device, chain->Data()); #ifdef _WIN32 shared.emplace(true, true); RunSharedImport(*device, shared->Data()); diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/DeviceQueuePlan.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/DeviceQueuePlan.cpp index ca3c05ab27..032a78ccc8 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/DeviceQueuePlan.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/DeviceQueuePlan.cpp @@ -34,16 +34,40 @@ VkQueueFamilyProperties family(VkQueueFlags flags, std::uint32_t queues) { } std::string describe(const AgcDriver::DeviceQueuePlan& plan) { - return "main " + std::to_string(plan.mainCount) + " queues, settle " + (plan.settle ? std::to_string(plan.settleFamily) + ":" + std::to_string(plan.settleIndex) : std::string("none")) + ", sparse " + (!plan.sparseBinding ? std::string("none") : plan.sparseFamily == Own ? std::string("on the main queue") : std::to_string(plan.sparseFamily) + ":" + std::to_string(plan.sparseIndex)); + return "main " + std::to_string(plan.mainCount) + " queues, present " + (plan.present ? std::to_string(plan.presentIndex) : std::string("none")) + ", settle " + (plan.settle ? std::to_string(plan.settleFamily) + ":" + std::to_string(plan.settleIndex) : std::string("none")) + ", sparse " + (!plan.sparseBinding ? std::string("none") : plan.sparseFamily == Own ? std::string("on the main queue") : std::to_string(plan.sparseFamily) + ":" + std::to_string(plan.sparseIndex)); } void check(const Case& test) { - const auto plan = AgcDriver::PlanDeviceQueues(test.families, 0, test.settles, true); - const auto dense = AgcDriver::PlanDeviceQueues(test.families, 0, test.settles, false); + const auto plan = AgcDriver::PlanDeviceQueues(test.families, 0, test.settles, true, false); + const auto dense = AgcDriver::PlanDeviceQueues(test.families, 0, test.settles, false, false); Require(plan.mainCount == dense.mainCount && plan.settle == dense.settle && plan.settleFamily == dense.settleFamily && plan.settleIndex == dense.settleIndex, std::string("device queue plan, ") + test.name + ": sparse binding changed the queues: " + describe(dense) + " without it, " + describe(plan) + " with it"); Require(!dense.sparseBinding && dense.sparseFamily == Own, std::string("device queue plan, ") + test.name + ": a device without sparse binding got a sparse queue: " + describe(dense)); const bool expected = plan.mainCount == test.mainCount && plan.settle == test.settle && (!test.settle || (plan.settleFamily == test.settleFamily && plan.settleIndex == test.settleIndex)) && plan.sparseBinding == test.sparseBinding && plan.sparseFamily == test.sparseFamily && (test.sparseFamily == Own || plan.sparseIndex == test.sparseIndex); - Require(expected, std::string("device queue plan, ") + test.name + ": got " + describe(plan)); + Require(expected && !plan.present, std::string("device queue plan, ") + test.name + ": got " + describe(plan)); + const auto windowed = AgcDriver::PlanDeviceQueues(test.families, 0, test.settles, true, true); + const bool kept = windowed.settle == plan.settle && windowed.settleFamily == plan.settleFamily && windowed.settleIndex == plan.settleIndex && windowed.sparseBinding == plan.sparseBinding && windowed.sparseFamily == plan.sparseFamily && windowed.sparseIndex == plan.sparseIndex; + const bool counted = windowed.present ? windowed.presentIndex == plan.mainCount && windowed.mainCount == plan.mainCount + 1 : windowed.mainCount == plan.mainCount && plan.mainCount >= test.families[0].queueCount; + Require(kept && counted, std::string("device queue plan, ") + test.name + ": a window changed more than the presentation queue: " + describe(plan) + " without it, " + describe(windowed) + " with it"); +} + +struct WindowCase { + const char* name; + std::vector families; + bool settles; + std::uint32_t mainCount; + bool present; + std::uint32_t presentIndex; + bool settle; + std::uint32_t settleFamily; + std::uint32_t settleIndex; + std::uint32_t sparseFamily; + std::uint32_t sparseIndex; +}; + +void check(const WindowCase& test) { + const auto plan = AgcDriver::PlanDeviceQueues(test.families, 0, test.settles, true, true); + const bool expected = plan.mainCount == test.mainCount && plan.present == test.present && (!test.present || plan.presentIndex == test.presentIndex) && plan.settle == test.settle && (!test.settle || (plan.settleFamily == test.settleFamily && plan.settleIndex == test.settleIndex)) && plan.sparseFamily == test.sparseFamily && (test.sparseFamily == Own || plan.sparseIndex == test.sparseIndex); + Require(expected, std::string("device queue plan with a window, ") + test.name + ": got " + describe(plan)); } } @@ -62,6 +86,15 @@ int main() { {"only the settle queue binds", {family(Graphics, 1), family(VK_QUEUE_TRANSFER_BIT | Sparse, 1)}, true, 1, true, 1, 0, false, Own, 0}, }; for (const auto& test : cases) check(test); + const std::vector windowCases{ + {"one queue with a window", {family(Graphics | Sparse, 1)}, true, 1, false, 0, false, 0, 0, Own, 0}, + {"two queues, no settles, with a window", {family(Graphics, 2)}, false, 2, true, 1, false, 0, 0, Own, 0}, + {"two queues taken by the main and settle queues, with a window", {family(Graphics, 2)}, true, 2, false, 0, true, 0, 1, Own, 0}, + {"settle on the main family, three queues, with a window", {family(Graphics | Sparse, 3), family(VK_QUEUE_TRANSFER_BIT | Sparse, 1)}, true, 3, true, 2, true, 0, 1, 1, 0}, + {"one main queue and settle on another family, with a window", {family(Graphics, 1), family(VK_QUEUE_TRANSFER_BIT, 1)}, true, 1, false, 0, true, 1, 0, Own, 0}, + {"sparse-only family preferred, with a window", {family(Graphics | Sparse, 16), family(VK_QUEUE_TRANSFER_BIT | Sparse, 2), family(Sparse, 1)}, true, 3, true, 2, true, 0, 1, 2, 0}, + }; + for (const auto& test : windowCases) check(test); std::puts("device queue plan tests passed"); return 0; } catch (const std::exception& error) { diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/F32ConvertDenormalModes.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/F32ConvertDenormalModes.cpp new file mode 100644 index 0000000000..9dcc8b2bf9 --- /dev/null +++ b/core/libs/prx/libSceAgcDriver/tests/execution/F32ConvertDenormalModes.cpp @@ -0,0 +1,212 @@ +#include "prx/libSceAgcDriver/Execution/include/VulkanDevice.hpp" +#include "prx/libSceAgcDriver/Graphics/include/Draw.hpp" +#include "Recompiler.hpp" +#include "VulkanTestDevice.hpp" +#include +#include +#include +#include +#include +#include +#include +#include + +namespace { + +using AgcDriver::Graphics::Require; +using ShaderRecompiler::ShaderStage; + +constexpr std::uint32_t Threads = 64; +constexpr std::uint32_t Inputs = 4; +constexpr std::uint32_t Results = 16; +constexpr std::uint32_t Columns = 12; +constexpr std::uint32_t Float64Low = 5; +constexpr std::uint32_t Float64High = 6; +alignas(256) std::array Input{}; +alignas(256) std::array Output{}; + +alignas(256) constexpr std::array Code{ + 0x34020084u, 0x34040086u, 0xe0381000u, 0x80000401u, 0xbf8c3f70u, 0x7e141104u, 0x7e160f04u, 0x7e181904u, + 0x7e1a1b04u, 0x7e1c7f04u, 0xd7680011u, 0x00020b04u, 0xd7690012u, 0x00020b04u, 0xd55e0013u, 0x02010104u, + 0x5e280b04u, 0x7e2a1504u, 0xe0781000u, 0x80010a02u, 0xe0781010u, 0x80010e02u, 0xe0781020u, 0x80011202u, + 0xbf810000u, +}; + +alignas(256) constexpr std::array Float64Code{ + 0x34020084u, 0x34040086u, 0xe0381000u, 0x80000401u, 0xbf8c3f70u, 0x7e1e2104u, 0xe0781000u, 0x80010a02u, + 0xe0781010u, 0x80010e02u, 0xe0781020u, 0x80011202u, 0xbf810000u, +}; + +constexpr const char* Names[Columns] = { + "v_cvt_i32_f32 v10, v4", + "v_cvt_u32_f32 v11, v4", + "v_cvt_rpi_i32_f32 v12, v4", + "v_cvt_flr_i32_f32 v13, v4", + "v_frexp_exp_i32_f32 v14, v4", + "v_cvt_f64_f32 v[15:16], v4 (low)", + "v_cvt_f64_f32 v[15:16], v4 (high)", + "v_cvt_pknorm_i16_f32 v17, v4, v5", + "v_cvt_pknorm_u16_f32 v18, v4, v5", + "v_cvt_pk_u8_f32 v19, v4, 0, 0", + "v_cvt_pkrtz_f16_f32 v20, v4, v5", + "v_cvt_f16_f32 v21, v4", +}; + +struct ConvertVector { + std::uint32_t operands[2]; + std::uint32_t denormalsFlushed[Columns]; + std::uint32_t denormalsKept[Columns]; +}; + +constexpr std::array Vectors{{ + {{0x00000001u, 0x00400000u}, {0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u}, {0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0xffffff6cu, 0x00000000u, 0x36a00000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u}}, + {{0x007fffffu, 0x80000001u}, {0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x80000000u, 0x00000000u}, {0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0xffffff82u, 0xc0000000u, 0x380fffffu, 0x00000000u, 0x00000000u, 0x00000000u, 0x80000000u, 0x00000000u}}, + {{0x00400000u, 0x3f800000u}, {0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x7fff0000u, 0xffff0000u, 0x00000000u, 0x3c000000u, 0x00000000u}, {0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0xffffff82u, 0x00000000u, 0x38000000u, 0x7fff0000u, 0xffff0000u, 0x00000000u, 0x3c000000u, 0x00000000u}}, + {{0x80000001u, 0x007fffffu}, {0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x80000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00008000u, 0x00008000u}, {0x00000000u, 0x00000000u, 0x00000000u, 0xffffffffu, 0xffffff6cu, 0x00000000u, 0xb6a00000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00008000u, 0x00008000u}}, + {{0x807fffffu, 0x00000001u}, {0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x80000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00008000u, 0x00008000u}, {0x00000000u, 0x00000000u, 0x00000000u, 0xffffffffu, 0xffffff82u, 0xc0000000u, 0xb80fffffu, 0x00000000u, 0x00000000u, 0x00000000u, 0x00008000u, 0x00008000u}}, + {{0x80400000u, 0xbf000000u}, {0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x80000000u, 0xc0000000u, 0x00000000u, 0x00000000u, 0xb8008000u, 0x00008000u}, {0x00000000u, 0x00000000u, 0x00000000u, 0xffffffffu, 0xffffff82u, 0x00000000u, 0xb8000000u, 0xc0000000u, 0x00000000u, 0x00000000u, 0xb8008000u, 0x00008000u}}, + {{0x00800000u, 0x80400000u}, {0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0xffffff83u, 0x00000000u, 0x38100000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x80000000u, 0x00000000u}, {0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0xffffff83u, 0x00000000u, 0x38100000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x80000000u, 0x00000000u}}, + {{0x80800000u, 0x00000000u}, {0x00000000u, 0x00000000u, 0x00000000u, 0xffffffffu, 0xffffff83u, 0x00000000u, 0xb8100000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00008000u, 0x00008000u}, {0x00000000u, 0x00000000u, 0x00000000u, 0xffffffffu, 0xffffff83u, 0x00000000u, 0xb8100000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00008000u, 0x00008000u}}, + {{0x3f000000u, 0x00000001u}, {0x00000000u, 0x00000000u, 0x00000001u, 0x00000000u, 0x00000000u, 0x00000000u, 0x3fe00000u, 0x00004000u, 0x00008000u, 0x00000000u, 0x00003800u, 0x00003800u}, {0x00000000u, 0x00000000u, 0x00000001u, 0x00000000u, 0x00000000u, 0x00000000u, 0x3fe00000u, 0x00004000u, 0x00008000u, 0x00000000u, 0x00003800u, 0x00003800u}}, + {{0xbfc00000u, 0x807fffffu}, {0xffffffffu, 0x00000000u, 0xffffffffu, 0xfffffffeu, 0x00000001u, 0x00000000u, 0xbff80000u, 0x00008001u, 0x00000000u, 0x00000000u, 0x8000be00u, 0x0000be00u}, {0xffffffffu, 0x00000000u, 0xffffffffu, 0xfffffffeu, 0x00000001u, 0x00000000u, 0xbff80000u, 0x00008001u, 0x00000000u, 0x00000000u, 0x8000be00u, 0x0000be00u}}, + {{0x3f800000u, 0x80000002u}, {0x00000001u, 0x00000001u, 0x00000001u, 0x00000001u, 0x00000001u, 0x00000000u, 0x3ff00000u, 0x00007fffu, 0x0000ffffu, 0x00000001u, 0x80003c00u, 0x00003c00u}, {0x00000001u, 0x00000001u, 0x00000001u, 0x00000001u, 0x00000001u, 0x00000000u, 0x3ff00000u, 0x00007fffu, 0x0000ffffu, 0x00000001u, 0x80003c00u, 0x00003c00u}}, + {{0x00000000u, 0x00000002u}, {0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u}, {0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u}}, + {{0x80000000u, 0x3f800000u}, {0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x80000000u, 0x7fff0000u, 0xffff0000u, 0x00000000u, 0x3c008000u, 0x00008000u}, {0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x80000000u, 0x7fff0000u, 0xffff0000u, 0x00000000u, 0x3c008000u, 0x00008000u}}, + {{0x33800000u, 0x00000001u}, {0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0xffffffe9u, 0x00000000u, 0x3e700000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000001u, 0x00000001u}, {0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0xffffffe9u, 0x00000000u, 0x3e700000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000001u, 0x00000001u}}, + {{0x477fe000u, 0x80000001u}, {0x0000ffe0u, 0x0000ffe0u, 0x0000ffe0u, 0x0000ffe0u, 0x00000010u, 0x00000000u, 0x40effc00u, 0x00007fffu, 0x0000ffffu, 0x000000ffu, 0x80007bffu, 0x00007bffu}, {0x0000ffe0u, 0x0000ffe0u, 0x0000ffe0u, 0x0000ffe0u, 0x00000010u, 0x00000000u, 0x40effc00u, 0x00007fffu, 0x0000ffffu, 0x000000ffu, 0x80007bffu, 0x00007bffu}}, + {{0x501502f9u, 0x00800000u}, {0x7fffffffu, 0xffffffffu, 0x7fffffffu, 0x7fffffffu, 0x00000022u, 0x20000000u, 0x4202a05fu, 0x00007fffu, 0x0000ffffu, 0x000000ffu, 0x00007bffu, 0x00007c00u}, {0x7fffffffu, 0xffffffffu, 0x7fffffffu, 0x7fffffffu, 0x00000022u, 0x20000000u, 0x4202a05fu, 0x00007fffu, 0x0000ffffu, 0x000000ffu, 0x00007bffu, 0x00007c00u}}, + {{0xd01502f9u, 0x007fffffu}, {0x80000000u, 0x00000000u, 0x80000000u, 0x80000000u, 0x00000022u, 0x20000000u, 0xc202a05fu, 0x00008001u, 0x00000000u, 0x00000000u, 0x0000fbffu, 0x0000fc00u}, {0x80000000u, 0x00000000u, 0x80000000u, 0x80000000u, 0x00000022u, 0x20000000u, 0xc202a05fu, 0x00008001u, 0x00000000u, 0x00000000u, 0x0000fbffu, 0x0000fc00u}}, + {{0x7f800000u, 0xbfc00000u}, {0x7fffffffu, 0xffffffffu, 0x7fffffffu, 0x7fffffffu, 0x00000000u, 0x00000000u, 0x7ff00000u, 0x80017fffu, 0x0000ffffu, 0x000000ffu, 0xbe007c00u, 0x00007c00u}, {0x7fffffffu, 0xffffffffu, 0x7fffffffu, 0x7fffffffu, 0x00000000u, 0x00000000u, 0x7ff00000u, 0x80017fffu, 0x0000ffffu, 0x000000ffu, 0xbe007c00u, 0x00007c00u}}, + {{0xff800000u, 0x00000001u}, {0x80000000u, 0x00000000u, 0x80000000u, 0x80000000u, 0x00000000u, 0x00000000u, 0xfff00000u, 0x00008001u, 0x00000000u, 0x00000000u, 0x0000fc00u, 0x0000fc00u}, {0x80000000u, 0x00000000u, 0x80000000u, 0x80000000u, 0x00000000u, 0x00000000u, 0xfff00000u, 0x00008001u, 0x00000000u, 0x00000000u, 0x0000fc00u, 0x0000fc00u}}, + {{0x7fc00000u, 0x80400000u}, {0x00000000u, 0x00000000u, 0x7fffffffu, 0x7fffffffu, 0x00000000u, 0x00000000u, 0x7ff80000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x80007e00u, 0x00007e00u}, {0x00000000u, 0x00000000u, 0x7fffffffu, 0x7fffffffu, 0x00000000u, 0x00000000u, 0x7ff80000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x80007e00u, 0x00007e00u}}, + {{0xffc00000u, 0x00400000u}, {0x00000000u, 0x00000000u, 0x80000000u, 0x80000000u, 0x00000000u, 0x00000000u, 0xfff80000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x0000fe00u, 0x0000fe00u}, {0x00000000u, 0x00000000u, 0x80000000u, 0x80000000u, 0x00000000u, 0x00000000u, 0xfff80000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x0000fe00u, 0x0000fe00u}}, + {{0x4f800000u, 0x80000000u}, {0x7fffffffu, 0xffffffffu, 0x7fffffffu, 0x7fffffffu, 0x00000021u, 0x00000000u, 0x41f00000u, 0x00007fffu, 0x0000ffffu, 0x000000ffu, 0x80007bffu, 0x00007c00u}, {0x7fffffffu, 0xffffffffu, 0x7fffffffu, 0x7fffffffu, 0x00000021u, 0x00000000u, 0x41f00000u, 0x00007fffu, 0x0000ffffu, 0x000000ffu, 0x80007bffu, 0x00007c00u}}, + {{0xcf000000u, 0x007fffffu}, {0x80000000u, 0x00000000u, 0x80000000u, 0x80000000u, 0x00000020u, 0x00000000u, 0xc1e00000u, 0x00008001u, 0x00000000u, 0x00000000u, 0x0000fbffu, 0x0000fc00u}, {0x80000000u, 0x00000000u, 0x80000000u, 0x80000000u, 0x00000020u, 0x00000000u, 0xc1e00000u, 0x00008001u, 0x00000000u, 0x00000000u, 0x0000fbffu, 0x0000fc00u}}, + {{0x3f7fffffu, 0x80000001u}, {0x00000000u, 0x00000000u, 0x00000001u, 0x00000000u, 0x00000000u, 0xe0000000u, 0x3fefffffu, 0x00007fffu, 0x0000ffffu, 0x00000001u, 0x80003bffu, 0x00003c00u}, {0x00000000u, 0x00000000u, 0x00000001u, 0x00000000u, 0x00000000u, 0xe0000000u, 0x3fefffffu, 0x00007fffu, 0x0000ffffu, 0x00000001u, 0x80003bffu, 0x00003c00u}}, + {{0x00000002u, 0x3f800000u}, {0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x7fff0000u, 0xffff0000u, 0x00000000u, 0x3c000000u, 0x00000000u}, {0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0xffffff6du, 0x00000000u, 0x36b00000u, 0x7fff0000u, 0xffff0000u, 0x00000000u, 0x3c000000u, 0x00000000u}}, + {{0x80000002u, 0x00000003u}, {0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x80000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00008000u, 0x00008000u}, {0x00000000u, 0x00000000u, 0x00000000u, 0xffffffffu, 0xffffff6du, 0x00000000u, 0xb6b00000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00008000u, 0x00008000u}}, + {{0x00000001u, 0x00000001u}, {0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u}, {0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0xffffff6cu, 0x00000000u, 0x36a00000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u}}, + {{0x007fffffu, 0x807fffffu}, {0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x80000000u, 0x00000000u}, {0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0xffffff82u, 0xc0000000u, 0x380fffffu, 0x00000000u, 0x00000000u, 0x00000000u, 0x80000000u, 0x00000000u}}, + {{0x3f000000u, 0x80000001u}, {0x00000000u, 0x00000000u, 0x00000001u, 0x00000000u, 0x00000000u, 0x00000000u, 0x3fe00000u, 0x00004000u, 0x00008000u, 0x00000000u, 0x80003800u, 0x00003800u}, {0x00000000u, 0x00000000u, 0x00000001u, 0x00000000u, 0x00000000u, 0x00000000u, 0x3fe00000u, 0x00004000u, 0x00008000u, 0x00000000u, 0x80003800u, 0x00003800u}}, + {{0x80000001u, 0x00400000u}, {0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x80000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00008000u, 0x00008000u}, {0x00000000u, 0x00000000u, 0x00000000u, 0xffffffffu, 0xffffff6cu, 0x00000000u, 0xb6a00000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00008000u, 0x00008000u}}, + {{0x3e800000u, 0x80800000u}, {0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0xffffffffu, 0x00000000u, 0x3fd00000u, 0x00002000u, 0x00004000u, 0x00000000u, 0x80003400u, 0x00003400u}, {0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0xffffffffu, 0x00000000u, 0x3fd00000u, 0x00002000u, 0x00004000u, 0x00000000u, 0x80003400u, 0x00003400u}}, + {{0xbf800000u, 0x00000001u}, {0xffffffffu, 0x00000000u, 0xffffffffu, 0xffffffffu, 0x00000001u, 0x00000000u, 0xbff00000u, 0x00008001u, 0x00000000u, 0x00000000u, 0x0000bc00u, 0x0000bc00u}, {0xffffffffu, 0x00000000u, 0xffffffffu, 0xffffffffu, 0x00000001u, 0x00000000u, 0xbff00000u, 0x00008001u, 0x00000000u, 0x00000000u, 0x0000bc00u, 0x0000bc00u}}, +}}; + +std::array BufferDescriptor(const void* data, std::uint32_t bytes) { + const auto address = reinterpret_cast(data); + return {static_cast(address), static_cast((address >> 32u) & 0xffffu), bytes, 0x31016facu}; +} + +std::string Hex(std::uint32_t value) { + char text[16]; + std::snprintf(text, sizeof(text), "0x%08x", value); + return text; +} + +bool InPass(std::uint32_t column, bool float64) { + return (column == Float64Low || column == Float64High) == float64; +} + +std::vector Run(AgcDriver::VulkanDevice& device, bool float64, ShaderRecompiler::ShaderFloatMode floatMode) { + Input.fill(0u); + for (std::uint32_t lane = 0; lane < Vectors.size(); ++lane) { + Input[lane * Inputs] = Vectors[lane].operands[0]; + Input[lane * Inputs + 1u] = Vectors[lane].operands[1]; + } + Output.fill(0xdeadbeefu); + std::vector userData(8, 0u); + const auto input = BufferDescriptor(Input.data(), static_cast(Input.size() * 4u)); + const auto output = BufferDescriptor(Output.data(), static_cast(Output.size() * 4u)); + std::copy(input.begin(), input.end(), userData.begin()); + std::copy(output.begin(), output.end(), userData.begin() + 4); + const auto code = float64 ? std::span(Float64Code) : std::span(Code); + const std::array memory{{{reinterpret_cast(code.data()), std::as_bytes(code)}}}; + const ShaderRecompiler::ShaderComputeStageInfo compute{{Threads, 1, 1}, 0, {false, false, false}, false, 1}; + ShaderRecompiler::RecompileRequest request{ + {ShaderStage::Compute, reinterpret_cast(code.data()), code, 0, {}}, + {32, 0, userData, compute, std::nullopt, std::nullopt, memory}, + device.Target(), + {0, 0, 0, 128} + }; + request.useCache = false; + request.context.floatMode = floatMode; + const auto result = ShaderRecompiler::Recompile(request); + device.Dispatch(result, 1, 1, 1, {}, reinterpret_cast(code.data())); + device.WaitIdle(); + return {Output.begin(), Output.end()}; +} + +std::string Where(std::uint32_t lane, std::uint32_t column, std::uint32_t denormals, bool ieee) { + return std::string(Names[column]) + " of " + Hex(Vectors[lane].operands[0]) + ", " + Hex(Vectors[lane].operands[1]) + " in f32 denormal mode " + + std::to_string(denormals) + (ieee ? ", IEEE=1" : ", IEEE=0"); +} + +void CheckFlushed(const std::vector& output, bool float64, std::uint32_t denormals, bool ieee) { + for (std::uint32_t lane = 0; lane < Vectors.size(); ++lane) { + for (std::uint32_t column = 0; column < Columns; ++column) { + if (!InPass(column, float64)) continue; + const auto value = output[lane * Results + column]; + const auto expected = Vectors[lane].denormalsFlushed[column]; + Require(value == expected, Where(lane, column, denormals, ieee) + " is " + Hex(value) + ", expected " + Hex(expected)); + } + } +} + +void CheckKept(const std::vector& output, bool float64, bool ieee) { + for (std::uint32_t lane = 0; lane < Vectors.size(); ++lane) { + for (std::uint32_t column = 0; column < Columns; ++column) { + if (!InPass(column, float64)) continue; + const auto value = output[lane * Results + column]; + const auto& vector = Vectors[lane]; + Require(value == vector.denormalsKept[column] || value == vector.denormalsFlushed[column], + Where(lane, column, 3u, ieee) + " is " + Hex(value) + ", expected " + Hex(vector.denormalsKept[column]) + " or, on a driver that flushes f32 denormals, " + + Hex(vector.denormalsFlushed[column])); + } + } +} + +void CheckSame(const std::vector& output, const std::vector& reference, bool float64, std::uint32_t denormals, std::uint32_t like, bool ieee) { + for (std::uint32_t lane = 0; lane < Vectors.size(); ++lane) { + for (std::uint32_t column = 0; column < Columns; ++column) { + if (!InPass(column, float64)) continue; + const auto value = output[lane * Results + column]; + const auto expected = reference[lane * Results + column]; + Require(value == expected, Where(lane, column, denormals, ieee) + " is " + Hex(value) + ", but mode " + std::to_string(like) + " gave " + Hex(expected)); + } + } +} + +ShaderRecompiler::ShaderFloatMode Mode(std::uint32_t denormals, bool ieee) { + return ShaderRecompiler::ShaderFloatMode{0xc0u | denormals << 4u, true, ieee, false}; +} + +} + +int main() { + try { + const auto device = OpenVulkanTestDevice(); + if (!device) return VulkanTestSkipped; + const bool hasFloat64 = TargetHasCapability(device->Target(), spv::CapabilityFloat64); + if (!hasFloat64) std::puts("v_cvt_f64_f32 skipped, the device has no shaderFloat64"); + for (const bool float64 : {false, true}) { + if (float64 && !hasFloat64) continue; + for (const bool ieee : {false, true}) { + const auto flushed = Run(*device, float64, Mode(0u, ieee)); + CheckFlushed(flushed, float64, 0u, ieee); + const auto inputsFlushed = Run(*device, float64, Mode(2u, ieee)); + CheckFlushed(inputsFlushed, float64, 2u, ieee); + CheckSame(inputsFlushed, flushed, float64, 2u, 0u, ieee); + const auto kept = Run(*device, float64, Mode(3u, ieee)); + CheckKept(kept, float64, ieee); + const auto outputsFlushed = Run(*device, float64, Mode(1u, ieee)); + CheckSame(outputsFlushed, kept, float64, 1u, 3u, ieee); + } + } + std::puts("f32 conversion denormal mode tests passed"); + return 0; + } catch (const std::exception& error) { + std::cerr << error.what() << '\n'; + return 1; + } +} diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/GpuMapOnFiber.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/GpuMapOnFiber.cpp index 5a4da94b89..6137424eba 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/GpuMapOnFiber.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/GpuMapOnFiber.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceFiber/include/Api.hpp" #include "prx/libSceAgcDriver/Execution/include/Driver/Driver.hpp" #include "prx/libc/include/GuestAllocations.hpp" #include "prx/libc/include/general/VabiMacros.hpp" @@ -17,15 +18,6 @@ #include #include -using GuestFiberEntry = void (APS5_VABI*)(std::uint64_t, std::uint64_t); - -extern "C" { -std::int32_t APS5_VABI _sceFiberInitializeImpl_nid_postfix(FiberObject*, const char*, GuestFiberEntry, std::uint64_t, void*, std::uint64_t, const void*, std::uint32_t); -std::int32_t APS5_VABI sceFiberFinalize(FiberObject*); -std::int32_t APS5_VABI sceFiberRun_nid_postfix(FiberObject*, std::uint64_t, std::uint64_t*); -std::int32_t APS5_VABI sceFiberReturnToThread(std::uint64_t, std::uint64_t*); -} - namespace { using AgcDriver::DriverDetail::Driver; @@ -77,6 +69,7 @@ void MapForGpu() { void APS5_VABI MapOnFiber(std::uint64_t, std::uint64_t) { MapForGpu(); sceFiberReturnToThread(0, nullptr); + } void ReleaseMapping() { diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/GuestMemoryLifetime.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/GuestMemoryLifetime.cpp index 2d737ebc4e..7d6a257711 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/GuestMemoryLifetime.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/GuestMemoryLifetime.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libSceAgcDriver/Execution/include/GuestMemory.hpp" #include "prx/libSceAgcDriver/Execution/include/VulkanDevice.hpp" #include "prx/libSceAgcDriver/Graphics/include/GuestBufferMemory.hpp" @@ -17,19 +19,6 @@ #include #include -extern "C" { -void* APS5_VABI mmap_nid_postfix(void*, std::size_t, int, int, int, std::int64_t) noexcept; -int APS5_VABI munmap_nid_postfix(void*, std::size_t) noexcept; -int APS5_VABI mprotect_nid_postfix(void*, std::size_t, int) noexcept; -void* APS5_VABI memalign_nid_postfix(std::size_t, std::size_t); -void* APS5_VABI realloc_nid_postfix(void*, std::size_t); -void APS5_VABI free_nid_postfix(void*); -int APS5_VABI sceKernelMapFlexibleMemory(void**, std::size_t, int, int); -int APS5_VABI sceKernelAllocateDirectMemory(std::int64_t, std::int64_t, std::size_t, std::size_t, int, std::int64_t*); -int APS5_VABI sceKernelMapDirectMemory(void**, std::size_t, int, int, std::int64_t, std::size_t); -int APS5_VABI sceKernelReleaseDirectMemory(std::int64_t, std::size_t); -} - namespace { constexpr std::size_t BlockBytes = 65536; @@ -141,12 +130,14 @@ void CheckHeap(AgcDriver::VulkanDevice& device) { Require(!Imported(device, allocation), "host import survived guest realloc"); CheckPattern(replacement); free_nid_postfix(replacement); + for (int iteration = 0; iteration < 3; ++iteration) { allocation = memalign_nid_postfix(BlockBytes, BlockBytes); Require(allocation != nullptr, "guest heap reuse allocation failed"); std::memset(allocation, 0, BlockBytes); Fill(device, allocation); free_nid_postfix(allocation); + Require(!Imported(device, allocation), "host import survived guest free or heap cache eviction"); } } diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/ImageTable.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/ImageTable.cpp index d5a89a1586..5ee8abca21 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/ImageTable.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/ImageTable.cpp @@ -47,6 +47,7 @@ constexpr std::uint32_t MaxGroups = 8; constexpr std::uint32_t Format32UInt = 20; constexpr std::uint32_t Format32SInt = 21; constexpr std::uint32_t Format32Float = 22; +constexpr std::uint32_t Format32_32UInt = 62; constexpr std::uint32_t Format11_11_10UInt = 34; constexpr std::uint32_t Format8_8Srgb = 129; constexpr std::uint32_t Type2D = 9; @@ -56,6 +57,7 @@ constexpr std::uint32_t DepthSwizzleMode = 0x18; alignas(256) std::array FloatTexels{}; alignas(256) std::array OtherFloatTexels{}; alignas(256) std::array UintTexels{}; +alignas(256) std::array Uint64Texels{}; alignas(256) std::array SintTexels{}; alignas(4096) std::array DepthStorage{}; alignas(256) std::array Table{}; @@ -208,6 +210,12 @@ alignas(256) constexpr std::array AtomicAddLaneTableCode{ 0xf42c0802u, 0x24000000u, 0x360200bfu, 0x7e040280u, 0x7e080301u, 0xf0448108u, 0x00090401u, 0xbf810000u, }; +alignas(256) constexpr std::array AtomicAdd64LaneTableCode{ + 0xf4080100u, 0xfa000000u, 0xf4080200u, 0xfa000010u, 0x8f108202u, 0xf4200444u, 0x20000000u, 0x9312b011u, + 0xf42c0802u, 0x24000000u, 0x360200bfu, 0x7e040280u, 0x7e080301u, 0x7e0a02ffu, 0x00000000u, 0xf0448308u, + 0x00090401u, 0xbf810000u, +}; + alignas(256) constexpr std::array AtomicSwapLaneTableCode{ 0xf4080100u, 0xfa000000u, 0xf4080200u, 0xfa000010u, 0x8f108202u, 0xf4200444u, 0x20000000u, 0x9312b011u, 0xf42c0802u, 0x24000000u, 0x360200bfu, 0x7e040280u, 0x7e080301u, 0xf03c8108u, 0x00090401u, 0xbf810000u, @@ -1168,6 +1176,32 @@ void RunAtomicTests(AgcDriver::VulkanDevice& device) { for (std::uint32_t x = 0; x < Width; ++x) Require(UintTexels[x] == (x ^ 1u) && std::bit_cast(FloatTexels[x]) == 0x3f800000u + x, "image table atomic: an add through a null entry reached an image:\n" + null.log); } +void RunAtomic64Tests(AgcDriver::VulkanDevice& device) { + if (!TargetHasCapability(device.Target(), spv::CapabilityInt64ImageEXT)) { + std::puts("skipped the 64-bit table atomic rows, the device has no shaderImageInt64Atomics"); + return; + } + struct Registration { + void* data; + Registration(void* data, std::size_t bytes) : data(data) { GuestAllocations::Mutation().Add(data, bytes, true, true, true); } + ~Registration() { GuestAllocations::Mutation().Remove(data); } + } registered(Uint64Texels.data(), sizeof(Uint64Texels)); + SetClassRecords(); + for (std::uint32_t x = 0; x < Width; ++x) Uint64Texels[x] = 0x5000000000000000ull + x; + SetRecord(9, PointClamp, Image(Uint64Texels.data(), Format32_32UInt)); + Keys = {}; + Keys[0] = 9; + const auto added = Run(device, AtomicAdd64LaneTableCode, 1, Lanes, 64); + AgcDriver::Graphics::StorageTexture::FlushAllPending("image table atomic64 test"); + Require(!Faulted(added), "image table atomic64: an add through a table faulted:\n" + added.log); + Require(added.imageTableCount != 0u, "image table atomic64: the add bound no storage table elements"); + for (std::uint32_t x = 0; x < Width; ++x) Require(Uint64Texels[x] == 0x5000000000000000ull + x + x, "image table atomic64: texel " + std::to_string(x) + " is wrong"); + Keys[0] = 6; + const auto null = Run(device, AtomicAdd64LaneTableCode, 1, Lanes, 64); + AgcDriver::Graphics::StorageTexture::FlushAllPending("image table atomic64 test"); + for (std::uint32_t x = 0; x < Width; ++x) Require(Uint64Texels[x] == 0x5000000000000000ull + x + x, "image table atomic64: an add through a null entry reached an image:\n" + null.log); +} + void RunSelectedStoreTests(AgcDriver::VulkanDevice& device) { alignas(256) static std::array storeTexels{}; struct Registration { @@ -1561,6 +1595,7 @@ int main() { RunModeTests(*device); RunStoreTests(*device); RunAtomicTests(*device); + RunAtomic64Tests(*device); RunSelectedStoreTests(*device); RunPointerTests(*device); RunPointerRecordTests(*device); diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/JobManagerCompute.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/JobManagerCompute.cpp index 8d5f9f14c7..0e677dd20c 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/JobManagerCompute.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/JobManagerCompute.cpp @@ -1,7 +1,12 @@ +#include "prx/libSceAgcDriver/libSceAgcDriver.hpp" +#include "prx/libSceAgc/libSceAgc.hpp" +#include "prx/libSceAgcDriver/Execution/include/Driver.hpp" +#include "prx/libkernel/include/Api.hpp" +#include "prx/libSceJobManager/libSceJobManager.hpp" #include "VulkanTestDevice.hpp" #include "SceTypes.hpp" -#include "prx/libc/include/GuestArena.hpp" #include +#include "prx/libc/include/GuestArena.hpp" #include #include #include @@ -15,63 +20,6 @@ #include #include -extern "C" void AgcDriverShutdown_nid_postfix(); - -struct MemorySizeQueryParams { - std::uint32_t version; - std::uint32_t workers; - std::uint32_t sequences; - std::uint32_t invocations; - std::uint32_t dispatches; - std::uint32_t syncPoints; - std::uint32_t waits; - std::uint32_t computeSequences; - std::uint64_t computeQueueMask; -}; - -struct ConfigParams { - std::uint32_t version; - std::uint32_t threadFlags; - std::uint32_t stackSize; - std::uint32_t priority; - const char* threadName; - std::uint32_t spinMicroseconds; - std::uint32_t computeAffinity; - std::uint32_t computePriority; - std::uint32_t reserved; -}; - -using JobEntry = void (APS5_VABI*)(void*, std::uint32_t); - -struct Sequence { - APS5_VABI virtual int Dispatch(JobEntry, void*, std::uint32_t, const char*) = 0; - APS5_VABI virtual int SyncPoint() = 0; - APS5_VABI virtual int Wait() = 0; - APS5_VABI virtual void CompleteDestructor() = 0; - APS5_VABI virtual void DeletingDestructor() = 0; - APS5_VABI virtual int DispatchCompute(const void*, void*, std::int32_t, std::int32_t, std::int32_t, const char*) = 0; - APS5_VABI virtual int DispatchComputeIndirect(const void*, void*, const void*, const char*) = 0; -}; - -struct SequenceFactory { - APS5_VABI virtual int Create(Sequence**, std::uint32_t, std::uint32_t, std::uint32_t, std::uint32_t, const char*) = 0; - APS5_VABI virtual int Destroy(Sequence*) = 0; - APS5_VABI virtual void CompleteDestructor() = 0; - APS5_VABI virtual void DeletingDestructor() = 0; - APS5_VABI virtual int CreateCompute(Sequence**, std::uint32_t, std::uint32_t, std::uint32_t, std::uint32_t, const char*) = 0; - APS5_VABI virtual int DestroyCompute(Sequence*) = 0; -}; - -extern "C" { -int APS5_VABI sceKernelAllocateDirectMemory(std::int64_t, std::int64_t, std::size_t, std::size_t, int, std::int64_t*); -int APS5_VABI sceKernelMapDirectMemory(void**, std::size_t, int, int, std::int64_t, std::size_t); -int APS5_VABI sceKernelReleaseDirectMemory(std::int64_t, std::size_t); -void APS5_VABI _ZN3sce3Job10JobManagerC1Ev(void*); -std::uint64_t APS5_VABI _ZN3sce3Job10JobManager27calculateRequiredMemorySizeEPKNS1_21MemorySizeQueryParamsE(const MemorySizeQueryParams*); -int APS5_VABI _ZN3sce3Job10JobManager10initializeEPvmjjjmPKNS1_12ConfigParamsE(void*, void*, std::uint64_t, std::uint32_t, std::uint32_t, std::uint32_t, std::uint64_t, const ConfigParams*); -int APS5_VABI _ZN3sce3Job10JobManager8shutdownEv(void*); -SequenceFactory* APS5_VABI _ZN3sce3Job10JobManager34getUnifiedSequenceFactoryInterfaceENS1_8PriorityE(void*, std::uint32_t); -} #define Construct _ZN3sce3Job10JobManagerC1Ev #define RequiredSize _ZN3sce3Job10JobManager27calculateRequiredMemorySizeEPKNS1_21MemorySizeQueryParamsE @@ -136,6 +84,7 @@ std::uint64_t SizeFor(std::uint32_t computeSequences, std::uint64_t mask, bool l std::atomic Released{false}; std::atomic SeenByJob{0}; +std::atomic SecondSeenByJob{0}; void APS5_VABI BlockingJob(void*, std::uint32_t) { while (!Released) std::this_thread::yield(); @@ -145,6 +94,12 @@ void APS5_VABI ReadOutputJob(void*, std::uint32_t) { SeenByJob = Output[0]; } +void APS5_VABI ReadBothOutputsJob(void* argument, std::uint32_t) { + SeenByJob = Output[0]; + SecondSeenByJob = Output[1]; + std::atomic_ref(*static_cast(argument)).store(1); +} + void APS5_VABI Nothing(void*, std::uint32_t) { } @@ -171,9 +126,9 @@ void RunCase() { Require(Initialize(manager, memory, size, 2, 1, 1, 2, &wideAffinity) == InvalidArgument, "a handler affinity beyond 13 cores was accepted"); Require(Initialize(manager, memory, size, 2, 1, 0xffffffffu, 2, nullptr) == InvalidArgument, "a sequence count that wraps was accepted"); Require(Initialize(manager, memory, size, 2, 1, 1, 2, nullptr) == 0, "initialize with one compute sequence failed"); - SequenceFactory* factory = Factories(manager, 0); - Sequence* sequence = nullptr; - Sequence* other = nullptr; + ISequenceFactory* factory = Factories(manager, 0); + ISequence* sequence = nullptr; + ISequence* other = nullptr; Require(factory->CreateCompute(&sequence, 100, 4, 4, 2, "compute") == 0, "the compute sequence was not created"); Require(factory->CreateCompute(&other, 1, 1, 1, 1, "second") == NoneFree, "a second compute sequence was created"); Require(factory->Create(&other, 1, 1, 1, 1, "cpu") == 0, "the CPU sequence was not created"); @@ -260,7 +215,7 @@ void CapacityCase() { Construct(manager); Require(Initialize(manager, memory, size, 1, 0, 1, 1, nullptr) == 0, "capacity manager initialization failed"); auto* factory = Factories(manager, 0); - Sequence* sequence = nullptr; + ISequence* sequence = nullptr; Require(factory->CreateCompute(&sequence, 0, 2, 0, 1, nullptr) == 0, "capacity sequence creation failed"); for (std::uint32_t round = 0; round < 2; ++round) { Value[0] = 0xabcd0000u + round; @@ -284,6 +239,256 @@ void CapacityCase() { ::operator delete(memory, std::align_val_t{256}); } +void DeferredInputsCase(bool mixed) { + for (const bool indirect : {false, true}) { + const auto size = SizeFor(1, 1, true); + auto* memory = static_cast(::operator new(size, std::align_val_t{256})); + std::memset(memory, 0, size); + alignas(64) unsigned char manager[0x100]{}; + Construct(manager); + Require(Initialize(manager, memory, size, 2, 1, 1, 1, nullptr) == 0, "snapshot manager initialization failed"); + auto* factory = Factories(manager, 0); + ISequence* sequence = nullptr; + Require(factory->CreateCompute(&sequence, 1, 3, 1, 1, nullptr) == 0, "snapshot sequence creation failed"); + auto registers = Registers; + auto shader = Shader; + const ShaderRegister* pointer = registers.data(); + std::memcpy(shader.data() + 0x20, &pointer, sizeof(pointer)); + alignas(16) const std::array redirected{Low(Output + 1), High(Output + 1) & 0xffffu, sizeof(Output[1]), 0x31016facu}; + const std::string expected = indirect ? "snapshot indirect" : "snapshot direct"; + std::array marker{}; + std::memcpy(marker.data(), expected.c_str(), expected.size() + 1); + Released = false; + Output[0] = 0; + Output[1] = 0; + Value[0] = indirect ? 0x51a70002u : 0x51a70001u; + if (mixed) Require(sequence->DispatchCompute(Shader.data(), Table.data(), 1, 1, 1, nullptr) == 0, "snapshot parallel compute dispatch failed"); + Require(sequence->Dispatch(BlockingJob, nullptr, 1, nullptr) == 0, "snapshot blocking job failed"); + Require(sequence->SyncPoint() == 0, "snapshot sync point failed"); + const int result = indirect ? sequence->DispatchComputeIndirect(shader.data(), Table.data(), IndirectArguments.data(), marker.data()) + : sequence->DispatchCompute(shader.data(), Table.data(), 1, 1, 1, marker.data()); + Require(result == 0, "snapshot dispatch failed"); + const bool encoded = std::search(memory, memory + size, expected.begin(), expected.end()) != memory + size; + registers[7].value = Low(redirected.data()); + registers[8].value = High(redirected.data()); + std::memset(marker.data(), 'x', expected.size()); + Released = true; + Require(sequence->Wait() == 0, "snapshot wait failed"); + const bool updated = Output[0] == (mixed ? Value[0] : 0) && Output[1] == Value[0]; + const bool markerUpdated = std::search(memory, memory + size, marker.begin(), marker.begin() + expected.size()) != memory + size; + Require(factory->DestroyCompute(sequence) == 0, "snapshot destruction failed"); + Require(Shutdown(manager) == 0, "snapshot shutdown failed"); + ::operator delete(memory, std::align_val_t{256}); + Require(!encoded, "compute commands were encoded before their CPU barrier retired"); + Require(updated, "queued compute commands did not read their deferred shader registers"); + Require(markerUpdated, "queued compute commands did not read their deferred marker"); + } +} + +void GpuBarriersCase() { + for (const bool indirect : {false, true}) { + const auto size = SizeFor(1, 2, true); + auto* memory = static_cast(::operator new(size, std::align_val_t{256})); + std::memset(memory, 0, size); + alignas(64) unsigned char manager[0x100]{}; + Construct(manager); + Require(Initialize(manager, memory, size, 2, 1, 1, 2, nullptr) == 0, "GPU barrier initialization failed"); + auto* factory = Factories(manager, 0); + ISequence* sequence = nullptr; + Require(factory->CreateCompute(&sequence, 1, 8, 4, 2, nullptr) == 0, "GPU barrier sequence creation failed"); + auto registers = Registers; + auto shader = Shader; + const ShaderRegister* pointer = registers.data(); + std::memcpy(shader.data() + 0x20, &pointer, sizeof(pointer)); + alignas(16) const std::array redirected{Low(Output + 1), High(Output + 1) & 0xffffu, sizeof(Output[1]), 0x31016facu}; + alignas(64) std::uint32_t gate = 0; + alignas(256) std::array commands{}; + CommandBuffer buffer{commands.data(), commands.data() + commands.size(), commands.data(), commands.data() + commands.size(), nullptr, nullptr, 0}; + Require(sceAgcAcbWaitRegMem(&buffer, 0, 3, 3, &gate, 1, 0xffffffffu, 0x190) != nullptr, "GPU barrier gate encoding failed"); + const Packet packet{commands.data(), static_cast(buffer.cursor_up - commands.data()), 0, {}}; + Require(sceAgcDriverSubmitAcb(0x21, &packet) == 0, "GPU barrier gate submission failed"); + Output[0] = 0; + Output[1] = 0; + Value[0] = indirect ? 0x51a80002u : 0x51a80001u; + Require(sequence->DispatchCompute(Shader.data(), Table.data(), 1, 1, 1, "first") == 0, "GPU barrier first dispatch failed"); + Require(sequence->SyncPoint() == 0, "GPU barrier sync point failed"); + const std::string expected = indirect ? "GPU barrier indirect" : "GPU barrier direct"; + std::array marker{}; + std::memcpy(marker.data(), expected.c_str(), expected.size() + 1); + const int result = indirect ? sequence->DispatchComputeIndirect(shader.data(), Table.data(), IndirectArguments.data(), marker.data()) + : sequence->DispatchCompute(shader.data(), Table.data(), 1, 1, 1, marker.data()); + Require(result == 0, "GPU barrier second dispatch failed"); + const bool encoded = std::search(memory, memory + size, expected.begin(), expected.end()) != memory + size; + registers[7].value = Low(redirected.data()); + registers[8].value = High(redirected.data()); + std::memset(marker.data(), 'x', expected.size()); + std::atomic_ref(gate).store(1); + Require(sequence->Wait() == 0, "GPU barrier wait failed"); + Require(encoded, "GPU-only sync deferred the following dispatch inputs"); + Require(Output[0] == Value[0] && Output[1] == 0, "GPU-only sync did not capture shader registers before dispatch returned"); + alignas(16) const std::array dependentTable{Low(Output), High(Output)}; + for (std::uint32_t round = 0; round < 3; ++round) { + Output[0] = 0; + Output[1] = 0; + Value[0] = 0x52a80000u + round; + std::atomic_ref(gate).store(0); + Require(sceAgcDriverSubmitAcb(0x21, &packet) == 0, "GPU dependency gate submission failed"); + Require(sequence->DispatchCompute(Shader.data(), Table.data(), 1, 1, 1, nullptr) == 0, "GPU dependency producer failed"); + Require(sequence->SyncPoint() == 0, "GPU dependency sync failed"); + Require(sequence->DispatchCompute(shader.data(), const_cast(dependentTable.data()), 1, 1, 1, nullptr) == 0, "GPU dependency consumer failed"); + std::atomic_ref(gate).store(1); + Require(sequence->Wait() == 0, "GPU dependency wait failed"); + Require(Output[0] == Value[0] && Output[1] == Value[0], "GPU sync did not make producer writes visible to its consumer"); + } + if (!indirect) { + alignas(64) std::uint32_t overlapGate = 0; + alignas(256) std::array overlapCommands{}; + CommandBuffer overlapBuffer{overlapCommands.data(), overlapCommands.data() + overlapCommands.size(), overlapCommands.data(), overlapCommands.data() + overlapCommands.size(), nullptr, nullptr, 0}; + Require(sceAgcAcbWaitRegMem(&overlapBuffer, 0, 3, 3, &overlapGate, 1, 0xffffffffu, 0x190) != nullptr, "GPU overlap gate encoding failed"); + const Packet overlapPacket{overlapCommands.data(), static_cast(overlapBuffer.cursor_up - overlapCommands.data()), 0, {}}; + Output[0] = 0; + Output[1] = 0; + std::atomic_ref(gate).store(0); + Require(sceAgcDriverSubmitAcb(0x21, &packet) == 0, "GPU overlap gate submission failed"); + Require(sequence->DispatchCompute(Shader.data(), Table.data(), 1, 1, 1, nullptr) == 0, "GPU overlap producer failed"); + Require(sequence->SyncPoint() == 0, "GPU overlap sync failed"); + Require(sceAgcDriverSubmitAcb(0x21, &overlapPacket) == 0, "GPU overlap gate submission failed"); + Require(sequence->DispatchCompute(shader.data(), Table.data(), 1, 1, 1, nullptr) == 0, "GPU overlap consumer failed"); + Require(sequence->Dispatch(ReadBothOutputsJob, &overlapGate, 1, nullptr) == 0, "GPU overlap CPU callback failed"); + std::atomic missedDeadline{false}; + std::jthread rescue([&](std::stop_token stop) { + const auto deadline = std::chrono::steady_clock::now() + std::chrono::seconds(3); + const std::atomic_ref signal(overlapGate); + while (!stop.stop_requested() && signal.load() == 0 && std::chrono::steady_clock::now() < deadline) std::this_thread::yield(); + if (signal.load() == 0) { + missedDeadline = true; + signal.store(1); + } + }); + std::atomic_ref(gate).store(1); + Require(sequence->Wait() == 0, "GPU overlap wait failed"); + rescue.request_stop(); + rescue.join(); + Require(!missedDeadline, "CPU work did not release GPU work beyond its preceding sync"); + Require(SeenByJob == Value[0] && SecondSeenByJob == 0, "CPU work waited for GPU work beyond its preceding sync"); + Require(Output[1] != 0, "GPU overlap consumer did not finish before Wait returned"); + alignas(16) const std::array originalTarget{Low(Output + 2), High(Output + 2) & 0xffffu, sizeof(Output[2]), 0x31016facu}; + alignas(16) const std::array changedTarget{Low(Output + 3), High(Output + 3) & 0xffffu, sizeof(Output[3]), 0x31016facu}; + Output[2] = 0; + Output[3] = 0; + registers[7].value = Low(originalTarget.data()); + registers[8].value = High(originalTarget.data()); + const std::string afterWait = "after waiting caller"; + std::memcpy(marker.data(), afterWait.c_str(), afterWait.size() + 1); + std::atomic_ref(gate).store(0); + Require(sceAgcDriverSubmitAcb(0x21, &packet) == 0, "GPU wait-boundary gate submission failed"); + Require(sequence->DispatchCompute(Shader.data(), Table.data(), 1, 1, 1, nullptr) == 0, "GPU wait-boundary producer failed"); + Require(sequence->SyncPoint() == 0, "GPU wait-boundary sync failed"); + Require(sequence->DispatchCompute(Shader.data(), Table.data(), 1, 1, 1, nullptr) == 0, "GPU wait-boundary second dispatch failed"); + std::atomic waiting{false}; + std::thread waiter([&] { + waiting.store(true); + Require(sequence->Wait() == 0, "GPU wait-boundary first wait failed"); + }); + while (!waiting.load()) std::this_thread::yield(); + std::this_thread::sleep_for(std::chrono::milliseconds(50)); + Require(sequence->DispatchCompute(shader.data(), Table.data(), 1, 1, 1, marker.data()) == 0, "GPU dispatch after a queued wait failed"); + const bool crossedWait = std::search(memory, memory + size, afterWait.begin(), afterWait.end()) != memory + size; + registers[7].value = Low(changedTarget.data()); + registers[8].value = High(changedTarget.data()); + std::atomic_ref(gate).store(1); + waiter.join(); + Require(sequence->Wait() == 0, "GPU wait-boundary final wait failed"); + Require(!crossedWait && Output[2] == 0 && Output[3] == Value[0], "compute lookahead crossed a waiting caller's boundary"); + } + Require(factory->DestroyCompute(sequence) == 0, "GPU barrier destruction failed"); + Require(Shutdown(manager) == 0, "GPU barrier shutdown failed"); + ::operator delete(memory, std::align_val_t{256}); + } +} + +void ComputeShutdownCase() { + for (const std::uint32_t mode : {0u, 1u, 2u}) { + const bool waiting = mode == 1; + const bool queuedCpu = mode == 2; + const auto size = SizeFor(1, 2, true); + const auto allocationSize = (size + 255) & ~std::uint64_t{255}; + auto* memory = static_cast(::operator new(allocationSize, std::align_val_t{256})); + std::memset(memory, 0, size); + std::memset(memory + size, 0xa5, allocationSize - size); + alignas(64) unsigned char manager[0x100]{}; + Construct(manager); + Require(Initialize(manager, memory, size, 2, 1, 1, 2, nullptr) == 0, "compute shutdown initialization failed"); + auto* factory = Factories(manager, 0); + ISequence* sequence = nullptr; + Require(factory->CreateCompute(&sequence, 1, 4, 2, 2, nullptr) == 0, "compute shutdown sequence creation failed"); + auto registers = Registers; + auto shader = Shader; + alignas(16) const std::array descriptor{Low(Output + 1), High(Output + 1) & 0xffffu, sizeof(Output[1]), 0x31016facu}; + registers[7].value = Low(descriptor.data()); + registers[8].value = High(descriptor.data()); + const ShaderRegister* registerPointer = registers.data(); + std::memcpy(shader.data() + 0x20, ®isterPointer, sizeof(registerPointer)); + alignas(64) std::uint32_t gate = 0; + alignas(256) std::array commands{}; + CommandBuffer buffer{commands.data(), commands.data() + commands.size(), commands.data(), commands.data() + commands.size(), nullptr, nullptr, 0}; + Require(sceAgcAcbWaitRegMem(&buffer, 0, 3, 3, &gate, 1, 0xffffffffu, 0x190) != nullptr, "compute shutdown gate encoding failed"); + const Packet packet{commands.data(), static_cast(buffer.cursor_up - commands.data()), 0, {}}; + Require(sceAgcDriverSubmitAcb(0x21, &packet) == 0, "compute shutdown gate submission failed"); + Output[0] = 0; + Output[1] = 0; + SeenByJob = 0; + Value[0] = 0x5a170000u + mode; + Require(sequence->DispatchCompute(Shader.data(), Table.data(), 1, 1, 1, nullptr) == 0, "compute shutdown first dispatch failed"); + Require(sequence->SyncPoint() == 0, "compute shutdown first sync failed"); + if (queuedCpu) { + Require(sequence->Dispatch(ReadOutputJob, nullptr, 1, nullptr) == 0, "compute shutdown queued CPU dispatch failed"); + Require(sequence->SyncPoint() == 0, "compute shutdown second sync failed"); + } + Require(sequence->DispatchCompute(shader.data(), Table.data(), 1, 1, 1, nullptr) == 0, "compute shutdown second dispatch failed"); + std::atomic waitingStarted{false}; + std::atomic waitingReturned{false}; + std::thread waiter; + if (waiting) { + waiter = std::thread([&] { + waitingStarted.store(true); + Require(sequence->Wait() == 0, "compute shutdown canceled wait failed"); + waitingReturned.store(true); + }); + while (!waitingStarted.load()) std::this_thread::yield(); + std::this_thread::sleep_for(std::chrono::milliseconds(50)); + Require(!waitingReturned.load(), "compute shutdown wait passed the held GPU gate"); + } + std::atomic stopped{false}; + std::thread stopper([&] { + Require(Shutdown(manager) == 0, "compute shutdown failed"); + stopped.store(true); + }); + const auto stopDeadline = std::chrono::steady_clock::now() + std::chrono::seconds(3); + while (!stopped.load() && std::chrono::steady_clock::now() < stopDeadline) std::this_thread::yield(); + const bool stoppedBeforeGpu = stopped.load(); + while (waiting && !waitingReturned.load() && std::chrono::steady_clock::now() < stopDeadline) std::this_thread::yield(); + const bool waiterBeforeGpu = !waiting || waitingReturned.load(); + std::atomic_ref(gate).store(1); + stopper.join(); + if (waiting) waiter.join(); + alignas(256) Label fence{}; + alignas(256) std::array tailWords{}; + CommandBuffer tail{tailWords.data(), tailWords.data() + tailWords.size(), tailWords.data(), tailWords.data() + tailWords.size(), nullptr, nullptr, 0}; + Require(sceAgcCbReleaseMem(&tail, 0x2f, 0x200, 1, 3, &fence, 1, 1, 0, 0, 0, 0) != nullptr, "compute shutdown tail fence encoding failed"); + const Packet tailPacket{tailWords.data(), static_cast(tail.cursor_up - tailWords.data()), 0, {}}; + Require(sceAgcDriverSubmitAcb(0x21, &tailPacket) == 0, "compute shutdown tail fence submission failed"); + const auto gpuDeadline = std::chrono::steady_clock::now() + std::chrono::seconds(3); + while (fence.value != 1 && std::chrono::steady_clock::now() < gpuDeadline) std::this_thread::yield(); + Require(fence.value == 1, "submitted compute work did not survive manager shutdown"); + Require(stoppedBeforeGpu && waiterBeforeGpu, "shutdown waited for GPU completion"); + Require(Output[0] == Value[0] && Output[1] == (queuedCpu ? 0 : Value[0]), "shutdown changed submitted or deferred compute work"); + Require(SeenByJob == 0, "shutdown published queued CPU work after GPU completion"); + for (auto offset = size; offset < allocationSize; ++offset) Require(memory[offset] == 0xa5, "compute shutdown wrote past the caller work area"); + ::operator delete(memory, std::align_val_t{256}); + } +} + void StorageCase(bool directMemory) { constexpr std::uint64_t mask = (1u << 1) | (1u << 5) | (1u << 8); const MemorySizeQueryParams query{1, 2, 0, 0, 32, 8, 4, 2, mask}; @@ -305,9 +510,21 @@ void StorageCase(bool directMemory) { alignas(64) unsigned char manager[0x100]{}; Construct(manager); Require(Initialize(manager, memory, size, 2, 0, 2, mask, nullptr) == 0, "storage manager initialization failed"); + const auto inside = [memory, size](const void* pointer) { + const auto base = reinterpret_cast(memory); + const auto address = reinterpret_cast(pointer); + return address >= base && address < base + size; + }; + void* implementation = nullptr; + std::memcpy(&implementation, manager, sizeof(implementation)); + Require(inside(implementation), "manager state is outside the supplied work area"); auto* factory = Factories(manager, 0); - std::array sequences{}; - for (auto& sequence : sequences) Require(factory->CreateCompute(&sequence, 0, 16, 4, 2, nullptr) == 0, "storage sequence creation failed"); + Require(inside(factory), "compute factory is outside the supplied work area"); + std::array sequences{}; + for (auto& sequence : sequences) { + Require(factory->CreateCompute(&sequence, 0, 16, 4, 2, nullptr) == 0, "storage sequence creation failed"); + Require(inside(sequence), "compute sequence is outside the supplied work area"); + } for (std::uint32_t round = 0; round < 3; ++round) { for (auto* sequence : sequences) { Value[0] = 0x56780000u + round; @@ -348,7 +565,7 @@ void StorageCase(bool directMemory) { int RunJobManagerCase(const char* name) { try { - Require(std::strcmp(name, "compute") == 0 || std::strcmp(name, "size") == 0 || std::strcmp(name, "execution") == 0 || std::strcmp(name, "storage") == 0 || std::strcmp(name, "capacity") == 0, "unknown compute fixture"); + Require(std::strcmp(name, "compute") == 0 || std::strcmp(name, "size") == 0 || std::strcmp(name, "execution") == 0 || std::strcmp(name, "storage") == 0 || std::strcmp(name, "capacity") == 0 || std::strcmp(name, "deferred_inputs") == 0 || std::strcmp(name, "gpu_barriers") == 0 || std::strcmp(name, "compute_shutdown") == 0, "unknown compute fixture"); #ifndef ANYPS5_JOB_MANAGER_REFERENCE auto device = OpenVulkanTestDevice(); if (!device) return VulkanTestSkipped; @@ -358,6 +575,12 @@ int RunJobManagerCase(const char* name) { if (std::strcmp(name, "compute") == 0 || std::strcmp(name, "size") == 0) SizeCase(); if (std::strcmp(name, "compute") == 0 || std::strcmp(name, "execution") == 0) RunCase(); if (std::strcmp(name, "compute") == 0 || std::strcmp(name, "capacity") == 0) CapacityCase(); + if (std::strcmp(name, "compute") == 0 || std::strcmp(name, "deferred_inputs") == 0) { + DeferredInputsCase(false); + DeferredInputsCase(true); + } + if (std::strcmp(name, "compute") == 0 || std::strcmp(name, "gpu_barriers") == 0) GpuBarriersCase(); + if (std::strcmp(name, "compute") == 0 || std::strcmp(name, "compute_shutdown") == 0) ComputeShutdownCase(); if (std::strcmp(name, "compute") == 0 || std::strcmp(name, "storage") == 0) { StorageCase(false); StorageCase(true); diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/NativeMultisampleDepth.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/NativeMultisampleDepth.cpp index 5548d5d7fa..b837e0411d 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/NativeMultisampleDepth.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/NativeMultisampleDepth.cpp @@ -671,6 +671,39 @@ void CheckDrawFeedback() { std::puts("Native depth feedback refused through the draw resource path; a written surface refused and a depth-tested one retired on guest read"); } +void CheckDepthAttachmentAlias() { + const auto device = OpenVulkanTestDevice(); + Require(device != nullptr, "native depth attachment alias requires Vulkan"); + const auto context = device->graphicsContext(); + constexpr VkExtent2D extent{5u, 3u}; + constexpr std::uint32_t samples = 4u; + const auto bytes = static_cast(MultisampledDepthBytes_nid_no_patch(extent, 4u, samples)); + TargetMemory memory(bytes), firstMetadata(65536u), secondMetadata(65536u); + std::memset(memory.Data(), 0x3c, bytes); + std::memset(firstMetadata.Data(), 0, 65536u); + std::memset(secondMetadata.Data(), 0, 65536u); + struct Cleanup { + AgcDriver::VulkanDevice& device; + ~Cleanup() { device.WaitIdle(); ClearCachedTextures(device.Device()); ClearDepthSurfaces(device.Device()); } + } cleanup{*device}; + DepthTarget first{memory.Address(), 0u, extent, VK_FORMAT_D32_SFLOAT, 0.0f, 0u, firstMetadata.Address(), false, samples}; + first.depthSwizzle = 24u; + first.iterate256 = first.htilePipeAligned = first.htileDepthOnly = true; + const auto firstView = DepthSurfaceView(context, first); + const auto words = DepthSampleWords(first); + auto kept = DepthSurfaceTexture(context, words, DecodeTextureResource(words), VkComponentMapping{}); + Require(kept != nullptr, "attachment alias fixture has no held native depth view"); + auto second = first; + second.extent.width = 6u; + second.htileAddress = secondMetadata.Address(); + Require(MultisampledDepthBytes_nid_no_patch(second.extent, 4u, samples) <= bytes, "attachment alias fixture exceeds its backing"); + const auto secondView = DepthSurfaceView(context, second); + Require(secondView != VK_NULL_HANDLE && secondView != firstView, "an aliased depth attachment reused the previous layout's view"); + Require(DepthSurfaceView(context, second) == secondView, "an unchanged native depth attachment was not reused"); + for (std::size_t offset = 0u; offset < bytes; ++offset) Require(memory.Data()[offset] == std::byte{0x3c}, "retiring an unwritten attachment alias changed guest bytes"); + std::puts("native depth attachment alias changes layout while retaining held GPU views"); +} + enum class ClearFault { None, PartialStore, CpuWrite, DepthWrite, BadMetadata, UnprovenDispatch, PendingWrite, Overlap, PossibleStore, CompletedPossibleStore, DriverDispatch, ImportWindowWrite }; void CheckClearDispatch() { @@ -926,10 +959,10 @@ void CheckDepthTarget(Context context, VkFormat format, std::uint32_t fragments, Require(probe[0] == std::byte{0xa5}, "resident depth guard blocked an unrelated read"); auto alias = target; alias.htileAddress += 65536u; - TargetRefuses([&] { DepthSurfaceView(context, alias); }, "layout or metadata changed"); + TargetRefuses([&] { DepthSurfaceView(context, alias); }, "sample-preserving guest publication"); alias = target; alias.htileDepthOnly = !target.htileDepthOnly; - TargetRefuses([&] { DepthSurfaceView(context, alias); }, "layout or metadata changed"); + TargetRefuses([&] { DepthSurfaceView(context, alias); }, "sample-preserving guest publication"); auto resource = DecodeTextureResource(words); for (std::uint32_t field = 0u; field < 18u; ++field) { auto changed = resource; @@ -1041,7 +1074,7 @@ void CheckHtileRouting(Context context, VkFormat format, std::uint32_t fragments auto alias = target; alias.samples = 1u; alias.address = single.Address(); - TargetRefuses([&] { DepthSurfaceView(context, alias); }, "layout or metadata changed"); + Require(DepthSurfaceView(context, alias) != VK_NULL_HANDLE, "a single-sample bind could not retire an unwritten native HTILE owner"); Require(untouched(), "a single-sample bind over a native owner's HTILE stored expanded words into it"); std::printf("Native depth format=%u samples=%u: binds over the owner's HTILE left its words alone\n", static_cast(format), fragments); } @@ -1303,6 +1336,7 @@ int main(int argc, char** argv) { } CheckDrawFeedback(); const auto context = device->GetContext(); + if (argc == 1) CheckDepthAttachmentAlias(); std::unique_lock lock(AgcDriver::GuestMemory::GpuMutex()); Require(DepthSupported(context, VK_FORMAT_D32_SFLOAT, 4u), "the native depth regression requires sampled D32 with four samples"); if (argc == 2 && std::string_view(argv[1]) == "--clear-refusals") { diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/OptimizeOnFiber.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/OptimizeOnFiber.cpp index 36fc0c7c91..68f3ccb6a6 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/OptimizeOnFiber.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/OptimizeOnFiber.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceFiber/include/Api.hpp" #if defined(ANYPS5_ENABLE_SPIRV_TOOLS) && ANYPS5_ENABLE_SPIRV_TOOLS #include "SpirvBackend/SpirvOptimizer.hpp" #include "prx/libc/include/general/VabiMacros.hpp" @@ -10,15 +11,6 @@ #include #include -using GuestFiberEntry = void (APS5_VABI*)(std::uint64_t, std::uint64_t); - -extern "C" { -std::int32_t APS5_VABI _sceFiberInitializeImpl_nid_postfix(FiberObject*, const char*, GuestFiberEntry, std::uint64_t, void*, std::uint64_t, const void*, std::uint32_t); -std::int32_t APS5_VABI sceFiberFinalize(FiberObject*); -std::int32_t APS5_VABI sceFiberRun_nid_postfix(FiberObject*, std::uint64_t, std::uint64_t*); -std::int32_t APS5_VABI sceFiberReturnToThread(std::uint64_t, std::uint64_t*); -} - namespace { constexpr std::size_t ContextBytes = 64 * 1024; diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/PipelinedDispatch.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/PipelinedDispatch.cpp index 8cc143e3c5..4996854346 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/PipelinedDispatch.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/PipelinedDispatch.cpp @@ -132,10 +132,8 @@ void Submit(std::vector& words) { int main() { #ifdef _WIN32 _putenv_s("APS5_PIPELINED_DRAWS", "1"); - _putenv_s("APS5_PIPELINE_DMA", "1"); #else setenv("APS5_PIPELINED_DRAWS", "1", 1); - setenv("APS5_PIPELINE_DMA", "1", 1); #endif try { { diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/PipelinedDma.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/PipelinedDma.cpp index d43e135c35..7a62e1e7cf 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/PipelinedDma.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/PipelinedDma.cpp @@ -74,10 +74,8 @@ void ExpectNoDrain(std::uint32_t opcode, std::uint64_t before, const char* what) int main() { #ifdef _WIN32 _putenv_s("APS5_PIPELINED_DRAWS", "1"); - _putenv_s("APS5_PIPELINE_DMA", "1"); #else setenv("APS5_PIPELINED_DRAWS", "1", 1); - setenv("APS5_PIPELINE_DMA", "1", 1); #endif try { alignas(256) static std::array first{}; diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/PipelinedMetadataPass.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/PipelinedMetadataPass.cpp index 7fa9eb1f07..0410e4c9a6 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/PipelinedMetadataPass.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/PipelinedMetadataPass.cpp @@ -120,11 +120,9 @@ void expectEliminated(const std::string& what) { int main() { #ifdef _WIN32 _putenv_s("APS5_PIPELINED_DRAWS", "1"); - _putenv_s("APS5_PIPELINE_DMA", "1"); _putenv_s("APS5_DRAW_PIPELINE", "1"); #else setenv("APS5_PIPELINED_DRAWS", "1", 1); - setenv("APS5_PIPELINE_DMA", "1", 1); setenv("APS5_DRAW_PIPELINE", "1", 1); #endif try { diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/PipelinedPrefetch.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/PipelinedPrefetch.cpp index cf3574966c..fe2b116f63 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/PipelinedPrefetch.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/PipelinedPrefetch.cpp @@ -106,12 +106,12 @@ int main() { const auto prefetched = SubmitBehindBusyPipeline(prefetch, 0x11111111u, true); check(prefetched.outstanding >= 2, "a DMA_DATA prefetch drained the draw pipeline: the label behind it never queued behind the held commit (" + std::to_string(prefetched.outstanding) + " outstanding)"); check(prefetched.drains == 0, "a DMA_DATA prefetch drained the draw pipeline (" + std::to_string(prefetched.drains) + " packet drains)"); - const auto copied = SubmitBehindBusyPipeline(copy, 0x22222222u, false); - check(copied.outstanding == 1, "a DMA_DATA copy did not hold the queue worker (" + std::to_string(copied.outstanding) + " outstanding)"); - check(copied.drains == 1, "a DMA_DATA copy did not drain the draw pipeline (" + std::to_string(copied.drains) + " packet drains)"); + const auto copied = SubmitBehindBusyPipeline(copy, 0x22222222u, true); + check(copied.outstanding >= 2, "a DMA_DATA copy that misses every queued write drained the draw pipeline: the label behind it never queued behind the held commit (" + std::to_string(copied.outstanding) + " outstanding)"); + check(copied.drains == 0, "a DMA_DATA copy that misses every queued write drained the draw pipeline (" + std::to_string(copied.drains) + " packet drains)"); for (std::size_t i = 0; i < Destination.size(); ++i) check(Destination[i] == (i < 128 ? Source[i] : 0u), "the copy did not land, or wrote past its bytes"); LibcRunShutdown_nid_postfix(); - std::puts("a DMA_DATA prefetch keeps the draw pipeline, a copy drains it"); + std::puts("a DMA_DATA prefetch and a copy that misses every queued write keep the draw pipeline"); return 0; } catch (const std::exception& error) { std::cerr << error.what() << '\n'; diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/PreparationScopeSettle.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/PreparationScopeSettle.cpp index b67059d036..ab06a87e40 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/PreparationScopeSettle.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/PreparationScopeSettle.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceAgc/Shader/include/InterpolantMapping.hpp" #include "VulkanTestDevice.hpp" #include "SceShaders.hpp" #include "prx/libSceAgcDriver/Execution/include/Driver.hpp" @@ -15,8 +16,6 @@ #include #include -extern "C" int APS5_VABI sceAgcCreateInterpolantMapping_0100(ShaderRegister* regs, const Shader* gs, const Shader* ps); - namespace { void Require(bool condition, const char* message) { diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/PreparedShaders.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/PreparedShaders.cpp index 88ecd918f8..82c999000d 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/PreparedShaders.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/PreparedShaders.cpp @@ -1413,13 +1413,81 @@ void RelocatedHeaders() { ExpectFailure([&] { AgcDriverResolveShaderAbi_nid_postfix(&otherContext.shader, {}, primitive); }, "replaced shader header"); } +void DispatchAheadPrewarm() { + alignas(256) std::array pendingCode{0xbf810000u}; + alignas(256) std::array lazyCode{}; + lazyCode[0] = 0xbf810000u; + lazyCode[64] = 0xbf810000u; + struct Header { + Shader shader{}; + std::array registers{}; + ShaderSpecialRegs specials{}; + } pendingHeader, lazyHeader; + const auto fillHeader = [](Header& header, const void* code, std::size_t codeBytes) { + const auto address = reinterpret_cast(code); + header.shader.file_header = 0x34333231u; + header.shader.version = 0x18; + header.shader.header_size = sizeof(Header); + header.shader.shader_size = static_cast(codeBytes); + header.shader.code = const_cast(code); + header.shader.sh_registers = header.registers.data(); + header.shader.num_sh_registers = header.registers.size(); + header.shader.specials = &header.specials; + header.specials.dispatch_modifier = 0x8000; + header.registers = {{{0x20c, static_cast(address >> 8u)}, {0x20d, static_cast(address >> 40u)}, {0x207, 1}, {0x208, 1}, {0x209, 1}, {0x212, 0}, {0x213, 2}}}; + }; + fillHeader(pendingHeader, pendingCode.data(), sizeof(pendingCode)); + fillHeader(lazyHeader, lazyCode.data(), sizeof(lazyCode)); + AgcDriverRegisterShader_nid_postfix(&pendingHeader.shader); + AgcDriverRegisterShader_nid_postfix(&lazyHeader.shader); + AgcDriver::DriverDetail::AwaitRegistrationPreparation(); + const auto registry = AgcDriver::DriverDetail::Driver::Get().RegisteredShaders(); + Require(registry != nullptr, "dispatch ahead prewarm test published no shader registry"); + const auto pendingSnapshot = AgcDriver::DriverDetail::RegisteredHeader(*registry, &pendingHeader.shader); + const auto lazySnapshot = AgcDriver::DriverDetail::RegisteredHeader(*registry, &lazyHeader.shader); + Require(pendingSnapshot != nullptr && lazySnapshot != nullptr, "dispatch ahead prewarm test published no snapshots"); + { + std::lock_guard lock(pendingSnapshot->prepared->mutex); + pendingSnapshot->prepared->entries.clear(); + pendingSnapshot->prepared->demanded.store(false, std::memory_order_release); + pendingSnapshot->prepared->pending = true; + } + { + std::lock_guard lock(lazySnapshot->prepared->mutex); + lazySnapshot->prepared->entries.clear(); + lazySnapshot->prepared->pending = false; + } + alignas(256) static const std::array invalidCode{0xbf9f0000u}; + const auto invalidAddress = reinterpret_cast(invalidCode.data()); + const auto lazyOffsetAddress = reinterpret_cast(lazyCode.data() + 64); + alignas(16) const std::array indirectPairs{0x20cu, static_cast(lazyOffsetAddress >> 8u), 0x20du, static_cast(lazyOffsetAddress >> 40u), 0x240u, 7u}; + const auto pairsAddress = reinterpret_cast(indirectPairs.data()); + std::vector commands; + for (const auto reg : pendingHeader.registers) commands.insert(commands.end(), {0xc0017600u, reg.offset, reg.value}); + commands.insert(commands.end(), {0xc0017600u, 0x20cu, static_cast(invalidAddress >> 8u), 0xc0017600u, 0x20du, static_cast(invalidAddress >> 40u), 0xc0031500u, 1, 1, 1, 0x8041u, 0xffff1000u}); + commands.insert(commands.end(), {0xc0017600u, 0x20cu, pendingHeader.registers[0].value, 0xc0017600u, 0x20du, pendingHeader.registers[1].value, 0xc0031500u, 1, 1, 1, 0x8041u}); + commands.insert(commands.end(), {0xc0036300u, static_cast(pairsAddress), static_cast(pairsAddress >> 32u), 0x80000000u, 3u}); + commands.insert(commands.end(), {0xc0031500u, 1, 1, 1, 0x8041u}); + Packet packet{commands.data(), static_cast(commands.size()), 0, {}}; + Require(sceAgcDriverSubmitAcb(0x20, &packet) == 0, "dispatch ahead prewarm submit failed"); + ExpectFailure([] { AgcDriverWaitIdle_nid_postfix(); }, "s_code_end"); + AgcDriver::DriverDetail::AwaitRegistrationPreparation(); + AgcDriver::DriverDetail::AwaitLibraryPrebuilds(); + Require(pendingSnapshot->prepared->demanded.load(std::memory_order_acquire), "dispatch ahead did not prioritize the pending shader"); + { + std::lock_guard lock(lazySnapshot->prepared->mutex); + Require(lazySnapshot->prepared->entries.size() == 1 && lazySnapshot->prepared->entries.front().codeOffset == 64 && lazySnapshot->prepared->entries.front().handle != nullptr, "dispatch ahead did not prewarm the lazy shader for its dispatched offset"); + } + ExpectFailure([] { AgcDriverShutdown_nid_postfix(); }, "s_code_end"); +} + } int main(int argc, char** argv) { try { const std::string_view abiMode = argc == 2 ? argv[1] : ""; const bool abiDeferred = abiMode == "--abi-deferred-compute" || abiMode == "--abi-deferred-concurrent" || abiMode == "--abi-deferred-pixel" || abiMode == "--abi-deferred-stages" || abiMode == "--abi-deferred-rectangle" || abiMode == "--abi-deferred-undecodable-state" || abiMode == "--abi-deferred-registration-failure" || abiMode == "--abi-deferred-vertex-inputs" || abiMode == "--abi-deferred-rectangle-pairs"; - Require(argc == 1 || abiDeferred || (argc == 2 && (std::string_view(argv[1]) == "--indirect" || std::string_view(argv[1]) == "--fail-before-registration" || std::string_view(argv[1]) == "--deferred" || std::string_view(argv[1]) == "--deferred-undecodable" || std::string_view(argv[1]) == "--registered-workgroup" || std::string_view(argv[1]) == "--lazy")), "invalid test arguments"); + Require(argc == 1 || abiDeferred || (argc == 2 && (std::string_view(argv[1]) == "--indirect" || std::string_view(argv[1]) == "--fail-before-registration" || std::string_view(argv[1]) == "--deferred" || std::string_view(argv[1]) == "--deferred-undecodable" || std::string_view(argv[1]) == "--registered-workgroup" || std::string_view(argv[1]) == "--dispatch-ahead-prewarm" || std::string_view(argv[1]) == "--lazy")), "invalid test arguments"); if (abiDeferred) { if (!OpenVulkanTestDevice()) return VulkanTestSkipped; if (abiMode == "--abi-deferred-compute") AbiDeferredCompute(); @@ -1447,6 +1515,12 @@ int main(int argc, char** argv) { AgcDriverShutdown_nid_postfix(); return 0; } + if (argc == 2 && std::string_view(argv[1]) == "--dispatch-ahead-prewarm") { + if (!OpenVulkanTestDevice()) return VulkanTestSkipped; + DispatchAheadPrewarm(); + std::cout << "dispatch ahead prewarm tests passed\n"; + return 0; + } if (argc == 2 && std::string_view(argv[1]) == "--deferred") { if (!OpenVulkanTestDevice()) return VulkanTestSkipped; DeferredRegistration(); diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/QueueZeroLateInterrupt.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/QueueZeroLateInterrupt.cpp index 00f3ca4d2e..b1b08b90c9 100755 --- a/core/libs/prx/libSceAgcDriver/tests/execution/QueueZeroLateInterrupt.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/QueueZeroLateInterrupt.cpp @@ -1,3 +1,4 @@ +#include "prx/libkernel/include/Api.hpp" #include "prx/libSceAgcDriver/Execution/include/Driver.hpp" #include "prx/libSceAgcDriver/Execution/include/Driver/Draw/DrawPipeline.hpp" #include "prx/libSceAgcDriver/Execution/include/Driver/Synchronization/SynchronizationStatistics.hpp" @@ -27,9 +28,6 @@ #include #include -extern "C" int APS5_VABI sceKernelCreateEqueue(KernelEqueue* eq, const char* name); -extern "C" int APS5_VABI sceKernelDeleteEqueue(KernelEqueue eq); - namespace { constexpr std::uint32_t Lanes = 32; diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/QueuedIndexReadOrder.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/QueuedIndexReadOrder.cpp index acc2b1617a..d69048386f 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/QueuedIndexReadOrder.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/QueuedIndexReadOrder.cpp @@ -343,10 +343,8 @@ void CopyPendingImage(std::size_t bytes, const char* phase) { int main() { #ifdef _WIN32 _putenv_s("APS5_PIPELINED_DRAWS", "1"); - _putenv_s("APS5_PIPELINE_DMA", "1"); #else setenv("APS5_PIPELINED_DRAWS", "1", 1); - setenv("APS5_PIPELINE_DMA", "1", 1); #endif try { { @@ -373,6 +371,11 @@ int main() { AgcDriverWaitIdle_nid_postfix(); Require(AgcDriver::Graphics::StorageTexture::AnyPending(), "queued index read: the image write left no pending result to order against"); Require(IndicesIntact(), "queued index read: the image's results reached guest memory before any consumer asked"); + const auto copiedAddress = static_cast(reinterpret_cast(Copied)); + const auto heldQueries = AgcDriver::DriverDetail::DrawPipeline::HeldReadQueries(); + Require(!AgcDriver::Graphics::StorageTexture::FlushPending(copiedAddress, PoolBytes), "queued index read: a flush over memory without pending results stored something"); + Require(AgcDriver::DriverDetail::DrawPipeline::HeldReadQueries() == heldQueries, "queued index read: a flush with nothing to store asked the draw pipeline for held reads"); + Require(IndicesIntact(), "queued index read: a flush over other memory stored the image's results"); GateUntilQueued(); std::fill_n(ColorMemory, ColorBytes, std::byte{0}); Submit(Draw(Vertices.data(), Vertices.size()), "the indexed draw"); diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/SampleMultisampleTarget.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/SampleMultisampleTarget.cpp index 69392bd173..5870d759ac 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/SampleMultisampleTarget.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/SampleMultisampleTarget.cpp @@ -1015,6 +1015,20 @@ int main(int argc, char** argv) { Block stored(BlockBytes); StoreWords(stored, colorBytes, FillOnes); CheckUniform(LoadSamples(*device, stored), Ones, "from color memory of half-float ones no draw rendered to"); + Block reused(BlockBytes); + StoreWords(reused, colorBytes, FillOnes); + CheckUniform(LoadSamples(*device, reused), Ones, "from color memory of half-float ones no draw rendered to, before the title reuses it"); + AgcDriver::Graphics::RequireNoMultisampleColorTarget(reused.Address(), static_cast(colorBytes / 2u), "a storage image access"); + StoreWords(reused, colorBytes, 0u); + CheckUniform(LoadSamples(*device, reused), {}, "from color memory no draw rendered to after the title reused it for zeros"); + std::string drawnRefusal; + try { + AgcDriver::Graphics::RequireNoMultisampleColorTarget(block.Address(), static_cast(colorBytes / 2u), "a storage image access"); + } catch (const std::exception& error) { + drawnRefusal = error.what(); + } + Require(drawnRefusal.find("whose samples are only on the host") != std::string::npos, "a guest access over a drawn 4x target is not refused"); + std::puts("a guest access over a 4x texture no draw rendered to retires it, so a later load reads the memory's new value, and a guest access over a drawn target is still refused"); const auto storedState = TargetState(DecodeTarget(stored)); Draw(*device, storedState); CheckSamples(storedState, LoadSamples(*device, stored), Ones); @@ -1031,6 +1045,23 @@ int main(int argc, char** argv) { Block undrawn(BlockBytes); StoreSamples(*device, TargetDescriptor(undrawn, SampleShift), SampleWrites(leftHalf)); CheckWritten(std::vector>(Side * Side * Samples), LoadSamples(*device, undrawn), leftHalf, "into zeroed color memory no draw rendered to"); + const auto refusedOver = [&](const Block& over) { + try { + AgcDriver::Graphics::RequireNoMultisampleColorTarget(over.Address(), static_cast(colorBytes / 2u), "a storage image access"); + } catch (const std::exception& error) { + return std::string(error.what()).find("whose samples are only on the host") != std::string::npos; + } + return false; + }; + Require(refusedOver(undrawn), "a guest access over a 4x texture no draw rendered to but a dispatch wrote is not refused"); + Block absorbing(BlockBytes); + StoreWords(absorbing, colorBytes, FillOnes); + CheckUniform(LoadSamples(*device, absorbing), Ones, "from color memory of half-float ones no draw rendered to, before a fill the texture absorbs"); + Require(AgcDriver::Graphics::MultisampledColorFillAbsorbs(absorbing.Address(), static_cast(colorBytes), 0u), "a fill of 0 over the whole color memory of a 4x texture no draw rendered to is not absorbed"); + AgcDriver::Graphics::NoteColorMetadataFill(absorbing.Address(), static_cast(colorBytes), 0u); + Require(refusedOver(absorbing), "a guest access over a 4x texture no draw rendered to that absorbed a fill is not refused"); + CheckUniform(LoadSamples(*device, absorbing), {}, "from a 4x texture no draw rendered to after it absorbed a fill of 0"); + std::puts("a guest access over a 4x texture no draw rendered to is still refused once a dispatch wrote it or it absorbed a fill"); Block mixedStore(BlockBytes); StoreWords(mixedStore, colorBytes, FillOnes); std::memcpy(mixedStore.data + colorBytes - sizeof(odd), &odd, sizeof(odd)); diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/SkipShaderFile.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/SkipShaderFile.cpp new file mode 100644 index 0000000000..cec7c1cc4c --- /dev/null +++ b/core/libs/prx/libSceAgcDriver/tests/execution/SkipShaderFile.cpp @@ -0,0 +1,102 @@ +#include "prx/libSceAgcDriver/Execution/include/Driver.hpp" +#include "prx/libSceAgcDriver/Execution/include/GuestMemory.hpp" +#include "prx/libSceAgcDriver/Graphics/include/Draw.hpp" +#include "VulkanTestDevice.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace { + +using AgcDriver::Graphics::Require; + +alignas(256) constexpr std::array First{0xd7460000u, 0x04010c04u, 0x7e0202ffu, 0x12345678u, 0xe0702000u, 0x80000100u, 0xbf810000u}; +alignas(256) constexpr std::array Second{0xd7460000u, 0x04010c04u, 0x7e0202ffu, 0x12345678u, 0xe0702000u, 0x80000100u, 0xbf810000u}; +constexpr std::uint32_t Untouched = 0xcafebabeu; +constexpr std::uint32_t Stored = 0x12345678u; +alignas(256) std::array FirstOutput{}; +alignas(256) std::array SecondOutput{}; + +void Dispatch(const std::array& code, std::array& output) { + const auto address = reinterpret_cast(output.data()); + const std::array data{static_cast(address), static_cast((address >> 32u) & 0xffffu) | (4u << 16u), static_cast(output.size()), 0x00014204u}; + const auto program = reinterpret_cast(code.data()); + std::vector words{ + 0xc0037600u, 0x207, 64, 1, 1, + 0xc0027600u, 0x20c, static_cast(program >> 8u), static_cast(program >> 40u), + 0xc0017600u, 0x213, (4u << 1u) | (1u << 7u), + 0xc0047600u, 0x240, data[0], data[1], data[2], data[3], + 0xc0031500u, 1, 1, 1, 0x41u, + }; + Packet packet{words.data(), static_cast(words.size()), 0, {}}; + AgcDriver::Submit(&packet, 0); + AgcDriverWaitIdle_nid_postfix(); + AgcDriver::GuestMemory::FlushGpuWrites(address, sizeof(output)); +} + +std::string Hex(const void* address) { + char text[32]; + std::snprintf(text, sizeof(text), "%llx", static_cast(reinterpret_cast(address))); + return text; +} + +void List(const std::filesystem::path& path, const std::string& contents) { + std::ofstream(path, std::ios::trunc) << contents; + std::this_thread::sleep_for(std::chrono::milliseconds(1100)); +} + +void Run(const char* phase, bool firstSkipped, bool secondSkipped) { + FirstOutput.fill(Untouched); + SecondOutput.fill(Untouched); + Dispatch(First, FirstOutput); + Dispatch(Second, SecondOutput); + for (std::size_t i = 0; i < FirstOutput.size(); ++i) { + Require(FirstOutput[i] == (firstSkipped ? Untouched : Stored), std::string(phase) + ": the first shader's dispatch " + (firstSkipped ? "stored" : "did not store") + " dword " + std::to_string(i)); + Require(SecondOutput[i] == (secondSkipped ? Untouched : Stored), std::string(phase) + ": the second shader's dispatch " + (secondSkipped ? "stored" : "did not store") + " dword " + std::to_string(i)); + } +} + +} + +int main() { + const auto path = std::filesystem::temp_directory_path() / ("aps5-skip-shader-file-" + Hex(&FirstOutput) + ".txt"); + try { + List(path, "# listed\n" + Hex(First.data()) + "\n"); +#ifdef _WIN32 + Require(_putenv_s("APS5_SKIP_SHADER_FILE", path.string().c_str()) == 0, "cannot set APS5_SKIP_SHADER_FILE"); +#else + Require(setenv("APS5_SKIP_SHADER_FILE", path.string().c_str(), 1) == 0, "cannot set APS5_SKIP_SHADER_FILE"); +#endif + { + const auto device = OpenVulkanTestDevice(); + if (!device) { + std::filesystem::remove(path); + return VulkanTestSkipped; + } + } + Run("first listed", true, false); + List(path, Hex(Second.data()) + " # the first is not listed any more\n"); + Run("second listed", false, true); + List(path, Hex(First.data()) + "zz 1" + std::string(16, '0') + " 0x" + Hex(Second.data()) + "\n"); + Run("malformed and overflowing tokens", false, true); + List(path, ""); + Run("none listed", false, false); + AgcDriverShutdown_nid_postfix(); + std::filesystem::remove(path); + std::puts("skip shader file tests passed"); + return 0; + } catch (const std::exception& error) { + std::cerr << error.what() << '\n'; + AgcDriverShutdown_nid_postfix(); + std::error_code ignored; + std::filesystem::remove(path, ignored); + return 1; + } +} diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/StorageFileWrite.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/StorageFileWrite.cpp index d50aceebbc..8658f5b45b 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/StorageFileWrite.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/StorageFileWrite.cpp @@ -1,3 +1,6 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libkernel/File/include/File.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libSceAgcDriver/Execution/include/Driver.hpp" #include "prx/libSceAgcDriver/Execution/include/GuestMemory.hpp" #include "prx/libSceAgcDriver/Graphics/include/Draw.hpp" @@ -35,27 +38,6 @@ #endif class FileStream; -struct GuestIovec { void* base; std::size_t length; }; - -extern "C" { -int APS5_VABI sceKernelOpen(const char*, int, std::uint16_t); -int APS5_VABI sceKernelClose(int); -std::int64_t APS5_VABI sceKernelWrite(int, const void*, std::size_t); -std::int64_t APS5_VABI sceKernelPwrite(int, const void*, std::size_t, std::int64_t); -std::int64_t APS5_VABI sceKernelWritev(int, const GuestIovec*, int); -std::int64_t APS5_VABI sceKernelPwritev(int, const GuestIovec*, int, std::int64_t); -std::int64_t APS5_VABI write_nid_postfix(int, const char*, std::int64_t); -std::int64_t APS5_VABI _write_nid_postfix(int, const void*, std::size_t); -std::int64_t APS5_VABI pwrite_nid_disambig1_nid_postfix(int, const void*, std::size_t, std::int64_t); -std::int64_t APS5_VABI writev_nid_postfix(int, const GuestIovec*, int); -std::int64_t APS5_VABI pwritev_nid_postfix(int, const GuestIovec*, int, std::int64_t); -int APS5_VABI sceKernelAioSubmitWriteCommands(KernelAioRwRequest*, std::int32_t, std::int32_t, std::int32_t*); -int APS5_VABI sceKernelAioSubmitWriteCommandsMultiple(KernelAioRwRequest*, std::int32_t, std::int32_t, std::int32_t*); -int APS5_VABI sceKernelAioDeleteRequest(std::int32_t, std::int32_t*); -FileStream* APS5_VABI fopen_nid_postfix(const char*, const char*); -std::size_t APS5_VABI fwrite_nid_postfix(const void*, std::size_t, std::size_t, FileStream*); -int APS5_VABI fclose_nid_postfix(FileStream*); -} namespace { @@ -192,7 +174,7 @@ bool CheckWrite(Api api, const char* name, GuestSurface& surface, GuestSurface& const auto hold = ProduceHeld(surface, unrelated); OutputFile file; auto* source = surface.Data() + SourceOffset; - const std::array vectors{{{source, 111}, {nullptr, 0}, {source + 111, 65537}, {source + 65648, TransferBytes - 65648}}}; + const std::array vectors{{{source, 111}, {nullptr, 0}, {source + 111, 65537}, {source + 65648, TransferBytes - 65648}}}; const bool positioned = api == Api::Pwrite || api == Api::PosixPwrite || api == Api::Pwritev || api == Api::PosixPwritev || api == Api::Aio || api == Api::AioMultiple; if (api == Api::Fwrite) { auto* stream = fopen_nid_postfix(file.Name().c_str(), "wb"); @@ -326,8 +308,8 @@ void CheckShutdownAndGuard() { OutputFile file; std::vector source(TransferBytes, std::byte{0x5a}); AgcDriver::GuestMemory::SetFlushHook(nullptr); - AgcDriver::GuestMemory::SetReadGuard([](std::uint64_t, std::size_t) { throw std::runtime_error("file source read guard"); }); const auto descriptor = file.Open(); + AgcDriver::GuestMemory::SetReadGuard([](std::uint64_t, std::size_t) { throw std::runtime_error("file source read guard"); }); bool refused = false; try { sceKernelWrite(descriptor, source.data(), source.size()); } catch (const std::runtime_error& error) { refused = std::string(error.what()) == "file source read guard"; } diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/VCvtPkU8F32RoundMode.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/VCvtPkU8F32RoundMode.cpp index 777bd3e290..88725601dd 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/VCvtPkU8F32RoundMode.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/VCvtPkU8F32RoundMode.cpp @@ -26,6 +26,11 @@ alignas(256) constexpr std::array Code{ 0x80010a02u, 0xbf810000u, }; +alignas(256) std::array RoundModeCode{ + 0x34020084u, 0x34040082u, 0xe0381000u, 0x80000401u, 0xbf8c3f70u, 0xbfa40000u, 0xd55e000au, 0x02010104u, + 0xe0701000u, 0x80010a02u, 0xbf810000u, +}; + struct PackVector { std::uint32_t value; std::uint32_t denormalsFlushed[4]; @@ -84,7 +89,7 @@ std::string Hex(std::uint32_t value) { return text; } -void Run(AgcDriver::VulkanDevice& device, ShaderRecompiler::ShaderFloatMode floatMode) { +void Run(AgcDriver::VulkanDevice& device, std::span code, ShaderRecompiler::ShaderFloatMode floatMode) { Input.fill(0u); for (std::uint32_t lane = 0; lane < Vectors.size(); ++lane) Input[lane * Inputs] = Vectors[lane].value; Output.fill(0xdeadbeefu); @@ -93,7 +98,6 @@ void Run(AgcDriver::VulkanDevice& device, ShaderRecompiler::ShaderFloatMode floa const auto output = BufferDescriptor(Output.data(), static_cast(Output.size() * 4u)); std::copy(input.begin(), input.end(), userData.begin()); std::copy(output.begin(), output.end(), userData.begin() + 4); - const std::span code(Code); const std::array memory{{{reinterpret_cast(code.data()), std::as_bytes(code)}}}; const ShaderRecompiler::ShaderComputeStageInfo compute{{Threads, 1, 1}, 0, {false, false, false}, false, 1}; ShaderRecompiler::RecompileRequest request{ @@ -109,11 +113,11 @@ void Run(AgcDriver::VulkanDevice& device, ShaderRecompiler::ShaderFloatMode floa device.WaitIdle(); } -void Check(bool kept, std::uint32_t rounding, bool ieee) { +void Check(bool kept, std::uint32_t rounding, bool ieee, const std::string& setting) { for (std::uint32_t lane = 0; lane < Vectors.size(); ++lane) { const auto& vector = Vectors[lane]; const auto expected = kept ? vector.denormalsKept[rounding] : vector.denormalsFlushed[rounding]; - Require(Output[lane] == expected, std::string("v_cvt_pk_u8_f32 round mode ") + std::to_string(rounding) + (kept ? ", f32 denormals kept" : ", f32 denormals flushed") + + Require(Output[lane] == expected, std::string("v_cvt_pk_u8_f32 round mode ") + std::to_string(rounding) + setting + (kept ? ", f32 denormals kept" : ", f32 denormals flushed") + (ieee ? ", IEEE=1" : ", IEEE=0") + " of " + Hex(vector.value) + " is " + Hex(Output[lane]) + ", expected " + Hex(expected)); } } @@ -124,11 +128,16 @@ int main() { try { const auto device = OpenVulkanTestDevice(); if (!device) return VulkanTestSkipped; - for (const bool kept : {false, true}) { + for (std::uint32_t denormals = 0; denormals < 4u; ++denormals) { + const bool kept = (denormals & 1u) != 0u; + const std::string field = ", f32 denormal mode " + std::to_string(denormals); for (std::uint32_t rounding = 0; rounding < 4u; ++rounding) { for (const bool ieee : {false, true}) { - Run(*device, ShaderRecompiler::ShaderFloatMode{(kept ? 0xf0u : 0xc0u) | rounding, true, ieee, false}); - Check(kept, rounding, ieee); + Run(*device, Code, ShaderRecompiler::ShaderFloatMode{0xc0u | denormals << 4u | rounding, true, ieee, false}); + Check(kept, rounding, ieee, field); + RoundModeCode[5] = 0xbfa40000u | rounding; + Run(*device, RoundModeCode, ShaderRecompiler::ShaderFloatMode{0xc0u | denormals << 4u, true, ieee, false}); + Check(kept, rounding, ieee, field + " set by s_round_mode"); } } } diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/VertexClipCullDistances.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/VertexClipCullDistances.cpp index 08adb9fde4..23c82c25eb 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/VertexClipCullDistances.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/VertexClipCullDistances.cpp @@ -18,6 +18,7 @@ using ShaderRecompiler::ShaderStage; constexpr std::uint32_t Width = 192; constexpr std::uint32_t Height = 128; constexpr std::uint32_t DistanceVector = 0x00400000u; +constexpr std::uint32_t CullDistanceEnables = 0x0000ff00u; alignas(256) std::array Pixels{}; alignas(256) constexpr std::array VertexCode{ @@ -185,14 +186,19 @@ int main() { std::printf("skipped, subgroup size %u cannot hold a wave32\n", device->Target().subgroupSize); return VulkanTestSkipped; } + const bool cullDistance = TargetHasCapability(device->Target(), spv::CapabilityCullDistance); + if (!cullDistance) std::puts("cull distance cases skipped, the device has no shaderCullDistance"); + const auto runs = [&](const Row& row) { return cullDistance || (row.control & CullDistanceEnables) == 0u; }; for (const auto waveSize : {64u, 32u}) { for (const auto& row : Rows) { + if (!runs(row)) continue; Draw(*device, waveSize, row, false); Check(row, waveSize, false); } } if (device->Target().mesh.has_value()) { for (const auto& row : Rows) { + if (!runs(row)) continue; Draw(*device, 64u, row, true); Check(row, 64u, true); } diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/VertexClipCullDraw.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/VertexClipCullDraw.cpp index 076e006c49..b4d62cdc54 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/VertexClipCullDraw.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/VertexClipCullDraw.cpp @@ -33,6 +33,7 @@ using AgcDriver::Graphics::Require; constexpr std::uint32_t Width = 192; constexpr std::uint32_t Height = 128; constexpr std::uint32_t DistanceVector = 0x00400000u; +constexpr std::uint32_t CullDistanceEnables = 0x0000ff00u; constexpr std::uint32_t SetContextReg = 0x69u; constexpr std::uint32_t SetShReg = 0x76u; constexpr std::uint32_t SetUconfigReg = 0x79u; @@ -212,14 +213,18 @@ int main(int argc, char** argv) { const bool noKey = argc > 1 && std::string(argv[1]) == "no-key"; if (noKey) Require(std::getenv("APS5_NO_DRAW_KEY") != nullptr, "the no-key run must start with APS5_NO_DRAW_KEY set"); PositionExportLayoutTests(); + bool cullDistance = false; { const auto device = OpenVulkanTestDevice(); if (!device) return VulkanTestSkipped; + cullDistance = TargetHasCapability(device->Target(), spv::CapabilityCullDistance); } + if (!cullDistance) std::puts("cull distance steps skipped, the device has no shaderCullDistance"); ColorMemory = AllocateWatched(2 * Block); Register(VertexShader, VertexCode.data(), sizeof(VertexCode), 2); Register(PixelShader, PixelCode.data(), sizeof(PixelCode), 1); for (const auto& step : Steps) { + if (!cullDistance && (step.control & CullDistanceEnables) != 0u) continue; std::array vertices{}; for (std::size_t i = 0; i < vertices.size(); ++i) { vertices[i] = {{PositionX[i], PositionY[i], 0.5f, 1.0f}, {step.component0[i], step.component1[i], step.component2[i], 0.0f}}; diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/VertexUserDataTail.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/VertexUserDataTail.cpp index df9e6f2c6d..2130d6f232 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/VertexUserDataTail.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/VertexUserDataTail.cpp @@ -125,7 +125,7 @@ void ControlStateDraws(std::vector prefix) { CheckBranchColors(activeExec, emptyExec, "EXEC"); } -void VertexTailDraws() { +void VertexTailDraws(bool cullDistance) { std::vector prefix{ 0x7e000d05u, 0x080200f4u, 0x10020300u, 0x100202f4u, 0x060202f3u, 0x060400f3u, 0x10040500u, 0x060404f3u, 0x7e060280u, 0x7e0802f2u, 0xbe8c03ffu, 0x3f800000u, 0xbf060c0cu, @@ -142,8 +142,12 @@ void VertexTailDraws() { alignas(256) const std::array clipContinuation{0xbf840005u, 0x7e08020cu, 0xf80000cfu, 0x04030201u, 0xf80008dfu, 0x01010101u, 0xbf810000u}; const auto clipped = Check(prefix, clipContinuation, 0x00400001u, clipContinuation.size()); Require(clipped != original && std::count(clipped.begin(), clipped.end(), Kept) > kept, "a clip distance exported by the continuation did not clip the triangle"); - const auto culled = Check(prefix, clipContinuation, 0x00400100u, clipContinuation.size()); - Require(culled == original, "a mixed-sign cull distance discarded the triangle"); + if (cullDistance) { + const auto culled = Check(prefix, clipContinuation, 0x00400100u, clipContinuation.size()); + Require(culled == original, "a mixed-sign cull distance discarded the triangle"); + } else { + std::puts("cull distance draw skipped, the device has no shaderCullDistance"); + } ControlStateDraws(prefix); } @@ -151,11 +155,13 @@ void VertexTailDraws() { int main() { try { + bool cullDistance = false; { const auto device = OpenVulkanTestDevice(); if (!device) return VulkanTestSkipped; + cullDistance = TargetHasCapability(device->Target(), spv::CapabilityCullDistance); } - VertexTailDraws(); + VertexTailDraws(cullDistance); AgcDriverShutdown_nid_postfix(); std::puts("vertex user-data tail tests passed"); return 0; diff --git a/core/libs/prx/libSceAgcDriver/tools/FrameReplay.cpp b/core/libs/prx/libSceAgcDriver/tools/FrameReplay.cpp index ac6a434a0e..943f962b6e 100644 --- a/core/libs/prx/libSceAgcDriver/tools/FrameReplay.cpp +++ b/core/libs/prx/libSceAgcDriver/tools/FrameReplay.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceAgcDriver/State/include/Configuration.hpp" #include "prx/libSceAgcDriver/Execution/include/DisplayBuffer.hpp" #include "prx/libSceAgcDriver/Execution/include/Driver.hpp" #include "prx/libSceAgcDriver/Execution/include/FrameCapture.hpp" @@ -35,8 +36,6 @@ #include #endif -extern "C" int APS5_VABI sceAgcDriverSetTFRing(const volatile void* base, std::uint32_t size); - namespace { using AgcDriver::FrameCall; diff --git a/core/libs/prx/libSceAgcResourceRegistration/libSceAgcResourceRegistration.hpp b/core/libs/prx/libSceAgcResourceRegistration/libSceAgcResourceRegistration.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceAgcResourceRegistration/libSceAgcResourceRegistration.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceAgcVsh/Export.cpp b/core/libs/prx/libSceAgcVsh/Export.cpp index 0b65c5fa98..b648c87cc5 100644 --- a/core/libs/prx/libSceAgcVsh/Export.cpp +++ b/core/libs/prx/libSceAgcVsh/Export.cpp @@ -1,3 +1,153 @@ +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" +#include "prx/libSceAgcVsh/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceAgcVsh/include/Api.hpp b/core/libs/prx/libSceAgcVsh/include/Api.hpp new file mode 100644 index 0000000000..efe8a800e6 --- /dev/null +++ b/core/libs/prx/libSceAgcVsh/include/Api.hpp @@ -0,0 +1,158 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceAgcDcbCopyData_nid_no_patch(void); +int APS5_VABI sceAgcBranchPatchSetElseTarget_nid_no_patch(void); +int APS5_VABI sceAgcCbSetShRegistersDirect_nid_no_patch(void); +int APS5_VABI sceAgcCreateShader_nid_no_patch(void); +int APS5_VABI sceAgcDcbSetNumInstancesGetSize_nid_no_patch(void); +int APS5_VABI sceAgcDcbSetUcRegisterDirectGetSize_nid_no_patch(void); +int APS5_VABI sceAgcDcbDrawIndexIndirectMultiGetSize_nid_no_patch(void); +int APS5_VABI sceAgcDcbAtomicGdsGetSize_nid_no_patch(void); +int APS5_VABI sceAgcAcbCopyDataGetSize_nid_no_patch(void); +int APS5_VABI sceAgcAcbWaitUntilSafeForRendering_nid_no_patch(void); +int APS5_VABI sceAgcAsyncCondExecPatchSetEnd_nid_no_patch(void); +int APS5_VABI sceAgcDcbDmaDataGetSize_nid_no_patch(void); +int APS5_VABI sceAgcDcbSetUcRegistersIndirect_nid_no_patch(void); +int APS5_VABI sceAgcGetRegisterDefaults2_nid_no_patch(void); +int APS5_VABI sceAgcCbReleaseMem_nid_no_patch(void); +int APS5_VABI sceAgcCondExecPatchSetEnd_nid_no_patch(void); +int APS5_VABI sceAgcDcbAtomicGds_nid_no_patch(void); +int APS5_VABI sceAgcDcbSetCxRegistersIndirectGetSize_nid_no_patch(void); +int APS5_VABI sceAgcCbSetUcRegisterRangeDirect_nid_no_patch(void); +int APS5_VABI sceAgcDcbEventWrite_nid_no_patch(void); +int APS5_VABI sceAgcDcbWriteData_nid_no_patch(void); +int APS5_VABI sceAgcSetUcRegIndirectPatchSetAddress_nid_no_patch(void); +int APS5_VABI sceAgcCbCondWriteGetSize_nid_no_patch(void); +int APS5_VABI sceAgcDcbQueueEndOfShaderActionGetSize_nid_no_patch(void); +int APS5_VABI sceAgcGetPacketSize_nid_no_patch(void); +int APS5_VABI sceAgcAcbAcquireMem_nid_no_patch(void); +int APS5_VABI sceAgcAcbEventWriteGetSize_nid_no_patch(void); +int APS5_VABI sceAgcDcbSetIndexIndirectArgs_nid_no_patch(void); +int APS5_VABI sceAgcAcbDmaData_nid_no_patch(void); +int APS5_VABI sceAgcDcbDrawIndexIndirect_nid_no_patch(void); +int APS5_VABI sceAgcDcbPrimeUtcl2GetSize_nid_no_patch(void); +int APS5_VABI sceAgcAsyncCondExecPatchSetCommandAddress_nid_no_patch(void); +int APS5_VABI sceAgcAcbAcquireMemGetSize_nid_no_patch(void); +int APS5_VABI sceAgcDcbSetIndexIndirectArgsGetSize_nid_no_patch(void); +int APS5_VABI sceAgcCreateInterpolantMapping_nid_no_patch(void); +int APS5_VABI sceAgcDcbDrawIndexIndirectMulti_nid_no_patch(void); +int APS5_VABI sceAgcDcbEventWriteGetSize_nid_no_patch(void); +int APS5_VABI sceAgcDcbSetUcRegisterDirect_nid_no_patch(void); +int APS5_VABI sceAgcQueueEndOfPipeActionPatchAddress_nid_no_patch(void); +int APS5_VABI sceAgcDcbDrawIndirectMultiGetSize_nid_no_patch(void); +int APS5_VABI sceAgcDcbSetBaseDrawIndirectArgsGetSize_nid_no_patch(void); +int APS5_VABI sceAgcDcbSetNumInstances_nid_no_patch(void); +int APS5_VABI sceAgcDcbWaitOnAddressGetSize_nid_no_patch(void); +int APS5_VABI sceAgcAcbAtomicGds_nid_no_patch(void); +int APS5_VABI sceAgcDcbSetBoolPredicationEnableGetSize_nid_no_patch(void); +int APS5_VABI sceAgcAcbAtomicMemGetSize_nid_no_patch(void); +int APS5_VABI sceAgcDcbSetCfRegisterRangeDirect_nid_no_patch(void); +int APS5_VABI sceAgcDcbCondExecGetSize_nid_no_patch(void); +int APS5_VABI sceAgcDcbDrawIndexMultiInstanced_nid_no_patch(void); +int APS5_VABI sceAgcDcbSetCxRegistersIndirect_nid_no_patch(void); +int APS5_VABI sceAgcCbSetShRegistersDirectGetSize_nid_no_patch(void); +int APS5_VABI sceAgcCondExecPatchSetCommandAddress_nid_no_patch(void); +int APS5_VABI sceAgcRewindPatchSetRewindState_nid_no_patch(void); +int APS5_VABI sceAgcQueueEndOfPipeActionPatchGcrCntl_nid_no_patch(void); +int APS5_VABI sceAgcWaitRegMemPatchReference_nid_no_patch(void); +int APS5_VABI sceAgcAcbRewind_nid_no_patch(void); +int APS5_VABI sceAgcAcbCondExecGetSize_nid_no_patch(void); +int APS5_VABI sceAgcSuspendPointAndCheckStatus_nid_no_patch(void); +int APS5_VABI sceAgcAcbWaitRegMem_nid_no_patch(void); +int APS5_VABI sceAgcDcbAcquireMem_nid_no_patch(void); +int APS5_VABI sceAgcSetCxRegIndirectPatchSetNumRegisters_nid_no_patch(void); +int APS5_VABI sceAgcDcbContextStateOp_nid_no_patch(void); +int APS5_VABI sceAgcAcbWriteData_nid_no_patch(void); +int APS5_VABI sceAgcAcbDmaDataGetSize_nid_no_patch(void); +int APS5_VABI sceAgcCbSetShRegisterRangeDirectGetSize_nid_no_patch(void); +int APS5_VABI sceAgcCbNop_nid_no_patch(void); +int APS5_VABI sceAgcDcbResetQueue_nid_no_patch(void); +int APS5_VABI sceAgcDcbDmaData_nid_no_patch(void); +int APS5_VABI sceAgcDcbDrawIndexGetSize_nid_no_patch(void); +int APS5_VABI sceAgcDmaDataPatchSetDstAddressOrOffset_nid_no_patch(void); +int APS5_VABI sceAgcCbQueueEndOfPipeActionGetSize_nid_no_patch(void); +int APS5_VABI sceAgcDcbSetFlip_nid_no_patch(void); +int APS5_VABI sceAgcDcbSetMarker_nid_no_patch(void); +int APS5_VABI sceAgcDcbSetPredication_nid_no_patch(void); +int APS5_VABI sceAgcDcbAtomicMem_nid_no_patch(void); +int APS5_VABI sceAgcGetRegisterDefaults2Internal_nid_no_patch(void); +int APS5_VABI sceAgcSetShRegIndirectPatchAddRegisters_nid_no_patch(void); +int APS5_VABI sceAgcDcbPrimeUtcl2_nid_no_patch(void); +int APS5_VABI sceAgcAcbRewindGetSize_nid_no_patch(void); +int APS5_VABI sceAgcDcbSetZPassPredicationEnableGetSize_nid_no_patch(void); +int APS5_VABI sceAgcDcbWaitUntilSafeForRendering_nid_no_patch(void); +int APS5_VABI sceAgcBranchPatchSetThenTarget_nid_no_patch(void); +int APS5_VABI sceAgcSetCxRegIndirectPatchSetAddress_nid_no_patch(void); +int APS5_VABI sceAgcDcbAtomicMemGetSize_nid_no_patch(void); +int APS5_VABI sceAgcUpdatePrimState_nid_no_patch(void); +int APS5_VABI sceAgcCbNopGetSize_nid_no_patch(void); +int APS5_VABI sceAgcDcbGetLodStats_nid_no_patch(void); +int APS5_VABI sceAgcWaitRegMemPatchAddress_nid_no_patch(void); +int APS5_VABI sceAgcQueueEndOfPipeActionPatchData_nid_no_patch(void); +int APS5_VABI sceAgcGetRegisterDefaultsInternal_nid_no_patch(void); +int APS5_VABI sceAgcInit_nid_no_patch(void); +int APS5_VABI sceAgcDcbDispatchIndirectGetSize_nid_no_patch(void); +int APS5_VABI sceAgcDcbCondExec_nid_no_patch(void); +int APS5_VABI sceAgcAcbSetMarker_nid_no_patch(void); +int APS5_VABI sceAgcDcbDrawIndexOffsetGetSize_nid_no_patch(void); +int APS5_VABI sceAgcAcbJump_nid_no_patch(void); +int APS5_VABI sceAgcDcbSetIndexCount_nid_no_patch(void); +int APS5_VABI sceAgcDcbSetShRegistersIndirectGetSize_nid_no_patch(void); +int APS5_VABI sceAgcDcbStallCommandBufferParserGetSize_nid_no_patch(void); +int APS5_VABI sceAgcSuspendPoint_nid_no_patch(void); +int APS5_VABI sceAgcWaitRegMemPatchMask_nid_no_patch(void); +int APS5_VABI sceAgcAcbDispatchIndirectGetSize_nid_no_patch(void); +int APS5_VABI sceAgcAcbAtomicGdsGetSize_nid_no_patch(void); +int APS5_VABI sceAgcCbCondWrite_nid_no_patch(void); +int APS5_VABI sceAgcDcbEndOcclusionQueryGetSize_nid_no_patch(void); +int APS5_VABI sceAgcDcbSetPredicationDisableGetSize_nid_no_patch(void); +int APS5_VABI sceAgcLinkShaders_nid_no_patch(void); +int APS5_VABI sceAgcDcbWaitRegMem_nid_no_patch(void); +int APS5_VABI sceAgcGetRegisterDefaults_nid_no_patch(void); +int APS5_VABI sceAgcCbSetShRegisterRangeDirect_nid_no_patch(void); +int APS5_VABI sceAgcSetCxRegIndirectPatchAddRegisters_nid_no_patch(void); +int APS5_VABI sceAgcDcbDispatchIndirect_nid_no_patch(void); +int APS5_VABI sceAgcCbMemSemaphore_nid_no_patch(void); +int APS5_VABI sceAgcCbSetUcRegisterRangeDirectGetSize_nid_no_patch(void); +int APS5_VABI sceAgcCbDispatch_nid_no_patch(void); +int APS5_VABI sceAgcDcbCopyDataGetSize_nid_no_patch(void); +int APS5_VABI sceAgcDcbDrawIndexMultiInstancedGetSize_nid_no_patch(void); +int APS5_VABI sceAgcDmaDataPatchSetSrcAddressOrOffsetOrImmediate_nid_no_patch(void); +int APS5_VABI sceAgcSetShRegIndirectPatchSetAddress_nid_no_patch(void); +int APS5_VABI sceAgcDcbJump_nid_no_patch(void); +int APS5_VABI sceAgcDcbJumpGetSize_nid_no_patch(void); +int APS5_VABI sceAgcAcbPrimeUtcl2_nid_no_patch(void); +int APS5_VABI sceAgcDcbSetCxRegisterDirectGetSize_nid_no_patch(void); +int APS5_VABI sceAgcQueueEndOfPipeActionPatchType_nid_no_patch(void); +int APS5_VABI sceAgcDcbSetCxRegisterDirect_nid_no_patch(void); +int APS5_VABI sceAgcDcbDrawIndex_nid_no_patch(void); +int APS5_VABI sceAgcCbDispatchGetSize_nid_no_patch(void); +int APS5_VABI sceAgcDcbGetLodStatsGetSize_nid_no_patch(void); +int APS5_VABI sceAgcGetDataPacketPayloadAddress_nid_no_patch(void); +int APS5_VABI sceAgcDcbDrawIndirect_nid_no_patch(void); +int APS5_VABI sceAgcAcbSetFlip_nid_no_patch(void); +int APS5_VABI sceAgcGetFusedShaderSize_nid_no_patch(void); +int APS5_VABI sceAgcSetRangePredication_nid_no_patch(void); +int APS5_VABI sceAgcDcbSetShRegisterDirectGetSize_nid_no_patch(void); +int APS5_VABI sceAgcDcbSetIndexSize_nid_no_patch(void); +int APS5_VABI sceAgcSetPacketPredication_nid_no_patch(void); +int APS5_VABI sceAgcDcbDrawIndexOffset_nid_no_patch(void); +int APS5_VABI sceAgcAsyncRewindPatchSetRewindState_nid_no_patch(void); +int APS5_VABI sceAgcJumpPatchSetTarget_nid_no_patch(void); +int APS5_VABI sceAgcBranchPatchSetCompareAddress_nid_no_patch(void); +int APS5_VABI sceAgcAcbJumpGetSize_nid_no_patch(void); +int APS5_VABI sceAgcCbBranch_nid_no_patch(void); +int APS5_VABI sceAgcDcbDrawIndexIndirectGetSize_nid_no_patch(void); +int APS5_VABI sceAgcAcbCopyData_nid_no_patch(void); +int APS5_VABI sceAgcDcbWriteDataGetSize_nid_no_patch(void); +int APS5_VABI sceAgcAcbAtomicMem_nid_no_patch(void); +int APS5_VABI sceAgcAcbPrimeUtcl2GetSize_nid_no_patch(void); +int APS5_VABI sceAgcAcbResetQueue_nid_no_patch(void); +int APS5_VABI sceAgcAcbQueueEndOfShaderActionGetSize_nid_no_patch(void); +int APS5_VABI sceAgcDcbBeginOcclusionQueryGetSize_nid_no_patch(void); + +} diff --git a/core/libs/prx/libSceAgcVsh/libSceAgcVsh.hpp b/core/libs/prx/libSceAgcVsh/libSceAgcVsh.hpp new file mode 100644 index 0000000000..9291d1e52e --- /dev/null +++ b/core/libs/prx/libSceAgcVsh/libSceAgcVsh.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceAgcVsh/include/Api.hpp" diff --git a/core/libs/prx/libSceAgcVshDebug/libSceAgcVshDebug.hpp b/core/libs/prx/libSceAgcVshDebug/libSceAgcVshDebug.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceAgcVshDebug/libSceAgcVshDebug.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceAjm.native/Export.cpp b/core/libs/prx/libSceAjm.native/Export.cpp index 3b0b5e4a8a..c9f1f976a7 100644 --- a/core/libs/prx/libSceAjm.native/Export.cpp +++ b/core/libs/prx/libSceAjm.native/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceAjm.native/include/Api.hpp" #include #include #include "SceTypes.hpp" @@ -13,32 +14,6 @@ static void AjmStub(const char* name) { NotImplemented_nid_no_patch(name); } -struct WVorbisHeaderPacketParameter { - std::size_t size; - std::int32_t channels; - std::uint32_t sampleRate; - std::int32_t bytesPerSecond; - std::int32_t shortBlockExponent; - std::int32_t longBlockExponent; - std::uint32_t reserved; - const void* setupPacket; - std::size_t setupPacketSize; - void* output; - std::size_t outputCapacity; - std::size_t outputSize; -}; - -struct WVorbisSetupPacketParameter { - std::size_t size; - std::int32_t channels; - std::uint32_t reserved; - const void* input; - std::size_t inputSize; - void* output; - std::size_t outputCapacity; - std::size_t outputSize; -}; - static_assert(sizeof(WVorbisHeaderPacketParameter) == 72); static_assert(offsetof(WVorbisHeaderPacketParameter, setupPacket) == 32); static_assert(sizeof(WVorbisSetupPacketParameter) == 56); diff --git a/core/libs/prx/libSceAjm.native/include/Api.hpp b/core/libs/prx/libSceAjm.native/include/Api.hpp new file mode 100644 index 0000000000..3c1f8608ed --- /dev/null +++ b/core/libs/prx/libSceAjm.native/include/Api.hpp @@ -0,0 +1,74 @@ +#pragma once + +#include "SceTypes.hpp" + +struct WVorbisHeaderPacketParameter { + std::size_t size; + std::int32_t channels; + std::uint32_t sampleRate; + std::int32_t bytesPerSecond; + std::int32_t shortBlockExponent; + std::int32_t longBlockExponent; + std::uint32_t reserved; + const void* setupPacket; + std::size_t setupPacketSize; + void* output; + std::size_t outputCapacity; + std::size_t outputSize; +}; + +struct WVorbisSetupPacketParameter { + std::size_t size; + std::int32_t channels; + std::uint32_t reserved; + const void* input; + std::size_t inputSize; + void* output; + std::size_t outputCapacity; + std::size_t outputSize; +}; + +extern "C" { + +int APS5_VABI sceAjmBatchJobEncode(AjmBatchInfo* info, uint32_t instance, const void* pcmInput, size_t pcmInputSize, void* bitstreamOutput, size_t bitstreamOutputSize, void* result); +const char* APS5_VABI sceAjmStrError(int error); +int APS5_VABI sceAjmDecWVorbisCreateHeaderPacket(WVorbisHeaderPacketParameter* param); +int APS5_VABI sceAjmDecWVorbisCreateSetupPacket(WVorbisSetupPacketParameter* parameter); +int APS5_VABI sceAjmBatchGetLog(); +int APS5_VABI sceAjmInstanceAvailable(); +uint32_t APS5_VABI sceAjmInstanceCodecType(uint32_t instanceId); +int APS5_VABI sceAjmInstanceExtend(uint32_t context, uint32_t codec, uint64_t flags, uint32_t instance); +int APS5_VABI sceAjmInstanceSwitch(uint32_t context, uint32_t codec, uint64_t flags, uint32_t instance); +int APS5_VABI sceAjmInitialize(int64_t reserved, uint32_t* context); +int APS5_VABI sceAjmFinalize(uint32_t context); +int APS5_VABI sceAjmModuleRegister(uint32_t context, uint32_t codec, int64_t reserved); +int APS5_VABI sceAjmModuleUnregister(uint32_t context, uint32_t codec); +int APS5_VABI sceAjmMemoryRegister(uint32_t context, void* ptr, size_t pages); +int APS5_VABI sceAjmMemoryUnregister(uint32_t context, void* ptr); +int APS5_VABI sceAjmInstanceCreate(uint32_t context, uint32_t codec, uint64_t flags, uint32_t* instance); +int APS5_VABI sceAjmInstanceDestroy(uint32_t context, uint32_t instance); +int APS5_VABI sceAjmDecAt9ParseConfigData(const void* configData, AjmDecAt9ConfigDataInfo* configInfo); +int APS5_VABI sceAjmDecMp3ParseFrame(const uint8_t* stream, uint32_t streamSize, int parseOfl, AjmDecMp3ParseFrame* frame); +int APS5_VABI sceAjmBatchInitialize(void* buffer, size_t size, AjmBatchInfo* info); +int APS5_VABI sceAjmBatchJobInitialize(AjmBatchInfo* info, uint32_t instance, const void* codecParameters, size_t codecParametersSize, void* result); +int APS5_VABI sceAjmBatchJobClearContext(AjmBatchInfo* info, uint32_t instance, void* result); +int APS5_VABI sceAjmBatchJobSetGaplessDecode(AjmBatchInfo* info, uint32_t instance, const void* gaplessDecode, int reset, void* result); +int APS5_VABI sceAjmBatchJobControl(AjmBatchInfo* info, uint32_t instance, uint64_t flags, const void* sidebandInput, size_t sidebandInputSize, void* sidebandOutput, size_t sidebandOutputSize); +int APS5_VABI sceAjmBatchJobRunSplit(AjmBatchInfo* info, uint32_t instance, uint64_t flags, const AjmBuffer* inputBuffers, size_t inputBuffersNum, const AjmBuffer* outputBuffers, size_t outputBuffersNum, void* sidebandOutput, size_t sidebandOutputSize); +int APS5_VABI sceAjmBatchJobRun(AjmBatchInfo* info, uint32_t instance, uint64_t flags, const void* dataInput, size_t dataInputSize, void* dataOutput, size_t dataOutputSize, void* sidebandOutput, size_t sidebandOutputSize); +int APS5_VABI sceAjmBatchJobSetResampleParameters(AjmBatchInfo* info, uint32_t instance, float ratio, uint32_t flags, void* result); +int APS5_VABI sceAjmBatchJobSetResampleParametersEx(AjmBatchInfo* info, uint32_t instance, float ratioStart, float ratioChangePerSample, uint32_t flags, void* result); +int APS5_VABI sceAjmBatchJobGetResampleInfo(AjmBatchInfo* info, uint32_t instance, void* result); +int APS5_VABI sceAjmBatchJobDecode(AjmBatchInfo* info, uint32_t instance, const void* bitstreamInput, size_t bitstreamInputSize, void* pcmOutput, size_t pcmOutputSize, void* result); +int APS5_VABI sceAjmBatchJobDecodeSplit(AjmBatchInfo* info, uint32_t instance, const AjmBuffer* inputBuffers, size_t inputBuffersNum, const AjmBuffer* outputBuffers, size_t outputBuffersNum, void* result); +int APS5_VABI sceAjmBatchJobDecodeSingle(AjmBatchInfo* info, uint32_t instance, const void* bitstreamInput, size_t bitstreamInputSize, void* pcmOutput, size_t pcmOutputSize, void* result); +int APS5_VABI sceAjmBatchJobGetGaplessDecode(AjmBatchInfo* info, uint32_t instance, void* result); +int APS5_VABI sceAjmBatchJobGetInfo(AjmBatchInfo* info, uint32_t instance, void* result); +int APS5_VABI sceAjmBatchJobGetCodecInfo(AjmBatchInfo* info, uint32_t instance, void* result, size_t resultSize); +int APS5_VABI sceAjmBatchJobGetStatistics(AjmBatchInfo* info, float interval, void* result); +int APS5_VABI sceAjmBatchStart(uint32_t context, const AjmBatchInfo* info, int priority, AjmBatchError* error, uint32_t* batch); +int APS5_VABI sceAjmBatchWait(uint32_t context, uint32_t batch, uint32_t timeout, AjmBatchError* error); +int APS5_VABI sceAjmBatchCancel(uint32_t context, uint32_t batch); +int APS5_VABI sceAjmBatchErrorDump(const AjmBatchInfo* info, AjmBatchError* error); + +} diff --git a/core/libs/prx/libSceAjm.native/libSceAjm.native.hpp b/core/libs/prx/libSceAjm.native/libSceAjm.native.hpp new file mode 100644 index 0000000000..ed8be05e6b --- /dev/null +++ b/core/libs/prx/libSceAjm.native/libSceAjm.native.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceAjm.native/include/Api.hpp" diff --git a/core/libs/prx/libSceAjm.native/src/Ajm.cpp b/core/libs/prx/libSceAjm.native/src/Ajm.cpp index 1a27be97b1..7661f2477d 100644 --- a/core/libs/prx/libSceAjm.native/src/Ajm.cpp +++ b/core/libs/prx/libSceAjm.native/src/Ajm.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceAjm.native/include/Api.hpp" #include #include #include "SceTypes.hpp" @@ -1136,7 +1137,6 @@ std::size_t OpusPacketSamples(const std::uint8_t* packet, std::size_t size) { return frames * frameSamples; } - std::size_t OpusLength(const std::uint8_t* data, std::size_t size, std::size_t& at) { if (at >= size) return SIZE_MAX; const std::size_t first = data[at++]; diff --git a/core/libs/prx/libSceAjm/Export.cpp b/core/libs/prx/libSceAjm/Export.cpp index 508f721ede..be23cfdc39 100644 --- a/core/libs/prx/libSceAjm/Export.cpp +++ b/core/libs/prx/libSceAjm/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceAjm/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceAjm/include/Api.hpp b/core/libs/prx/libSceAjm/include/Api.hpp new file mode 100644 index 0000000000..1be3b9a23e --- /dev/null +++ b/core/libs/prx/libSceAjm/include/Api.hpp @@ -0,0 +1,11 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceAjmBatchJobControlBufferRa(); +int APS5_VABI sceAjmBatchJobRunSplitBufferRa(); +int APS5_VABI sceAjmBatchStartBuffer(); + +} diff --git a/core/libs/prx/libSceAjm/libSceAjm.hpp b/core/libs/prx/libSceAjm/libSceAjm.hpp new file mode 100644 index 0000000000..302a86a22a --- /dev/null +++ b/core/libs/prx/libSceAjm/libSceAjm.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceAjm/include/Api.hpp" diff --git a/core/libs/prx/libSceAjmi/Export.cpp b/core/libs/prx/libSceAjmi/Export.cpp index 83e8ac5ffa..3941ee53aa 100644 --- a/core/libs/prx/libSceAjmi/Export.cpp +++ b/core/libs/prx/libSceAjmi/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceAjmi/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceAjmi/include/Api.hpp b/core/libs/prx/libSceAjmi/include/Api.hpp new file mode 100644 index 0000000000..cf36eb1119 --- /dev/null +++ b/core/libs/prx/libSceAjmi/include/Api.hpp @@ -0,0 +1,10 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceAjmBatchJobInlineBuffer(void); +int APS5_VABI sceAjmBatchJobRunBufferRa(void); + +} diff --git a/core/libs/prx/libSceAjmi/libSceAjmi.hpp b/core/libs/prx/libSceAjmi/libSceAjmi.hpp new file mode 100644 index 0000000000..739e63957f --- /dev/null +++ b/core/libs/prx/libSceAjmi/libSceAjmi.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceAjmi/include/Api.hpp" diff --git a/core/libs/prx/libSceAmpr/Export.cpp b/core/libs/prx/libSceAmpr/Export.cpp index ca51ae70f2..ab976c5ed3 100644 --- a/core/libs/prx/libSceAmpr/Export.cpp +++ b/core/libs/prx/libSceAmpr/Export.cpp @@ -1,3 +1,5 @@ +#include "prx/libc/include/Api.hpp" +#include "prx/libSceAmpr/include/Api.hpp" #include #include #include @@ -226,22 +228,11 @@ static int RecordWriteAddressFromCounterPair(Apr::CommandBufferObject* buffer, v static std::atomic_flag sharedPtrSpinLock; -struct AmmUsageStatsData { - std::uint64_t sizeInBytes; - std::uint16_t numPageTablePoolEntries; - std::uint16_t allocatedPageTablePoolEntries; - std::uint16_t highWatermarkAllocatedEntries; - std::uint16_t reserved; - std::uint32_t ringIdleFlags; -}; static_assert(sizeof(AmmUsageStatsData) == 0x18); static constexpr std::uint16_t AmmPageTablePoolEntries = 512; static constexpr std::uint32_t AmmRingIdleFlags = 0x7; extern "C" { -int APS5_VABI _Cnd_init_nid_postfix(void** handle); -int APS5_VABI wcstombs_s_nid_postfix(std::size_t* result, char* destination, std::size_t capacity, const std::uint16_t* source, std::size_t limit); -[[noreturn]] void APS5_VABI __cxa_call_terminate_nid_postfix(void* exception); int APS5_VABI sceAmprCommandBufferWriteAddressOnCompletion(Apr::CommandBufferObject* buffer, volatile std::uint64_t* address, std::uint64_t value) { if (!ValidWriteAddress(address)) return SCE_KERNEL_ERROR_EINVAL; @@ -624,11 +615,6 @@ std::uint64_t APS5_VABI sceAmprMeasureCommandSizeWriteKernelEventQueue_04_00(std return sizeof(Apr::WriteKernelEventQueueCommand); } -struct AmmSubmitResult { - std::int32_t result; - std::uint32_t errorOffset; -}; - int APS5_VABI sceAmprAmmCommandBufferConstructor(Apr::CommandBufferObject* buffer) { (void)buffer; return 0; @@ -867,8 +853,8 @@ void APS5_VABI _Lock_shared_ptr_spin_lock_nid_postfix(void) { while (sharedPtrSpinLock.test_and_set(std::memory_order_acquire)) std::this_thread::yield(); } - [[noreturn]] void APS5_VABI __cxa_call_unexpected_nid_postfix(void* unwindException) { + __cxa_call_terminate_nid_postfix(unwindException); } diff --git a/core/libs/prx/libSceAmpr/include/Api.hpp b/core/libs/prx/libSceAmpr/include/Api.hpp new file mode 100644 index 0000000000..8939494652 --- /dev/null +++ b/core/libs/prx/libSceAmpr/include/Api.hpp @@ -0,0 +1,159 @@ +#pragma once + +#include "prx/libkernel/Apr/include/AprCommandBuffer.hpp" +#include "prx/libc/include/GuestTime.hpp" +#include "SceTypes.hpp" + +struct AmmSubmitResult { + std::int32_t result; + std::uint32_t errorOffset; +}; + +struct AmmUsageStatsData { + std::uint64_t sizeInBytes; + std::uint16_t numPageTablePoolEntries; + std::uint16_t allocatedPageTablePoolEntries; + std::uint16_t highWatermarkAllocatedEntries; + std::uint16_t reserved; + std::uint32_t ringIdleFlags; +}; + +extern "C" { + +int APS5_VABI sceAmprCommandBufferWriteAddressOnCompletion(Apr::CommandBufferObject* buffer, volatile std::uint64_t* address, std::uint64_t value); +int APS5_VABI sceAmprCommandBufferWriteCounterOnCompletion(Apr::CommandBufferObject* buffer, std::uint8_t counter, std::uint32_t value); +int APS5_VABI sceAmprCommandBufferWaitOnAddress(Apr::CommandBufferObject* buffer, volatile std::uint64_t* address, std::uint64_t reference, std::uint8_t compare, std::uint8_t flush); +int APS5_VABI sceAmprCommandBufferWaitOnCounter(Apr::CommandBufferObject* buffer, std::uint8_t counter, std::uint32_t reference, std::uint8_t compare, std::uint8_t flush); +int APS5_VABI sceAmprCommandBufferWriteKernelEventQueueOnCompletion(Apr::CommandBufferObject* buffer, std::uint64_t equeue, std::int32_t ident, std::uint64_t data); +int APS5_VABI sceAmprCommandBufferWriteAddressFromTimeCounterOnCompletion(Apr::CommandBufferObject* buffer, volatile std::uint64_t* address); +int APS5_VABI sceAmprCommandBufferWriteAddressFromCounterOnCompletion(Apr::CommandBufferObject* buffer, volatile std::uint64_t* address, std::uint8_t counter); +int APS5_VABI sceAmprCommandBufferWriteAddressFromCounterPairOnCompletion(Apr::CommandBufferObject* buffer, volatile std::uint64_t* address, std::uint8_t counter); +std::uint64_t APS5_VABI sceAmprMeasureCommandSizeWriteAddressOnCompletion(); +std::uint64_t APS5_VABI sceAmprMeasureCommandSizeWriteCounterOnCompletion(); +std::uint64_t APS5_VABI sceAmprMeasureCommandSizeWaitOnAddress(); +std::uint64_t APS5_VABI sceAmprMeasureCommandSizeWaitOnCounter(); +std::uint64_t APS5_VABI sceAmprMeasureCommandSizeWriteKernelEventQueueOnCompletion(); +int APS5_VABI sceAmprAprCommandBufferConstructor(Apr::CommandBufferObject* buffer, uint64_t* gatherState, uint64_t* scatterState); +int APS5_VABI sceAmprAprCommandBufferDestructor(Apr::CommandBufferObject* buffer, uint64_t* gatherState, uint64_t* scatterState); +int APS5_VABI sceAmprAprCommandBufferMapBegin(Apr::CommandBufferObject* buffer, std::uint64_t address, std::uint64_t size, std::int32_t type, std::int32_t protection); +int APS5_VABI sceAmprAprCommandBufferMapDirectBegin(Apr::CommandBufferObject* buffer, std::uint64_t address, std::uint64_t directOffset, std::uint64_t size, std::int32_t type, std::int32_t protection); +int APS5_VABI sceAmprAprCommandBufferMapEnd(Apr::CommandBufferObject* buffer); +int APS5_VABI sceAmprAprCommandBufferReadFile(Apr::CommandBufferObject* buffer, uint64_t* gatherState, uint64_t* scatterState, uint32_t fileId, void* destination, uint64_t size, uint64_t offset); +int APS5_VABI sceAmprAprCommandBufferReadFileGather(Apr::CommandBufferObject* buffer, std::uint64_t* mapState, std::uint64_t* scatterGatherState, std::uint64_t size, std::uint64_t offset); +int APS5_VABI sceAmprAprCommandBufferReadFileGatherScatter(Apr::CommandBufferObject* buffer, std::uint64_t* mapState, std::uint64_t* scatterGatherState, void* destination, std::uint64_t size, std::uint64_t offset); +int APS5_VABI sceAmprAprCommandBufferReadFileScatter(Apr::CommandBufferObject* buffer, std::uint64_t* mapState, std::uint64_t* scatterGatherState, void* destination, std::uint64_t size); +int APS5_VABI sceAmprAprCommandBufferResetGatherScatterState(Apr::CommandBufferObject* buffer); +void* APS5_VABI sceAmprCommandBufferClearBuffer(Apr::CommandBufferObject* buffer); +int APS5_VABI sceAmprCommandBufferConstructMarker(Apr::CommandBufferObject* buffer, std::uint32_t type, const char* text, const std::uint32_t* color); +int APS5_VABI sceAmprCommandBufferConstructNop(Apr::CommandBufferObject* buffer, std::int16_t type, const void* payload, std::uint32_t payloadBytes, const std::uint32_t* word); +int APS5_VABI sceAmprCommandBufferConstructor(Apr::CommandBufferObject* buffer); +int APS5_VABI sceAmprCommandBufferDestructor(Apr::CommandBufferObject* buffer); +void* APS5_VABI sceAmprCommandBufferGetBufferBaseAddress(const Apr::CommandBufferObject* buffer); +uint32_t APS5_VABI sceAmprCommandBufferGetCurrentOffset(const Apr::CommandBufferObject* buffer); +uint32_t APS5_VABI sceAmprCommandBufferGetNumCommands(const Apr::CommandBufferObject* buffer); +uint32_t APS5_VABI sceAmprCommandBufferGetSize(const Apr::CommandBufferObject* buffer); +uint32_t APS5_VABI sceAmprCommandBufferGetType(const Apr::CommandBufferObject* buffer); +int APS5_VABI sceAmprCommandBufferNop(Apr::CommandBufferObject* buffer, std::uint32_t dwords); +int APS5_VABI sceAmprCommandBufferNopWithData(Apr::CommandBufferObject* buffer, std::uint32_t dwords, const std::uint32_t* data); +int APS5_VABI sceAmprCommandBufferPopMarker(Apr::CommandBufferObject* buffer); +int APS5_VABI sceAmprCommandBufferPushMarker(Apr::CommandBufferObject* buffer, const char* text); +int APS5_VABI sceAmprCommandBufferPushMarkerWithColor(Apr::CommandBufferObject* buffer, const char* text, std::uint32_t color); +int APS5_VABI sceAmprCommandBufferReset(Apr::CommandBufferObject* buffer); +int APS5_VABI sceAmprCommandBufferSetBuffer(Apr::CommandBufferObject* buffer, void* memory, uint32_t size); +int APS5_VABI sceAmprCommandBufferSetMarker(Apr::CommandBufferObject* buffer, const char* text); +int APS5_VABI sceAmprCommandBufferSetMarkerWithColor(Apr::CommandBufferObject* buffer, const char* text, const std::uint32_t* color); +int APS5_VABI sceAmprCommandBufferWaitOnAddress_04_00(Apr::CommandBufferObject* buffer, volatile std::uint64_t* address, std::uint64_t reference, std::uint8_t compare, std::uint8_t flush); +int APS5_VABI sceAmprCommandBufferWaitOnCounter_04_00(Apr::CommandBufferObject* buffer, std::uint8_t counter, std::uint8_t access, std::uint64_t reference, std::uint8_t compare, std::uint8_t maskOperation, std::uint64_t mask, std::uint8_t flush); +int APS5_VABI sceAmprCommandBufferWriteAddressFromCounterPair_04_00(Apr::CommandBufferObject* buffer, volatile std::uint64_t* address, std::uint8_t counter, std::uint64_t atStart); +int APS5_VABI sceAmprCommandBufferWriteAddressFromCounter_04_00(Apr::CommandBufferObject* buffer, volatile std::uint64_t* address, std::uint8_t counter, std::uint64_t atStart); +int APS5_VABI sceAmprCommandBufferWriteAddressFromTimeCounter_04_00(Apr::CommandBufferObject* buffer, volatile std::uint64_t* address, std::uint64_t atStart); +int APS5_VABI sceAmprCommandBufferWriteAddress_04_00(Apr::CommandBufferObject* buffer, uint64_t* address, uint64_t value, uint32_t flags); +int APS5_VABI sceAmprCommandBufferWriteCounter_04_00(Apr::CommandBufferObject* buffer, std::uint8_t counter, std::uint8_t access, std::uint64_t value, std::uint8_t operation, std::uint8_t atStart); +int APS5_VABI sceAmprCommandBufferWriteKernelEventQueue_04_00(Apr::CommandBufferObject* buffer, std::uint64_t equeue, std::int32_t ident, std::uint64_t data, std::uint64_t atStart); +std::uint64_t APS5_VABI sceAmprMeasureCommandSizeMapBegin(std::uint64_t address, std::uint64_t size, std::uint32_t type, std::uint32_t protection); +std::uint64_t APS5_VABI sceAmprMeasureCommandSizeMapDirectBegin(std::uint64_t address, std::uint64_t directOffset, std::uint64_t size, std::uint32_t type, std::uint32_t protection); +std::uint64_t APS5_VABI sceAmprMeasureCommandSizeMapEnd(); +std::uint64_t APS5_VABI sceAmprMeasureCommandSizeNop(std::uint32_t dwords); +std::uint64_t APS5_VABI sceAmprMeasureCommandSizeNopWithData(std::uint32_t dwords); +std::uint64_t APS5_VABI sceAmprMeasureCommandSizePopMarker(); +std::uint64_t APS5_VABI sceAmprMeasureCommandSizePushMarker(const char* text); +std::uint64_t APS5_VABI sceAmprMeasureCommandSizePushMarkerWithColor(const char* text, std::uint32_t color); +uint32_t APS5_VABI sceAmprMeasureCommandSizeReadFile(void); +std::uint64_t APS5_VABI sceAmprMeasureCommandSizeReadFileGather(std::uint64_t size, std::uint64_t offset); +std::uint64_t APS5_VABI sceAmprMeasureCommandSizeReadFileGatherScatter(void* destination, std::uint64_t size, std::uint64_t offset); +std::uint64_t APS5_VABI sceAmprMeasureCommandSizeReadFileScatter(void* destination, std::uint64_t size); +std::uint64_t APS5_VABI sceAmprMeasureCommandSizeResetGatherScatterState(); +std::uint64_t APS5_VABI sceAmprMeasureCommandSizeSetMarker(const char* text); +std::uint64_t APS5_VABI sceAmprMeasureCommandSizeSetMarkerWithColor(const char* text, std::uint32_t color); +std::uint64_t APS5_VABI sceAmprMeasureCommandSizeWaitOnAddress_04_00(volatile std::uint64_t* address, std::uint64_t, std::uint8_t compare, std::uint8_t flush); +std::uint64_t APS5_VABI sceAmprMeasureCommandSizeWaitOnCounter_04_00(std::uint8_t, std::uint8_t access, std::uint64_t, std::uint8_t compare, std::uint8_t maskOperation, std::uint64_t, std::uint8_t flush); +std::uint64_t APS5_VABI sceAmprMeasureCommandSizeWriteAddressFromCounterPair_04_00(volatile std::uint64_t* address, std::uint8_t counter); +std::uint64_t APS5_VABI sceAmprMeasureCommandSizeWriteAddressFromCounter_04_00(volatile std::uint64_t* address, std::uint8_t counter); +std::uint64_t APS5_VABI sceAmprMeasureCommandSizeWriteAddressFromTimeCounter_04_00(volatile std::uint64_t* address); +uint32_t APS5_VABI sceAmprMeasureCommandSizeWriteAddress_04_00(void); +std::uint64_t APS5_VABI sceAmprMeasureCommandSizeWriteCounter_04_00(std::uint8_t counter, std::uint8_t access, std::uint64_t, std::uint8_t operation); +std::uint64_t APS5_VABI sceAmprMeasureCommandSizeWriteKernelEventQueue_04_00(std::uint64_t, std::int32_t, std::uint64_t); +int APS5_VABI sceAmprAmmCommandBufferConstructor(Apr::CommandBufferObject* buffer); +int APS5_VABI sceAmprAmmCommandBufferDestructor(Apr::CommandBufferObject* buffer); +int APS5_VABI sceAmprAmmCommandBufferMap(Apr::CommandBufferObject* buffer, std::uint64_t address, std::uint64_t size, std::int32_t type, std::int32_t protection); +int APS5_VABI sceAmprAmmCommandBufferMapWithGpuMaskId(Apr::CommandBufferObject* buffer, std::uint64_t address, std::uint64_t size, std::int32_t type, std::int32_t protection, std::uint8_t gpuMaskId); +int APS5_VABI sceAmprAmmCommandBufferMapDirect(Apr::CommandBufferObject* buffer, std::uint64_t address, std::uint64_t directOffset, std::uint64_t size, std::int32_t type, std::int32_t protection); +int APS5_VABI sceAmprAmmCommandBufferMapDirectWithGpuMaskId(Apr::CommandBufferObject* buffer, std::uint64_t address, std::uint64_t directOffset, std::uint64_t size, std::int32_t type, std::int32_t protection, std::uint8_t gpuMaskId); +int APS5_VABI sceAmprAmmCommandBufferUnmap(Apr::CommandBufferObject* buffer, std::uint64_t address, std::uint64_t size); +std::int64_t APS5_VABI sceAmprAmmMeasureAmmCommandSizeMap(std::uint64_t address, std::uint64_t size, std::int32_t type, std::int32_t protection); +std::int64_t APS5_VABI sceAmprAmmMeasureAmmCommandSizeMapWithGpuMaskId(std::uint64_t address, std::uint64_t size, std::int32_t type, std::int32_t protection, std::uint8_t gpuMaskId); +std::int64_t APS5_VABI sceAmprAmmMeasureAmmCommandSizeMapDirect(std::uint64_t address, std::uint64_t directOffset, std::uint64_t size, std::int32_t type, std::int32_t protection); +std::int64_t APS5_VABI sceAmprAmmMeasureAmmCommandSizeMapDirectWithGpuMaskId(std::uint64_t address, std::uint64_t directOffset, std::uint64_t size, std::int32_t type, std::int32_t protection, std::uint8_t gpuMaskId); +std::int64_t APS5_VABI sceAmprAmmMeasureAmmCommandSizeUnmap(std::uint64_t address, std::uint64_t size); +int APS5_VABI sceAmprAmmCommandBufferRemap(Apr::CommandBufferObject* buffer, std::uint64_t address, std::uint64_t source, std::uint64_t size, std::int32_t protection); +int APS5_VABI sceAmprAmmCommandBufferRemapWithGpuMaskId(Apr::CommandBufferObject* buffer, std::uint64_t address, std::uint64_t source, std::uint64_t size, std::int32_t protection, std::uint8_t gpuMaskId); +int APS5_VABI sceAmprAmmCommandBufferMultiMap(Apr::CommandBufferObject* buffer, std::uint64_t address, std::uint64_t alias, std::uint64_t size, std::int32_t protection); +int APS5_VABI sceAmprAmmCommandBufferMultiMapWithGpuMaskId(Apr::CommandBufferObject* buffer, std::uint64_t address, std::uint64_t alias, std::uint64_t size, std::int32_t protection, std::uint8_t gpuMaskId); +int APS5_VABI sceAmprAmmCommandBufferModifyProtect(Apr::CommandBufferObject* buffer, std::uint64_t address, std::uint64_t size, std::int32_t protection, std::int32_t mask); +int APS5_VABI sceAmprAmmCommandBufferModifyProtectWithGpuMaskId(Apr::CommandBufferObject* buffer, std::uint64_t address, std::uint64_t size, std::int32_t protection, std::int32_t mask, std::uint8_t gpuMaskId); +int APS5_VABI sceAmprAmmCommandBufferModifyMtypeProtect(Apr::CommandBufferObject* buffer, std::uint64_t address, std::uint64_t size, std::int32_t type, std::int32_t protection, std::int32_t mask); +int APS5_VABI sceAmprAmmCommandBufferModifyMtypeProtectWithGpuMaskId(Apr::CommandBufferObject* buffer, std::uint64_t address, std::uint64_t size, std::int32_t type, std::int32_t protection, std::int32_t mask, std::uint8_t gpuMaskId); +std::int64_t APS5_VABI sceAmprAmmMeasureAmmCommandSizeRemap(std::uint64_t address, std::uint64_t source, std::uint64_t size, std::int32_t protection); +std::int64_t APS5_VABI sceAmprAmmMeasureAmmCommandSizeRemapWithGpuMaskId(std::uint64_t address, std::uint64_t source, std::uint64_t size, std::int32_t protection, std::uint8_t gpuMaskId); +std::int64_t APS5_VABI sceAmprAmmMeasureAmmCommandSizeMultiMap(std::uint64_t address, std::uint64_t alias, std::uint64_t size, std::int32_t protection); +std::int64_t APS5_VABI sceAmprAmmMeasureAmmCommandSizeMultiMapWithGpuMaskId(std::uint64_t address, std::uint64_t alias, std::uint64_t size, std::int32_t protection, std::uint8_t gpuMaskId); +std::int64_t APS5_VABI sceAmprAmmMeasureAmmCommandSizeModifyProtect(std::uint64_t address, std::uint64_t size, std::int32_t protection, std::int32_t mask); +std::int64_t APS5_VABI sceAmprAmmMeasureAmmCommandSizeModifyProtectWithGpuMaskId(std::uint64_t address, std::uint64_t size, std::int32_t protection, std::int32_t mask, std::uint8_t gpuMaskId); +std::int64_t APS5_VABI sceAmprAmmMeasureAmmCommandSizeModifyMtypeProtect(std::uint64_t address, std::uint64_t size, std::int32_t type, std::int32_t protection, std::int32_t mask); +std::int64_t APS5_VABI sceAmprAmmMeasureAmmCommandSizeModifyMtypeProtectWithGpuMaskId(std::uint64_t address, std::uint64_t size, std::int32_t type, std::int32_t protection, std::int32_t mask, std::uint8_t gpuMaskId); +int APS5_VABI sceAmprAmmCommandBufferMapAsPrt(Apr::CommandBufferObject* buffer, std::uint64_t address, std::uint64_t size); +int APS5_VABI sceAmprAmmCommandBufferAllocatePaForPrt(Apr::CommandBufferObject* buffer, std::uint64_t address, std::uint64_t size, std::int32_t type, std::int32_t protection); +int APS5_VABI sceAmprAmmCommandBufferRemapIntoPrt(Apr::CommandBufferObject* buffer, std::uint64_t address, std::uint64_t source, std::uint64_t size, std::int32_t protection, std::uint32_t opcode); +int APS5_VABI sceAmprAmmCommandBufferUnmapToPrt(Apr::CommandBufferObject* buffer, std::uint64_t address, std::uint64_t size); +std::int64_t APS5_VABI sceAmprAmmMeasureAmmCommandSizeMapAsPrt(std::uint64_t address, std::uint64_t size); +std::int64_t APS5_VABI sceAmprAmmMeasureAmmCommandSizeAllocatePaForPrt(std::uint64_t address, std::uint64_t size, std::int32_t type, std::int32_t protection); +int APS5_VABI sceAmprAmmGiveDirectMemory(std::int64_t searchStart, std::int64_t searchEnd, std::size_t size, std::size_t alignment, int usage, std::int64_t* offset); +int APS5_VABI sceAmprAmmGetVirtualAddressRanges(std::uint64_t* start, std::uint64_t* end, std::uint64_t* multimapStart, std::uint64_t* multimapEnd); +int APS5_VABI sceAmprAmmSetPageTablePoolOccupancyNotificationThreshold(void); +int APS5_VABI sceAmprAmmSubmitCommandBuffer(void* base, std::uint32_t offset, std::uint32_t priority); +int APS5_VABI sceAmprAmmSubmitCommandBuffer2(void* base, std::uint32_t offset, std::uint32_t priority, AmmSubmitResult* result, std::uint32_t* id); +int APS5_VABI sceAmprAmmSubmitCommandBuffer3(void* base, std::uint32_t offset, std::uint32_t priority, std::uint32_t* id); +int APS5_VABI sceAmprAmmWaitCommandBufferCompletion(std::uint32_t id); +void APS5_VABI _Unlock_shared_ptr_spin_lock_nid_postfix(void); +int APS5_VABI _Cnd_init_with_name_nid_postfix(void** handle, const char*); +int APS5_VABI _ZNKSt8time_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE3getES3_S3_RSt8ios_baseRNSt5_IosbIiE8_IostateEP2tmPKcSE__nid_postfix(void); +int APS5_VABI _ZNSt8time_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE7_GetcatEPPKNSt6locale5facetEPKS5__nid_postfix(void); +void APS5_VABI _Lock_shared_ptr_spin_lock_nid_postfix(void); +SonyLconv* APS5_VABI sceAmprLocaleconv(void); +unsigned __int128 APS5_VABI sceAmprUdivti3(unsigned __int128 dividend, unsigned __int128 divisor); +double APS5_VABI sceAmprSinh(double x, double y); +char* APS5_VABI sceAmprStrtokS(char* str, const char* delim, char** context); +int APS5_VABI sceAmprCtimeS(char* buffer, std::size_t size, const std::int64_t* time); +int APS5_VABI sceAmprWcscpyS(std::uint16_t* dest, std::size_t size, const std::uint16_t* src); +void* APS5_VABI sceAmprSetConstraintHandlerS(void* handler); +int APS5_VABI sceAmprFltrounds(void); +void APS5_VABI sceAmprIgnoreHandlerS(const char* message, void* pointer, int error); +int APS5_VABI sceAmprWcstombsS(std::size_t* result, char* destination, std::size_t capacity, const std::uint16_t* source, std::size_t limit); +std::size_t APS5_VABI sceAmprMbstowcs(std::uint16_t* dest, const char* src, std::size_t size); +int APS5_VABI sceAmprAsctimeS(char* buffer, std::size_t size, const GuestTm* time); +int APS5_VABI sceAmprFpclassifyd(double value); +int APS5_VABI sceAmprAmmGetUsageStatsData(AmmUsageStatsData* stats); + +[[noreturn]] void APS5_VABI __cxa_call_unexpected_nid_postfix(void* unwindException); + +} diff --git a/core/libs/prx/libSceAmpr/libSceAmpr.hpp b/core/libs/prx/libSceAmpr/libSceAmpr.hpp new file mode 100644 index 0000000000..de5e0e7862 --- /dev/null +++ b/core/libs/prx/libSceAmpr/libSceAmpr.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceAmpr/include/Api.hpp" diff --git a/core/libs/prx/libSceAppChecker/Export.cpp b/core/libs/prx/libSceAppChecker/Export.cpp index b50753644e..1ed8f0345d 100644 --- a/core/libs/prx/libSceAppChecker/Export.cpp +++ b/core/libs/prx/libSceAppChecker/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceAppChecker/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceAppChecker/include/Api.hpp b/core/libs/prx/libSceAppChecker/include/Api.hpp new file mode 100644 index 0000000000..9c850dbc67 --- /dev/null +++ b/core/libs/prx/libSceAppChecker/include/Api.hpp @@ -0,0 +1,11 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceAppCheckerAbort(); +int APS5_VABI sceAppCheckerExecute(); +int APS5_VABI sceAppCheckerExecuteEx(); + +} diff --git a/core/libs/prx/libSceAppChecker/libSceAppChecker.hpp b/core/libs/prx/libSceAppChecker/libSceAppChecker.hpp new file mode 100644 index 0000000000..471d19be34 --- /dev/null +++ b/core/libs/prx/libSceAppChecker/libSceAppChecker.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceAppChecker/include/Api.hpp" diff --git a/core/libs/prx/libSceAppContent/Export.cpp b/core/libs/prx/libSceAppContent/Export.cpp index 6854c950da..e5c956f2ee 100644 --- a/core/libs/prx/libSceAppContent/Export.cpp +++ b/core/libs/prx/libSceAppContent/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceAppContent/include/Api.hpp" #include #include #include "SceTypes.hpp" @@ -26,11 +27,6 @@ static constexpr char TEMPORARY_MOUNT_POINT[] = "/temp0"; static constexpr char DOWNLOAD_MOUNT_POINT[] = "/download0"; static constexpr uint32_t TEMPORARY_DATA_OPTION_FORMAT = 1; -struct AppContentAddcontInfo { - NpUnifiedEntitlementLabel entitlement_label; - uint32_t status; -}; - namespace { std::atomic_bool initialized{false}; @@ -209,7 +205,6 @@ int APS5_VABI sceAppContentTemporaryDataUnmount(const AppContentMountPoint* moun return 0; } - int APS5_VABI sceAppContentAddcontEnqueueDownload(uint32_t service_label, const NpUnifiedEntitlementLabel* entitlement_label) { if (!initialized.load()) return SCE_APP_CONTENT_ERROR_NOT_INITIALIZED; (void)service_label; diff --git a/core/libs/prx/libSceAppContent/include/Api.hpp b/core/libs/prx/libSceAppContent/include/Api.hpp new file mode 100644 index 0000000000..938424fd88 --- /dev/null +++ b/core/libs/prx/libSceAppContent/include/Api.hpp @@ -0,0 +1,45 @@ +#pragma once + +#include "SceTypes.hpp" + +struct AppContentAddcontInfo { + NpUnifiedEntitlementLabel entitlement_label; + uint32_t status; +}; + +extern "C" { + +int APS5_VABI sceAppContentAddcontMount(uint32_t serviceLabel, const NpUnifiedEntitlementLabel* entitlementLabel, AppContentMountPoint* mountPoint); +int APS5_VABI sceAppContentAddcontUnmount(const AppContentMountPoint* mountPoint); +int APS5_VABI sceAppContentGetAddcontInfo(uint32_t serviceLabel, const NpUnifiedEntitlementLabel* entitlementLabel, AppContentAddcontInfo* info); +int APS5_VABI sceAppContentGetAddcontInfoList(uint32_t serviceLabel, AppContentAddcontInfo* list, uint32_t listNum, uint32_t* hitNum); +int APS5_VABI sceAppContentAppParamGetInt(uint32_t paramId, int32_t* value); +int APS5_VABI sceAppContentDownloadDataFormat(const AppContentMountPoint* mountPoint); +int APS5_VABI sceAppContentDownloadDataGetAvailableSpaceKb(const AppContentMountPoint* mountPoint, size_t* availableSpaceKb); +int APS5_VABI sceAppContentInitialize(const AppContentInitParam* initParam, AppContentBootParam* bootParam); +int APS5_VABI sceAppContentTemporaryDataFormat(const AppContentMountPoint* mountPoint); +int APS5_VABI sceAppContentTemporaryDataGetAvailableSpaceKb(const AppContentMountPoint* mountPoint, size_t* availableSpaceKb); +int APS5_VABI sceAppContentTemporaryDataMount2(uint32_t option, AppContentMountPoint* mountPoint); +int APS5_VABI sceAppContentTemporaryDataUnmount(const AppContentMountPoint* mountPoint); +int APS5_VABI sceAppContentAddcontEnqueueDownload(uint32_t serviceLabel, const NpUnifiedEntitlementLabel* entitlementLabel); +int APS5_VABI sceAppContentAddcontDelete(uint32_t serviceLabel, const NpUnifiedEntitlementLabel* entitlementLabel); +int APS5_VABI sceAppContentGetAddcontDownloadProgress(uint32_t serviceLabel, const NpUnifiedEntitlementLabel* entitlementLabel, void* progress); +int APS5_VABI sceAppContentAddcontEnqueueDownloadByEntitlemetId(void); +int APS5_VABI sceAppContentAddcontEnqueueDownloadSp(void); +int APS5_VABI sceAppContentAddcontMountByEntitlemetId(void); +int APS5_VABI sceAppContentAddcontShrink(void); +int APS5_VABI sceAppContentAppParamGetString(void); +int APS5_VABI sceAppContentDownload0Expand(void); +int APS5_VABI sceAppContentDownload0Shrink(void); +int APS5_VABI sceAppContentDownload1Expand(void); +int APS5_VABI sceAppContentDownload1Shrink(void); +int APS5_VABI sceAppContentGetAddcontInfoByEntitlementId(void); +int APS5_VABI sceAppContentGetAddcontInfoListByIroTag(void); +int APS5_VABI sceAppContentGetDownloadedStoreCountry(void); +int APS5_VABI sceAppContentGetEntitlementKey(void); +int APS5_VABI sceAppContentGetPftFlag(void); +int APS5_VABI sceAppContentGetRegion(void); +int APS5_VABI sceAppContentRequestPatchInstall(void); +int APS5_VABI sceAppContentTemporaryDataMount(AppContentMountPoint* mountPoint); + +} diff --git a/core/libs/prx/libSceAppContent/libSceAppContent.hpp b/core/libs/prx/libSceAppContent/libSceAppContent.hpp new file mode 100644 index 0000000000..d92b11cf65 --- /dev/null +++ b/core/libs/prx/libSceAppContent/libSceAppContent.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceAppContent/include/Api.hpp" diff --git a/core/libs/prx/libSceAppDbShellCoreClient/libSceAppDbShellCoreClient.hpp b/core/libs/prx/libSceAppDbShellCoreClient/libSceAppDbShellCoreClient.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceAppDbShellCoreClient/libSceAppDbShellCoreClient.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceAppDbShellCoreClientForSystemService/libSceAppDbShellCoreClientForSystemService.hpp b/core/libs/prx/libSceAppDbShellCoreClientForSystemService/libSceAppDbShellCoreClientForSystemService.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceAppDbShellCoreClientForSystemService/libSceAppDbShellCoreClientForSystemService.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceAppInstUtil/Export.cpp b/core/libs/prx/libSceAppInstUtil/Export.cpp index 87f1cb3954..51721067a8 100644 --- a/core/libs/prx/libSceAppInstUtil/Export.cpp +++ b/core/libs/prx/libSceAppInstUtil/Export.cpp @@ -1,10 +1,9 @@ +#include "prx/libSceAppInstUtil/include/Api.hpp" #include #include #include "SceTypes.hpp" #include "prx/libc/include/General.hpp" -struct AppInstallProgressInfo; - extern "C" { int APS5_VABI sceAppInstUtilInitialize(void) { diff --git a/core/libs/prx/libSceAppInstUtil/include/Api.hpp b/core/libs/prx/libSceAppInstUtil/include/Api.hpp new file mode 100644 index 0000000000..eeb9b40a31 --- /dev/null +++ b/core/libs/prx/libSceAppInstUtil/include/Api.hpp @@ -0,0 +1,128 @@ +#pragma once + +#include "SceTypes.hpp" + +struct AppInstallProgressInfo; + +extern "C" { + +int APS5_VABI sceAppInstUtilInitialize(void); +int APS5_VABI sceAppInstUtilTerminate(void); +int APS5_VABI sceAppInstUtilAppInstallAll(void* reserved); +int APS5_VABI sceAppInstUtilAppInstallTitleDir(const char* titleId, const char* titleDir, void* reserved); +int APS5_VABI sceAppInstUtilAppIsInInstalling(int32_t* installing); +int APS5_VABI sceAppInstUtilAppIsInUpdating(const char* titleId, bool* updating); +int APS5_VABI sceAppInstUtilAppExists(const char* titleId, int32_t* exists); +int APS5_VABI sceAppInstUtilAppGetSize(const char* titleId, std::uint64_t* size); +int APS5_VABI sceAppInstUtilAppInstallPkg(const char* packagePath, std::uint64_t serviceArgument); +int APS5_VABI sceAppInstUtilAppPrepareOverwritePkg(); +int APS5_VABI sceAppInstUtilAppRecoverApp(); +int APS5_VABI sceAppInstUtilAppUnInstall(const char* titleId); +int APS5_VABI sceAppInstUtilAppUnInstallAddcont(const char* titleId, const char* contentLabel); +int APS5_VABI sceAppInstUtilAppUnInstallPat(const char* titleId); +int APS5_VABI sceAppInstUtilAppUnInstallTheme(); +int APS5_VABI sceAppInstUtilAppUnInstallTypes(const char* titleId, std::uint32_t types); +int APS5_VABI sceAppInstUtilGetInstallProgressInfo(const char* titleId, AppInstallProgressInfo* info); +int APS5_VABI sceAppInstUtilGetInstallProgress(const char* titleId, void* progress); +int APS5_VABI sceAppInstUtilGetPrimaryAppSlot(const char* titleId, void* slot); + +int APS5_VABI sceAppInstUtilAppGetAppInstallStatusByAppInfo(void); +int APS5_VABI sceAppInstUtilAppUnInstall2(void); +int APS5_VABI sceAppInstUtilAppUnInstallForRemote(void); +int APS5_VABI sceAppInstUtilAppUnInstallForRemote2(void); +int APS5_VABI sceAppInstUtilAppGetAddcontListTotalSize(void); +int APS5_VABI sceAppInstUtilAppGetAddcontInfo(void); +int APS5_VABI sceAppInstUtilAppGetAddcontInfoByContentId(void); +int APS5_VABI sceAppInstUtilGetAddcontInstalledStatus(void); +int APS5_VABI sceAppInstUtilAppGetInsertedDiscTitleId(void); +int APS5_VABI sceAppInstUtilAppUpdateStartTime(void); +int APS5_VABI sceAppInstUtilAppInstallSharePlayLink(void); +int APS5_VABI sceAppInstUtilAppInstallSharePlayLinkByUser(void); +int APS5_VABI sceAppInstUtilAppGetAddcontNum(void); +int APS5_VABI sceAppInstUtilAppCancelUnInstall(void); +int APS5_VABI sceAppInstUtilAppDestroyMetadata(void); +int APS5_VABI sceAppInstUtilCheckAppSystemVer(void); +int APS5_VABI sceAppInstUtilAppConvertAppDownloadToDisc(void); +int APS5_VABI sceAppInstUtilGetMainAppTitleIdForSP(void); +int APS5_VABI sceAppInstUtilGetSubAppTitleIdForSP(void); +int APS5_VABI sceAppInstUtilGetMainAppTitleId(void); +int APS5_VABI sceAppInstUtilGetSubAppTitleId(void); +int APS5_VABI sceAppInstUtilAppGetAppInstallStatus(void); +int APS5_VABI sceAppInstUtilAppDestroyPkg(void); +int APS5_VABI sceAppInstUtilJson(void); +int APS5_VABI sceAppInstUtilGetInsertedDiscRoleType(void); +int APS5_VABI sceAppInstUtilRequestInstallDiscGame(void); +int APS5_VABI sceAppInstUtilRequestDataDiscCopy(void); +int APS5_VABI sceAppInstUtilCancelDataDiscCopy(void); +int APS5_VABI sceAppInstUtilGetDataDiscCopyProgress(void); +int APS5_VABI sceAppInstUtilSetPrimaryAppSlot(void); +int APS5_VABI sceAppInstUtilGetAppSlotInfoList(void); +int APS5_VABI sceAppInstUtilGetAppEmptySlot(void); +int APS5_VABI sceAppInstUtilAppInstallGetLinkState(void); +int APS5_VABI sceAppInstUtilAppUnInstallForMultiInstall(void); +int APS5_VABI sceAppInstUtilAppInstallPs4CloudGame(void); +int APS5_VABI sceAppInstUtilAppStoreCompilationDiscInfo(void); +int APS5_VABI sceAppInstUtilAppGetCompilationDiscInfo(void); +int APS5_VABI sceAppInstUtilAppGetStoreCompilationDiscInfo(void); +int APS5_VABI sceAppInstUtilAppGetInsertedDiscTitleIdList(void); +int APS5_VABI sceAppInstUtilAppInstallRequestCompilationDiscApp(void); +int APS5_VABI sceAppInstUtilAppGetNoRelatedAddcontTitleList(void); +int APS5_VABI sceAppInstUtilAppGetIrremovableAppList(void); +int APS5_VABI sceAppInstUtilAppRequestMoveApps(void); +int APS5_VABI sceAppInstUtilAppProhibitDownloadInstall(void); +int APS5_VABI sceAppInstUtilAppAllowDownloadInstall(void); +int APS5_VABI sceAppInstUtilGetAppMoveProgressInfo(void); +int APS5_VABI sceAppInstUtilAppCancelMoveApps(void); +int APS5_VABI sceAppInstUtilAppGetMoveErrorAppList(void); +int APS5_VABI sceAppInstUtilAppGetAllAppSize(void); +int APS5_VABI sceAppInstUtilAppCancelGetAllAppSize(void); +int APS5_VABI sceAppInstUtilAppGetInsertedDiscMasterDataId(void); +int APS5_VABI sceAppInstUtilAppGetAppOtherSize(void); +int APS5_VABI sceAppInstUtilAppCancelGetAppOtherSize(void); +int APS5_VABI sceAppInstUtilGetInsertedDiscTotal(void); +int APS5_VABI sceAppInstUtilAppSetRemasterInstallType(void); +int APS5_VABI sceAppInstUtilGetInstallProgressInfoForMultiDisc(void); +int APS5_VABI sceAppInstUtilMountBdEmu(void); +int APS5_VABI sceAppInstUtilUnmountBdEmu(void); +int APS5_VABI sceAppInstUtilGetInstallStatus(void); +int APS5_VABI sceAppInstUtilResumeInstall(void); +int APS5_VABI sceAppInstUtilPauseInstall(void); +int APS5_VABI sceAppInstUtilRegisterDownload(void); +int APS5_VABI sceAppInstUtilInstall(void); +int APS5_VABI sceAppInstUtilStartInstall(void); +int APS5_VABI sceAppInstUtilInstallPatch(void); +int APS5_VABI sceAppInstUtilGetPatchInstallStatus(void); +int APS5_VABI sceAppInstUtilResumePatchInstall(void); +int APS5_VABI sceAppInstUtilPausePatchInstall(void); +int APS5_VABI sceAppInstUtilCancelInstallPatch(void); +int APS5_VABI sceAppInstUtilCancelInstallAddcont(void); +int APS5_VABI sceAppInstUtilCancelInstall(void); +int APS5_VABI sceAppInstUtilCancelForMultiInstall(void); +int APS5_VABI sceAppInstUtilInstallByPackage(void); +int APS5_VABI sceAppInstUtilIsRestoreState(void); +int APS5_VABI sceAppInstUtilGetRestoreState(void); +int APS5_VABI sceAppInstUtilGetAddons(void); +int APS5_VABI sceAppInstUtilGetInstallOptions(void); +int APS5_VABI sceAppInstUtilGetContentSize(void); +int APS5_VABI sceAppInstUtilCancelGetInformation(void); +int APS5_VABI sceAppInstUtilGetWorkspaceStatus(void); +int APS5_VABI sceAppInstUtilDeleteWorkspace(void); +int APS5_VABI sceAppInstUtilGetParentalControlLevel(void); +int APS5_VABI sceAppInstUtilCheckLatestPatch(void); +int APS5_VABI sceAppInstUtilCancelCheckPatch(void); +int APS5_VABI sceAppInstUtilAppInstallPsNowIcon(void); +int APS5_VABI sceAppInstUtilGetAddcontInfoList2(void); +int APS5_VABI sceAppInstUtilGetAddcontInfoList3(void); +int APS5_VABI sceAppInstUtilClearAddcontInfoCache(void); +int APS5_VABI sceAppInstUtilGetContentSize2(void); +int APS5_VABI sceAppInstUtilAppInstallContentPush(void); +int APS5_VABI sceAppInstUtilGetAvailableStorage(void); +int APS5_VABI sceAppInstUtilSwitchInstallLocation(void); +int APS5_VABI sceAppInstUtilGetConfigList(void); +int APS5_VABI sceAppInstUtilSwitchConfig(void); +int APS5_VABI sceAppInstUtilRestoreDataSource(void); +int APS5_VABI sceAppInstUtilGetNeededStorageSize(void); +int APS5_VABI sceAppInstUtilAppGetStorageDestType(void); +int APS5_VABI sceAppInstUtilInstallAddons(void); + +} diff --git a/core/libs/prx/libSceAppInstUtil/libSceAppInstUtil.hpp b/core/libs/prx/libSceAppInstUtil/libSceAppInstUtil.hpp new file mode 100644 index 0000000000..8d20c5a6f2 --- /dev/null +++ b/core/libs/prx/libSceAppInstUtil/libSceAppInstUtil.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceAppInstUtil/include/Api.hpp" diff --git a/core/libs/prx/libSceAsyncStorageInternal/libSceAsyncStorageInternal.hpp b/core/libs/prx/libSceAsyncStorageInternal/libSceAsyncStorageInternal.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceAsyncStorageInternal/libSceAsyncStorageInternal.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceAt9Enc/Export.cpp b/core/libs/prx/libSceAt9Enc/Export.cpp index 77fee077ec..09b53ddbc8 100644 --- a/core/libs/prx/libSceAt9Enc/Export.cpp +++ b/core/libs/prx/libSceAt9Enc/Export.cpp @@ -1,9 +1,9 @@ +#include "prx/libSceAt9Enc/include/Api.hpp" #include #include #include "SceTypes.hpp" #include "prx/libc/include/General.hpp" - extern "C" { int32_t APS5_VABI sceAt9EncClearContext(void *pAt9EncWorkArea, int32_t *pInternalResult) { diff --git a/core/libs/prx/libSceAt9Enc/include/Api.hpp b/core/libs/prx/libSceAt9Enc/include/Api.hpp new file mode 100644 index 0000000000..e060d77e4b --- /dev/null +++ b/core/libs/prx/libSceAt9Enc/include/Api.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int32_t APS5_VABI sceAt9EncClearContext(void *pAt9EncWorkArea, int32_t *pInternalResult); +int32_t APS5_VABI sceAt9EncCreateEncoder(void *pAt9EncWorkArea, void *pAt9EncParam, int32_t memSize, int32_t *pInternalResult); +int32_t APS5_VABI sceAt9EncEncode(void *pAt9EncWorkArea, const void *pInputBuf, void *pOutputBuf, uint32_t inputBufSize, uint32_t outputBufSize, uint32_t *pOutputDataByte, uint32_t *pUsedBufSize, int32_t *pInternalResult); +int32_t APS5_VABI sceAt9EncFlush(void *pAt9EncWorkArea, void *pOutputBuf, uint32_t outputBufSize, uint32_t *pOutputDataByte, int32_t *pInternalResult); +int32_t APS5_VABI sceAt9EncQueryMemSize(void *pAt9EncParam, int32_t *pMemSize, int32_t *pInternalResult); + +} diff --git a/core/libs/prx/libSceAt9Enc/libSceAt9Enc.hpp b/core/libs/prx/libSceAt9Enc/libSceAt9Enc.hpp new file mode 100644 index 0000000000..c0960da642 --- /dev/null +++ b/core/libs/prx/libSceAt9Enc/libSceAt9Enc.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceAt9Enc/include/Api.hpp" diff --git a/core/libs/prx/libSceAudio/libSceAudio.hpp b/core/libs/prx/libSceAudio/libSceAudio.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceAudio/libSceAudio.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceAudio3d/Export.cpp b/core/libs/prx/libSceAudio3d/Export.cpp index eed6da479e..0eddd25c80 100644 --- a/core/libs/prx/libSceAudio3d/Export.cpp +++ b/core/libs/prx/libSceAudio3d/Export.cpp @@ -1,3 +1,6 @@ +#include "prx/libSceAudioOut/include/AudioOut2.hpp" +#include "prx/libSceAudioOut/include/AudioOut.hpp" +#include "prx/libSceAudio3d/include/Audio3d.hpp" #include #include #include @@ -14,12 +17,6 @@ #include "SceTypes.hpp" #include "prx/libc/include/General.hpp" -extern "C" { -int APS5_VABI sceAudioOutOpen(int user_id, int type, int index, std::uint32_t len, std::uint32_t freq, std::uint32_t param); -int APS5_VABI sceAudioOutOutput(int handle, const void* ptr); -int APS5_VABI sceAudioOutClose(int handle); -} - namespace { constexpr int AUDIO3D_ERROR_INVALID_PORT = static_cast(0x80EA0002); @@ -472,19 +469,6 @@ int APS5_VABI sceAudio3dReportUnregisterHandler(void) { return 0; } -size_t APS5_VABI sceAudioOut2GetSpeakerArrayMemorySize(uint32_t num_speakers, uint8_t is_3d, uint8_t is_ambisonics); -int APS5_VABI sceAudioOut2SpeakerArrayCreate(AudioOut2SpeakerArrayHandle* handle, const void* vbap_params, const void* ambi_params); -int APS5_VABI sceAudioOut2SpeakerArrayDestroy(AudioOut2SpeakerArrayHandle handle); -int APS5_VABI sceAudioOut2GetSpeakerArrayCoefficients(AudioOut2SpeakerArrayHandle handle, AudioOut2Position pos, float spread, float* coefficients, uint32_t num_coefficients, uint8_t height_aware, float downmix_spread_radius); - -struct Audio3dSpeakerArrayParameters { - const AudioOut2Position* positions; - std::uint32_t numSpeakers; - std::uint8_t is3d; - void* memory; - std::size_t memorySize; -}; - static_assert(sizeof(Audio3dSpeakerArrayParameters) == 0x20); size_t APS5_VABI sceAudio3dGetSpeakerArrayMemorySize(uint32_t num_speakers, uint8_t is_3d) { diff --git a/core/libs/prx/libSceAudio3d/include/Audio3d.hpp b/core/libs/prx/libSceAudio3d/include/Audio3d.hpp new file mode 100644 index 0000000000..54c1e127b3 --- /dev/null +++ b/core/libs/prx/libSceAudio3d/include/Audio3d.hpp @@ -0,0 +1,48 @@ +#pragma once + +#include "SceTypes.hpp" + +struct Audio3dSpeakerArrayParameters { + const AudioOut2Position* positions; + std::uint32_t numSpeakers; + std::uint8_t is3d; + void* memory; + std::size_t memorySize; +}; + +extern "C" { + +void APS5_VABI sceAudio3dGetDefaultOpenParameters(Audio3dOpenParameters* p); +int APS5_VABI sceAudio3dInitialize(int64_t reserved); +int APS5_VABI sceAudio3dTerminate(); +int APS5_VABI sceAudio3dPortAdvance(uint32_t portId); +int APS5_VABI sceAudio3dPortClose(uint32_t portId); +int APS5_VABI sceAudio3dPortGetQueueLevel(uint32_t portId, uint32_t* queueLevel, uint32_t* queueAvailable); +int APS5_VABI sceAudio3dPortGetAttributesSupported(uint32_t portId, uint32_t* attributes, uint32_t* numAttributes); +int APS5_VABI sceAudio3dPortOpen(int userId, const Audio3dOpenParameters* parameters, uint32_t* id); +int APS5_VABI sceAudio3dPortPush(uint32_t portId, uint32_t blocking); +int APS5_VABI sceAudio3dPortSetAttribute(uint32_t portId, uint32_t attributeId, const void* attribute, size_t attributeSize); +int APS5_VABI sceAudio3dObjectReserve(uint32_t portId, uint32_t* objectId); +int APS5_VABI sceAudio3dObjectUnreserve(uint32_t portId, uint32_t objectId); +int APS5_VABI sceAudio3dObjectSetAttributes(uint32_t portId, uint32_t objectId, uint64_t numAttributes, const Audio3dAttribute* attributeArray); +int APS5_VABI sceAudio3dPortFlush(uint32_t portId); +int APS5_VABI sceAudio3dBedWrite2(uint32_t portId, uint32_t numChannels, uint32_t format, const void* buffer, uint32_t numSamples, uint32_t outputRoute, bool); +int APS5_VABI sceAudio3dBedWrite(uint32_t portId, uint32_t numChannels, uint32_t format, const void* buffer, uint32_t numSamples); +int APS5_VABI sceAudio3dAudioOutOpen(uint32_t portId, int userId, std::int32_t type, std::int32_t index, uint32_t len, uint32_t freq, uint32_t param); +int APS5_VABI sceAudio3dAudioOutClose(std::int32_t handle); +int APS5_VABI sceAudio3dAudioOutOutput(std::int32_t handle, const void* ptr); +int APS5_VABI sceAudio3dAudioOutOutputs(AudioOutOutputParam* param, uint32_t num); +int APS5_VABI sceAudio3dStrError(void); +int APS5_VABI sceAudio3dPortOpenEx(void); +int APS5_VABI sceAudio3dPortCreate(void); +int APS5_VABI sceAudio3dPortDestroy(void); +int APS5_VABI sceAudio3dPortGetStatus(void); +int APS5_VABI sceAudio3dReportRegisterHandler(void); +int APS5_VABI sceAudio3dReportUnregisterHandler(void); +size_t APS5_VABI sceAudio3dGetSpeakerArrayMemorySize(uint32_t numSpeakers, uint8_t is3d); +int APS5_VABI sceAudio3dCreateSpeakerArray(AudioOut2SpeakerArrayHandle* handle, const Audio3dSpeakerArrayParameters* parameters); +int APS5_VABI sceAudio3dDeleteSpeakerArray(AudioOut2SpeakerArrayHandle handle); +int APS5_VABI sceAudio3dGetSpeakerArrayMixCoefficients(AudioOut2SpeakerArrayHandle handle, AudioOut2Position pos, float spread, float* coefficients, uint32_t numCoefficients); +int APS5_VABI sceAudio3dGetSpeakerArrayMixCoefficients2(AudioOut2SpeakerArrayHandle handle, AudioOut2Position pos, float spread, float* coefficients, uint32_t numCoefficients, uint8_t heightAware, float downmixSpreadRadius); + +} diff --git a/core/libs/prx/libSceAudio3d/libSceAudio3d.hpp b/core/libs/prx/libSceAudio3d/libSceAudio3d.hpp new file mode 100644 index 0000000000..dcdc650f61 --- /dev/null +++ b/core/libs/prx/libSceAudio3d/libSceAudio3d.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceAudio3d/include/Audio3d.hpp" diff --git a/core/libs/prx/libSceAudioIn/Export.cpp b/core/libs/prx/libSceAudioIn/Export.cpp index 0a1712b5da..b1d4089ca1 100644 --- a/core/libs/prx/libSceAudioIn/Export.cpp +++ b/core/libs/prx/libSceAudioIn/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceAudioIn/include/AudioIn.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceAudioIn/include/AudioIn.hpp b/core/libs/prx/libSceAudioIn/include/AudioIn.hpp new file mode 100644 index 0000000000..f4d273aab6 --- /dev/null +++ b/core/libs/prx/libSceAudioIn/include/AudioIn.hpp @@ -0,0 +1,50 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceAudioInInit(); +int APS5_VABI sceAudioInGetSilentState(int handle); +int APS5_VABI sceAudioInInput(int handle, void* dest); +int APS5_VABI sceAudioInOpen(int userId, uint32_t type, uint32_t index, uint32_t len, uint32_t freq, uint32_t param); +int32_t APS5_VABI sceAudioInClose(int32_t handle); +int32_t APS5_VABI sceAudioInHqOpen(int32_t userId, uint32_t type, uint32_t index, uint32_t len, uint32_t freq, uint32_t param); +int32_t APS5_VABI sceAudioInAsyncOpen(int32_t userId, uint32_t type, uint32_t index, uint32_t len, uint32_t freq, uint32_t param); +int32_t APS5_VABI sceAudioInIsPadEmbeddedMic(int32_t handle); +int32_t APS5_VABI sceAudioInGetGain(int32_t handle, float* gain); +int32_t APS5_VABI sceAudioInGetRerouteCount(int32_t handle); +int APS5_VABI sceAudioInDeviceIdOpen(void); +int APS5_VABI sceAudioInDeviceIdAsyncOpen(void); +int APS5_VABI sceAudioInSetUsbGain(void); +int APS5_VABI sceAudioInIsSharedDevice(void); +int APS5_VABI sceAudioInDeviceIdHqOpen(void); +int APS5_VABI sceAudioInDeviceHqOpen(void); +int APS5_VABI sceAudioInSetConnections(void); +int APS5_VABI sceAudioInSetPortConnections(void); +int APS5_VABI sceAudioInSetPortStatuses(void); +int APS5_VABI sceAudioInGetHandleStatusInfo(void); +int APS5_VABI sceAudioInOpenEx(int userId, uint32_t type, uint32_t index, uint32_t extra, uint32_t len, uint32_t freq, uint32_t param); +int APS5_VABI sceAudioInHqOpenEx(int userId, uint32_t type, uint32_t index, uint32_t extra, uint32_t len, uint32_t freq, uint32_t param); +int APS5_VABI sceAudioInDeviceOpenEx(void); +int APS5_VABI sceAudioInChangeAppModuleState(void); +int APS5_VABI sceAudioInSetSparkParam(void); +int APS5_VABI sceAudioInSetSparkSideTone(void); +int APS5_VABI sceAudioInSetCompressorPreGain(void); +int APS5_VABI sceAudioInSetNoiseGateThreshold(void); +int APS5_VABI sceAudioInSetMicLevel(void); +int APS5_VABI sceAudioInSetDeviceMuteStatus(void); +int APS5_VABI sceAudioInSetDevConnection(void); +int APS5_VABI sceAudioInCountPorts(void); +int APS5_VABI sceAudioInSetUserMute(void); +int APS5_VABI sceAudioInVmicCreate(void); +int APS5_VABI sceAudioInVmicDestroy(void); +int APS5_VABI sceAudioInVmicWrite(void); +int APS5_VABI sceAudioInVmicGetStatus(void); +int APS5_VABI sceAudioInVmicSetMute(void); +int APS5_VABI sceAudioInSetMode(void); +int APS5_VABI sceAudioInSetMode2(void); +int APS5_VABI sceAudioInExtCtrl(void); +int APS5_VABI sceAudioInInputs(void); + +} diff --git a/core/libs/prx/libSceAudioIn/libSceAudioIn.hpp b/core/libs/prx/libSceAudioIn/libSceAudioIn.hpp new file mode 100644 index 0000000000..6da8abb473 --- /dev/null +++ b/core/libs/prx/libSceAudioIn/libSceAudioIn.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceAudioIn/include/AudioIn.hpp" diff --git a/core/libs/prx/libSceAudioLatencyEstimation/Export.cpp b/core/libs/prx/libSceAudioLatencyEstimation/Export.cpp index 71b2edeba4..566f101c98 100644 --- a/core/libs/prx/libSceAudioLatencyEstimation/Export.cpp +++ b/core/libs/prx/libSceAudioLatencyEstimation/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceAudioLatencyEstimation/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceAudioLatencyEstimation/include/Api.hpp b/core/libs/prx/libSceAudioLatencyEstimation/include/Api.hpp new file mode 100644 index 0000000000..7d8dffbfc4 --- /dev/null +++ b/core/libs/prx/libSceAudioLatencyEstimation/include/Api.hpp @@ -0,0 +1,12 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceAudioLatencyEstimationAddData(); +int APS5_VABI sceAudioLatencyEstimationGetDelayTime(); +int APS5_VABI sceAudioLatencyEstimationInitialize(); +int APS5_VABI sceAudioLatencyEstimationRelease(); + +} diff --git a/core/libs/prx/libSceAudioLatencyEstimation/libSceAudioLatencyEstimation.hpp b/core/libs/prx/libSceAudioLatencyEstimation/libSceAudioLatencyEstimation.hpp new file mode 100644 index 0000000000..5df8b57860 --- /dev/null +++ b/core/libs/prx/libSceAudioLatencyEstimation/libSceAudioLatencyEstimation.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceAudioLatencyEstimation/include/Api.hpp" diff --git a/core/libs/prx/libSceAudioOut/include/AudioOut.hpp b/core/libs/prx/libSceAudioOut/include/AudioOut.hpp new file mode 100644 index 0000000000..ba5e6b3e93 --- /dev/null +++ b/core/libs/prx/libSceAudioOut/include/AudioOut.hpp @@ -0,0 +1,80 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceAudioOutInit(); +int APS5_VABI sceAudioOutOpen(int userId, int type, int index, std::uint32_t len, std::uint32_t freq, std::uint32_t param); +int APS5_VABI sceAudioOutClose(int handle); +int APS5_VABI sceAudioOutOutput(int handle, const void* ptr); +int APS5_VABI sceAudioOutOutputs(AudioOutOutputParam* param, std::uint32_t num); +int APS5_VABI sceAudioOutSetVolume(int handle, std::uint32_t flag, int* vol); +int APS5_VABI sceAudioOutGetLastOutputTime(int handle, std::uint64_t* outputTime); +int APS5_VABI sceAudioOutGetPortState(int handle, AudioOutPortState* state); +int APS5_VABI sceAudioOutDeviceIdOpen(std::uint64_t deviceId, std::int32_t type, std::int32_t index, std::uint32_t length, std::int32_t frequency, std::uint32_t parameter); +int APS5_VABI sceAudioOutSysClose(int handle); +int APS5_VABI sceAudioOutSysConfigureOutput(int type, std::uint64_t flags, std::uint32_t mode, std::uint32_t target, std::uint64_t option); +int APS5_VABI sceAudioOutSysGetHdmiMonitorInfo(int type, void* info, std::uint32_t size); +int APS5_VABI sceAudioOutSysOpen(int userId, std::uint32_t mode); +int APS5_VABI sceAudioOutSetMixLevelPadSpk(int handle, std::uint32_t mixLevel); +int APS5_VABI sceAudioOutExClose(int handle); +int APS5_VABI sceAudioOutExConfigureOutput(int control, std::uint64_t flags, std::uint32_t mode, std::uint32_t target, std::uint64_t option); +int APS5_VABI sceAudioOutExGetMonitorInfo(int type, int index, void* info, std::uint32_t size); +int APS5_VABI sceAudioOutExOpen(int userId, std::uint32_t mode); +int APS5_VABI sceAudioOutGetSystemState(AudioOutSystemState* state); +int APS5_VABI sceAudioOutOpenEx(void); +int APS5_VABI sceAudioOutSetSystemDebugState(void); +int APS5_VABI sceAudioOutGetHandleStatusInfo(void); +int APS5_VABI sceAudioOutGetSimulatedHandleStatusInfo2(void); +int APS5_VABI sceAudioOutChangeAppModuleState(void); +int APS5_VABI sceAudioOutGetSimulatedHandleStatusInfo(void); +int APS5_VABI sceAudioOutGetSimulatedBusUsableStatusByBusType(void); +int APS5_VABI sceAudioOutAttachToApplicationByPid(void); +int APS5_VABI sceAudioOutDetachFromApplicationByPid(void); +int APS5_VABI sceAudioOutPtOpen(void); +int APS5_VABI sceAudioOutPtClose(void); +int APS5_VABI sceAudioOutPtGetLastOutputTime(void); +int APS5_VABI sceAudioOutExPtOpen(void); +int APS5_VABI sceAudioOutExPtClose(void); +int APS5_VABI sceAudioOutExPtGetLastOutputTime(void); +int APS5_VABI sceAudioOutExGetLastOutputTime(void); +int APS5_VABI sceAudioOutGetInfoOpenNum(void); +int APS5_VABI sceAudioOutGetInfo(void); +int APS5_VABI sceAudioOutMasteringInit(uint32_t flags); +int APS5_VABI sceAudioOutMasteringSetParam(const AudioOut2MasteringParamsHeader* param, uint32_t flags); +int APS5_VABI sceAudioOutMasteringGetState(AudioOut2MasteringStatesHeader* state); +int APS5_VABI sceAudioOutMasteringTerm(void); +int APS5_VABI sceAudioOutSetPadSpkVolume(void); +int APS5_VABI sceAudioOutSetPadJackVolume(void); +int APS5_VABI sceAudioOutSetUsbVolume(void); +int APS5_VABI sceAudioOutSetCaesarVolume(void); +int APS5_VABI sceAudioOutSetHeadphoneOutMode(void); +int APS5_VABI sceAudioOutGetFocusEnablePid(void); +int APS5_VABI sceAudioOutSetMainOutput(void); +int APS5_VABI sceAudioOutSetVolumeDown(void); +int APS5_VABI sceAudioOutSetChatBalance(void); +int APS5_VABI sceAudioOutSetRecMode(void); +int APS5_VABI sceAudioOutSetAllMute(void); +int APS5_VABI sceAudioOutSetSparkEQ(void); +int APS5_VABI sceAudioOutArbitrationInitialize(void); +int APS5_VABI sceAudioOutEnable3DAudioByArbitration(void); +int APS5_VABI sceAudioOutAssignHRTF(void); +int APS5_VABI sceAudioOutEnable3DAudioForUser(void); +int APS5_VABI sceAudioOutEnableMonoHpOutput(void); +int APS5_VABI sceAudioOutEnableTVVirtual(void); +int APS5_VABI sceAudioOutEnableTVCorrection(void); +int APS5_VABI sceAudioOutEnableVrControllerLowPowerMode(void); +int APS5_VABI sceAudioOutEnableCinematicVrRotation(void); +int APS5_VABI sceAudioOutCustomHrtfIsExist(void); +int APS5_VABI sceAudioOutExConfigureOutputMode(void); +int APS5_VABI sceAudioOutExSystemInfoIsSupportedAudioOutExMode(void); +int APS5_VABI sceAudioOutExGetSystemInfo(void); +int APS5_VABI sceAudioOutExGetOutputInfo(void); +int APS5_VABI sceAudioOutSysConfigureOutputMode(void); +int APS5_VABI sceAudioOutSysGetMonitorInfo(void); +int APS5_VABI sceAudioOutSysHdmiMonitorInfoIsSupportedAudioOutMode(void); +int APS5_VABI sceAudioOutSysGetSystemInfo(void); +int APS5_VABI sceAudioOutSysGetOutputInfo(void); + +} diff --git a/core/libs/prx/libSceAudioOut/include/AudioOut2.hpp b/core/libs/prx/libSceAudioOut/include/AudioOut2.hpp new file mode 100644 index 0000000000..d7212024f9 --- /dev/null +++ b/core/libs/prx/libSceAudioOut/include/AudioOut2.hpp @@ -0,0 +1,82 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceAudioOut2ContextAdvance(AudioOut2ContextHandle ctx); +int APS5_VABI sceAudioOut2ContextCreate(const AudioOut2ContextParam* params, void* buffer, size_t bufferSize, AudioOut2ContextHandle* ctx); +int APS5_VABI sceAudioOut2ContextDestroy(AudioOut2ContextHandle ctx); +int APS5_VABI sceAudioOut2ContextGetQueueLevel(AudioOut2ContextHandle ctx, uint32_t* queueLevel, uint32_t* availableQueue); +int APS5_VABI sceAudioOut2ContextPush(AudioOut2ContextHandle ctx, uint32_t blocking); +int APS5_VABI sceAudioOut2ContextQueryMemory(const AudioOut2ContextParam* params, size_t* memorySize); +int APS5_VABI sceAudioOut2ContextResetParam(AudioOut2ContextParam* params); +int APS5_VABI sceAudioOut2ContextSetAttributes(AudioOut2ContextHandle ctx, const AudioOut2Attribute* attributes, uint32_t num); +int APS5_VABI sceAudioOut2LoInit(void); +int APS5_VABI sceAudioOut2LoTerminate(void); +int APS5_VABI sceAudioOut2LoContextQueryMemory(const AudioOut2ContextParam* params, size_t* memorySize); +int APS5_VABI sceAudioOut2LoContextCreate(const AudioOut2ContextParam* params, void* buffer, size_t bufferSize, AudioOut2ContextHandle* ctx); +int APS5_VABI sceAudioOut2LoContextDestroy(AudioOut2ContextHandle ctx); +int APS5_VABI sceAudioOut2LoContextSetAttributes(AudioOut2ContextHandle ctx, const AudioOut2Attribute* attributes, uint32_t num); +int APS5_VABI sceAudioOut2LoContextAdvance(AudioOut2ContextHandle ctx); +int APS5_VABI sceAudioOut2LoContextPush(AudioOut2ContextHandle ctx, uint32_t blocking); +int APS5_VABI sceAudioOut2LoContextGetQueueLevel(AudioOut2ContextHandle ctx, uint32_t* queueLevel, uint32_t* availableQueue); +int APS5_VABI sceAudioOut2LoPortCreate(AudioOut2ContextHandle ctx, const AudioOut2PortParam* params, AudioOut2PortHandle* port); +int APS5_VABI sceAudioOut2LoPortDestroy(AudioOut2PortHandle port); +int APS5_VABI sceAudioOut2LoPortSetAttributes(AudioOut2PortHandle port, const AudioOut2Attribute* attributes, uint32_t num); +int APS5_VABI sceAudioOut2LoPortGetState(AudioOut2PortHandle port, AudioOut2PortState* state); +int APS5_VABI sceAudioOut2MasteringInit(uint32_t flags); +int APS5_VABI sceAudioOut2MasteringInitEx(uint32_t flags); +int APS5_VABI sceAudioOut2MasteringTerm(void); +int APS5_VABI sceAudioOut2MasteringGetState(AudioOut2MasteringStatesHeader* state, uint32_t output, AudioOut2UserHandle user); +int APS5_VABI sceAudioOut2MasteringSetParam(const AudioOut2MasteringParamsHeader* param, uint32_t output, uint32_t flags); +int APS5_VABI sceAudioOut2PortCreate(AudioOut2ContextHandle ctx, const AudioOut2PortParam* params, AudioOut2PortHandle* port); +int APS5_VABI sceAudioOut2PortDestroy(AudioOut2PortHandle port); +int APS5_VABI sceAudioOut2PortGetState(AudioOut2PortHandle port, AudioOut2PortState* state); +int APS5_VABI sceAudioOut2PortSetAttributes(AudioOut2PortHandle port, const AudioOut2Attribute* attributes, uint32_t num); +int APS5_VABI sceAudioOut2SpeakerArrayCreate(AudioOut2SpeakerArrayHandle* handle, const void* vbapParams, const void* ambiParams); +int APS5_VABI sceAudioOut2SpeakerArrayDestroy(AudioOut2SpeakerArrayHandle handle); +int APS5_VABI sceAudioOut2GetSpeakerArrayAmbisonicsCoefficients(AudioOut2SpeakerArrayHandle handle, uint32_t ambisonicsChannel, float* coefficients, uint32_t numCoefficients); +int APS5_VABI sceAudioOut2GetSpeakerArrayCoefficients(AudioOut2SpeakerArrayHandle handle, AudioOut2Position pos, float spread, float* coefficients, uint32_t numCoefficients, uint8_t heightAware, float downmixSpreadRadius); +size_t APS5_VABI sceAudioOut2GetSpeakerArrayMemorySize(uint32_t numSpeakers, uint8_t is3d, uint8_t isAmbisonics); +int APS5_VABI sceAudioOut2GetSpeakerInfo(AudioOut2SpeakerInfo* info, uint32_t flags); +int APS5_VABI sceAudioOut2Initialize(void); +int APS5_VABI sceAudioOut2InitializeEx(std::uint32_t param); +int APS5_VABI sceAudioOut2Set3DLatency(int userId, std::uint32_t output); +int APS5_VABI sceAudioOut2GetSystemState(AudioOut2SystemState* state); +int APS5_VABI sceAudioOut2SetSystemDebugState(const AudioOut2SystemDebugStateParam* param); +int APS5_VABI sceAudioOut2EnableChat(void); +int APS5_VABI sceAudioOut2DisableChat(void); +int APS5_VABI sceAudioOut2UserCreate(uint32_t userId, AudioOut2UserHandle* handle); +int APS5_VABI sceAudioOut2UserDestroy(AudioOut2UserHandle handle); +int APS5_VABI sceAudioOut2UserGetSupportedAttributes(AudioOut2UserHandle handle, uint32_t* contextAttributes, uint32_t* portAttributes); +int APS5_VABI sceAudioOut2UserCreateEx(void); +int APS5_VABI sceAudioOut2ArbitrationInitialize(void); +int APS5_VABI sceAudioOut2MbusInit(void); +int APS5_VABI sceAudioOut2MbusSetPortConnections(void); +int APS5_VABI sceAudioOut2MbusSetConnections(void); +int APS5_VABI sceAudioOut2MbusSetPortStatuses(void); +int APS5_VABI sceAudioOut2MbusSetHeadphoneOutMode(void); +int APS5_VABI sceAudioOut2MbusUserLoginFor3DAudio(void); +int APS5_VABI sceAudioOut2MbusSetDeviceConnections(void); +int APS5_VABI sceAudioOut2MbusSetMorpheusParam(void); +int APS5_VABI sceAudioOut2MbusSetCaesarParam(void); +int APS5_VABI sceAudioOut2MbusSetSparkParam(void); +int APS5_VABI sceAudioOut2AllAudioMainToHeadphoneForDiag(void); +int APS5_VABI sceAudioOut2LoPortGetStateEx(void); +int APS5_VABI sceAudioOut2ReportRegisterHandler(void); +int APS5_VABI sceAudioOut2ReportUnregisterHandler(void); +int APS5_VABI sceAudioOut2GetTvCorrectionInfo(void); +int APS5_VABI sceAudioOut2GetIpcHandle(void); +int APS5_VABI sceAudioOut2GetSystemStateEx(void); +int APS5_VABI sceAudioOut2SetDebugHeadphoneMode(void); +int APS5_VABI sceAudioOut2DebugStateCtrl(void); +int APS5_VABI sceAudioOut2ContextBedWrite(void); +int APS5_VABI sceAudioOut2PortCreateEx(void); +int APS5_VABI sceAudioOut2Terminate(void); +int APS5_VABI sceAudioOut2PortRegister(void); +int APS5_VABI sceAudioOut2PortUnregister(void); +int APS5_VABI sceAudioOut2GetAmbisonicsEncodeCoefficients(void); +int APS5_VABI sceAudioOut2GetHrtfIdForCronos(void); + +} diff --git a/core/libs/prx/libSceAudioOut/libSceAudioOut.hpp b/core/libs/prx/libSceAudioOut/libSceAudioOut.hpp new file mode 100644 index 0000000000..d092ed95af --- /dev/null +++ b/core/libs/prx/libSceAudioOut/libSceAudioOut.hpp @@ -0,0 +1,4 @@ +#pragma once + +#include "prx/libSceAudioOut/include/AudioOut.hpp" +#include "prx/libSceAudioOut/include/AudioOut2.hpp" diff --git a/core/libs/prx/libSceAudioOut/src/AudioOut.cpp b/core/libs/prx/libSceAudioOut/src/AudioOut.cpp index c5051500a0..4459dc8152 100644 --- a/core/libs/prx/libSceAudioOut/src/AudioOut.cpp +++ b/core/libs/prx/libSceAudioOut/src/AudioOut.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceAudioOut/include/AudioOut.hpp" #include #include #include diff --git a/core/libs/prx/libSceAudioOut/src/AudioOut2Context.cpp b/core/libs/prx/libSceAudioOut/src/AudioOut2Context.cpp index e11ee633e5..905eaa42f5 100644 --- a/core/libs/prx/libSceAudioOut/src/AudioOut2Context.cpp +++ b/core/libs/prx/libSceAudioOut/src/AudioOut2Context.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceAudioOut/include/AudioOut2.hpp" #include #include #include diff --git a/core/libs/prx/libSceAudioOut/src/AudioOut2Low.cpp b/core/libs/prx/libSceAudioOut/src/AudioOut2Low.cpp index eac5204b6d..e427f40302 100644 --- a/core/libs/prx/libSceAudioOut/src/AudioOut2Low.cpp +++ b/core/libs/prx/libSceAudioOut/src/AudioOut2Low.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceAudioOut/include/AudioOut2.hpp" #include #include #include "SceTypes.hpp" @@ -5,19 +6,6 @@ extern "C" { -int APS5_VABI sceAudioOut2Initialize(void); -int APS5_VABI sceAudioOut2ContextQueryMemory(const AudioOut2ContextParam* params, size_t* memory_size); -int APS5_VABI sceAudioOut2ContextCreate(const AudioOut2ContextParam* params, void* buffer, size_t buffer_size, AudioOut2ContextHandle* ctx); -int APS5_VABI sceAudioOut2ContextDestroy(AudioOut2ContextHandle ctx); -int APS5_VABI sceAudioOut2ContextSetAttributes(AudioOut2ContextHandle ctx, const AudioOut2Attribute* attributes, uint32_t num); -int APS5_VABI sceAudioOut2ContextAdvance(AudioOut2ContextHandle ctx); -int APS5_VABI sceAudioOut2ContextPush(AudioOut2ContextHandle ctx, uint32_t blocking); -int APS5_VABI sceAudioOut2ContextGetQueueLevel(AudioOut2ContextHandle ctx, uint32_t* queue_level, uint32_t* available_queue); -int APS5_VABI sceAudioOut2PortCreate(AudioOut2ContextHandle ctx, const AudioOut2PortParam* params, AudioOut2PortHandle* port); -int APS5_VABI sceAudioOut2PortDestroy(AudioOut2PortHandle port); -int APS5_VABI sceAudioOut2PortSetAttributes(AudioOut2PortHandle port, const AudioOut2Attribute* attributes, uint32_t num); -int APS5_VABI sceAudioOut2PortGetState(AudioOut2PortHandle port, AudioOut2PortState* state); - int APS5_VABI sceAudioOut2LoInit(void) { return sceAudioOut2Initialize(); } diff --git a/core/libs/prx/libSceAudioOut/src/AudioOut2Mastering.cpp b/core/libs/prx/libSceAudioOut/src/AudioOut2Mastering.cpp index 2a5d1be319..88e948e434 100644 --- a/core/libs/prx/libSceAudioOut/src/AudioOut2Mastering.cpp +++ b/core/libs/prx/libSceAudioOut/src/AudioOut2Mastering.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceAudioOut/include/AudioOut2.hpp" #include #include #include diff --git a/core/libs/prx/libSceAudioOut/src/AudioOut2Port.cpp b/core/libs/prx/libSceAudioOut/src/AudioOut2Port.cpp index 14c9bc2c63..e8a547fefc 100644 --- a/core/libs/prx/libSceAudioOut/src/AudioOut2Port.cpp +++ b/core/libs/prx/libSceAudioOut/src/AudioOut2Port.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceAudioOut/include/AudioOut2.hpp" #include #include #include diff --git a/core/libs/prx/libSceAudioOut/src/AudioOut2SpeakerArray.cpp b/core/libs/prx/libSceAudioOut/src/AudioOut2SpeakerArray.cpp index cee71ecc16..36b6746149 100644 --- a/core/libs/prx/libSceAudioOut/src/AudioOut2SpeakerArray.cpp +++ b/core/libs/prx/libSceAudioOut/src/AudioOut2SpeakerArray.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceAudioOut/include/AudioOut2.hpp" #include #include #include diff --git a/core/libs/prx/libSceAudioOut/src/AudioOut2System.cpp b/core/libs/prx/libSceAudioOut/src/AudioOut2System.cpp index 0be9bc4cf3..6723eb1371 100644 --- a/core/libs/prx/libSceAudioOut/src/AudioOut2System.cpp +++ b/core/libs/prx/libSceAudioOut/src/AudioOut2System.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceAudioOut/include/AudioOut2.hpp" #include #include #include @@ -12,8 +13,6 @@ static std::atomic g_chatEnabled{false}; extern "C" { -int APS5_VABI sceAudioOut2Initialize(void); - int APS5_VABI sceAudioOut2InitializeEx(std::uint32_t param) { (void)param; return sceAudioOut2Initialize(); diff --git a/core/libs/prx/libSceAudioOut/src/AudioOut2User.cpp b/core/libs/prx/libSceAudioOut/src/AudioOut2User.cpp index 1a514be246..5a8bce8592 100644 --- a/core/libs/prx/libSceAudioOut/src/AudioOut2User.cpp +++ b/core/libs/prx/libSceAudioOut/src/AudioOut2User.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceAudioOut/include/AudioOut2.hpp" #include #include "SceTypes.hpp" #include "prx/libc/include/General.hpp" diff --git a/core/libs/prx/libSceAudioOut/src/Unimplemented.cpp b/core/libs/prx/libSceAudioOut/src/Unimplemented.cpp index 4afa07f903..1e44d76aa6 100644 --- a/core/libs/prx/libSceAudioOut/src/Unimplemented.cpp +++ b/core/libs/prx/libSceAudioOut/src/Unimplemented.cpp @@ -1,3 +1,5 @@ +#include "prx/libSceAudioOut/include/AudioOut2.hpp" +#include "prx/libSceAudioOut/include/AudioOut.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceAudioOut/tests/AudioOut2DeviceState.cpp b/core/libs/prx/libSceAudioOut/tests/AudioOut2DeviceState.cpp index 5ada5b5529..82e8464648 100644 --- a/core/libs/prx/libSceAudioOut/tests/AudioOut2DeviceState.cpp +++ b/core/libs/prx/libSceAudioOut/tests/AudioOut2DeviceState.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceAudioOut/libSceAudioOut.hpp" #include "SceTypes.hpp" #include @@ -8,19 +9,6 @@ #include #include -extern "C" { -int APS5_VABI sceAudioOutInit(); -int APS5_VABI sceAudioOut2Initialize(); -int APS5_VABI sceAudioOut2ContextResetParam(AudioOut2ContextParam*); -int APS5_VABI sceAudioOut2ContextCreate(const AudioOut2ContextParam*, void*, std::size_t, AudioOut2ContextHandle*); -int APS5_VABI sceAudioOut2ContextDestroy(AudioOut2ContextHandle); -int APS5_VABI sceAudioOut2PortCreate(AudioOut2ContextHandle, const AudioOut2PortParam*, AudioOut2PortHandle*); -int APS5_VABI sceAudioOut2PortDestroy(AudioOut2PortHandle); -int APS5_VABI sceAudioOut2PortGetState(AudioOut2PortHandle, AudioOut2PortState*); -int APS5_VABI sceAudioOut2GetSpeakerInfo(AudioOut2SpeakerInfo*, std::uint32_t); -int APS5_VABI sceAudioOut2GetSystemState(AudioOut2SystemState*); -} - static void Require(bool value) { if (!value) std::abort(); } namespace { diff --git a/core/libs/prx/libSceAudioOut/tests/AudioOut2Latency.cpp b/core/libs/prx/libSceAudioOut/tests/AudioOut2Latency.cpp index df12a6d6a9..cc08e950f6 100644 --- a/core/libs/prx/libSceAudioOut/tests/AudioOut2Latency.cpp +++ b/core/libs/prx/libSceAudioOut/tests/AudioOut2Latency.cpp @@ -1,3 +1,5 @@ +#include "prx/libSceAudioOut/include/AudioOut.hpp" +#include "prx/libSceAudioOut/include/AudioOut2.hpp" #include "SceTypes.hpp" #include "prx/libc/include/general/VabiMacros.hpp" @@ -9,26 +11,6 @@ #include #include -extern "C" { -int APS5_VABI sceAudioOut2Initialize(); -int APS5_VABI sceAudioOut2InitializeEx(std::uint32_t); -int APS5_VABI sceAudioOut2LoInit(); -int APS5_VABI sceAudioOut2LoTerminate(); -int APS5_VABI sceAudioOut2Set3DLatency(int, std::uint32_t); -int APS5_VABI sceAudioOut2MasteringInit(std::uint32_t); -int APS5_VABI sceAudioOut2MasteringInitEx(std::uint32_t); -int APS5_VABI sceAudioOut2MasteringTerm(); -int APS5_VABI sceAudioOut2MasteringSetParam(const void*, std::uint32_t, std::uint32_t); -int APS5_VABI sceAudioOut2MasteringGetState(void*, std::uint32_t, std::uint64_t); -int APS5_VABI sceAudioOut2SetSystemDebugState(const void*); -int APS5_VABI sceAudioOutMasteringInit(std::uint32_t); -int APS5_VABI sceAudioOutMasteringTerm(); -int APS5_VABI sceAudioOutMasteringSetParam(const void*, std::uint32_t); -int APS5_VABI sceAudioOutMasteringGetState(void*); -int APS5_VABI sceAudioOut2EnableChat(); -int APS5_VABI sceAudioOut2DisableChat(); -} - static void Require(bool value, const char* message) { if (value) return; std::fprintf(stderr, "%s\n", message); @@ -86,12 +68,12 @@ void TestSet3DLatency() { } void TestMasteringInit() { - const std::uint32_t params[4] = {1u, 0u, 0u, 0u}; - alignas(16) std::uint8_t storage[512] {}; + const AudioOut2MasteringParamsHeader params{1u}; + AudioOut2MasteringStates storage{}; Require(sceAudioOut2MasteringTerm() == errorMasteringNotInitialized, "termination before initialization is refused"); - Require(sceAudioOut2MasteringSetParam(params, 0, 0) == errorMasteringNotInitialized, "parameters before initialization are refused"); + Require(sceAudioOut2MasteringSetParam(¶ms, 0, 0) == errorMasteringNotInitialized, "parameters before initialization are refused"); Require(sceAudioOut2MasteringGetState(nullptr, 0, 0) == errorMasteringNotInitialized, "the initialization check comes before the null check"); - Require(sceAudioOut2MasteringGetState(storage, 0, 0) == errorMasteringNotInitialized, "states before initialization are refused"); + Require(sceAudioOut2MasteringGetState(&storage.states_header, 0, 0) == errorMasteringNotInitialized, "states before initialization are refused"); Require(sceAudioOut2MasteringInit(1) == errorMasteringInvalidApiParam, "flags 1 are refused"); Require(sceAudioOut2MasteringInit(0x80000000u) == errorMasteringInvalidApiParam, "sceAudioOut2MasteringInit accepts no flag"); Require(sceAudioOut2MasteringInit(0) == 0, "flags 0 must be accepted"); @@ -110,37 +92,37 @@ void TestMasteringTerm() { } void TestMasteringSetParam() { - const std::uint32_t params[4] = {1u, 0u, 0u, 0u}; - Require(sceAudioOut2MasteringSetParam(params, 0, 0) == 0, "mastering parameters must be accepted"); - Require(sceAudioOut2MasteringSetParam(params, 2, 0) == 0, "mastering parameters for output 2 must be accepted"); + const AudioOut2MasteringParamsHeader params{1u}; + Require(sceAudioOut2MasteringSetParam(¶ms, 0, 0) == 0, "mastering parameters must be accepted"); + Require(sceAudioOut2MasteringSetParam(¶ms, 2, 0) == 0, "mastering parameters for output 2 must be accepted"); Require(sceAudioOut2MasteringSetParam(nullptr, 0, 0) == errorMasteringInvalidApiParam, "null mastering parameters return the invalid API parameter error"); Require(sceAudioOut2MasteringSetParam(nullptr, 0, 2) == errorMasteringInvalidApiParam, "the null check comes before the flag check"); - Require(sceAudioOut2MasteringSetParam(params, 0, 1) == 0, "flags 1 must be accepted"); - Require(sceAudioOut2MasteringSetParam(params, 0, 2) == errorMasteringInvalidFlag, "flags above 1 are refused"); + Require(sceAudioOut2MasteringSetParam(¶ms, 0, 1) == 0, "flags 1 must be accepted"); + Require(sceAudioOut2MasteringSetParam(¶ms, 0, 2) == errorMasteringInvalidFlag, "flags above 1 are refused"); } void TestMasteringGetState() { alignas(16) std::uint8_t storage[512]; Require(sceAudioOut2MasteringGetState(nullptr, 0, 0) == errorInvalidPointer, "a null state returns the invalid pointer error"); - auto* header = reinterpret_cast(storage); + auto* header = reinterpret_cast(storage); auto* words = reinterpret_cast(storage); - *header = 1u; - Require(sceAudioOut2MasteringGetState(storage, 0, 0) == 0, "states id 1 must be accepted"); - Require(*header == 1u, "states id 1 is kept"); + header->states_id = 1u; + Require(sceAudioOut2MasteringGetState(header, 0, 0) == 0, "states id 1 must be accepted"); + Require(header->states_id == 1u, "states id 1 is kept"); Require(words[4] == 0x01010001u && words[5] == 8u + 8u + 3u * 8u * 4u * 2u, "the compressor states descriptor is filled"); Require(words[56] == 0x01010003u && words[57] == 8u + 8u + 8u * 4u * 3u, "the limiter states descriptor is filled"); std::fill(storage, storage + sizeof(storage), 0xA5); - *header = 2u; - Require(sceAudioOut2MasteringGetState(storage, 2, 1) == 0, "states id 2 must be accepted"); - Require(*header == 2u, "states id 2 is kept"); + header->states_id = 2u; + Require(sceAudioOut2MasteringGetState(header, 2, 1) == 0, "states id 2 must be accepted"); + Require(header->states_id == 2u, "states id 2 is kept"); Require(words[4] == 0x01020001u && words[5] == 8u + 8u + 4u * 8u * 4u * 2u, "the V2 compressor states descriptor is filled"); Require(words[72] == 0x01010003u && words[73] == 8u + 8u + 8u * 4u * 3u, "the V2 limiter states descriptor is filled"); Require(std::all_of(storage + 8, storage + 16, [](std::uint8_t byte) { return byte == 0; }), "the reserved words are zeroed"); Require(std::all_of(storage + 24, storage + 288, [](std::uint8_t byte) { return byte == 0; }), "the V2 compressor states are zeroed"); - *header = 3u; - Require(sceAudioOut2MasteringGetState(storage, 0, 0) == errorMasteringInvalidStatesId, "an unknown states id is refused"); - *header = 0u; - Require(sceAudioOut2MasteringGetState(storage, 0, 0) == errorMasteringInvalidStatesId, "states id 0 is refused"); + header->states_id = 3u; + Require(sceAudioOut2MasteringGetState(header, 0, 0) == errorMasteringInvalidStatesId, "an unknown states id is refused"); + header->states_id = 0u; + Require(sceAudioOut2MasteringGetState(header, 0, 0) == errorMasteringInvalidStatesId, "states id 0 is refused"); } void TestLegacyMasteringInit() { @@ -162,19 +144,19 @@ void TestLegacyMasteringSetParam() { alignas(16) std::uint32_t params[16]; std::fill(params, params + 16, 0xA5A5A5A5u); params[0] = 1u; - Require(sceAudioOutMasteringSetParam(params, 0) == 0, "legacy mastering parameters must be accepted"); - Require(ThrowsException([&] { sceAudioOutMasteringSetParam(params, 1); }), "legacy parameters with SwapEqCompressor must throw"); + Require(sceAudioOutMasteringSetParam(reinterpret_cast(params), 0) == 0, "legacy mastering parameters must be accepted"); + Require(ThrowsException([&] { sceAudioOutMasteringSetParam(reinterpret_cast(params), 1); }), "legacy parameters with SwapEqCompressor must throw"); Require(params[0] == 1u && params[1] == 0xA5A5A5A5u && params[15] == 0xA5A5A5A5u, "legacy mastering parameters are not modified"); - Require(ThrowsException([&] { sceAudioOutMasteringSetParam(params, 2); }), "legacy parameters with flags bit 1 must throw"); - Require(ThrowsException([&] { sceAudioOutMasteringSetParam(params, 0xFFFFFFFFu); }), "legacy parameters with unknown flags must throw"); + Require(ThrowsException([&] { sceAudioOutMasteringSetParam(reinterpret_cast(params), 2); }), "legacy parameters with flags bit 1 must throw"); + Require(ThrowsException([&] { sceAudioOutMasteringSetParam(reinterpret_cast(params), 0xFFFFFFFFu); }), "legacy parameters with unknown flags must throw"); Require(ThrowsException([] { sceAudioOutMasteringSetParam(nullptr, 0); }), "null legacy parameters must throw"); Require(ThrowsException([] { sceAudioOutMasteringSetParam(nullptr, 2); }), "null legacy parameters with unknown flags must throw"); params[0] = 0u; - Require(ThrowsException([&] { sceAudioOutMasteringSetParam(params, 0); }), "legacy params id 0 must throw"); + Require(ThrowsException([&] { sceAudioOutMasteringSetParam(reinterpret_cast(params), 0); }), "legacy params id 0 must throw"); params[0] = 2u; - Require(ThrowsException([&] { sceAudioOutMasteringSetParam(params, 0); }), "legacy params id 2 must throw"); + Require(ThrowsException([&] { sceAudioOutMasteringSetParam(reinterpret_cast(params), 0); }), "legacy params id 2 must throw"); params[0] = 0x01010001u; - Require(ThrowsException([&] { sceAudioOutMasteringSetParam(params, 0); }), "an unknown legacy params id must throw"); + Require(ThrowsException([&] { sceAudioOutMasteringSetParam(reinterpret_cast(params), 0); }), "an unknown legacy params id must throw"); } void TestLegacyMasteringGetState() { @@ -184,7 +166,7 @@ void TestLegacyMasteringGetState() { auto* header = reinterpret_cast(storage); std::fill(storage, storage + size, 0xA5); *header = 1u; - Require(sceAudioOutMasteringGetState(storage) == 0, "legacy states id 1 must be accepted"); + Require(sceAudioOutMasteringGetState(reinterpret_cast(storage)) == 0, "legacy states id 1 must be accepted"); Require(*header == 1u, "legacy states id 1 is kept"); const std::pair meters[] = {{32, 128}, {128, 224}, {240, 272}, {272, 304}, {304, 336}}; for (const auto& meter : meters) { @@ -193,12 +175,12 @@ void TestLegacyMasteringGetState() { Require(std::all_of(storage + 4, storage + 32, [](std::uint8_t byte) { return byte == 0xA5; }), "the bytes before the compressor meters are not modified"); Require(std::all_of(storage + 224, storage + 240, [](std::uint8_t byte) { return byte == 0xA5; }), "the limiter descriptor bytes are not modified"); Require(std::all_of(storage + statesSize, storage + size, [](std::uint8_t byte) { return byte == 0xA5; }), "the bytes after the states are not modified"); - Require(sceAudioOutMasteringGetState(storage) == 0, "legacy states id 1 must be accepted again"); + Require(sceAudioOutMasteringGetState(reinterpret_cast(storage)) == 0, "legacy states id 1 must be accepted again"); for (std::uint32_t id : {0u, 2u, 3u, 0x01010001u, 0xFFFFFFFFu}) { std::fill(storage, storage + size, 0xA5); *header = id; - Require(ThrowsException([&] { sceAudioOutMasteringGetState(storage); }), "an unknown legacy states id must throw"); + Require(ThrowsException([&] { sceAudioOutMasteringGetState(reinterpret_cast(storage)); }), "an unknown legacy states id must throw"); Require(*header == id && std::all_of(storage + 4, storage + size, [](std::uint8_t byte) { return byte == 0xA5; }), "a refused legacy states id leaves the buffer unmodified"); } Require(ThrowsException([] { sceAudioOutMasteringGetState(nullptr); }), "a null legacy state must throw"); diff --git a/core/libs/prx/libSceAudioOut/tests/AudioOut2PortBuffers.cpp b/core/libs/prx/libSceAudioOut/tests/AudioOut2PortBuffers.cpp index b1d5725eca..fff06c8167 100644 --- a/core/libs/prx/libSceAudioOut/tests/AudioOut2PortBuffers.cpp +++ b/core/libs/prx/libSceAudioOut/tests/AudioOut2PortBuffers.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceAudioOut/include/AudioOut2.hpp" #include "SceTypes.hpp" #include @@ -17,18 +18,6 @@ #include #include -extern "C" { -int APS5_VABI sceAudioOut2ContextResetParam(AudioOut2ContextParam*); -int APS5_VABI sceAudioOut2ContextCreate(const AudioOut2ContextParam*, void*, std::size_t, AudioOut2ContextHandle*); -int APS5_VABI sceAudioOut2ContextDestroy(AudioOut2ContextHandle); -int APS5_VABI sceAudioOut2ContextAdvance(AudioOut2ContextHandle); -int APS5_VABI sceAudioOut2ContextGetQueueLevel(AudioOut2ContextHandle, std::uint32_t*, std::uint32_t*); -int APS5_VABI sceAudioOut2ContextPush(AudioOut2ContextHandle, std::uint32_t); -int APS5_VABI sceAudioOut2PortCreate(AudioOut2ContextHandle, const AudioOut2PortParam*, AudioOut2PortHandle*); -int APS5_VABI sceAudioOut2PortDestroy(AudioOut2PortHandle); -int APS5_VABI sceAudioOut2PortSetAttributes(AudioOut2PortHandle, const AudioOut2Attribute*, std::uint32_t); -} - static void Require(bool value) { if (!value) std::abort(); } static void SetEnvironment(const char* name, const std::string& value) { diff --git a/core/libs/prx/libSceAudioOut/tests/AudioOut2PortLayouts.cpp b/core/libs/prx/libSceAudioOut/tests/AudioOut2PortLayouts.cpp index 7fcfa50334..dcdcb0268c 100644 --- a/core/libs/prx/libSceAudioOut/tests/AudioOut2PortLayouts.cpp +++ b/core/libs/prx/libSceAudioOut/tests/AudioOut2PortLayouts.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceAudioOut/include/AudioOut2.hpp" #include "SceTypes.hpp" #include @@ -14,19 +15,6 @@ #include #include -extern "C" { -int APS5_VABI sceAudioOut2UserCreate(std::uint32_t, AudioOut2UserHandle*); -int APS5_VABI sceAudioOut2UserDestroy(AudioOut2UserHandle); -int APS5_VABI sceAudioOut2UserGetSupportedAttributes(AudioOut2UserHandle, std::uint32_t*, std::uint32_t*); -int APS5_VABI sceAudioOut2ContextResetParam(AudioOut2ContextParam*); -int APS5_VABI sceAudioOut2ContextCreate(const AudioOut2ContextParam*, void*, std::size_t, AudioOut2ContextHandle*); -int APS5_VABI sceAudioOut2ContextDestroy(AudioOut2ContextHandle); -int APS5_VABI sceAudioOut2ContextPush(AudioOut2ContextHandle, std::uint32_t); -int APS5_VABI sceAudioOut2PortCreate(AudioOut2ContextHandle, const AudioOut2PortParam*, AudioOut2PortHandle*); -int APS5_VABI sceAudioOut2PortDestroy(AudioOut2PortHandle); -int APS5_VABI sceAudioOut2PortSetAttributes(AudioOut2PortHandle, const AudioOut2Attribute*, std::uint32_t); -} - static void Require(bool value) { if (!value) std::abort(); } static void SetEnvironment(const char* name, const std::string& value) { diff --git a/core/libs/prx/libSceAudioOut/tests/AudioOut2Timing.cpp b/core/libs/prx/libSceAudioOut/tests/AudioOut2Timing.cpp index 36074daece..0dfd811378 100644 --- a/core/libs/prx/libSceAudioOut/tests/AudioOut2Timing.cpp +++ b/core/libs/prx/libSceAudioOut/tests/AudioOut2Timing.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceAudioOut/include/AudioOut2.hpp" #include "SceTypes.hpp" #include @@ -14,29 +15,6 @@ #include #include -extern "C" { -int APS5_VABI sceAudioOut2ContextResetParam(AudioOut2ContextParam*); -int APS5_VABI sceAudioOut2ContextQueryMemory(const AudioOut2ContextParam*, std::size_t*); -int APS5_VABI sceAudioOut2ContextCreate(const AudioOut2ContextParam*, void*, std::size_t, AudioOut2ContextHandle*); -int APS5_VABI sceAudioOut2ContextDestroy(AudioOut2ContextHandle); -int APS5_VABI sceAudioOut2ContextPush(AudioOut2ContextHandle, std::uint32_t); -int APS5_VABI sceAudioOut2ContextGetQueueLevel(AudioOut2ContextHandle, std::uint32_t*, std::uint32_t*); -int APS5_VABI sceAudioOut2PortCreate(AudioOut2ContextHandle, const AudioOut2PortParam*, AudioOut2PortHandle*); -int APS5_VABI sceAudioOut2PortDestroy(AudioOut2PortHandle); -int APS5_VABI sceAudioOut2PortSetAttributes(AudioOut2PortHandle, const AudioOut2Attribute*, std::uint32_t); -int APS5_VABI sceAudioOut2LoContextQueryMemory(const AudioOut2ContextParam*, std::size_t*); -int APS5_VABI sceAudioOut2LoContextCreate(const AudioOut2ContextParam*, void*, std::size_t, AudioOut2ContextHandle*); -int APS5_VABI sceAudioOut2LoContextDestroy(AudioOut2ContextHandle); -int APS5_VABI sceAudioOut2LoContextSetAttributes(AudioOut2ContextHandle, const AudioOut2Attribute*, std::uint32_t); -int APS5_VABI sceAudioOut2LoContextAdvance(AudioOut2ContextHandle); -int APS5_VABI sceAudioOut2LoContextPush(AudioOut2ContextHandle, std::uint32_t); -int APS5_VABI sceAudioOut2LoContextGetQueueLevel(AudioOut2ContextHandle, std::uint32_t*, std::uint32_t*); -int APS5_VABI sceAudioOut2LoPortCreate(AudioOut2ContextHandle, const AudioOut2PortParam*, AudioOut2PortHandle*); -int APS5_VABI sceAudioOut2LoPortDestroy(AudioOut2PortHandle); -int APS5_VABI sceAudioOut2LoPortSetAttributes(AudioOut2PortHandle, const AudioOut2Attribute*, std::uint32_t); -int APS5_VABI sceAudioOut2LoPortGetState(AudioOut2PortHandle, AudioOut2PortState*); -} - static void Require(bool value) { if (!value) std::abort(); } static void SetEnvironment(const char* name, const std::string& value) { diff --git a/core/libs/prx/libSceAudioOut/tests/AudioOutBufferSize.cpp b/core/libs/prx/libSceAudioOut/tests/AudioOutBufferSize.cpp index d51eda399a..6b2eaaef4e 100644 --- a/core/libs/prx/libSceAudioOut/tests/AudioOutBufferSize.cpp +++ b/core/libs/prx/libSceAudioOut/tests/AudioOutBufferSize.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceAudioOut/include/AudioOut.hpp" #include "SDL.h" #include "prx/libSceAudioOut/include/AudioOutSdl.hpp" #include "prx/libc/include/general/VabiMacros.hpp" @@ -8,12 +9,6 @@ #include #include -extern "C" { -int APS5_VABI sceAudioOutOpen(int, int, int, std::uint32_t, std::uint32_t, std::uint32_t); -int APS5_VABI sceAudioOutClose(int); -int APS5_VABI sceAudioOutOutput(int, const void*); -} - namespace { constexpr SDL_AudioDeviceID device = 7; int opened = 0; diff --git a/core/libs/prx/libSceAudioOut/tests/AudioOutEx.cpp b/core/libs/prx/libSceAudioOut/tests/AudioOutEx.cpp index b96f9dd570..0242fe8839 100644 --- a/core/libs/prx/libSceAudioOut/tests/AudioOutEx.cpp +++ b/core/libs/prx/libSceAudioOut/tests/AudioOutEx.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceAudioOut/include/AudioOut.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -5,13 +6,6 @@ #include #include -extern "C" { -int APS5_VABI sceAudioOutExOpen(int userId, std::uint32_t mode); -int APS5_VABI sceAudioOutExConfigureOutput(int control, std::uint64_t flags, std::uint32_t mode, std::uint32_t target, std::uint64_t option); -int APS5_VABI sceAudioOutExClose(int handle); -int APS5_VABI sceAudioOutOutput(int handle, const void* ptr); -} - static constexpr int SYSTEM_USER = 0xFF; static constexpr int ERROR_EX_INVALID_MODE = static_cast(0x80260015u); static constexpr int ERROR_EX_INVALID_CONTROL = static_cast(0x80268009u); diff --git a/core/libs/prx/libSceAudioOut/tests/AudioOutExMonitorInfo.cpp b/core/libs/prx/libSceAudioOut/tests/AudioOutExMonitorInfo.cpp index 6fcced4ffb..6e6194c862 100644 --- a/core/libs/prx/libSceAudioOut/tests/AudioOutExMonitorInfo.cpp +++ b/core/libs/prx/libSceAudioOut/tests/AudioOutExMonitorInfo.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceAudioOut/include/AudioOut.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -6,10 +7,6 @@ #include #include -extern "C" { -int APS5_VABI sceAudioOutExGetMonitorInfo(int, int, void*, std::uint32_t); -} - static void Require(bool value, const char* message) { if (value) return; std::fprintf(stderr, "%s\n", message); diff --git a/core/libs/prx/libSceAudioOut/tests/AudioOutInfo.cpp b/core/libs/prx/libSceAudioOut/tests/AudioOutInfo.cpp index 78d9fe32cb..f246625a21 100644 --- a/core/libs/prx/libSceAudioOut/tests/AudioOutInfo.cpp +++ b/core/libs/prx/libSceAudioOut/tests/AudioOutInfo.cpp @@ -1,14 +1,9 @@ +#include "prx/libSceAudioOut/include/AudioOut.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include -extern "C" { -int APS5_VABI sceAudioOutGetSimulatedHandleStatusInfo(); -int APS5_VABI sceAudioOutGetInfoOpenNum(); -int APS5_VABI sceAudioOutGetInfo(); -} - static void Require(bool value, const char* message) { if (value) return; std::fprintf(stderr, "%s\n", message); diff --git a/core/libs/prx/libSceAudioOut/tests/AudioOutLastOutputTime.cpp b/core/libs/prx/libSceAudioOut/tests/AudioOutLastOutputTime.cpp index e6cdeed0d7..487624514e 100644 --- a/core/libs/prx/libSceAudioOut/tests/AudioOutLastOutputTime.cpp +++ b/core/libs/prx/libSceAudioOut/tests/AudioOutLastOutputTime.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/Time/include/Time.hpp" +#include "prx/libSceAudioOut/include/AudioOut.hpp" #include "SceTypes.hpp" #include "prx/libc/include/general/VabiMacros.hpp" @@ -9,16 +11,6 @@ #include #include -extern "C" { -int APS5_VABI sceAudioOutOpen(int, int, int, std::uint32_t, std::uint32_t, std::uint32_t); -int APS5_VABI sceAudioOutClose(int); -int APS5_VABI sceAudioOutOutput(int, const void*); -int APS5_VABI sceAudioOutOutputs(AudioOutOutputParam*, std::uint32_t); -int APS5_VABI sceAudioOutGetPortState(int, AudioOutPortState*); -int APS5_VABI sceAudioOutGetLastOutputTime(int, std::uint64_t*); -std::uint64_t APS5_VABI sceKernelGetProcessTime(); -} - static void Require(bool value, const char* message) { if (value) return; std::fprintf(stderr, "%s\n", message); @@ -231,6 +223,7 @@ int main() { setenv("SDL_AUDIODRIVER", "dummy", 1); #endif sceKernelGetProcessTime(); + TestOutput(portTypeMain); TestOutput(portTypeVibration); TestPortsAreIndependent(); diff --git a/core/libs/prx/libSceAudioOut/tests/AudioOutMixLevelPadSpk.cpp b/core/libs/prx/libSceAudioOut/tests/AudioOutMixLevelPadSpk.cpp index ca25acb711..ae686bee18 100644 --- a/core/libs/prx/libSceAudioOut/tests/AudioOutMixLevelPadSpk.cpp +++ b/core/libs/prx/libSceAudioOut/tests/AudioOutMixLevelPadSpk.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceAudioOut/include/AudioOut.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -11,14 +12,6 @@ #include #include -extern "C" { -int APS5_VABI sceAudioOutOpen(int, int, int, std::uint32_t, std::uint32_t, std::uint32_t); -int APS5_VABI sceAudioOutClose(int); -int APS5_VABI sceAudioOutOutput(int, const void*); -int APS5_VABI sceAudioOutSetVolume(int, std::uint32_t, int*); -int APS5_VABI sceAudioOutSetMixLevelPadSpk(int, std::uint32_t); -} - static void Require(bool value) { if (!value) std::abort(); } static void SetEnvironment(const char* name, const std::string& value) { diff --git a/core/libs/prx/libSceAudioOut/tests/AudioOutPortLocks.cpp b/core/libs/prx/libSceAudioOut/tests/AudioOutPortLocks.cpp index 107a2ef2f5..15703d8ba8 100644 --- a/core/libs/prx/libSceAudioOut/tests/AudioOutPortLocks.cpp +++ b/core/libs/prx/libSceAudioOut/tests/AudioOutPortLocks.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceAudioOut/include/AudioOut.hpp" #include "SDL.h" #include "prx/libc/include/general/VabiMacros.hpp" @@ -12,12 +13,6 @@ #include #include -extern "C" { -int APS5_VABI sceAudioOutOpen(int, int, int, std::uint32_t, std::uint32_t, std::uint32_t); -int APS5_VABI sceAudioOutOutput(int, const void*); -int APS5_VABI sceAudioOutClose(int); -} - namespace { constexpr std::uint32_t Grain = 256; diff --git a/core/libs/prx/libSceAudioOut/tests/AudioOutResampling.cpp b/core/libs/prx/libSceAudioOut/tests/AudioOutResampling.cpp index c56be14970..6b9577e91d 100644 --- a/core/libs/prx/libSceAudioOut/tests/AudioOutResampling.cpp +++ b/core/libs/prx/libSceAudioOut/tests/AudioOutResampling.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceAudioOut/include/AudioOut.hpp" #include "SDL.h" #include "prx/libc/include/general/VabiMacros.hpp" @@ -7,12 +8,6 @@ #include #include -extern "C" { -int APS5_VABI sceAudioOutOpen(int, int, int, std::uint32_t, std::uint32_t, std::uint32_t); -int APS5_VABI sceAudioOutOutput(int, const void*); -int APS5_VABI sceAudioOutClose(int); -} - namespace { constexpr std::uint32_t grain = 256; diff --git a/core/libs/prx/libSceAudioOut/tests/AudioOutShutdown.cpp b/core/libs/prx/libSceAudioOut/tests/AudioOutShutdown.cpp index dd5390753d..fcadcec548 100644 --- a/core/libs/prx/libSceAudioOut/tests/AudioOutShutdown.cpp +++ b/core/libs/prx/libSceAudioOut/tests/AudioOutShutdown.cpp @@ -1,3 +1,5 @@ +#include "prx/libSceAudioOut/include/AudioOut2.hpp" +#include "prx/libSceAudioOut/include/AudioOut.hpp" #include "SceTypes.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libc/include/Shutdown.hpp" @@ -11,17 +13,6 @@ #include #include -extern "C" { -int APS5_VABI sceAudioOut2ContextResetParam(AudioOut2ContextParam*); -int APS5_VABI sceAudioOut2ContextCreate(const AudioOut2ContextParam*, void*, std::size_t, AudioOut2ContextHandle*); -int APS5_VABI sceAudioOut2ContextAdvance(AudioOut2ContextHandle); -int APS5_VABI sceAudioOut2ContextPush(AudioOut2ContextHandle, std::uint32_t); -int APS5_VABI sceAudioOut2PortCreate(AudioOut2ContextHandle, const AudioOut2PortParam*, AudioOut2PortHandle*); -int APS5_VABI sceAudioOut2PortSetAttributes(AudioOut2PortHandle, const AudioOut2Attribute*, std::uint32_t); -int APS5_VABI sceAudioOutOpen(int, int, int, std::uint32_t, std::uint32_t, std::uint32_t); -int APS5_VABI sceAudioOutOutput(int, const void*); -} - namespace { constexpr std::uint32_t grain = 256; diff --git a/core/libs/prx/libSceAudioOut/tests/AudioOutSys.cpp b/core/libs/prx/libSceAudioOut/tests/AudioOutSys.cpp index eb5878fc18..73ea859c0b 100644 --- a/core/libs/prx/libSceAudioOut/tests/AudioOutSys.cpp +++ b/core/libs/prx/libSceAudioOut/tests/AudioOutSys.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceAudioOut/include/AudioOut.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -5,14 +6,6 @@ #include #include -extern "C" { -int APS5_VABI sceAudioOutSysOpen(int userId, std::uint32_t mode); -int APS5_VABI sceAudioOutSysConfigureOutput(int type, std::uint64_t flags, std::uint32_t mode, std::uint32_t target, std::uint64_t option); -int APS5_VABI sceAudioOutSysClose(int handle); -int APS5_VABI sceAudioOutExOpen(int userId, std::uint32_t mode); -int APS5_VABI sceAudioOutOutput(int handle, const void* ptr); -} - static constexpr int SYSTEM_USER = 0xFF; static bool failed = false; diff --git a/core/libs/prx/libSceAudioOut/tests/AudioOutSysHdmiMonitorInfo.cpp b/core/libs/prx/libSceAudioOut/tests/AudioOutSysHdmiMonitorInfo.cpp index 7eb1547ce7..1ea013ca7d 100644 --- a/core/libs/prx/libSceAudioOut/tests/AudioOutSysHdmiMonitorInfo.cpp +++ b/core/libs/prx/libSceAudioOut/tests/AudioOutSysHdmiMonitorInfo.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceAudioOut/include/AudioOut.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -8,10 +9,6 @@ #include #include -extern "C" { -int APS5_VABI sceAudioOutSysGetHdmiMonitorInfo(int, void*, std::uint32_t); -} - static void Require(bool value, const char* message) { if (value) return; std::fprintf(stderr, "%s\n", message); diff --git a/core/libs/prx/libSceAudioOut/tests/AudioOutSystemState.cpp b/core/libs/prx/libSceAudioOut/tests/AudioOutSystemState.cpp index 614a2ba2eb..c925334fbd 100644 --- a/core/libs/prx/libSceAudioOut/tests/AudioOutSystemState.cpp +++ b/core/libs/prx/libSceAudioOut/tests/AudioOutSystemState.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceAudioOut/include/AudioOut.hpp" #include "SceTypes.hpp" #include "prx/libc/include/general/VabiMacros.hpp" @@ -5,10 +6,6 @@ #include #include -extern "C" { -int APS5_VABI sceAudioOutGetSystemState(AudioOutSystemState*); -} - static void Require(bool value, const char* message) { if (value) return; std::fprintf(stderr, "%s\n", message); diff --git a/core/libs/prx/libSceAudioOut/tests/AudioOutVibration.cpp b/core/libs/prx/libSceAudioOut/tests/AudioOutVibration.cpp index 4f27e0bf7d..6c01a3a317 100644 --- a/core/libs/prx/libSceAudioOut/tests/AudioOutVibration.cpp +++ b/core/libs/prx/libSceAudioOut/tests/AudioOutVibration.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceAudioOut/include/AudioOut.hpp" #include "prx/libScePad/include/PadState.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -7,15 +8,6 @@ #include #include -extern "C" { -int APS5_VABI sceAudioOutOpen(int, int, int, std::uint32_t, std::uint32_t, std::uint32_t); -int APS5_VABI sceAudioOutExOpen(int, std::uint32_t); -int APS5_VABI sceAudioOutClose(int); -int APS5_VABI sceAudioOutOutput(int, const void*); -int APS5_VABI sceAudioOutOutputs(AudioOutOutputParam*, std::uint32_t); -int APS5_VABI sceAudioOutSetVolume(int, std::uint32_t, int*); -} - static void Require(bool value, const char* message) { if (!value) throw std::runtime_error(message); } diff --git a/core/libs/prx/libSceAudioOut/tests/AudioOutVibrationDevice.cpp b/core/libs/prx/libSceAudioOut/tests/AudioOutVibrationDevice.cpp index 6d0a7ca4f1..79681dff96 100644 --- a/core/libs/prx/libSceAudioOut/tests/AudioOutVibrationDevice.cpp +++ b/core/libs/prx/libSceAudioOut/tests/AudioOutVibrationDevice.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceAudioOut/include/AudioOut.hpp" #include "SDL.h" #include "prx/libSceAudioOut/include/AudioOutSdl.hpp" #include "prx/libScePad/include/PadState.hpp" @@ -13,15 +14,6 @@ #include #include -extern "C" { -int APS5_VABI sceAudioOutOpen(int, int, int, std::uint32_t, std::uint32_t, std::uint32_t); -int APS5_VABI sceAudioOutClose(int); -int APS5_VABI sceAudioOutOutput(int, const void*); -int APS5_VABI sceAudioOutOutputs(AudioOutOutputParam*, std::uint32_t); -int APS5_VABI sceAudioOutSetVolume(int, std::uint32_t, int*); -int APS5_VABI sceAudioOutGetLastOutputTime(int, std::uint64_t*); -} - namespace { constexpr std::uint32_t frames = 256; bool available = true; diff --git a/core/libs/prx/libSceAudioPropagation/Export.cpp b/core/libs/prx/libSceAudioPropagation/Export.cpp index 3d6eb191e0..2c257811bf 100644 --- a/core/libs/prx/libSceAudioPropagation/Export.cpp +++ b/core/libs/prx/libSceAudioPropagation/Export.cpp @@ -1,3 +1,5 @@ +#include "prx/libSceAudioPropagation/include/Api.hpp" +#include "prx/libSceAudioPropagation/AudioPropagation.hpp" #include "AudioPropagation.hpp" #include "prx/libc/include/General.hpp" diff --git a/core/libs/prx/libSceAudioPropagation/include/Api.hpp b/core/libs/prx/libSceAudioPropagation/include/Api.hpp new file mode 100644 index 0000000000..131fe6b5cc --- /dev/null +++ b/core/libs/prx/libSceAudioPropagation/include/Api.hpp @@ -0,0 +1,18 @@ +#pragma once + +#include "prx/libSceAudioPropagation/AudioPropagation.hpp" +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceAudioPropagationReportApi(std::uint32_t category, AudioPropagationHandle handle, std::int32_t result, std::int32_t operation, const char* function, const char* format, ...); +int APS5_VABI sceAudioPropagationResetAttributes(AudioPropagation::Attribute* attributes, std::uint32_t count); +int APS5_VABI sceAudioPropagationSourceQueryInfo(AudioPropagationHandle source, AudioPropagation::SourceInfo* info); +int APS5_VABI sceAudioPropagationSystemLock(AudioPropagationHandle system); +int APS5_VABI sceAudioPropagationSystemQueryInfo(AudioPropagationHandle system, AudioPropagation::SystemInfo* info, std::size_t size); +int APS5_VABI sceAudioPropagationReportRegisterHandler(std::uint32_t category, AudioPropagation::ReportHandler handler, void* userData, AudioPropagation::ReportRegistration** registration); +int APS5_VABI sceAudioPropagationReportUnregisterHandler(AudioPropagation::ReportRegistration* registration); +int APS5_VABI sceAudioPropagationSystemEnumHandles(AudioPropagationHandle* handles, std::uint32_t capacity); +int APS5_VABI sceAudioPropagationSystemUnlock(AudioPropagationHandle system); + +} diff --git a/core/libs/prx/libSceAudioPropagation/libSceAudioPropagation.hpp b/core/libs/prx/libSceAudioPropagation/libSceAudioPropagation.hpp new file mode 100644 index 0000000000..6431f41cde --- /dev/null +++ b/core/libs/prx/libSceAudioPropagation/libSceAudioPropagation.hpp @@ -0,0 +1,4 @@ +#pragma once + +#include "prx/libSceAudioPropagation/AudioPropagation.hpp" +#include "prx/libSceAudioPropagation/include/Api.hpp" diff --git a/core/libs/prx/libSceAudioSystem/Export.cpp b/core/libs/prx/libSceAudioSystem/Export.cpp index d5c4291d01..de11eb33dd 100644 --- a/core/libs/prx/libSceAudioSystem/Export.cpp +++ b/core/libs/prx/libSceAudioSystem/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceAudioSystem/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceAudioSystem/include/Api.hpp b/core/libs/prx/libSceAudioSystem/include/Api.hpp new file mode 100644 index 0000000000..c15ab7a627 --- /dev/null +++ b/core/libs/prx/libSceAudioSystem/include/Api.hpp @@ -0,0 +1,10 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceAudioSystemSystemResume(); +int APS5_VABI sceAudioSystemSystemSuspend(); + +} diff --git a/core/libs/prx/libSceAudioSystem/libSceAudioSystem.hpp b/core/libs/prx/libSceAudioSystem/libSceAudioSystem.hpp new file mode 100644 index 0000000000..092b35b31a --- /dev/null +++ b/core/libs/prx/libSceAudioSystem/libSceAudioSystem.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceAudioSystem/include/Api.hpp" diff --git a/core/libs/prx/libSceAudiodReport/libSceAudiodReport.hpp b/core/libs/prx/libSceAudiodReport/libSceAudiodReport.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceAudiodReport/libSceAudiodReport.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceAudiodec.native/Export.cpp b/core/libs/prx/libSceAudiodec.native/Export.cpp index 4f00015020..96acf5c292 100644 --- a/core/libs/prx/libSceAudiodec.native/Export.cpp +++ b/core/libs/prx/libSceAudiodec.native/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceAudiodec.native/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceAudiodec.native/include/Api.hpp b/core/libs/prx/libSceAudiodec.native/include/Api.hpp new file mode 100644 index 0000000000..f5050e0019 --- /dev/null +++ b/core/libs/prx/libSceAudiodec.native/include/Api.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceAudiodecClearContextEx(void); +int APS5_VABI sceAudiodecCreateDecoderEx(void); +int APS5_VABI sceAudiodecDecode2(void); +int APS5_VABI sceAudiodecDecode2Ex(void); +int APS5_VABI sceAudiodecDecode2WithPriority(void); +int APS5_VABI sceAudiodecDecode2WithPriorityEx(void); +int APS5_VABI sceAudiodecDecodeEx(void); +int APS5_VABI sceAudiodecDecodeWithPriority(void); +int APS5_VABI sceAudiodecDecodeWithPriorityEx(void); +int APS5_VABI sceAudiodecDeleteDecoderEx(void); +int APS5_VABI sceAudiodecGetContext(void); +int APS5_VABI sceAudiodecInitialize(void); +int APS5_VABI sceAudiodecRegisterCodec(void); +int APS5_VABI sceAudiodecTerminate(void); + +} diff --git a/core/libs/prx/libSceAudiodec.native/libSceAudiodec.native.hpp b/core/libs/prx/libSceAudiodec.native/libSceAudiodec.native.hpp new file mode 100644 index 0000000000..2f7cfa515f --- /dev/null +++ b/core/libs/prx/libSceAudiodec.native/libSceAudiodec.native.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceAudiodec.native/include/Api.hpp" diff --git a/core/libs/prx/libSceAudiodec/Export.cpp b/core/libs/prx/libSceAudiodec/Export.cpp index 5e2b911800..4840fde2d0 100644 --- a/core/libs/prx/libSceAudiodec/Export.cpp +++ b/core/libs/prx/libSceAudiodec/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceAudiodec/include/Api.hpp" #include #include #include diff --git a/core/libs/prx/libSceAudiodec/include/Api.hpp b/core/libs/prx/libSceAudiodec/include/Api.hpp new file mode 100644 index 0000000000..e02050acef --- /dev/null +++ b/core/libs/prx/libSceAudiodec/include/Api.hpp @@ -0,0 +1,14 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int32_t APS5_VABI sceAudiodecInitLibrary(uint32_t codecType); +int32_t APS5_VABI sceAudiodecTermLibrary(uint32_t codecType); +int32_t APS5_VABI sceAudiodecCreateDecoder(AudiodecCtrl* ctrl, uint32_t codecType); +int32_t APS5_VABI sceAudiodecDeleteDecoder(int32_t handle); +int32_t APS5_VABI sceAudiodecClearContext(int32_t handle); +int32_t APS5_VABI sceAudiodecDecode(int32_t handle, AudiodecCtrl* ctrl); + +} diff --git a/core/libs/prx/libSceAudiodec/libSceAudiodec.hpp b/core/libs/prx/libSceAudiodec/libSceAudiodec.hpp new file mode 100644 index 0000000000..b8ec4f574f --- /dev/null +++ b/core/libs/prx/libSceAudiodec/libSceAudiodec.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceAudiodec/include/Api.hpp" diff --git a/core/libs/prx/libSceAudiodecCpu/Export.cpp b/core/libs/prx/libSceAudiodecCpu/Export.cpp index c0c2f83744..e4ac1ea15b 100644 --- a/core/libs/prx/libSceAudiodecCpu/Export.cpp +++ b/core/libs/prx/libSceAudiodecCpu/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceAudiodecCpu/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceAudiodecCpu/include/Api.hpp b/core/libs/prx/libSceAudiodecCpu/include/Api.hpp new file mode 100644 index 0000000000..336933274e --- /dev/null +++ b/core/libs/prx/libSceAudiodecCpu/include/Api.hpp @@ -0,0 +1,16 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceAudiodecCpuClearContext(void); +int APS5_VABI sceAudiodecCpuDecode(void); +int APS5_VABI sceAudiodecCpuInitDecoder(void); +int APS5_VABI sceAudiodecCpuInternalClearContext(void); +int APS5_VABI sceAudiodecCpuInternalDecode(void); +int APS5_VABI sceAudiodecCpuInternalInitDecoder(void); +int APS5_VABI sceAudiodecCpuInternalQueryMemSize(void); +int APS5_VABI sceAudiodecCpuQueryMemSize(void); + +} diff --git a/core/libs/prx/libSceAudiodecCpu/libSceAudiodecCpu.hpp b/core/libs/prx/libSceAudiodecCpu/libSceAudiodecCpu.hpp new file mode 100644 index 0000000000..e896a52007 --- /dev/null +++ b/core/libs/prx/libSceAudiodecCpu/libSceAudiodecCpu.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceAudiodecCpu/include/Api.hpp" diff --git a/core/libs/prx/libSceAudiodecCpuAlac/libSceAudiodecCpuAlac.hpp b/core/libs/prx/libSceAudiodecCpuAlac/libSceAudiodecCpuAlac.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceAudiodecCpuAlac/libSceAudiodecCpuAlac.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceAudiodecCpuDdp/libSceAudiodecCpuDdp.hpp b/core/libs/prx/libSceAudiodecCpuDdp/libSceAudiodecCpuDdp.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceAudiodecCpuDdp/libSceAudiodecCpuDdp.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceAudiodecCpuDts/libSceAudiodecCpuDts.hpp b/core/libs/prx/libSceAudiodecCpuDts/libSceAudiodecCpuDts.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceAudiodecCpuDts/libSceAudiodecCpuDts.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceAudiodecCpuDtsHdLbr/libSceAudiodecCpuDtsHdLbr.hpp b/core/libs/prx/libSceAudiodecCpuDtsHdLbr/libSceAudiodecCpuDtsHdLbr.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceAudiodecCpuDtsHdLbr/libSceAudiodecCpuDtsHdLbr.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceAudiodecCpuDtsHdMa/libSceAudiodecCpuDtsHdMa.hpp b/core/libs/prx/libSceAudiodecCpuDtsHdMa/libSceAudiodecCpuDtsHdMa.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceAudiodecCpuDtsHdMa/libSceAudiodecCpuDtsHdMa.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceAudiodecCpuFlac/libSceAudiodecCpuFlac.hpp b/core/libs/prx/libSceAudiodecCpuFlac/libSceAudiodecCpuFlac.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceAudiodecCpuFlac/libSceAudiodecCpuFlac.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceAudiodecCpuLpcm/libSceAudiodecCpuLpcm.hpp b/core/libs/prx/libSceAudiodecCpuLpcm/libSceAudiodecCpuLpcm.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceAudiodecCpuLpcm/libSceAudiodecCpuLpcm.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceAudiodecCpuM4aac/libSceAudiodecCpuM4aac.hpp b/core/libs/prx/libSceAudiodecCpuM4aac/libSceAudiodecCpuM4aac.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceAudiodecCpuM4aac/libSceAudiodecCpuM4aac.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceAudiodecCpuTrhd/libSceAudiodecCpuTrhd.hpp b/core/libs/prx/libSceAudiodecCpuTrhd/libSceAudiodecCpuTrhd.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceAudiodecCpuTrhd/libSceAudiodecCpuTrhd.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceAutoMounterClient/Export.cpp b/core/libs/prx/libSceAutoMounterClient/Export.cpp index 77af95c0ff..ab7eed9165 100644 --- a/core/libs/prx/libSceAutoMounterClient/Export.cpp +++ b/core/libs/prx/libSceAutoMounterClient/Export.cpp @@ -1,20 +1,9 @@ +#include "prx/libSceAutoMounterClient/include/Api.hpp" #include #include #include "SceTypes.hpp" #include "prx/libc/include/General.hpp" -struct AutoMounterUsbDeviceInfo { - char deviceName[128]; - std::byte metadata[22]; - std::byte data0[256]; - std::byte padding[2]; - std::uint64_t data0Size; - std::byte data1[256]; - std::uint64_t data1Size; - std::byte data2[256]; - std::uint64_t data2Size; -}; - static_assert(sizeof(AutoMounterUsbDeviceInfo) == 944); static_assert(offsetof(AutoMounterUsbDeviceInfo, data0) == 150); static_assert(offsetof(AutoMounterUsbDeviceInfo, data0Size) == 408); diff --git a/core/libs/prx/libSceAutoMounterClient/include/Api.hpp b/core/libs/prx/libSceAutoMounterClient/include/Api.hpp new file mode 100644 index 0000000000..766f754f18 --- /dev/null +++ b/core/libs/prx/libSceAutoMounterClient/include/Api.hpp @@ -0,0 +1,26 @@ +#pragma once + +#include "SceTypes.hpp" + +struct AutoMounterUsbDeviceInfo { + char deviceName[128]; + std::byte metadata[22]; + std::byte data0[256]; + std::byte padding[2]; + std::uint64_t data0Size; + std::byte data1[256]; + std::uint64_t data1Size; + std::byte data2[256]; + std::uint64_t data2Size; +}; + +extern "C" { + +int APS5_VABI sceAutoMounterClientGetUsbDeviceInfo(const char* deviceName, AutoMounterUsbDeviceInfo* info); +int APS5_VABI sceAutoMounterClientGetUsbDeviceList(char (*deviceNames)[64], std::int32_t* count); +int APS5_VABI sceAutoMounterClientInit(PthreadAttr* threadAttr); +int APS5_VABI sceAutoMounterClientRegisterCallback(); +int APS5_VABI sceAutoMounterClientTerm(); +int APS5_VABI sceAutoMounterClientUnregisterCallback(); + +} diff --git a/core/libs/prx/libSceAutoMounterClient/libSceAutoMounterClient.hpp b/core/libs/prx/libSceAutoMounterClient/libSceAutoMounterClient.hpp new file mode 100644 index 0000000000..dd1e89097a --- /dev/null +++ b/core/libs/prx/libSceAutoMounterClient/libSceAutoMounterClient.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceAutoMounterClient/include/Api.hpp" diff --git a/core/libs/prx/libSceAvPlayer.native/Export.cpp b/core/libs/prx/libSceAvPlayer.native/Export.cpp index 2584dda091..3834e0cfb5 100644 --- a/core/libs/prx/libSceAvPlayer.native/Export.cpp +++ b/core/libs/prx/libSceAvPlayer.native/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceAvPlayer.native/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceAvPlayer.native/include/Api.hpp b/core/libs/prx/libSceAvPlayer.native/include/Api.hpp new file mode 100644 index 0000000000..bb1e1f40dc --- /dev/null +++ b/core/libs/prx/libSceAvPlayer.native/include/Api.hpp @@ -0,0 +1,10 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceAvPlayerPrintf(void); +int APS5_VABI sceAvPlayerVprintf(void); + +} diff --git a/core/libs/prx/libSceAvPlayer.native/libSceAvPlayer.native.hpp b/core/libs/prx/libSceAvPlayer.native/libSceAvPlayer.native.hpp new file mode 100644 index 0000000000..589a07f273 --- /dev/null +++ b/core/libs/prx/libSceAvPlayer.native/libSceAvPlayer.native.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceAvPlayer.native/include/Api.hpp" diff --git a/core/libs/prx/libSceAvPlayer/Export.cpp b/core/libs/prx/libSceAvPlayer/Export.cpp index 8eba9a183b..a580ff2899 100644 --- a/core/libs/prx/libSceAvPlayer/Export.cpp +++ b/core/libs/prx/libSceAvPlayer/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceAvPlayer/include/Api.hpp" // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later diff --git a/core/libs/prx/libSceAvPlayer/include/Api.hpp b/core/libs/prx/libSceAvPlayer/include/Api.hpp new file mode 100644 index 0000000000..ac8eb6cf31 --- /dev/null +++ b/core/libs/prx/libSceAvPlayer/include/Api.hpp @@ -0,0 +1,47 @@ +#pragma once + +#include "prx/libSceAvPlayer/include/AvPlayer.hpp" +#include "SceTypes.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern "C" { + +int APS5_VABI sceAvPlayerAddSource(AvPlayerInternal* h, const char* filename); +int APS5_VABI sceAvPlayerAddSourceEx(AvPlayerInternal* h, uint32_t uriType, const AvPlayerSourceDetails* sourceDetails); +int APS5_VABI sceAvPlayerChangeStream(AvPlayerInternal* h, uint32_t oldStreamId, uint32_t newStreamId); +int APS5_VABI sceAvPlayerClose(AvPlayerInternal* h); +uint64_t APS5_VABI sceAvPlayerCurrentTime(AvPlayerInternal* h); +int APS5_VABI sceAvPlayerDisableStream(AvPlayerInternal* h, uint32_t streamId); +int APS5_VABI sceAvPlayerEnableStream(AvPlayerInternal* h, uint32_t streamId); +Bool APS5_VABI sceAvPlayerGetAudioData(AvPlayerInternal* h, AvPlayerFrameInfo* audioInfo); +int APS5_VABI sceAvPlayerGetStreamInfo(AvPlayerInternal* h, uint32_t streamId, AvPlayerStreamInfo* info); +int APS5_VABI sceAvPlayerGetStreamInfoEx(AvPlayerInternal* h, uint32_t streamId, AvPlayerStreamInfoEx* info); +Bool APS5_VABI sceAvPlayerGetVideoData(AvPlayerInternal* h, AvPlayerFrameInfo* videoInfo); +Bool APS5_VABI sceAvPlayerGetVideoDataEx(AvPlayerInternal* h, AvPlayerFrameInfoEx* videoInfo); +AvPlayerInternal* APS5_VABI sceAvPlayerInit(AvPlayerInitData* init); +int APS5_VABI sceAvPlayerInitEx(const AvPlayerInitDataEx* initEx, AvPlayerInternal** handle); +Bool APS5_VABI sceAvPlayerIsActive(AvPlayerInternal* h); +int APS5_VABI sceAvPlayerJumpToTime(AvPlayerInternal* h, uint64_t timeMs); +int APS5_VABI sceAvPlayerPause(AvPlayerInternal* h); +int APS5_VABI sceAvPlayerPostInit(AvPlayerInternal* h, const AvPlayerPostInitData* postInit); +int APS5_VABI sceAvPlayerResume(AvPlayerInternal* h); +int APS5_VABI sceAvPlayerSetAvSyncMode(AvPlayerInternal* h, uint32_t syncMode); +int APS5_VABI sceAvPlayerSetAvailableBandwidth(AvPlayerInternal* h, uint32_t startBandwidth, uint32_t minimumBandwidth, uint32_t maximumBandwidth); +int APS5_VABI sceAvPlayerSetLogCallback(void* callback, void* userData); +int APS5_VABI sceAvPlayerSetLooping(AvPlayerInternal* h, Bool loop); +int APS5_VABI sceAvPlayerSetTrickSpeed(AvPlayerInternal* h, int32_t trickSpeed); +int APS5_VABI sceAvPlayerStart(AvPlayerInternal* h); +int APS5_VABI sceAvPlayerStartEx(AvPlayerInternal* handle, const AvPlayer::StartInfo* startInfo); +int APS5_VABI sceAvPlayerStop(AvPlayerInternal* h); +int APS5_VABI sceAvPlayerStreamCount(AvPlayerInternal* h); + +} diff --git a/core/libs/prx/libSceAvPlayer/libSceAvPlayer.hpp b/core/libs/prx/libSceAvPlayer/libSceAvPlayer.hpp new file mode 100644 index 0000000000..9a78810578 --- /dev/null +++ b/core/libs/prx/libSceAvPlayer/libSceAvPlayer.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceAvPlayer/include/Api.hpp" diff --git a/core/libs/prx/libSceAvPlayerStreaming/Export.cpp b/core/libs/prx/libSceAvPlayerStreaming/Export.cpp index b484bc1af2..ba81d51df8 100644 --- a/core/libs/prx/libSceAvPlayerStreaming/Export.cpp +++ b/core/libs/prx/libSceAvPlayerStreaming/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceAvPlayerStreaming/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceAvPlayerStreaming/include/Api.hpp b/core/libs/prx/libSceAvPlayerStreaming/include/Api.hpp new file mode 100644 index 0000000000..0fcaf246ad --- /dev/null +++ b/core/libs/prx/libSceAvPlayerStreaming/include/Api.hpp @@ -0,0 +1,41 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI MvpHttpAbort_nid_postfix(void); +int APS5_VABI MvpHttpDeInit_nid_postfix(void); +int APS5_VABI MvpHttpGet_nid_postfix(void); +int APS5_VABI MvpHttpGetLastError_nid_postfix(void); +int APS5_VABI MvpHttpHead_nid_postfix(void); +int APS5_VABI MvpHttpHeadCleanup_nid_postfix(void); +int APS5_VABI MvpHttpInit_nid_postfix(void); +int APS5_VABI MvpHttpPost_nid_postfix(void); +int APS5_VABI MvpHttpSetCert_nid_postfix(void); +int APS5_VABI MvpHttpSetRecvTimeout_nid_postfix(void); +int APS5_VABI MvpHttpSetRedirectCb_nid_postfix(void); +int APS5_VABI sceTsCloseFile(void); +int APS5_VABI sceTsDisableRepresentation(void); +int APS5_VABI sceTsEnableRepresentation(void); +int APS5_VABI sceTsEnableStream(void); +int APS5_VABI sceTsGetAvailableBW(void); +int APS5_VABI sceTsGetLiveStatus(void); +int APS5_VABI sceTsGetNextAuInfo(void); +int APS5_VABI sceTsGetNextUnitData(void); +int APS5_VABI sceTsGetRepresentationCount(void); +int APS5_VABI sceTsGetRepresentationInfo(void); +int APS5_VABI sceTsGetSeekWindow(void); +int APS5_VABI sceTsGetStreamInfo(void); +int APS5_VABI sceTsGetUrlEncryptionType(void); +int APS5_VABI sceTsJumpPTS(void); +int APS5_VABI sceTsOpenFile(void); +int APS5_VABI sceTsOpenFileEx(void); +int APS5_VABI sceTsReleaseBuffer(void); +int APS5_VABI sceTsRepresentationIsEnabled(void); +int APS5_VABI sceTsSetAvailableBW(void); +int APS5_VABI sceTsSetStartingBW(void); +int APS5_VABI sceTsStartFileStreaming(void); +int APS5_VABI sceTsStopFileStreaming(void); + +} diff --git a/core/libs/prx/libSceAvPlayerStreaming/libSceAvPlayerStreaming.hpp b/core/libs/prx/libSceAvPlayerStreaming/libSceAvPlayerStreaming.hpp new file mode 100644 index 0000000000..b6ecf8bfa3 --- /dev/null +++ b/core/libs/prx/libSceAvPlayerStreaming/libSceAvPlayerStreaming.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceAvPlayerStreaming/include/Api.hpp" diff --git a/core/libs/prx/libSceAvSetting/Export.cpp b/core/libs/prx/libSceAvSetting/Export.cpp index e53788bea3..1861a92646 100644 --- a/core/libs/prx/libSceAvSetting/Export.cpp +++ b/core/libs/prx/libSceAvSetting/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceAvSetting/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceAvSetting/include/Api.hpp b/core/libs/prx/libSceAvSetting/include/Api.hpp new file mode 100644 index 0000000000..6ce470cc12 --- /dev/null +++ b/core/libs/prx/libSceAvSetting/include/Api.hpp @@ -0,0 +1,32 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceAvControlGetPuTypeByMonitorInfo(void); +int APS5_VABI sceAvControlIsVideoOutModeSupportedByMonitorInfoWithOptions(void); +int APS5_VABI sceAvControlSetDitherModeForDiag(void); +int APS5_VABI sceAvControlSetLayoutModeForDiag(void); +int APS5_VABI sceAvControlSetMonitorFakeMode(void); +int APS5_VABI sceAvControlGetCurrentOutputSysMode(void); +int APS5_VABI sceAvControlGetNativeHdmiMonitorInfo(void); +int APS5_VABI sceAvControlGetRawMonitorInfo(void); +int APS5_VABI sceAvControlGetKsvList(void); +int APS5_VABI sceAvControlGetRawEdid(void); +int APS5_VABI sceAvControlRemoveProcessOutputMode(void); +int APS5_VABI sceAvControlUpdateDriverStatus(void); +int APS5_VABI sceAvControlNotifyUmdEvent(void); +int APS5_VABI sceAvControlAddCallbacksForLnc(void); +int APS5_VABI sceAvControlAddCallbacksForResourceArbitrator(void); +int APS5_VABI sceAvControlRemoveCallbacks(void); +int APS5_VABI sceAvControlCheckCallback(void); +int APS5_VABI sceAvControlWaitCallback(void); +int APS5_VABI sceAvControlSetColorMode(void); +int APS5_VABI sceAvControlCheckMonitorInfoCapability(void); +int APS5_VABI sceAvControlCheckVideoOutMode(void); +int APS5_VABI sceAvControlSetCheckoutputMode(void); +int APS5_VABI sceAvControlSetSystemVideoMode(void); +int APS5_VABI sceAvControlDebugAddCallbacks(void); + +} diff --git a/core/libs/prx/libSceAvSetting/libSceAvSetting.hpp b/core/libs/prx/libSceAvSetting/libSceAvSetting.hpp new file mode 100644 index 0000000000..76b2b29473 --- /dev/null +++ b/core/libs/prx/libSceAvSetting/libSceAvSetting.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceAvSetting/include/Api.hpp" diff --git a/core/libs/prx/libSceAvcap2/libSceAvcap2.hpp b/core/libs/prx/libSceAvcap2/libSceAvcap2.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceAvcap2/libSceAvcap2.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceAvcap2mvr/libSceAvcap2mvr.hpp b/core/libs/prx/libSceAvcap2mvr/libSceAvcap2mvr.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceAvcap2mvr/libSceAvcap2mvr.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceBackupRestoreUtil/Export.cpp b/core/libs/prx/libSceBackupRestoreUtil/Export.cpp index 77695475b9..a737e30ad8 100644 --- a/core/libs/prx/libSceBackupRestoreUtil/Export.cpp +++ b/core/libs/prx/libSceBackupRestoreUtil/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceBackupRestoreUtil/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceBackupRestoreUtil/include/Api.hpp b/core/libs/prx/libSceBackupRestoreUtil/include/Api.hpp new file mode 100644 index 0000000000..7851d2c315 --- /dev/null +++ b/core/libs/prx/libSceBackupRestoreUtil/include/Api.hpp @@ -0,0 +1,24 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceBackupRestoreUtilBackupData(); +int APS5_VABI sceBackupRestoreUtilCancelBackupData(); +int APS5_VABI sceBackupRestoreUtilCancelGetRequiredSize(); +int APS5_VABI sceBackupRestoreUtilCancelGetTitles(); +int APS5_VABI sceBackupRestoreUtilCancelRestoreData(); +int APS5_VABI sceBackupRestoreUtilDeleteBackupData(); +int APS5_VABI sceBackupRestoreUtilGetBackupDataInfo(); +int APS5_VABI sceBackupRestoreUtilGetBackupParam(); +int APS5_VABI sceBackupRestoreUtilGetBackupProgress(); +int APS5_VABI sceBackupRestoreUtilGetRequiredSize(); +int APS5_VABI sceBackupRestoreUtilGetRestoreProgress(); +int APS5_VABI sceBackupRestoreUtilGetTitles(); +int APS5_VABI sceBackupRestoreUtilInitialize(); +int APS5_VABI sceBackupRestoreUtilPrepareBackup(); +int APS5_VABI sceBackupRestoreUtilRestoreData(); +int APS5_VABI sceBackupRestoreUtilTerminate(); + +} diff --git a/core/libs/prx/libSceBackupRestoreUtil/libSceBackupRestoreUtil.hpp b/core/libs/prx/libSceBackupRestoreUtil/libSceBackupRestoreUtil.hpp new file mode 100644 index 0000000000..357f0a92c0 --- /dev/null +++ b/core/libs/prx/libSceBackupRestoreUtil/libSceBackupRestoreUtil.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceBackupRestoreUtil/include/Api.hpp" diff --git a/core/libs/prx/libSceBeisobmf/Export.cpp b/core/libs/prx/libSceBeisobmf/Export.cpp index a2eee1a93d..31c0e4b2fe 100644 --- a/core/libs/prx/libSceBeisobmf/Export.cpp +++ b/core/libs/prx/libSceBeisobmf/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceBeisobmf/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceBeisobmf/include/Api.hpp b/core/libs/prx/libSceBeisobmf/include/Api.hpp new file mode 100644 index 0000000000..60bc60a75e --- /dev/null +++ b/core/libs/prx/libSceBeisobmf/include/Api.hpp @@ -0,0 +1,26 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI isobmf_box_getchildbox_nid_postfix(void); +int APS5_VABI isobmf_box_getdiskoffset_nid_postfix(void); +int APS5_VABI isobmf_box_getflags32b_nid_postfix(void); +int APS5_VABI isobmf_box_getmember_length_nid_postfix(void); +int APS5_VABI isobmf_box_getmember_ptr_nid_postfix(void); +int APS5_VABI isobmf_box_getmember_type_nid_postfix(void); +int APS5_VABI isobmf_box_getnextbox_nid_postfix(void); +int APS5_VABI isobmf_box_getstate_nid_postfix(void); +int APS5_VABI isobmf_box_gettype_nid_postfix(void); +int APS5_VABI isobmf_decoder_clear_nid_postfix(void); +int APS5_VABI isobmf_decoder_create_nid_postfix(void); +int APS5_VABI isobmf_decoder_decode_nid_postfix(void); +int APS5_VABI isobmf_decoder_destroy_nid_postfix(void); +int APS5_VABI isobmf_decoder_get_decoder_tree_nid_postfix(void); +int APS5_VABI isobmf_decoder_getquerydata_nid_postfix(void); +int APS5_VABI isobmf_decoder_next_disk_offset_nid_postfix(void); +int APS5_VABI isobmf_decoder_query_nid_postfix(void); +int APS5_VABI isobmf_memmanager_set_nid_postfix(void); + +} diff --git a/core/libs/prx/libSceBeisobmf/libSceBeisobmf.hpp b/core/libs/prx/libSceBeisobmf/libSceBeisobmf.hpp new file mode 100644 index 0000000000..7b7de4f4a4 --- /dev/null +++ b/core/libs/prx/libSceBeisobmf/libSceBeisobmf.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceBeisobmf/include/Api.hpp" diff --git a/core/libs/prx/libSceBemp2sys/Export.cpp b/core/libs/prx/libSceBemp2sys/Export.cpp index 3bf12ad835..94f4dd4563 100644 --- a/core/libs/prx/libSceBemp2sys/Export.cpp +++ b/core/libs/prx/libSceBemp2sys/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceBemp2sys/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceBemp2sys/include/Api.hpp b/core/libs/prx/libSceBemp2sys/include/Api.hpp new file mode 100644 index 0000000000..82e55243e5 --- /dev/null +++ b/core/libs/prx/libSceBemp2sys/include/Api.hpp @@ -0,0 +1,39 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI bemp2sys_logprintf_getlevel_nid_postfix(void); +int APS5_VABI bemp2sys_logprintf_setfunc_nid_postfix(void); +int APS5_VABI bemp2sys_logprintf_setlevel_nid_postfix(void); +int APS5_VABI bemp2sys_memmanager_set_nid_postfix(void); +int APS5_VABI bemp2sys_packetizer_create_nid_postfix(void); +int APS5_VABI bemp2sys_packetizer_destroy_nid_postfix(void); +int APS5_VABI bemp2sys_packetizer_init_nid_postfix(void); +int APS5_VABI bemp2sys_packetizer_release_nid_postfix(void); +int APS5_VABI bemp2sys_pesparser_create_nid_postfix(void); +int APS5_VABI bemp2sys_pesparser_destroy_nid_postfix(void); +int APS5_VABI bemp2sys_pesparser_init_nid_postfix(void); +int APS5_VABI bemp2sys_pesparser_parse_nid_postfix(void); +int APS5_VABI bemp2sys_pesparser_release_nid_postfix(void); +int APS5_VABI bemp2sys_pesparser_sendmessage_nid_postfix(void); +int APS5_VABI bemp2sys_psdecoder_create_nid_postfix(void); +int APS5_VABI bemp2sys_psdecoder_destroy_nid_postfix(void); +int APS5_VABI bemp2sys_psdecoder_init_nid_postfix(void); +int APS5_VABI bemp2sys_psdecoder_readpacket_nid_postfix(void); +int APS5_VABI bemp2sys_psdecoder_release_nid_postfix(void); +int APS5_VABI bemp2sys_psdecoder_sendmessage_nid_postfix(void); +int APS5_VABI bemp2sys_tsdecoder_create_nid_postfix(void); +int APS5_VABI bemp2sys_tsdecoder_destroy_nid_postfix(void); +int APS5_VABI bemp2sys_tsdecoder_init_nid_postfix(void); +int APS5_VABI bemp2sys_tsdecoder_readpacket_nid_postfix(void); +int APS5_VABI bemp2sys_tsdecoder_release_nid_postfix(void); +int APS5_VABI bemp2sys_tsdecoder_sendmessage_nid_postfix(void); +int APS5_VABI bemp2sys_tsfilter_create_nid_postfix(void); +int APS5_VABI bemp2sys_tsfilter_destroy_nid_postfix(void); +int APS5_VABI bemp2sys_tsfilter_init_nid_postfix(void); +int APS5_VABI bemp2sys_tsfilter_release_nid_postfix(void); +int APS5_VABI bemp2sys_tsfilter_sendmessage_nid_postfix(void); + +} diff --git a/core/libs/prx/libSceBemp2sys/libSceBemp2sys.hpp b/core/libs/prx/libSceBemp2sys/libSceBemp2sys.hpp new file mode 100644 index 0000000000..23c390341f --- /dev/null +++ b/core/libs/prx/libSceBemp2sys/libSceBemp2sys.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceBemp2sys/include/Api.hpp" diff --git a/core/libs/prx/libSceBgft/Export.cpp b/core/libs/prx/libSceBgft/Export.cpp index 68c25e4d3a..c94cfeb6b8 100644 --- a/core/libs/prx/libSceBgft/Export.cpp +++ b/core/libs/prx/libSceBgft/Export.cpp @@ -1,33 +1,9 @@ +#include "prx/libSceBgft/include/Api.hpp" #include #include #include "SceTypes.hpp" #include "prx/libc/include/General.hpp" -struct BgftInitParam { - void* heap; - uint64_t heapSize; -}; - -struct BgftProgress; -struct BgftStorageTaskParam { - std::uint32_t value0; - std::uint32_t value4; - const char* contentId; - const char* text16; - std::byte unused24[8]; - const char* text32; - const char* text40; - const char* text48; - std::uint32_t value56; - std::byte padding60[4]; - const char* text64; - const char* text72; - const char* text80; - const char* text88; - std::uint64_t value96; - std::uint32_t value104; -}; - static_assert(sizeof(BgftStorageTaskParam) == 112); static_assert(offsetof(BgftStorageTaskParam, contentId) == 8); static_assert(offsetof(BgftStorageTaskParam, text32) == 32); @@ -109,7 +85,7 @@ int APS5_VABI sceBgftServiceIntDownloadGetGameAndGameAcProgress(const char* cont NotImplemented_nid_no_patch(__func__); return 0; } -int APS5_VABI sceBgftServiceIntDownloadGetPatchProgress() { +int APS5_VABI sceBgftServiceIntDownloadGetPatchProgress(const char* contentId, BgftProgress* progress) { NotImplemented_nid_no_patch(__func__); return 0; } @@ -121,7 +97,7 @@ int APS5_VABI sceBgftServiceIntDownloadGetProgress(int32_t taskId, BgftProgress* NotImplemented_nid_no_patch(__func__); return 0; } -int APS5_VABI sceBgftServiceIntDownloadGetTaskInfo() { +int APS5_VABI sceBgftServiceIntDownloadGetTaskInfo(int32_t taskId, BgftTaskInfo* taskInfo) { NotImplemented_nid_no_patch(__func__); return 0; } diff --git a/core/libs/prx/libSceBgft/include/Api.hpp b/core/libs/prx/libSceBgft/include/Api.hpp new file mode 100644 index 0000000000..9e39227e29 --- /dev/null +++ b/core/libs/prx/libSceBgft/include/Api.hpp @@ -0,0 +1,125 @@ +#pragma once + +#include "SceTypes.hpp" + +struct BgftInitParam { + void* heap; + uint64_t heapSize; +}; + +struct BgftProgress; +struct BgftTaskInfo; + +struct BgftStorageTaskParam { + std::uint32_t value0; + std::uint32_t value4; + const char* contentId; + const char* text16; + std::byte unused24[8]; + const char* text32; + const char* text40; + const char* text48; + std::uint32_t value56; + std::byte padding60[4]; + const char* text64; + const char* text72; + const char* text80; + const char* text88; + std::uint64_t value96; + std::uint32_t value104; +}; + +extern "C" { + +int APS5_VABI sceBgftServiceInit(const BgftInitParam* params); +int APS5_VABI sceBgftServiceTerm(void); +int APS5_VABI sceBgftServiceDownloadPauseTaskAll(); +int APS5_VABI sceBgftServiceDownloadResumeTaskAll(); +int APS5_VABI sceBgftServiceDownloadStartTaskAll(); +int APS5_VABI sceBgftServiceDownloadStopTaskAll(); +int APS5_VABI sceBgftServiceDownloadFindActivePatchTask(const char* contentId, int32_t* taskId); +int APS5_VABI sceBgftServiceDownloadFindActivePupTask(int32_t* taskId); +int APS5_VABI sceBgftServiceDownloadFindTaskByContentId(const char* contentId, int32_t subType, int32_t* taskId); +int APS5_VABI sceBgftServiceDownloadGetProgress(int32_t taskId, BgftProgress* progress); +int APS5_VABI sceBgftServiceDownloadPauseTask(int32_t taskId); +int APS5_VABI sceBgftServiceDownloadResumeTask(int32_t taskId); +int APS5_VABI sceBgftServiceDownloadStartTask(int32_t taskId); +int APS5_VABI sceBgftServiceDownloadStopTask(int32_t taskId); +int APS5_VABI sceBgftServiceIntDownloadFindActiveGameAndGameAcTask(const char* contentId, int32_t* taskId); +int APS5_VABI sceBgftServiceIntDownloadFindActiveTask(const char* contentId, int32_t subType, int32_t* taskId); +int APS5_VABI sceBgftServiceIntDownloadGetGameAndGameAcProgress(const char* contentId, BgftProgress* progress); +int APS5_VABI sceBgftServiceIntDownloadGetPatchProgress(const char* contentId, BgftProgress* progress); +int APS5_VABI sceBgftServiceIntDownloadGetPlayGoProgress(const char* contentId, BgftProgress* progress); +int APS5_VABI sceBgftServiceIntDownloadGetProgress(int32_t taskId, BgftProgress* progress); +int APS5_VABI sceBgftServiceIntDownloadGetTaskInfo(int32_t taskId, BgftTaskInfo* taskInfo); +int APS5_VABI sceBgftServiceIntDownloadPauseTask(int32_t taskId); +int APS5_VABI sceBgftServiceIntDownloadRegisterTaskByStorageEx(const BgftStorageTaskParam* params, int32_t* taskId); +int APS5_VABI sceBgftServiceIntDownloadResumeTask(int32_t taskId); +int APS5_VABI sceBgftServiceIntDownloadStopTask(int32_t taskId); +int APS5_VABI sceBgftServiceIntDownloadStartTask(int32_t taskId); +int APS5_VABI sceBgftServiceIntDownloadUnregisterTask(int32_t taskId); +int APS5_VABI sceBgftServiceIntInit(const BgftInitParam* params); +int APS5_VABI sceBgftServiceDownloadQueryTask(void); +int APS5_VABI sceBgftServiceIntDebugDownloadCorruptPkg(void); +int APS5_VABI sceBgftServiceIntDebugDownloadRequest(void); +int APS5_VABI sceBgftServiceIntDebugPlayGoGetPlayGoStatusString(void); +int APS5_VABI sceBgftServiceIntDebugPlayGoIsPaused(void); +int APS5_VABI sceBgftServiceIntDebugPlayGoResume(void); +int APS5_VABI sceBgftServiceIntDebugPlayGoRevertToFullState(void); +int APS5_VABI sceBgftServiceIntDebugPlayGoRevertToInitialState(void); +int APS5_VABI sceBgftServiceIntDebugPlayGoRevertToSnapshot(void); +int APS5_VABI sceBgftServiceIntDebugPlayGoSnapshotByTitleId(void); +int APS5_VABI sceBgftServiceIntDebugPlayGoSuspend(void); +int APS5_VABI sceBgftServiceIntDownloadDebugDeleteBgftEnvFile(void); +int APS5_VABI sceBgftServiceIntDownloadDebugDownloadBgftEnvFile(void); +int APS5_VABI sceBgftServiceIntDownloadDebugGetBgftEnvInfoString(void); +int APS5_VABI sceBgftServiceIntDownloadDebugGetStat(void); +int APS5_VABI sceBgftServiceIntDownloadGetExtUsbUserStorageSize(void); +int APS5_VABI sceBgftServiceIntDownloadGetUserStorageSize(void); +int APS5_VABI sceBgftServiceIntDownloadPauseTaskAll(void); +int APS5_VABI sceBgftServiceIntDownloadQueryTask(void); +int APS5_VABI sceBgftServiceIntDownloadRegisterTaskByStorage(void); +int APS5_VABI sceBgftServiceIntDownloadRestartTask(void); +int APS5_VABI sceBgftServiceIntDownloadResumeTaskAll(void); +int APS5_VABI sceBgftServiceIntDownloadStartTaskAll(void); +int APS5_VABI sceBgftServiceIntDownloadStopTaskAll(void); +int APS5_VABI sceBgftServiceIntDownloadUnregisterTaskAll(void); +int APS5_VABI sceBgftServiceIntExtUsbCheckActiveDownloadTasks(void); +int APS5_VABI sceBgftServiceIntGetTaskInfoValueInt(void); +int APS5_VABI sceBgftServiceIntGetTaskInfoValueString(void); +int APS5_VABI sceBgftServiceIntGetTaskInfoValueStringIndex(void); +int APS5_VABI sceBgftServiceIntPlayGoFindTaskId(void); +int APS5_VABI sceBgftServiceIntPlayGoGetDiscIniChunksInstallProgress(void); +int APS5_VABI sceBgftServiceIntPlayGoIsPaused(void); +int APS5_VABI sceBgftServiceIntPlayGoResume(void); +int APS5_VABI sceBgftServiceIntTerm(void); +int APS5_VABI sceBgftServiceIntUploadGetProgress(void); +int APS5_VABI sceBgftServiceIntUploadQueryTask(void); +int APS5_VABI sceBgftServiceIntUploadRegisterTask(void); +int APS5_VABI sceBgftServiceIntUploadRestartTask(void); +int APS5_VABI sceBgftServiceIntUploadStartTask(void); +int APS5_VABI sceBgftServiceIntUploadStartTaskAll(void); +int APS5_VABI sceBgftServiceIntUploadStopTask(void); +int APS5_VABI sceBgftServiceIntUploadStopTaskAll(void); +int APS5_VABI sceBgftServiceIntUploadUnregisterTask(void); +int APS5_VABI sceBgftServiceIntUploadUnregisterTaskAll(void); + +int APS5_VABI sceBgftServiceIntDebugPlayGoClearSetFreeZone(); +int APS5_VABI sceBgftServiceIntDebugPlayGoIsSetFreeZone(); +int APS5_VABI sceBgftServiceIntDownloadCheckPatchUpdateState(); +int APS5_VABI sceBgftServiceIntDownloadClearStats(); +int APS5_VABI sceBgftServiceIntDownloadGetApplicationDataSize(); +int APS5_VABI sceBgftServiceIntDownloadGetPatchGoProgress(); +int APS5_VABI sceBgftServiceIntDownloadHideTask(); +int APS5_VABI sceBgftServiceIntDownloadSetResumeState(); +int APS5_VABI sceBgftServiceIntDownloadSetStartState(); +int APS5_VABI sceBgftServiceIntPlayGoCheckDiscIniChunksInstall(); +int APS5_VABI sceBgftServiceIntPlayGoStartDataDiscInstall(); +int APS5_VABI sceBgftServiceIntSetTaskVisible(); +int APS5_VABI sceBgftServiceIntUploadGetAvailableTaskCount(); +int APS5_VABI sceBgftServiceIntUploadGetTaskInfo(); +int APS5_VABI sceBgftServiceIntUploadHideTask(); +int APS5_VABI sceBgftServiceIntUploadSetStartState(); +int APS5_VABI sceBgftServiceIntUploadSetUploadError(); + +} diff --git a/core/libs/prx/libSceBgft/libSceBgft.hpp b/core/libs/prx/libSceBgft/libSceBgft.hpp new file mode 100644 index 0000000000..27e9095851 --- /dev/null +++ b/core/libs/prx/libSceBgft/libSceBgft.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceBgft/include/Api.hpp" diff --git a/core/libs/prx/libSceBgsStorage/libSceBgsStorage.hpp b/core/libs/prx/libSceBgsStorage/libSceBgsStorage.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceBgsStorage/libSceBgsStorage.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceBluetoothHid/Export.cpp b/core/libs/prx/libSceBluetoothHid/Export.cpp index 63c76ddd55..e1e00be946 100644 --- a/core/libs/prx/libSceBluetoothHid/Export.cpp +++ b/core/libs/prx/libSceBluetoothHid/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceBluetoothHid/include/Api.hpp" #include #include #include "SceTypes.hpp" @@ -6,36 +7,6 @@ #include #include -struct BluetoothHidThreadParam { - std::int32_t priority; - std::uint32_t padding; - std::uint64_t affinityMask; - std::uint32_t reserved; - std::uint32_t tailPadding; -}; - -struct BluetoothHidParam { - const BluetoothHidThreadParam* threadParam; - std::uint32_t reserved; - std::uint32_t padding; -}; - -struct BluetoothHidEvent { - std::uint64_t deviceHandle; - std::uint16_t vendorId; - std::uint16_t productId; - std::uint8_t type; - std::uint8_t status; - std::uint16_t reportSize; - std::uint8_t reserved[8]; - std::uint8_t report[78]; - std::uint8_t padding[2]; -}; - -struct BluetoothHidDeviceInfo; -struct BluetoothHidDeviceName; -using BluetoothHidCallback = void (APS5_VABI *)(const BluetoothHidEvent*, std::int32_t, void*); - static_assert(sizeof(BluetoothHidThreadParam) == 24); static_assert(offsetof(BluetoothHidThreadParam, affinityMask) == 8); static_assert(offsetof(BluetoothHidThreadParam, reserved) == 16); diff --git a/core/libs/prx/libSceBluetoothHid/include/Api.hpp b/core/libs/prx/libSceBluetoothHid/include/Api.hpp new file mode 100644 index 0000000000..ff0741f33f --- /dev/null +++ b/core/libs/prx/libSceBluetoothHid/include/Api.hpp @@ -0,0 +1,61 @@ +#pragma once + +#include "SceTypes.hpp" +#include +#include +#include +#include + +struct BluetoothHidThreadParam { + std::int32_t priority; + std::uint32_t padding; + std::uint64_t affinityMask; + std::uint32_t reserved; + std::uint32_t tailPadding; +}; + +struct BluetoothHidParam { + const BluetoothHidThreadParam* threadParam; + std::uint32_t reserved; + std::uint32_t padding; +}; + +struct BluetoothHidEvent { + std::uint64_t deviceHandle; + std::uint16_t vendorId; + std::uint16_t productId; + std::uint8_t type; + std::uint8_t status; + std::uint16_t reportSize; + std::uint8_t reserved[8]; + std::uint8_t report[78]; + std::uint8_t padding[2]; +}; + +struct BluetoothHidDeviceInfo; + +struct BluetoothHidDeviceName; + +using BluetoothHidCallback = void (APS5_VABI *)(const BluetoothHidEvent*, std::int32_t, void*); + +extern "C" { + +std::int32_t APS5_VABI sceBluetoothHidInit(); +std::int32_t APS5_VABI sceBluetoothHidRegisterCallback(BluetoothHidCallback callback, void* userData, const BluetoothHidParam* param); +std::int32_t APS5_VABI sceBluetoothHidUnregisterCallback(); +std::int32_t APS5_VABI sceBluetoothHidRegisterDevice(std::uint16_t vendorId, std::uint16_t productId); +std::int32_t APS5_VABI sceBluetoothHidUnregisterDevice(std::uint16_t vendorId, std::uint16_t productId); +int APS5_VABI sceBluetoothHidGetDeviceName(std::uint64_t deviceHandle, BluetoothHidDeviceName* name); +int APS5_VABI sceBluetoothHidGetInputReport(std::uint64_t deviceHandle, std::uint8_t reportId); +int APS5_VABI sceBluetoothHidSetOutputReport(std::uint64_t deviceHandle, std::uint8_t reportId, const void* data, std::size_t size); +int APS5_VABI sceBluetoothHidDebugGetVersion(); +int APS5_VABI sceBluetoothHidDisconnectDevice(std::int32_t deviceId); +int APS5_VABI sceBluetoothHidGetDeviceInfo(std::int32_t deviceId, BluetoothHidDeviceInfo* info); +int APS5_VABI sceBluetoothHidGetFeatureReport(std::uint64_t deviceHandle, std::uint8_t reportId); +int APS5_VABI sceBluetoothHidGetReportDescriptor(std::uint64_t deviceHandle, void* descriptor, std::size_t size); +int APS5_VABI sceBluetoothHidInterruptOutput(std::uint64_t deviceHandle, std::uint8_t reportId, const void* data, std::size_t size); +int APS5_VABI sceBluetoothHidParamInitialize(BluetoothHidParam* param, const BluetoothHidThreadParam* threadParam); +int APS5_VABI sceBluetoothHidSetFeatureReport(std::uint64_t deviceHandle, std::uint8_t reportId, const void* data, std::size_t size); +int APS5_VABI sceBluetoothHidThreadParamInitialize(BluetoothHidThreadParam* param, std::int32_t priority, std::uint64_t affinityMask); + +} diff --git a/core/libs/prx/libSceBluetoothHid/libSceBluetoothHid.hpp b/core/libs/prx/libSceBluetoothHid/libSceBluetoothHid.hpp new file mode 100644 index 0000000000..ee177d4896 --- /dev/null +++ b/core/libs/prx/libSceBluetoothHid/libSceBluetoothHid.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceBluetoothHid/include/Api.hpp" diff --git a/core/libs/prx/libSceCamera/Export.cpp b/core/libs/prx/libSceCamera/Export.cpp index 2d7757d706..c4fa002d9d 100644 --- a/core/libs/prx/libSceCamera/Export.cpp +++ b/core/libs/prx/libSceCamera/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceCamera/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceCamera/include/Api.hpp b/core/libs/prx/libSceCamera/include/Api.hpp new file mode 100644 index 0000000000..169844eb58 --- /dev/null +++ b/core/libs/prx/libSceCamera/include/Api.hpp @@ -0,0 +1,125 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceCameraIsAttached(int32_t index); +int APS5_VABI sceCameraOpen(void); +int APS5_VABI sceCameraClose(void); +int APS5_VABI sceCameraStart(void); +int APS5_VABI sceCameraStop(void); +int APS5_VABI sceCameraGetConfig(void); +int APS5_VABI sceCameraSetConfig(void); +int APS5_VABI sceCameraSetAttribute(void); +int APS5_VABI sceCameraGetDeviceInfo(void); +int APS5_VABI sceCameraGetFrameData(void); +int APS5_VABI sceCameraIsValidFrameData(void); +int APS5_VABI sceCameraStopByHandle(void); +int APS5_VABI sceCameraGetDeviceIDWithoutOpen(void); +int APS5_VABI sceCameraGetAttribute(void); +int APS5_VABI sceCameraInitializeRegistryCalibData(void); +int APS5_VABI sceCamera2GetContrast(void); +int APS5_VABI sceCamera2Finalize(void); +int APS5_VABI sceCameraGetConnectedDeviceAndDriverMode(void); +int APS5_VABI sceCamera2IsAttached(void); +int APS5_VABI sceCamera2SetSharpness(void); +int APS5_VABI sceCameraSetTrackerMode(void); +int APS5_VABI sceCameraSetContrast(void); +int APS5_VABI sceCameraGetCalibDataForEve(void); +int APS5_VABI sceCameraGetCalibDataFromDevice(void); +int APS5_VABI sceCamera2SetContrast(void); +int APS5_VABI sceCameraIsConnectedForSystem(void); +int APS5_VABI sceCamera2SetExposureGain(void); +int APS5_VABI sceCameraSetRegister(void); +int APS5_VABI sceCameraSetVideoSyncInternal(void); +int APS5_VABI sceCameraSetConfigInternal(void); +int APS5_VABI sceCameraSetAttributeInternal(void); +int APS5_VABI sceCamera2SetWhiteBalance(void); +int APS5_VABI sceCameraGetMmapConnectedCount(void); +int APS5_VABI sceCamera2GetSaturation(void); +int APS5_VABI sceCameraGetDeviceConfig(void); +int APS5_VABI sceCameraAudioOpen(void); +int APS5_VABI sceCamera2GetAutoExposureGain(void); +int APS5_VABI sceCameraGetCalibDataFromDeviceForEve(void); +int APS5_VABI sceCameraGetWhiteBalance(void); +int APS5_VABI sceCameraGetVrCaptureInfo(void); +int APS5_VABI sceCameraSetCalibDataForEve(void); +int APS5_VABI sceCamera2GetAttribute(void); +int APS5_VABI sceCameraSetLensCorrection(void); +int APS5_VABI sceCameraSetCalibData(void); +int APS5_VABI sceCameraSetProcessFocusByHandle(void); +int APS5_VABI sceCamera2SetConfig(void); +int APS5_VABI sceCameraGetExposureGain(void); +int APS5_VABI sceCameraSetSharpness(void); +int APS5_VABI sceCamera2Initialize(void); +int APS5_VABI sceCameraSetHue(void); +int APS5_VABI sceCameraAccGetData(void); +int APS5_VABI sceCamera2SetAttribute(void); +int APS5_VABI sceCameraGetCalibrationData(void); +int APS5_VABI sceCameraGetSaturation(void); +int APS5_VABI sceCamera2GetHue(void); +int APS5_VABI sceCamera2Stop(void); +int APS5_VABI sceCamera2SetSaturation(void); +int APS5_VABI sceCamera2GetAutoWhiteBalance(void); +int APS5_VABI sceCameraAudioClose(void); +int APS5_VABI sceCameraGetProductInfo(void); +int APS5_VABI sceCameraGetGamma(void); +int APS5_VABI sceCameraGetLensCorrection(void); +int APS5_VABI sceCameraChangeAppModuleState(void); +int APS5_VABI sceCamera2GetFrameData(void); +int APS5_VABI sceCameraGetContrast(void); +int APS5_VABI sceCameraSetSaturation(void); +int APS5_VABI sceCameraGetSharpness(void); +int APS5_VABI sceCamera2GetExposureGain(void); +int APS5_VABI sceCameraStartByHandle(void); +int APS5_VABI sceCamera2Open(void); +int APS5_VABI sceCamera2Start(void); +int APS5_VABI sceCameraSetLensCorrectionInternal(void); +int APS5_VABI sceCameraOpenByModuleId(void); +int APS5_VABI sceCamera2GetCalibrationData(void); +int APS5_VABI sceCameraAudioGetData(void); +int APS5_VABI sceCamera2SetHue(void); +int APS5_VABI sceCamera2GetGamma(void); +int APS5_VABI sceCameraGetCalibData(void); +int APS5_VABI sceCameraWaitForEveReady(void); +int APS5_VABI sceCameraGetRegistryInfo(void); +int APS5_VABI sceCameraAudioGetData2(void); +int APS5_VABI sceCameraSetAppModuleFocus(void); +int APS5_VABI sceCameraSetDefectivePixelCancellation(void); +int APS5_VABI sceCameraGetDeviceID(void); +int APS5_VABI sceCameraSetForceActivate(void); +int APS5_VABI sceCameraSetWhiteBalance(void); +int APS5_VABI sceCamera2GetFieldOfView(void); +int APS5_VABI sceCamera2IsValidFrameData(void); +int APS5_VABI sceCameraSetProcessFocus(void); +int APS5_VABI sceCameraSetGamma(void); +int APS5_VABI sceCamera2GetConfig(void); +int APS5_VABI sceCamera2GetWhiteBalance(void); +int APS5_VABI sceCameraGetDeviceConfigWithoutHandle(void); +int APS5_VABI sceCameraDeviceOpen(void); +int APS5_VABI sceCameraSetUacModeInternal(void); +int APS5_VABI sceCameraGetAutoExposureGain(void); +int APS5_VABI sceCameraGetRegister(void); +int APS5_VABI sceCamera2SetGamma(void); +int APS5_VABI sceCameraRemoveAppModuleFocus(void); +int APS5_VABI sceCameraGetAutoWhiteBalance(void); +int APS5_VABI sceCameraGetDefectivePixelCancellation(void); +int APS5_VABI sceCamera2Close(void); +int APS5_VABI sceCamera2SetVideoSync(void); +int APS5_VABI sceCameraWaitForLukeReady(void); +int APS5_VABI sceCameraSetDefectivePixelCancellationInternal(void); +int APS5_VABI sceCamera2GetSharpness(void); +int APS5_VABI sceCamera2SetAutoWhiteBalance(void); +int APS5_VABI sceCameraSetDebugStop(void); +int APS5_VABI sceCamera2SetAutoExposureGain(void); +int APS5_VABI sceCameraIsConfigChangeDone(void); +int APS5_VABI sceCameraSetExposureGain(void); +int APS5_VABI sceCameraSetVideoSync(void); +int APS5_VABI sceCameraAudioReset(void); +int APS5_VABI sceCameraSetAutoExposureGain(void); +int APS5_VABI sceCameraSetAutoWhiteBalance(void); +int APS5_VABI sceCameraGetHue(void); +int APS5_VABI sceCameraCloseByHandle(void); + +} diff --git a/core/libs/prx/libSceCamera/libSceCamera.hpp b/core/libs/prx/libSceCamera/libSceCamera.hpp new file mode 100644 index 0000000000..f11c2f4973 --- /dev/null +++ b/core/libs/prx/libSceCamera/libSceCamera.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceCamera/include/Api.hpp" diff --git a/core/libs/prx/libSceCdlgG2P/Export.cpp b/core/libs/prx/libSceCdlgG2P/Export.cpp index 43abff189e..a6f7113420 100644 --- a/core/libs/prx/libSceCdlgG2P/Export.cpp +++ b/core/libs/prx/libSceCdlgG2P/Export.cpp @@ -1,3 +1,5 @@ +#include "prx/libSceCdlgG2P/include/Api.hpp" +#include "prx/libSceUserService/UserService.hpp" #include "SceTypes.hpp" #include #include @@ -7,8 +9,6 @@ #include "prx/libSceCommonDialog/CommonDialog.hpp" #include "prx/libc/include/General.hpp" -extern "C" int APS5_VABI sceUserServiceGetLoginUserIdList(UserServiceLoginUserIdList* users); - namespace { constexpr int COMMON_DIALOG_STATUS_NONE = 0; diff --git a/core/libs/prx/libSceCdlgG2P/include/Api.hpp b/core/libs/prx/libSceCdlgG2P/include/Api.hpp new file mode 100644 index 0000000000..5233fb9246 --- /dev/null +++ b/core/libs/prx/libSceCdlgG2P/include/Api.hpp @@ -0,0 +1,16 @@ +#pragma once + +#include "prx/libSceCommonDialog/CommonDialog.hpp" +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceG2PDialogInitialize(void); +int APS5_VABI sceG2PDialogOpen(const G2PDialogParam* param); +int APS5_VABI sceG2PDialogUpdateStatus(void); +int APS5_VABI sceG2PDialogGetStatus(void); +int APS5_VABI sceG2PDialogGetResult(CommonDialogResultPrefix* result); +int APS5_VABI sceG2PDialogClose(void); +int APS5_VABI sceG2PDialogTerminate(void); + +} diff --git a/core/libs/prx/libSceCdlgG2P/libSceCdlgG2P.hpp b/core/libs/prx/libSceCdlgG2P/libSceCdlgG2P.hpp new file mode 100644 index 0000000000..b01cc903f1 --- /dev/null +++ b/core/libs/prx/libSceCdlgG2P/libSceCdlgG2P.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceCdlgG2P/include/Api.hpp" diff --git a/core/libs/prx/libSceCdlgPlayerReview/Export.cpp b/core/libs/prx/libSceCdlgPlayerReview/Export.cpp index 4db4e1760e..75e23b282e 100644 --- a/core/libs/prx/libSceCdlgPlayerReview/Export.cpp +++ b/core/libs/prx/libSceCdlgPlayerReview/Export.cpp @@ -1,3 +1,5 @@ +#include "prx/libSceCdlgPlayerReview/include/Api.hpp" +#include "prx/libSceUserService/UserService.hpp" #include "SceTypes.hpp" #include #include @@ -5,8 +7,6 @@ #include "prx/libSceCommonDialog/CommonDialog.hpp" #include "prx/libc/include/General.hpp" -extern "C" int APS5_VABI sceUserServiceGetLoginUserIdList(UserServiceLoginUserIdList* users); - namespace { std::atomic g_status{0}; diff --git a/core/libs/prx/libSceCdlgPlayerReview/include/Api.hpp b/core/libs/prx/libSceCdlgPlayerReview/include/Api.hpp new file mode 100644 index 0000000000..5951bb3d08 --- /dev/null +++ b/core/libs/prx/libSceCdlgPlayerReview/include/Api.hpp @@ -0,0 +1,16 @@ +#pragma once + +#include "prx/libSceCommonDialog/CommonDialog.hpp" +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI scePlayerReviewDialogInitialize(void); +int APS5_VABI scePlayerReviewDialogTerminate(void); +int APS5_VABI scePlayerReviewDialogOpen(const PlayerReviewDialogParam* param); +int APS5_VABI scePlayerReviewDialogClose(void); +int APS5_VABI scePlayerReviewDialogGetStatus(void); +int APS5_VABI scePlayerReviewDialogUpdateStatus(void); +int APS5_VABI scePlayerReviewDialogGetResult(CommonDialogResultPrefix* result); + +} diff --git a/core/libs/prx/libSceCdlgPlayerReview/libSceCdlgPlayerReview.hpp b/core/libs/prx/libSceCdlgPlayerReview/libSceCdlgPlayerReview.hpp new file mode 100644 index 0000000000..a7037746d2 --- /dev/null +++ b/core/libs/prx/libSceCdlgPlayerReview/libSceCdlgPlayerReview.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceCdlgPlayerReview/include/Api.hpp" diff --git a/core/libs/prx/libSceCdlgUtilServer/libSceCdlgUtilServer.hpp b/core/libs/prx/libSceCdlgUtilServer/libSceCdlgUtilServer.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceCdlgUtilServer/libSceCdlgUtilServer.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceCesCs-module/libSceCesCs-module.hpp b/core/libs/prx/libSceCesCs-module/libSceCesCs-module.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceCesCs-module/libSceCesCs-module.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceCesCs/Export.cpp b/core/libs/prx/libSceCesCs/Export.cpp index 0ba8d0ae27..15e18e9e3b 100644 --- a/core/libs/prx/libSceCesCs/Export.cpp +++ b/core/libs/prx/libSceCesCs/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceCesCs/include/Api.hpp" #include #include #include @@ -21,10 +22,13 @@ namespace { constexpr int CES_ERROR_INVALID_PARAMETER = static_cast(0x805C0001); +constexpr int CES_ERROR_INVALID_PROFILE = static_cast(0x805C0004); constexpr int CES_ERROR_INVALID_SRC_BUFFER = static_cast(0x805C0010); constexpr int CES_ERROR_SRC_BUFFER_END = static_cast(0x805C0011); constexpr int CES_ERROR_INVALID_ENCODE = static_cast(0x805C0014); +constexpr int CES_ERROR_ILLEGAL_CODE = static_cast(0x805C0015); constexpr int CES_ERROR_UNASSIGNED_CODE = static_cast(0x805C0020); +constexpr int CES_ERROR_UNSUPPORTED_CODE = static_cast(0x805C0024); constexpr int CES_ERROR_INVALID_DST_BUFFER = static_cast(0x805C0030); constexpr int CES_ERROR_DST_BUFFER_END = static_cast(0x805C0031); @@ -34,13 +38,13 @@ constexpr const uint8_t* CP1251_PROFILE = PROFILES[1]; constexpr const uint8_t* CP1250_PROFILE = PROFILES[2]; constexpr uint16_t CP1252_HIGH[32] = { - 0x20AC, 0x0081, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, 0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x008D, 0x017D, 0x008F, - 0x0090, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0x009D, 0x017E, 0x0178, + 0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, 0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x0000, 0x017D, 0x0000, + 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0x0000, 0x017E, 0x0178, }; constexpr uint16_t CP1251_HIGH[128] = { 0x0402, 0x0403, 0x201A, 0x0453, 0x201E, 0x2026, 0x2020, 0x2021, 0x20AC, 0x2030, 0x0409, 0x2039, 0x040A, 0x040C, 0x040B, 0x040F, - 0x0452, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x0098, 0x2122, 0x0459, 0x203A, 0x045A, 0x045C, 0x045B, 0x045F, + 0x0452, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x0000, 0x2122, 0x0459, 0x203A, 0x045A, 0x045C, 0x045B, 0x045F, 0x00A0, 0x040E, 0x045E, 0x0408, 0x00A4, 0x0490, 0x00A6, 0x00A7, 0x0401, 0x00A9, 0x0404, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x0407, 0x00B0, 0x00B1, 0x0406, 0x0456, 0x0491, 0x00B5, 0x00B6, 0x00B7, 0x0451, 0x2116, 0x0454, 0x00BB, 0x0458, 0x0405, 0x0455, 0x0457, 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F, @@ -50,8 +54,8 @@ constexpr uint16_t CP1251_HIGH[128] = { }; constexpr uint16_t CP1250_HIGH[128] = { - 0x20AC, 0x0081, 0x201A, 0x0083, 0x201E, 0x2026, 0x2020, 0x2021, 0x0088, 0x2030, 0x0160, 0x2039, 0x015A, 0x0164, 0x017D, 0x0179, - 0x0090, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x0098, 0x2122, 0x0161, 0x203A, 0x015B, 0x0165, 0x017E, 0x017A, + 0x20AC, 0x0000, 0x201A, 0x0000, 0x201E, 0x2026, 0x2020, 0x2021, 0x0000, 0x2030, 0x0160, 0x2039, 0x015A, 0x0164, 0x017D, 0x0179, + 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x0000, 0x2122, 0x0161, 0x203A, 0x015B, 0x0165, 0x017E, 0x017A, 0x00A0, 0x02C7, 0x02D8, 0x0141, 0x00A4, 0x0104, 0x00A6, 0x00A7, 0x00A8, 0x00A9, 0x015E, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x017B, 0x00B0, 0x00B1, 0x02DB, 0x0142, 0x00B4, 0x00B5, 0x00B6, 0x00B7, 0x00B8, 0x0105, 0x015F, 0x00BB, 0x013D, 0x02DD, 0x013E, 0x017C, 0x0154, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x0139, 0x0106, 0x00C7, 0x010C, 0x00C9, 0x0118, 0x00CB, 0x011A, 0x00CD, 0x00CE, 0x010E, @@ -79,9 +83,12 @@ const uint16_t* sbcHighTable(const void* profile) { return nullptr; } -uint32_t sbcToUnicode(const uint8_t* profile, uint8_t sbc) { - if (const uint16_t* high = sbcHighTable(profile)) return sbc >= 0x80 ? high[sbc - 0x80] : sbc; - return sbc >= 0x80 && sbc < 0xA0 ? CP1252_HIGH[sbc - 0x80] : sbc; +bool sbcToUnicode(const uint8_t* profile, uint8_t sbc, uint32_t& code) { + code = sbc; + if (sbc < 0x80) return true; + if (const uint16_t* high = sbcHighTable(profile)) code = high[sbc - 0x80]; + else if (sbc < 0xA0) code = CP1252_HIGH[sbc - 0x80]; + return code != 0; } bool unicodeToSbc(const uint8_t* profile, uint32_t code, uint8_t& sbc) { @@ -111,25 +118,32 @@ bool unicodeToSbc(const uint8_t* profile, uint32_t code, uint8_t& sbc) { return false; } -int decodeUtf8(const uint8_t* utf8, uint32_t utf8max, uint32_t& length, uint32_t& code) { +int decodeScalarUtf8(const uint8_t* utf8, uint32_t utf8max, uint32_t& length, uint32_t& code) { const uint8_t lead = utf8[0]; + length = 0; uint32_t minimum = 0; if (lead < 0x80) { length = 1; code = lead; return 0; } - if ((lead & 0xE0) == 0xC0) { length = 2; code = lead & 0x1F; minimum = 0x80; } - else if ((lead & 0xF0) == 0xE0) { length = 3; code = lead & 0x0F; minimum = 0x800; } - else if ((lead & 0xF8) == 0xF0) { length = 4; code = lead & 0x07; minimum = 0x10000; } - else return CES_ERROR_INVALID_ENCODE; - - for (uint32_t i = 1; i < length; ++i) { - if (i >= utf8max) return CES_ERROR_SRC_BUFFER_END; - if ((utf8[i] & 0xC0) != 0x80) return CES_ERROR_INVALID_ENCODE; + if (lead < 0xC0 || lead >= 0xFE) return CES_ERROR_INVALID_ENCODE; + if (lead < 0xE0) { length = 2; code = lead & 0x1F; minimum = 0x80; } + else if (lead < 0xF0) { length = 3; code = lead & 0x0F; minimum = 0x800; } + else if (lead < 0xF8) { length = 4; code = lead & 0x07; minimum = 0x10000; } + else if (lead < 0xFC) { length = 5; code = lead & 0x03; minimum = 0x200000; } + else { length = 6; code = lead & 0x01; minimum = 0x4000000; } + const bool truncated = utf8max < length; + const uint32_t present = truncated ? utf8max : length; + for (uint32_t i = 1; i < present; ++i) { + if ((utf8[i] & 0xC0) != 0x80) { + length = truncated ? i + 1 : i; + return CES_ERROR_INVALID_ENCODE; + } code = code << 6 | (utf8[i] & 0x3F); } - if (code < minimum || code > 0x10FFFF || (code >= 0xD800 && code <= 0xDFFF)) return CES_ERROR_INVALID_ENCODE; + if (truncated) return CES_ERROR_SRC_BUFFER_END; + if (code < minimum || (code >= 0xD800 && code <= 0xDFFF)) return CES_ERROR_ILLEGAL_CODE; return 0; } @@ -180,7 +194,7 @@ bool hasSs2(const void* profile) { } bool hasSs3(const void* profile) { - return hasTag(profile, EUC_JP_TAG) || hasTag(profile, EUC_JP_X0208_SS3_TAG); + return hasTag(profile, EUC_JP_X0208_SS3_TAG); } bool isSjisX0208(const void* profile) { @@ -569,6 +583,79 @@ int encodeDbcs(const std::vector& reverse, bool euc, uint32_t code, ui return 0; } +bool jisX0212RowEmpty(uint8_t row) { + for (uint32_t cell = 0; cell < 94; ++cell) { + if (JisX0212::TO_UCS2[(row - 0xA1) * 94 + cell] != 0) return false; + } + return true; +} + +int decodeEucJpScalar(const uint8_t* euc, uint32_t eucMax, uint32_t& length, uint32_t& code) { + const uint8_t lead = euc[0]; + length = 1; + if (lead == 0x0E || lead == 0xA0 || lead == 0xFF) return CES_ERROR_INVALID_ENCODE; + if (lead < 0xA0 && lead != 0x8E && lead != 0x8F) { + code = lead; + return 0; + } + const uint32_t needed = lead == 0x8F ? 3 : 2; + for (uint32_t i = 1; i < needed && i < eucMax; ++i) { + if (euc[i] == 0) { + length = i; + return CES_ERROR_INVALID_ENCODE; + } + } + length = needed; + if (eucMax < needed) return CES_ERROR_SRC_BUFFER_END; + const uint8_t trail = euc[1]; + if (lead == 0x8E) { + if (trail >= 0xA1 && trail <= 0xDF) { + code = 0xFF61 + (trail - 0xA1); + return 0; + } + return trail >= 0xE0 && trail <= 0xFE ? CES_ERROR_UNASSIGNED_CODE : CES_ERROR_INVALID_ENCODE; + } + if (lead == 0x8F) { + if (trail < 0xA1 || trail > 0xFE || euc[2] < 0xA1 || euc[2] > 0xFE) return CES_ERROR_INVALID_ENCODE; + return jisX0212RowEmpty(trail) ? CES_ERROR_UNASSIGNED_CODE : CES_ERROR_INVALID_ENCODE; + } + if (trail < 0xA1 || trail > 0xFE) return CES_ERROR_INVALID_ENCODE; + code = JisX0208::TO_UCS2[(lead - 0xA1) * 94 + (trail - 0xA1)]; + return code != 0 ? 0 : CES_ERROR_UNASSIGNED_CODE; +} + +int decodeEucJp(const void* profile, const uint8_t* mbcs, uint32_t mbcsMax, uint32_t& length, uint32_t& code) { + if (hasTag(profile, EUC_JP_TAG)) return decodeEucJpScalar(mbcs, mbcsMax, length, code); + const uint8_t lead = mbcs[0]; + if (lead < 0x80) { + length = 1; + code = lead; + return 0; + } + if (lead == 0x8E && hasSs2(profile)) { + if (mbcsMax < 2) return CES_ERROR_SRC_BUFFER_END; + if (mbcs[1] < 0xA1 || mbcs[1] > 0xDF) return CES_ERROR_INVALID_ENCODE; + length = 2; + code = 0xFF61 + (mbcs[1] - 0xA1); + return 0; + } + if (lead >= 0xA1 && lead <= 0xFE) { + if (mbcsMax < 2) return CES_ERROR_SRC_BUFFER_END; + if (mbcs[1] < 0xA1 || mbcs[1] > 0xFE) return CES_ERROR_INVALID_ENCODE; + length = 2; + code = jisX0208ToUnicode(isEucJpX0208(profile), (lead - 0xA1) * 94 + (mbcs[1] - 0xA1)); + return code != 0 ? 0 : CES_ERROR_UNASSIGNED_CODE; + } + if (lead == 0x8F && hasSs3(profile)) { + if (mbcsMax < 3) return CES_ERROR_SRC_BUFFER_END; + if (mbcs[1] < 0xA1 || mbcs[1] > 0xFE || mbcs[2] < 0xA1 || mbcs[2] > 0xFE) return CES_ERROR_INVALID_ENCODE; + length = 3; + code = JisX0212::TO_UCS2[(mbcs[1] - 0xA1) * 94 + (mbcs[2] - 0xA1)]; + return code != 0 ? 0 : CES_ERROR_UNASSIGNED_CODE; + } + return CES_ERROR_INVALID_ENCODE; +} + int decodeMbcs(const void* profile, const uint8_t* mbcs, uint32_t mbcsMax, uint32_t& length, uint32_t& code) { if (isEucKr(profile) || isUhc(profile)) return decodeCp949(isUhc(profile), mbcs, mbcsMax, length, code); if (isBig5(profile)) return decodeCp950(mbcs, mbcsMax, length, code); @@ -577,8 +664,7 @@ int decodeMbcs(const void* profile, const uint8_t* mbcs, uint32_t mbcsMax, uint3 const uint8_t lead = mbcs[0]; if (isSbc(profile)) { length = 1; - code = sbcToUnicode(static_cast(profile), lead); - return 0; + return sbcToUnicode(static_cast(profile), lead, code) ? 0 : CES_ERROR_UNASSIGNED_CODE; } if (isSjis(profile)) { const bool strict = isSjisX0208(profile); @@ -627,33 +713,7 @@ int decodeMbcs(const void* profile, const uint8_t* mbcs, uint32_t mbcsMax, uint3 } return CES_ERROR_INVALID_ENCODE; } - if (lead < 0x80) { - length = 1; - code = lead; - return 0; - } - if (lead == 0x8E && hasSs2(profile)) { - if (mbcsMax < 2) return CES_ERROR_SRC_BUFFER_END; - if (mbcs[1] < 0xA1 || mbcs[1] > 0xDF) return CES_ERROR_INVALID_ENCODE; - length = 2; - code = 0xFF61 + (mbcs[1] - 0xA1); - return 0; - } - if (lead >= 0xA1 && lead <= 0xFE) { - if (mbcsMax < 2) return CES_ERROR_SRC_BUFFER_END; - if (mbcs[1] < 0xA1 || mbcs[1] > 0xFE) return CES_ERROR_INVALID_ENCODE; - length = 2; - code = jisX0208ToUnicode(isEucJpX0208(profile), (lead - 0xA1) * 94 + (mbcs[1] - 0xA1)); - return code != 0 ? 0 : CES_ERROR_UNASSIGNED_CODE; - } - if (lead == 0x8F && hasSs3(profile)) { - if (mbcsMax < 3) return CES_ERROR_SRC_BUFFER_END; - if (mbcs[1] < 0xA1 || mbcs[1] > 0xFE || mbcs[2] < 0xA1 || mbcs[2] > 0xFE) return CES_ERROR_INVALID_ENCODE; - length = 3; - code = JisX0212::TO_UCS2[(mbcs[1] - 0xA1) * 94 + (mbcs[2] - 0xA1)]; - return code != 0 ? 0 : CES_ERROR_UNASSIGNED_CODE; - } - return CES_ERROR_INVALID_ENCODE; + return decodeEucJp(profile, mbcs, mbcsMax, length, code); } struct JisCell { @@ -686,6 +746,21 @@ const std::vector& jisReverse(bool strict) { return reverse; } +uint32_t jisAlias(uint32_t code) { + switch (code) { + case 0x00A2: return 0xFFE0; + case 0x00A3: return 0xFFE1; + case 0x00A5: return 0xFFE5; + case 0x00AC: return 0xFFE2; + case 0x2014: return 0x2015; + case 0x2016: return 0x2225; + case 0x203E: return 0xFFE3; + case 0x2212: return 0xFF0D; + case 0x301C: return 0xFF5E; + default: return code; + } +} + int encodeMbcs(const void* profile, uint32_t code, uint8_t* mbcs, uint32_t& length) { if (isEucKr(profile) || isUhc(profile)) return encodeDbcs(cp949Reverse(), isEucKr(profile), code, mbcs, length); if (isBig5(profile)) return encodeDbcs(cp950Reverse(), false, code, mbcs, length); @@ -703,6 +778,12 @@ int encodeMbcs(const void* profile, uint32_t code, uint8_t* mbcs, uint32_t& leng mbcs[0] = static_cast(code); return 0; } + if (!strict && code <= 0x9F) return CES_ERROR_UNSUPPORTED_CODE; + if (!strict && code == 0xFEFF) { + length = 0; + return 0; + } + if (!strict) code = jisAlias(code); if (code >= 0xFF61 && code <= 0xFF9F) { length = 1; mbcs[0] = static_cast(0xA1 + (code - 0xFF61)); @@ -717,11 +798,18 @@ int encodeMbcs(const void* profile, uint32_t code, uint8_t* mbcs, uint32_t& leng length = 2; return 0; } - if (code < 0x80) { + const bool strict = isEucJpX0208(profile); + if (!strict && code == 0x0E) return CES_ERROR_UNASSIGNED_CODE; + if (code < 0x80 || (!strict && code < 0xA0 && code != 0x8E && code != 0x8F)) { length = 1; mbcs[0] = static_cast(code); return 0; } + if (!strict && code == 0xFEFF) { + length = 0; + return 0; + } + if (!strict) code = jisAlias(code); if (code >= 0xFF61 && code <= 0xFF9F) { if (!hasSs2(profile)) return CES_ERROR_UNASSIGNED_CODE; length = 2; @@ -730,7 +818,6 @@ int encodeMbcs(const void* profile, uint32_t code, uint8_t* mbcs, uint32_t& leng return 0; } if (code > 0xFFFF) return CES_ERROR_UNASSIGNED_CODE; - const bool strict = isEucJpX0208(profile); if (strict && code == JIS_X0208_UNSETTLED_CODE) throw std::runtime_error(JIS_X0208_UNSETTLED); const auto& reverse = jisReverse(strict); const auto found = std::lower_bound(reverse.begin(), reverse.end(), static_cast(code), [](const JisCell& entry, uint16_t value) { return entry.code < value; }); @@ -751,7 +838,7 @@ int encodeMbcs(const void* profile, uint32_t code, uint8_t* mbcs, uint32_t& leng int decodeUcs2(const uint16_t* ucs2, uint32_t, uint32_t& length, uint32_t& code) { length = 1; code = ucs2[0]; - return code >= 0xD800 && code <= 0xDFFF ? CES_ERROR_INVALID_ENCODE : 0; + return code >= 0xD800 && code <= 0xDFFF ? CES_ERROR_ILLEGAL_CODE : 0; } uint32_t encodeUcs2(uint32_t code, uint16_t* ucs2) { @@ -770,58 +857,41 @@ uint32_t encodeUtf16(uint32_t code, uint16_t* utf16) { return 2; } -template -int toMbcs(const void* context, const Source* source, uint32_t sourceMax, uint32_t* sourceLen, uint8_t* mbcs, uint32_t mbcsMax, uint32_t* mbcsLen, Decode decode) { +template +int convertString(const void* context, const Source* source, uint32_t sourceMax, uint32_t* sourceLen, Target* target, uint32_t targetMax, uint32_t* targetLen, bool counting, Decode decode, Encode encode) { + if (sourceLen) *sourceLen = 0; + if (targetLen) *targetLen = 0; + if (target && targetMax > 0) target[0] = 0; if (!context) return CES_ERROR_INVALID_PARAMETER; const void* profile = contextProfile(context); if (!isMbcs(profile)) return CES_ERROR_INVALID_PARAMETER; if (!source) return CES_ERROR_INVALID_SRC_BUFFER; + if (!counting && !target) return CES_ERROR_INVALID_DST_BUFFER; uint32_t read = 0; uint32_t written = 0; - while (read < sourceMax && source[read] != 0) { + int result = 0; + while ((sourceMax == 0 || read < sourceMax) && source[read] != 0) { uint32_t length = 0; uint32_t code = 0; - if (const int result = decode(source + read, sourceMax - read, length, code); result != 0) return result; - uint8_t encoded[4]; - uint32_t size = 0; - if (const int result = encodeMbcs(profile, code, encoded, size); result != 0) return result; - if (mbcs) { - if (written + size > mbcsMax) return CES_ERROR_DST_BUFFER_END; - std::memcpy(mbcs + written, encoded, size); - } - read += length; - written += size; - } - if (sourceLen) *sourceLen = read; - if (mbcsLen) *mbcsLen = written; - return 0; -} - -template -int fromMbcs(const void* context, const uint8_t* mbcs, uint32_t mbcsMax, uint32_t* mbcsLen, Target* target, uint32_t targetMax, uint32_t* targetLen, Encode encode) { - if (!context) return CES_ERROR_INVALID_PARAMETER; - const void* profile = contextProfile(context); - if (!isMbcs(profile)) return CES_ERROR_INVALID_PARAMETER; - if (!mbcs) return CES_ERROR_INVALID_SRC_BUFFER; - uint32_t read = 0; - uint32_t written = 0; - while (read < mbcsMax && mbcs[read] != 0) { - uint32_t length = 0; - uint32_t code = 0; - if (const int result = decodeMbcs(profile, mbcs + read, mbcsMax - read, length, code); result != 0) return result; + const uint32_t available = sourceMax == 0 ? UINT32_MAX - read : sourceMax - read; + if ((result = decode(profile, source + read, available, length, code)) != 0) break; Target encoded[4]; - const uint32_t size = encode(code, encoded); - if (size == 0) return CES_ERROR_UNASSIGNED_CODE; - if (target) { - if (written + size > targetMax) return CES_ERROR_DST_BUFFER_END; + uint32_t size = 0; + if ((result = encode(profile, code, encoded, size)) != 0) break; + if (!counting) { + if (written + size >= targetMax) { + result = CES_ERROR_DST_BUFFER_END; + break; + } std::memcpy(target + written, encoded, size * sizeof(Target)); } read += length; written += size; } - if (mbcsLen) *mbcsLen = read; + if (!counting && written < targetMax) target[written] = 0; + if (sourceLen) *sourceLen = read; if (targetLen) *targetLen = written; - return 0; + return result; } int mbcsToUtf8(bool accepted, const void* profile, const uint8_t* mbcs, uint32_t mbcsMax, uint32_t* mbcsLen, uint8_t* utf8, uint32_t utf8Max, uint32_t* utf8Len) { @@ -861,6 +931,11 @@ bool isScalar(uint32_t code) { return code <= 0x10FFFF && (code < 0xD800 || code > 0xDFFF); } +int scalarError(uint32_t code) { + if (code > 0x10FFFF) return CES_ERROR_INVALID_ENCODE; + return code >= 0xD800 && code <= 0xDFFF ? CES_ERROR_ILLEGAL_CODE : 0; +} + template int decodeUtf16(const uint16_t* utf16, uint32_t utf16max, uint32_t& length, uint32_t& code) { code = loadUnit(utf16); @@ -948,8 +1023,14 @@ int encodeProfiled(const void* profile, uint32_t code, uint8_t* target, uint32_t int scalarToProfiled(bool (*matches)(const void*), uint32_t code, const void* profile, uint8_t* target, uint32_t targetMax, uint32_t* targetSize) { if (!matches(profile)) return CES_ERROR_INVALID_PARAMETER; if (!target) return CES_ERROR_INVALID_DST_BUFFER; - if (!isScalar(code)) return CES_ERROR_INVALID_ENCODE; - return encodeProfiled(profile, code, target, targetMax, targetSize); + int result = scalarError(code); + uint8_t encoded[4]; + uint32_t size = 0; + if (result == 0) result = encodeMbcs(profile, code, encoded, size); + if (result == 0 && targetMax < size) result = CES_ERROR_DST_BUFFER_END; + if (result == 0) std::memcpy(target, encoded, size); + if (targetSize) *targetSize = result == 0 || result == CES_ERROR_DST_BUFFER_END ? size : 0; + return result; } template @@ -984,11 +1065,21 @@ uint32_t encodeUtf32(uint32_t code, uint32_t* utf32) { return 1; } +template +int unitSource(const void*, const Unit* source, uint32_t sourceMax, uint32_t& length, uint32_t& code) { + return Decode(source, sourceMax, length, code); +} + +template +int unitTarget(const void*, uint32_t code, Unit* target, uint32_t& length) { + length = Encode(code, target); + return length != 0 ? 0 : CES_ERROR_UNASSIGNED_CODE; +} + int sbcToUnit(const uint8_t* profile, uint8_t sbc, const void* target, uint32_t& code) { if (!isSbc(profile)) return CES_ERROR_INVALID_PARAMETER; if (!target) return CES_ERROR_INVALID_DST_BUFFER; - code = sbcToUnicode(profile, sbc); - return 0; + return sbcToUnicode(profile, sbc, code) ? 0 : CES_ERROR_UNASSIGNED_CODE; } template @@ -1174,7 +1265,7 @@ void* APS5_VABI sceCesUcsProfileInitSJis1997X0208(void* sheet) { } int APS5_VABI sceCesMbcsUcsContextInit(void* context, const void* profile) { - if (!context) return CES_ERROR_INVALID_PARAMETER; + if (!context || !profile) return CES_ERROR_INVALID_PARAMETER; std::memcpy(context, &profile, sizeof(profile)); return 0; } @@ -1229,106 +1320,115 @@ void* APS5_VABI sceCesUcsProfileInitBig5Cp950(void* sheet) { } int APS5_VABI sceCesUtf8StrToMbcsStr(void* context, const uint8_t* utf8, uint32_t utf8max, uint32_t* utf8Len, uint8_t* mbcs, uint32_t mbcsMax, uint32_t* mbcsLen) { - if (!mbcs) return CES_ERROR_INVALID_DST_BUFFER; - return toMbcs(context, utf8, utf8max, utf8Len, mbcs, mbcsMax, mbcsLen, decodeUtf8); + return convertString(context, utf8, utf8max, utf8Len, mbcs, mbcsMax, mbcsLen, false, unitSource, encodeMbcs); } int APS5_VABI sceCesUtf8StrGetMbcsLen(void* context, const uint8_t* utf8, uint32_t utf8max, uint32_t* utf8Len, uint32_t* mbcsLen) { - return toMbcs(context, utf8, utf8max, utf8Len, static_cast(nullptr), 0, mbcsLen, decodeUtf8); + return convertString(context, utf8, utf8max, utf8Len, static_cast(nullptr), 0, mbcsLen, true, unitSource, encodeMbcs); } int APS5_VABI sceCesUcs2StrToMbcsStr(void* context, const uint16_t* ucs2, uint32_t ucs2max, uint32_t* ucs2Len, uint8_t* mbcs, uint32_t mbcsMax, uint32_t* mbcsLen) { - if (!mbcs) return CES_ERROR_INVALID_DST_BUFFER; - return toMbcs(context, ucs2, ucs2max, ucs2Len, mbcs, mbcsMax, mbcsLen, decodeUcs2); + return convertString(context, ucs2, ucs2max, ucs2Len, mbcs, mbcsMax, mbcsLen, false, unitSource, encodeMbcs); } int APS5_VABI sceCesUcs2StrGetMbcsLen(void* context, const uint16_t* ucs2, uint32_t ucs2max, uint32_t* ucs2Len, uint32_t* mbcsLen) { - return toMbcs(context, ucs2, ucs2max, ucs2Len, static_cast(nullptr), 0, mbcsLen, decodeUcs2); + return convertString(context, ucs2, ucs2max, ucs2Len, static_cast(nullptr), 0, mbcsLen, true, unitSource, encodeMbcs); } int APS5_VABI sceCesMbcsStrToUtf8Str(void* context, const uint8_t* mbcs, uint32_t mbcsMax, uint32_t* mbcsLen, uint8_t* utf8, uint32_t utf8max, uint32_t* utf8Len) { - if (!utf8) return CES_ERROR_INVALID_DST_BUFFER; - return fromMbcs(context, mbcs, mbcsMax, mbcsLen, utf8, utf8max, utf8Len, encodeUtf8); + return convertString(context, mbcs, mbcsMax, mbcsLen, utf8, utf8max, utf8Len, false, decodeMbcs, unitTarget); } int APS5_VABI sceCesMbcsStrGetUtf8Len(void* context, const uint8_t* mbcs, uint32_t mbcsMax, uint32_t* mbcsLen, uint32_t* utf8Len) { - return fromMbcs(context, mbcs, mbcsMax, mbcsLen, static_cast(nullptr), 0, utf8Len, encodeUtf8); + return convertString(context, mbcs, mbcsMax, mbcsLen, static_cast(nullptr), 0, utf8Len, true, decodeMbcs, unitTarget); } int APS5_VABI sceCesMbcsStrToUcs2Str(void* context, const uint8_t* mbcs, uint32_t mbcsMax, uint32_t* mbcsLen, uint16_t* ucs2, uint32_t ucs2max, uint32_t* ucs2Len) { - if (!ucs2) return CES_ERROR_INVALID_DST_BUFFER; - return fromMbcs(context, mbcs, mbcsMax, mbcsLen, ucs2, ucs2max, ucs2Len, encodeUcs2); + return convertString(context, mbcs, mbcsMax, mbcsLen, ucs2, ucs2max, ucs2Len, false, decodeMbcs, unitTarget); } int APS5_VABI sceCesMbcsStrGetUcs2Len(void* context, const uint8_t* mbcs, uint32_t mbcsMax, uint32_t* mbcsLen, uint32_t* ucs2Len) { - return fromMbcs(context, mbcs, mbcsMax, mbcsLen, static_cast(nullptr), 0, ucs2Len, encodeUcs2); + return convertString(context, mbcs, mbcsMax, mbcsLen, static_cast(nullptr), 0, ucs2Len, true, decodeMbcs, unitTarget); } int APS5_VABI sceCesEucJpToUcs2(const void* profile, const uint8_t* euc, uint32_t eucMax, uint32_t* eucSize, uint16_t* ucs2) { + if (eucSize) *eucSize = 0; + if (ucs2) *ucs2 = 0; + if (!profile) return CES_ERROR_INVALID_PROFILE; if (!isEucJp(profile)) return CES_ERROR_INVALID_PARAMETER; - if (!euc) return CES_ERROR_INVALID_SRC_BUFFER; - if (eucMax == 0) return CES_ERROR_SRC_BUFFER_END; - if (!ucs2) return CES_ERROR_INVALID_DST_BUFFER; + if (!euc || eucMax == 0) return CES_ERROR_INVALID_SRC_BUFFER; uint32_t length = 0; uint32_t code = 0; - if (const int result = decodeMbcs(profile, euc, eucMax, length, code); result != 0) return result; - *ucs2 = static_cast(code); + const int decoded = decodeEucJp(profile, euc, eucMax, length, code); if (eucSize) *eucSize = length; + if (decoded != 0) return decoded; + if (!ucs2) return CES_ERROR_INVALID_DST_BUFFER; + *ucs2 = static_cast(code); return 0; } int APS5_VABI sceCesSbcToUtf8(const uint8_t* profile, uint8_t sbc, uint8_t* utf8, uint32_t utf8max, uint32_t* utf8_len) { + if (utf8_len) *utf8_len = 0; + if (!profile) return CES_ERROR_INVALID_PROFILE; if (!isSbc(profile)) return CES_ERROR_INVALID_PARAMETER; - if (!utf8) return CES_ERROR_INVALID_DST_BUFFER; - + uint32_t code = 0; + if (!sbcToUnicode(profile, sbc, code)) return CES_ERROR_UNASSIGNED_CODE; uint8_t encoded[4]; - const uint32_t length = encodeUtf8(sbcToUnicode(profile, sbc), encoded); + const uint32_t length = encodeUtf8(code, encoded); + if (utf8_len) *utf8_len = length; + if (!utf8) return CES_ERROR_INVALID_DST_BUFFER; if (utf8max < length) return CES_ERROR_DST_BUFFER_END; for (uint32_t i = 0; i < length; ++i) utf8[i] = encoded[i]; - if (utf8_len) *utf8_len = length; return 0; } int APS5_VABI sceCesUtf8ToSbc(const uint8_t* utf8, uint32_t utf8max, uint32_t* utf8_len, const uint8_t* profile, uint8_t* sbc) { - if (!isSbc(profile)) return CES_ERROR_INVALID_PARAMETER; - if (!utf8) return CES_ERROR_INVALID_SRC_BUFFER; - if (utf8max == 0) return CES_ERROR_SRC_BUFFER_END; - if (!sbc) return CES_ERROR_INVALID_DST_BUFFER; - + if (utf8_len) *utf8_len = 0; + if (sbc) *sbc = 0; + if (!utf8 || utf8max == 0) return CES_ERROR_INVALID_SRC_BUFFER; uint32_t length = 0; uint32_t code = 0; - if (const int result = decodeUtf8(utf8, utf8max, length, code); result != 0) return result; - if (!unicodeToSbc(profile, code, *sbc)) return CES_ERROR_UNASSIGNED_CODE; + const int decoded = decodeScalarUtf8(utf8, utf8max, length, code); if (utf8_len) *utf8_len = length; + if (decoded != 0) return decoded; + if (!profile) return CES_ERROR_INVALID_PROFILE; + if (!isSbc(profile)) return CES_ERROR_INVALID_PARAMETER; + uint8_t value = 0; + if (!unicodeToSbc(profile, code, value)) return CES_ERROR_UNASSIGNED_CODE; + if (!sbc) return CES_ERROR_INVALID_DST_BUFFER; + *sbc = value; return 0; } int APS5_VABI sceCesEucJpToUtf8(const void* profile, const uint8_t* eucBuffer, uint32_t eucMax, uint32_t* eucLength, uint8_t* utf8Buffer, uint32_t utf8Max, uint32_t* utf8Length) { + if (eucLength) *eucLength = 0; + if (utf8Length) *utf8Length = 0; + if (!profile) return CES_ERROR_INVALID_PROFILE; if (!isEucJp(profile)) return CES_ERROR_INVALID_PARAMETER; - if (!eucBuffer) return CES_ERROR_INVALID_SRC_BUFFER; - if (eucMax == 0) return CES_ERROR_SRC_BUFFER_END; - if (!utf8Buffer) return CES_ERROR_INVALID_DST_BUFFER; + if (!eucBuffer || eucMax == 0) return CES_ERROR_INVALID_SRC_BUFFER; uint32_t consumed = 0; uint32_t code = 0; - if (const int result = decodeMbcs(profile, eucBuffer, eucMax, consumed, code); result != 0) return result; + const int decoded = decodeEucJp(profile, eucBuffer, eucMax, consumed, code); + if (eucLength) *eucLength = consumed; + if (decoded != 0) return decoded; uint8_t encoded[4]; const uint32_t produced = encodeUtf8(code, encoded); + if (utf8Length) *utf8Length = produced; + if (!utf8Buffer) return CES_ERROR_INVALID_DST_BUFFER; if (utf8Max < produced) return CES_ERROR_DST_BUFFER_END; std::memcpy(utf8Buffer, encoded, produced); - if (eucLength) *eucLength = consumed; - if (utf8Length) *utf8Length = produced; return 0; } -int APS5_VABI sceCesEucKrToUtf8(void* profile, uint8_t* eucBuffer, uint32_t eucMax, uint32_t* eucLength, uint8_t* utf8Buffer, uint32_t utf8Max, uint32_t* utf8Length) { +int APS5_VABI sceCesEucKrToUtf8(const void* profile, const uint8_t* eucBuffer, uint32_t eucMax, uint32_t* eucLength, uint8_t* utf8Buffer, uint32_t utf8Max, uint32_t* utf8Length) { return mbcsToUtf8(isEucKr(profile), profile, eucBuffer, eucMax, eucLength, utf8Buffer, utf8Max, utf8Length); } -int APS5_VABI sceCesBig5ToUtf8(void* profile, uint8_t* big5Buffer, uint32_t big5Max, uint32_t* big5Length, uint8_t* utf8Buffer, uint32_t utf8Max, uint32_t* utf8Length) { +int APS5_VABI sceCesBig5ToUtf8(const void* profile, const uint8_t* big5Buffer, uint32_t big5Max, uint32_t* big5Length, uint8_t* utf8Buffer, uint32_t utf8Max, uint32_t* utf8Length) { return mbcsToUtf8(isBig5(profile), profile, big5Buffer, big5Max, big5Length, utf8Buffer, utf8Max, utf8Length); } -int APS5_VABI sceCesUhcToUtf8(void* profile, uint8_t* uhcBuffer, uint32_t uhcMax, uint32_t* uhcLength, uint8_t* utf8Buffer, uint32_t utf8Max, uint32_t* utf8Length) { +int APS5_VABI sceCesUhcToUtf8(const void* profile, const uint8_t* uhcBuffer, uint32_t uhcMax, uint32_t* uhcLength, uint8_t* utf8Buffer, uint32_t utf8Max, uint32_t* utf8Length) { return mbcsToUtf8(isUhc(profile), profile, uhcBuffer, uhcMax, uhcLength, utf8Buffer, utf8Max, utf8Length); } @@ -1393,7 +1493,7 @@ int APS5_VABI sceCesUcs2ToSJis(uint16_t ucs2, const void* profile, uint8_t* sjis } int APS5_VABI sceCesUtf8ToSJis(const uint8_t* utf8Buffer, uint32_t utf8Max, uint32_t* utf8Length, const void* profile, uint8_t* sjisBuffer, uint32_t sjisMax, uint32_t* sjisSize) { - return bufferToProfiled(isSjis, utf8Buffer, utf8Max, utf8Length, profile, sjisBuffer, sjisMax, sjisSize, decodeUtf8); + return bufferToProfiled(isSjis, utf8Buffer, utf8Max, utf8Length, profile, sjisBuffer, sjisMax, sjisSize, decodeScalarUtf8); } int APS5_VABI sceCesUtf16ToSJis(const uint16_t* utf16Buffer, uint32_t utf16Max, uint32_t* utf16Length, const void* profile, uint8_t* sjisBuffer, uint32_t sjisMax, uint32_t* sjisSize) { @@ -1425,7 +1525,7 @@ int APS5_VABI sceCesUcs2ToEucJp(uint16_t ucs2, const void* profile, uint8_t* euc } int APS5_VABI sceCesUtf8ToEucJp(const uint8_t* utf8Buffer, uint32_t utf8Max, uint32_t* utf8Length, const void* profile, uint8_t* eucBuffer, uint32_t eucMax, uint32_t* eucSize) { - return bufferToProfiled(isEucJp, utf8Buffer, utf8Max, utf8Length, profile, eucBuffer, eucMax, eucSize, decodeUtf8); + return bufferToProfiled(isEucJp, utf8Buffer, utf8Max, utf8Length, profile, eucBuffer, eucMax, eucSize, decodeScalarUtf8); } int APS5_VABI sceCesUtf16ToEucJp(const uint16_t* utf16Buffer, uint32_t utf16Max, uint32_t* utf16Length, const void* profile, uint8_t* eucBuffer, uint32_t eucMax, uint32_t* eucSize) { @@ -1566,6 +1666,38 @@ int APS5_VABI sceCesMbcToUtf32le(const void* profile, const uint8_t* mbcBuffer, return profiledToUtf32(isMbcs, profile, mbcBuffer, mbcMax, mbcLen, utf32); } +int APS5_VABI sceCesUcs2ToMbc(uint16_t ucs2, const void* profile, uint8_t* mbcBuffer, uint32_t mbcMax, uint32_t* mbcLen) { + return scalarToProfiled(isMbcs, ucs2, profile, mbcBuffer, mbcMax, mbcLen); +} + +int APS5_VABI sceCesUtf8ToMbc(const uint8_t* utf8Buffer, uint32_t utf8Max, uint32_t* utf8Len, const void* profile, uint8_t* mbcBuffer, uint32_t mbcMax, uint32_t* mbcLen) { + return bufferToProfiled(isMbcs, utf8Buffer, utf8Max, utf8Len, profile, mbcBuffer, mbcMax, mbcLen, decodeScalarUtf8); +} + +int APS5_VABI sceCesUtf16ToMbc(const uint16_t* utf16Buffer, uint32_t utf16Max, uint32_t* utf16Len, const void* profile, uint8_t* mbcBuffer, uint32_t mbcMax, uint32_t* mbcLen) { + return bufferToProfiled(isMbcs, utf16Buffer, utf16Max, utf16Len, profile, mbcBuffer, mbcMax, mbcLen, decodeUtf16); +} + +int APS5_VABI sceCesUtf16beToMbc(const uint16_t* utf16Buffer, uint32_t utf16Max, uint32_t* utf16Len, const void* profile, uint8_t* mbcBuffer, uint32_t mbcMax, uint32_t* mbcLen) { + return bufferToProfiled(isMbcs, utf16Buffer, utf16Max, utf16Len, profile, mbcBuffer, mbcMax, mbcLen, decodeUtf16); +} + +int APS5_VABI sceCesUtf16leToMbc(const uint16_t* utf16Buffer, uint32_t utf16Max, uint32_t* utf16Len, const void* profile, uint8_t* mbcBuffer, uint32_t mbcMax, uint32_t* mbcLen) { + return bufferToProfiled(isMbcs, utf16Buffer, utf16Max, utf16Len, profile, mbcBuffer, mbcMax, mbcLen, decodeUtf16); +} + +int APS5_VABI sceCesUtf32ToMbc(uint32_t utf32, const void* profile, uint8_t* mbcBuffer, uint32_t mbcMax, uint32_t* mbcLen) { + return scalarToProfiled(isMbcs, utf32, profile, mbcBuffer, mbcMax, mbcLen); +} + +int APS5_VABI sceCesUtf32beToMbc(const uint32_t* utf32, const void* profile, uint8_t* mbcBuffer, uint32_t mbcMax, uint32_t* mbcLen) { + return utf32ToProfiled(isMbcs, utf32, profile, mbcBuffer, mbcMax, mbcLen); +} + +int APS5_VABI sceCesUtf32leToMbc(const uint32_t* utf32, const void* profile, uint8_t* mbcBuffer, uint32_t mbcMax, uint32_t* mbcLen) { + return utf32ToProfiled(isMbcs, utf32, profile, mbcBuffer, mbcMax, mbcLen); +} + int APS5_VABI sceCesSbcToUcs2(const uint8_t* profile, uint8_t sbc, uint16_t* ucs2) { uint32_t code = 0; if (const int result = sbcToUnit(profile, sbc, ucs2, code); result != 0) return result; @@ -1626,39 +1758,35 @@ int APS5_VABI sceCesUtf32leToSbc(const uint32_t* utf32, const uint8_t* profile, } int APS5_VABI sceCesUtf16StrToMbcsStr(void* context, const uint16_t* utf16, uint32_t utf16max, uint32_t* utf16Len, uint8_t* mbcs, uint32_t mbcsMax, uint32_t* mbcsLen) { - if (!mbcs) return CES_ERROR_INVALID_DST_BUFFER; - return toMbcs(context, utf16, utf16max, utf16Len, mbcs, mbcsMax, mbcsLen, decodeUtf16); + return convertString(context, utf16, utf16max, utf16Len, mbcs, mbcsMax, mbcsLen, false, unitSource, uint16_t>, encodeMbcs); } int APS5_VABI sceCesUtf16StrGetMbcsLen(void* context, const uint16_t* utf16, uint32_t utf16max, uint32_t* utf16Len, uint32_t* mbcsLen) { - return toMbcs(context, utf16, utf16max, utf16Len, static_cast(nullptr), 0, mbcsLen, decodeUtf16); + return convertString(context, utf16, utf16max, utf16Len, static_cast(nullptr), 0, mbcsLen, true, unitSource, uint16_t>, encodeMbcs); } int APS5_VABI sceCesMbcsStrToUtf16Str(void* context, const uint8_t* mbcs, uint32_t mbcsMax, uint32_t* mbcsLen, uint16_t* utf16, uint32_t utf16max, uint32_t* utf16Len) { - if (!utf16) return CES_ERROR_INVALID_DST_BUFFER; - return fromMbcs(context, mbcs, mbcsMax, mbcsLen, utf16, utf16max, utf16Len, encodeUtf16); + return convertString(context, mbcs, mbcsMax, mbcsLen, utf16, utf16max, utf16Len, false, decodeMbcs, unitTarget); } int APS5_VABI sceCesMbcsStrGetUtf16Len(void* context, const uint8_t* mbcs, uint32_t mbcsMax, uint32_t* mbcsLen, uint32_t* utf16Len) { - return fromMbcs(context, mbcs, mbcsMax, mbcsLen, static_cast(nullptr), 0, utf16Len, encodeUtf16); + return convertString(context, mbcs, mbcsMax, mbcsLen, static_cast(nullptr), 0, utf16Len, true, decodeMbcs, unitTarget); } int APS5_VABI sceCesUtf32StrToMbcsStr(void* context, const uint32_t* utf32, uint32_t utf32max, uint32_t* utf32Len, uint8_t* mbcs, uint32_t mbcsMax, uint32_t* mbcsLen) { - if (!mbcs) return CES_ERROR_INVALID_DST_BUFFER; - return toMbcs(context, utf32, utf32max, utf32Len, mbcs, mbcsMax, mbcsLen, decodeUtf32); + return convertString(context, utf32, utf32max, utf32Len, mbcs, mbcsMax, mbcsLen, false, unitSource, encodeMbcs); } int APS5_VABI sceCesUtf32StrGetMbcsLen(void* context, const uint32_t* utf32, uint32_t utf32max, uint32_t* utf32Len, uint32_t* mbcsLen) { - return toMbcs(context, utf32, utf32max, utf32Len, static_cast(nullptr), 0, mbcsLen, decodeUtf32); + return convertString(context, utf32, utf32max, utf32Len, static_cast(nullptr), 0, mbcsLen, true, unitSource, encodeMbcs); } int APS5_VABI sceCesMbcsStrToUtf32Str(void* context, const uint8_t* mbcs, uint32_t mbcsMax, uint32_t* mbcsLen, uint32_t* utf32, uint32_t utf32max, uint32_t* utf32Len) { - if (!utf32) return CES_ERROR_INVALID_DST_BUFFER; - return fromMbcs(context, mbcs, mbcsMax, mbcsLen, utf32, utf32max, utf32Len, encodeUtf32); + return convertString(context, mbcs, mbcsMax, mbcsLen, utf32, utf32max, utf32Len, false, decodeMbcs, unitTarget); } int APS5_VABI sceCesMbcsStrGetUtf32Len(void* context, const uint8_t* mbcs, uint32_t mbcsMax, uint32_t* mbcsLen, uint32_t* utf32Len) { - return fromMbcs(context, mbcs, mbcsMax, mbcsLen, static_cast(nullptr), 0, utf32Len, encodeUtf32); + return convertString(context, mbcs, mbcsMax, mbcsLen, static_cast(nullptr), 0, utf32Len, true, decodeMbcs, unitTarget); } void* APS5_VABI sceCesUcsProfileInitEucCnGb2312(void* sheet) { @@ -1722,7 +1850,7 @@ int APS5_VABI sceCesUcs2ToEucCn(uint16_t ucs2, const void* profile, uint8_t* euc } int APS5_VABI sceCesUtf8ToEucCn(const uint8_t* utf8Buffer, uint32_t utf8Max, uint32_t* utf8Length, const void* profile, uint8_t* eucBuffer, uint32_t eucMax, uint32_t* eucSize) { - return bufferToProfiled(isEucCn, utf8Buffer, utf8Max, utf8Length, profile, eucBuffer, eucMax, eucSize, decodeUtf8); + return bufferToProfiled(isEucCn, utf8Buffer, utf8Max, utf8Length, profile, eucBuffer, eucMax, eucSize, decodeScalarUtf8); } int APS5_VABI sceCesUtf16ToEucCn(const uint16_t* utf16Buffer, uint32_t utf16Max, uint32_t* utf16Length, const void* profile, uint8_t* eucBuffer, uint32_t eucMax, uint32_t* eucSize) { @@ -1786,7 +1914,7 @@ int APS5_VABI sceCesUcs2ToGb(uint16_t ucs2, const void* profile, uint8_t* gbBuff } int APS5_VABI sceCesUtf8ToGb(const uint8_t* utf8Buffer, uint32_t utf8Max, uint32_t* utf8Length, const void* profile, uint8_t* gbBuffer, uint32_t gbMax, uint32_t* gbSize) { - return bufferToProfiled(isGb, utf8Buffer, utf8Max, utf8Length, profile, gbBuffer, gbMax, gbSize, decodeUtf8); + return bufferToProfiled(isGb, utf8Buffer, utf8Max, utf8Length, profile, gbBuffer, gbMax, gbSize, decodeScalarUtf8); } int APS5_VABI sceCesUtf16ToGb(const uint16_t* utf16Buffer, uint32_t utf16Max, uint32_t* utf16Length, const void* profile, uint8_t* gbBuffer, uint32_t gbMax, uint32_t* gbSize) { @@ -1902,7 +2030,7 @@ int APS5_VABI sceCesUcs2ToEucKr(uint16_t ucs2, const void* profile, uint8_t* euc } int APS5_VABI sceCesUtf8ToEucKr(const uint8_t* utf8Buffer, uint32_t utf8Max, uint32_t* utf8Length, const void* profile, uint8_t* eucBuffer, uint32_t eucMax, uint32_t* eucSize) { - return bufferToProfiled(isEucKr, utf8Buffer, utf8Max, utf8Length, profile, eucBuffer, eucMax, eucSize, decodeUtf8); + return bufferToProfiled(isEucKr, utf8Buffer, utf8Max, utf8Length, profile, eucBuffer, eucMax, eucSize, decodeScalarUtf8); } int APS5_VABI sceCesUtf16ToEucKr(const uint16_t* utf16Buffer, uint32_t utf16Max, uint32_t* utf16Length, const void* profile, uint8_t* eucBuffer, uint32_t eucMax, uint32_t* eucSize) { @@ -1934,7 +2062,7 @@ int APS5_VABI sceCesUcs2ToUhc(uint16_t ucs2, const void* profile, uint8_t* uhcBu } int APS5_VABI sceCesUtf8ToUhc(const uint8_t* utf8Buffer, uint32_t utf8Max, uint32_t* utf8Length, const void* profile, uint8_t* uhcBuffer, uint32_t uhcMax, uint32_t* uhcSize) { - return bufferToProfiled(isUhc, utf8Buffer, utf8Max, utf8Length, profile, uhcBuffer, uhcMax, uhcSize, decodeUtf8); + return bufferToProfiled(isUhc, utf8Buffer, utf8Max, utf8Length, profile, uhcBuffer, uhcMax, uhcSize, decodeScalarUtf8); } int APS5_VABI sceCesUtf16ToUhc(const uint16_t* utf16Buffer, uint32_t utf16Max, uint32_t* utf16Length, const void* profile, uint8_t* uhcBuffer, uint32_t uhcMax, uint32_t* uhcSize) { @@ -1966,7 +2094,7 @@ int APS5_VABI sceCesUcs2ToBig5(uint16_t ucs2, const void* profile, uint8_t* big5 } int APS5_VABI sceCesUtf8ToBig5(const uint8_t* utf8Buffer, uint32_t utf8Max, uint32_t* utf8Length, const void* profile, uint8_t* big5Buffer, uint32_t big5Max, uint32_t* big5Size) { - return bufferToProfiled(isBig5, utf8Buffer, utf8Max, utf8Length, profile, big5Buffer, big5Max, big5Size, decodeUtf8); + return bufferToProfiled(isBig5, utf8Buffer, utf8Max, utf8Length, profile, big5Buffer, big5Max, big5Size, decodeScalarUtf8); } int APS5_VABI sceCesUtf16ToBig5(const uint16_t* utf16Buffer, uint32_t utf16Max, uint32_t* utf16Length, const void* profile, uint8_t* big5Buffer, uint32_t big5Max, uint32_t* big5Size) { diff --git a/core/libs/prx/libSceCesCs/PendingExports.cpp b/core/libs/prx/libSceCesCs/PendingExports.cpp index 1c38e00eed..ac98b0d50a 100644 --- a/core/libs/prx/libSceCesCs/PendingExports.cpp +++ b/core/libs/prx/libSceCesCs/PendingExports.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceCesCs/include/Api.hpp" #include "prx/libc/include/General.hpp" extern "C" { @@ -247,11 +248,6 @@ int APS5_VABI sceCesUcs2StrToIso2022Str(void) { return 0; } -int APS5_VABI sceCesUcs2ToMbc(void) { - NotImplemented_nid_no_patch(__func__); - return 0; -} - int APS5_VABI sceCesUcsProfileInitEucJis2004(void) { NotImplemented_nid_no_patch(__func__); return 0; @@ -297,21 +293,6 @@ int APS5_VABI sceCesUtf16StrToIso2022Str(void) { return 0; } -int APS5_VABI sceCesUtf16ToMbc(void) { - NotImplemented_nid_no_patch(__func__); - return 0; -} - -int APS5_VABI sceCesUtf16beToMbc(void) { - NotImplemented_nid_no_patch(__func__); - return 0; -} - -int APS5_VABI sceCesUtf16leToMbc(void) { - NotImplemented_nid_no_patch(__func__); - return 0; -} - int APS5_VABI sceCesUtf32StrGetIso2022Len(void) { NotImplemented_nid_no_patch(__func__); return 0; @@ -322,21 +303,6 @@ int APS5_VABI sceCesUtf32StrToIso2022Str(void) { return 0; } -int APS5_VABI sceCesUtf32ToMbc(void) { - NotImplemented_nid_no_patch(__func__); - return 0; -} - -int APS5_VABI sceCesUtf32beToMbc(void) { - NotImplemented_nid_no_patch(__func__); - return 0; -} - -int APS5_VABI sceCesUtf32leToMbc(void) { - NotImplemented_nid_no_patch(__func__); - return 0; -} - int APS5_VABI sceCesUtf8StrGetIso2022Len(void) { NotImplemented_nid_no_patch(__func__); return 0; @@ -347,9 +313,4 @@ int APS5_VABI sceCesUtf8StrToIso2022Str(void) { return 0; } -int APS5_VABI sceCesUtf8ToMbc(void) { - NotImplemented_nid_no_patch(__func__); - return 0; -} - } diff --git a/core/libs/prx/libSceCesCs/Unicode.cpp b/core/libs/prx/libSceCesCs/Unicode.cpp index 5a4b10399b..45f36923ee 100644 --- a/core/libs/prx/libSceCesCs/Unicode.cpp +++ b/core/libs/prx/libSceCesCs/Unicode.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceCesCs/include/Api.hpp" #include #include #include diff --git a/core/libs/prx/libSceCesCs/include/Api.hpp b/core/libs/prx/libSceCesCs/include/Api.hpp new file mode 100644 index 0000000000..de9d5746e4 --- /dev/null +++ b/core/libs/prx/libSceCesCs/include/Api.hpp @@ -0,0 +1,295 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +const uint8_t* APS5_VABI sceCesRefersUcsProfileCp1252(void); +const uint8_t* APS5_VABI sceCesRefersUcsProfileCp1251(void); +const void* APS5_VABI sceCesRefersUcsProfileCp1250(void); +const uint8_t* APS5_VABI sceCesRefersUcsProfileIso8859_1(void); +const uint8_t* APS5_VABI sceCesRefersUcsProfileIso8859_2(void); +const uint8_t* APS5_VABI sceCesRefersUcsProfileIso8859_4(void); +const uint8_t* APS5_VABI sceCesRefersUcsProfileIso8859_5(void); +const uint8_t* APS5_VABI sceCesRefersUcsProfileIso8859_9(void); +const uint8_t* APS5_VABI sceCesRefersUcsProfileIso8859_10(void); +const uint8_t* APS5_VABI sceCesRefersUcsProfileIso8859_13(void); +const uint8_t* APS5_VABI sceCesRefersUcsProfileIso8859_14(void); +const uint8_t* APS5_VABI sceCesRefersUcsProfileIso8859_15(void); +const uint8_t* APS5_VABI sceCesRefersUcsProfileIso8859_16(void); +const uint8_t* APS5_VABI sceCesRefersUcsProfileCp437(void); +const uint8_t* APS5_VABI sceCesRefersUcsProfileCp737(void); +const uint8_t* APS5_VABI sceCesRefersUcsProfileCp775(void); +const uint8_t* APS5_VABI sceCesRefersUcsProfileCp850(void); +const uint8_t* APS5_VABI sceCesRefersUcsProfileCp852(void); +const uint8_t* APS5_VABI sceCesRefersUcsProfileCp855(void); +const uint8_t* APS5_VABI sceCesRefersUcsProfileCp860(void); +const uint8_t* APS5_VABI sceCesRefersUcsProfileCp861(void); +const uint8_t* APS5_VABI sceCesRefersUcsProfileCp862(void); +const uint8_t* APS5_VABI sceCesRefersUcsProfileCp863(void); +const uint8_t* APS5_VABI sceCesRefersUcsProfileCp865(void); +const uint8_t* APS5_VABI sceCesRefersUcsProfileCp866(void); +const uint8_t* APS5_VABI sceCesRefersUcsProfileKoi8R(void); +const uint8_t* APS5_VABI sceCesRefersUcsProfileKoi8U(void); +const uint8_t* APS5_VABI sceCesRefersUcsProfileCp1254(void); +const uint8_t* APS5_VABI sceCesRefersUcsProfileCp1256(void); +const uint8_t* APS5_VABI sceCesRefersUcsProfileCp1258(void); +void* APS5_VABI sceCesUcsProfileInitSJis1997Cp932(void* sheet); +void* APS5_VABI sceCesUcsProfileInitSJis1997X0208(void* sheet); +int APS5_VABI sceCesMbcsUcsContextInit(void* context, const void* profile); +int APS5_VABI sceCesMbcsUcsContextInitCopy(void* context, const void* source); +void* APS5_VABI sceCesUcsProfileInitEucJpCp51932(void* sheet); +void* APS5_VABI sceCesUcsProfileInitEucJpX0208(void* sheet); +void* APS5_VABI sceCesUcsProfileInitEucJpX0208Ss2(void* sheet); +void* APS5_VABI sceCesUcsProfileInitEucJpX0208Ss2Ss3(void* sheet); +void* APS5_VABI sceCesUcsProfileInitEucKr(void* sheet); +void* APS5_VABI sceCesUcsProfileInitUhc(void* sheet); +void* APS5_VABI sceCesUcsProfileInitBig5Cp950(void* sheet); +int APS5_VABI sceCesUtf8StrToMbcsStr(void* context, const uint8_t* utf8, uint32_t utf8max, uint32_t* utf8Len, uint8_t* mbcs, uint32_t mbcsMax, uint32_t* mbcsLen); +int APS5_VABI sceCesUtf8StrGetMbcsLen(void* context, const uint8_t* utf8, uint32_t utf8max, uint32_t* utf8Len, uint32_t* mbcsLen); +int APS5_VABI sceCesUcs2StrToMbcsStr(void* context, const uint16_t* ucs2, uint32_t ucs2max, uint32_t* ucs2Len, uint8_t* mbcs, uint32_t mbcsMax, uint32_t* mbcsLen); +int APS5_VABI sceCesUcs2StrGetMbcsLen(void* context, const uint16_t* ucs2, uint32_t ucs2max, uint32_t* ucs2Len, uint32_t* mbcsLen); +int APS5_VABI sceCesMbcsStrToUtf8Str(void* context, const uint8_t* mbcs, uint32_t mbcsMax, uint32_t* mbcsLen, uint8_t* utf8, uint32_t utf8max, uint32_t* utf8Len); +int APS5_VABI sceCesMbcsStrGetUtf8Len(void* context, const uint8_t* mbcs, uint32_t mbcsMax, uint32_t* mbcsLen, uint32_t* utf8Len); +int APS5_VABI sceCesMbcsStrToUcs2Str(void* context, const uint8_t* mbcs, uint32_t mbcsMax, uint32_t* mbcsLen, uint16_t* ucs2, uint32_t ucs2max, uint32_t* ucs2Len); +int APS5_VABI sceCesMbcsStrGetUcs2Len(void* context, const uint8_t* mbcs, uint32_t mbcsMax, uint32_t* mbcsLen, uint32_t* ucs2Len); +int APS5_VABI sceCesEucJpToUcs2(const void* profile, const uint8_t* euc, uint32_t eucMax, uint32_t* eucSize, uint16_t* ucs2); +int APS5_VABI sceCesSbcToUtf8(const uint8_t* profile, uint8_t sbc, uint8_t* utf8, uint32_t utf8max, uint32_t* utf8_len); +int APS5_VABI sceCesUtf8ToSbc(const uint8_t* utf8, uint32_t utf8max, uint32_t* utf8_len, const uint8_t* profile, uint8_t* sbc); +int APS5_VABI sceCesEucJpToUtf8(const void* profile, const uint8_t* eucBuffer, uint32_t eucMax, uint32_t* eucLength, uint8_t* utf8Buffer, uint32_t utf8Max, uint32_t* utf8Length); +int APS5_VABI sceCesEucKrToUtf8(const void* profile, const uint8_t* eucBuffer, uint32_t eucMax, uint32_t* eucLength, uint8_t* utf8Buffer, uint32_t utf8Max, uint32_t* utf8Length); +int APS5_VABI sceCesBig5ToUtf8(const void* profile, const uint8_t* big5Buffer, uint32_t big5Max, uint32_t* big5Length, uint8_t* utf8Buffer, uint32_t utf8Max, uint32_t* utf8Length); +int APS5_VABI sceCesUhcToUtf8(const void* profile, const uint8_t* uhcBuffer, uint32_t uhcMax, uint32_t* uhcLength, uint8_t* utf8Buffer, uint32_t utf8Max, uint32_t* utf8Length); +int APS5_VABI sceCesSJisToUcs2(const void* profile, const uint8_t* sjisBuffer, uint32_t sjisMax, uint32_t* sjisSize, uint16_t* ucs2); +int APS5_VABI sceCesSJisToUtf8(const void* profile, const uint8_t* sjisBuffer, uint32_t sjisMax, uint32_t* sjisSize, uint8_t* utf8Buffer, uint32_t utf8Max, uint32_t* utf8Length); +int APS5_VABI sceCesSJisToUtf16(const void* profile, const uint8_t* sjisBuffer, uint32_t sjisMax, uint32_t* sjisSize, uint16_t* utf16Buffer, uint32_t utf16Max, uint32_t* utf16Length); +int APS5_VABI sceCesSJisToUtf16be(const void* profile, const uint8_t* sjisBuffer, uint32_t sjisMax, uint32_t* sjisSize, uint16_t* utf16Buffer, uint32_t utf16Max, uint32_t* utf16Length); +int APS5_VABI sceCesSJisToUtf16le(const void* profile, const uint8_t* sjisBuffer, uint32_t sjisMax, uint32_t* sjisSize, uint16_t* utf16Buffer, uint32_t utf16Max, uint32_t* utf16Length); +int APS5_VABI sceCesSJisToUtf32(const void* profile, const uint8_t* sjisBuffer, uint32_t sjisMax, uint32_t* sjisSize, uint32_t* utf32); +int APS5_VABI sceCesSJisToUtf32be(const void* profile, const uint8_t* sjisBuffer, uint32_t sjisMax, uint32_t* sjisSize, uint32_t* utf32); +int APS5_VABI sceCesSJisToUtf32le(const void* profile, const uint8_t* sjisBuffer, uint32_t sjisMax, uint32_t* sjisSize, uint32_t* utf32); +int APS5_VABI sceCesEucJpToUtf16(const void* profile, const uint8_t* eucBuffer, uint32_t eucMax, uint32_t* eucSize, uint16_t* utf16Buffer, uint32_t utf16Max, uint32_t* utf16Length); +int APS5_VABI sceCesEucJpToUtf16be(const void* profile, const uint8_t* eucBuffer, uint32_t eucMax, uint32_t* eucSize, uint16_t* utf16Buffer, uint32_t utf16Max, uint32_t* utf16Length); +int APS5_VABI sceCesEucJpToUtf16le(const void* profile, const uint8_t* eucBuffer, uint32_t eucMax, uint32_t* eucSize, uint16_t* utf16Buffer, uint32_t utf16Max, uint32_t* utf16Length); +int APS5_VABI sceCesEucJpToUtf32(const void* profile, const uint8_t* eucBuffer, uint32_t eucMax, uint32_t* eucSize, uint32_t* utf32); +int APS5_VABI sceCesEucJpToUtf32be(const void* profile, const uint8_t* eucBuffer, uint32_t eucMax, uint32_t* eucSize, uint32_t* utf32); +int APS5_VABI sceCesEucJpToUtf32le(const void* profile, const uint8_t* eucBuffer, uint32_t eucMax, uint32_t* eucSize, uint32_t* utf32); +int APS5_VABI sceCesUcs2ToSJis(uint16_t ucs2, const void* profile, uint8_t* sjisBuffer, uint32_t sjisMax, uint32_t* sjisSize); +int APS5_VABI sceCesUtf8ToSJis(const uint8_t* utf8Buffer, uint32_t utf8Max, uint32_t* utf8Length, const void* profile, uint8_t* sjisBuffer, uint32_t sjisMax, uint32_t* sjisSize); +int APS5_VABI sceCesUtf16ToSJis(const uint16_t* utf16Buffer, uint32_t utf16Max, uint32_t* utf16Length, const void* profile, uint8_t* sjisBuffer, uint32_t sjisMax, uint32_t* sjisSize); +int APS5_VABI sceCesUtf16beToSJis(const uint16_t* utf16Buffer, uint32_t utf16Max, uint32_t* utf16Length, const void* profile, uint8_t* sjisBuffer, uint32_t sjisMax, uint32_t* sjisSize); +int APS5_VABI sceCesUtf16leToSJis(const uint16_t* utf16Buffer, uint32_t utf16Max, uint32_t* utf16Length, const void* profile, uint8_t* sjisBuffer, uint32_t sjisMax, uint32_t* sjisSize); +int APS5_VABI sceCesUtf32ToSJis(uint32_t utf32, const void* profile, uint8_t* sjisBuffer, uint32_t sjisMax, uint32_t* sjisSize); +int APS5_VABI sceCesUtf32beToSJis(const uint32_t* utf32, const void* profile, uint8_t* sjisBuffer, uint32_t sjisMax, uint32_t* sjisSize); +int APS5_VABI sceCesUtf32leToSJis(const uint32_t* utf32, const void* profile, uint8_t* sjisBuffer, uint32_t sjisMax, uint32_t* sjisSize); +int APS5_VABI sceCesUcs2ToEucJp(uint16_t ucs2, const void* profile, uint8_t* eucBuffer, uint32_t eucMax, uint32_t* eucSize); +int APS5_VABI sceCesUtf8ToEucJp(const uint8_t* utf8Buffer, uint32_t utf8Max, uint32_t* utf8Length, const void* profile, uint8_t* eucBuffer, uint32_t eucMax, uint32_t* eucSize); +int APS5_VABI sceCesUtf16ToEucJp(const uint16_t* utf16Buffer, uint32_t utf16Max, uint32_t* utf16Length, const void* profile, uint8_t* eucBuffer, uint32_t eucMax, uint32_t* eucSize); +int APS5_VABI sceCesUtf16beToEucJp(const uint16_t* utf16Buffer, uint32_t utf16Max, uint32_t* utf16Length, const void* profile, uint8_t* eucBuffer, uint32_t eucMax, uint32_t* eucSize); +int APS5_VABI sceCesUtf16leToEucJp(const uint16_t* utf16Buffer, uint32_t utf16Max, uint32_t* utf16Length, const void* profile, uint8_t* eucBuffer, uint32_t eucMax, uint32_t* eucSize); +int APS5_VABI sceCesUtf32ToEucJp(uint32_t utf32, const void* profile, uint8_t* eucBuffer, uint32_t eucMax, uint32_t* eucSize); +int APS5_VABI sceCesUtf32beToEucJp(const uint32_t* utf32, const void* profile, uint8_t* eucBuffer, uint32_t eucMax, uint32_t* eucSize); +int APS5_VABI sceCesUtf32leToEucJp(const uint32_t* utf32, const void* profile, uint8_t* eucBuffer, uint32_t eucMax, uint32_t* eucSize); +int APS5_VABI sceCesSJisCodeToJisX0208(uint16_t sjisCode, uint8_t* ku, uint8_t* ten); +int APS5_VABI sceCesJisX0208ToSJisCode(uint8_t ku, uint8_t ten, uint16_t* sjisCode); +int APS5_VABI sceCesSJisCodeToJisX0213(uint16_t sjisCode, uint8_t* men, uint8_t* ku, uint8_t* ten); +int APS5_VABI sceCesJisX0213ToSJisCode(uint8_t men, uint8_t ku, uint8_t ten, uint16_t* sjisCode); +int APS5_VABI sceCesSJisGetCode(const uint8_t* sjisBuffer, uint32_t sjisMax, uint32_t* sjisSize, uint16_t* sjisCode); +int APS5_VABI sceCesSJisPutCode(uint16_t sjisCode, uint8_t* sjisBuffer, uint32_t sjisMax, uint32_t* sjisSize); +int APS5_VABI sceCesMbcToUcs2(const void* profile, const uint8_t* mbcBuffer, uint32_t mbcMax, uint32_t* mbcLen, uint16_t* ucs2); +int APS5_VABI sceCesMbcToUtf8(const void* profile, const uint8_t* mbcBuffer, uint32_t mbcMax, uint32_t* mbcLen, uint8_t* utf8Buffer, uint32_t utf8Max, uint32_t* utf8Len); +int APS5_VABI sceCesMbcToUtf16(const void* profile, const uint8_t* mbcBuffer, uint32_t mbcMax, uint32_t* mbcLen, uint16_t* utf16Buffer, uint32_t utf16Max, uint32_t* utf16Len); +int APS5_VABI sceCesMbcToUtf16be(const void* profile, const uint8_t* mbcBuffer, uint32_t mbcMax, uint32_t* mbcLen, uint16_t* utf16Buffer, uint32_t utf16Max, uint32_t* utf16Len); +int APS5_VABI sceCesMbcToUtf16le(const void* profile, const uint8_t* mbcBuffer, uint32_t mbcMax, uint32_t* mbcLen, uint16_t* utf16Buffer, uint32_t utf16Max, uint32_t* utf16Len); +int APS5_VABI sceCesMbcToUtf32(const void* profile, const uint8_t* mbcBuffer, uint32_t mbcMax, uint32_t* mbcLen, uint32_t* utf32); +int APS5_VABI sceCesMbcToUtf32be(const void* profile, const uint8_t* mbcBuffer, uint32_t mbcMax, uint32_t* mbcLen, uint32_t* utf32); +int APS5_VABI sceCesMbcToUtf32le(const void* profile, const uint8_t* mbcBuffer, uint32_t mbcMax, uint32_t* mbcLen, uint32_t* utf32); +int APS5_VABI sceCesSbcToUcs2(const uint8_t* profile, uint8_t sbc, uint16_t* ucs2); +int APS5_VABI sceCesSbcToUtf16(const uint8_t* profile, uint8_t sbc, uint16_t* utf16, uint32_t utf16max, uint32_t* utf16Len); +int APS5_VABI sceCesSbcToUtf16be(const uint8_t* profile, uint8_t sbc, uint16_t* utf16, uint32_t utf16max, uint32_t* utf16Len); +int APS5_VABI sceCesSbcToUtf16le(const uint8_t* profile, uint8_t sbc, uint16_t* utf16, uint32_t utf16max, uint32_t* utf16Len); +int APS5_VABI sceCesSbcToUtf32(const uint8_t* profile, uint8_t sbc, uint32_t* utf32); +int APS5_VABI sceCesSbcToUtf32be(const uint8_t* profile, uint8_t sbc, uint32_t* utf32); +int APS5_VABI sceCesSbcToUtf32le(const uint8_t* profile, uint8_t sbc, uint32_t* utf32); +int APS5_VABI sceCesUcs2ToSbc(uint16_t ucs2, const uint8_t* profile, uint8_t* sbc); +int APS5_VABI sceCesUtf16ToSbc(const uint16_t* utf16, uint32_t utf16max, uint32_t* utf16Len, const uint8_t* profile, uint8_t* sbc); +int APS5_VABI sceCesUtf16beToSbc(const uint16_t* utf16, uint32_t utf16max, uint32_t* utf16Len, const uint8_t* profile, uint8_t* sbc); +int APS5_VABI sceCesUtf16leToSbc(const uint16_t* utf16, uint32_t utf16max, uint32_t* utf16Len, const uint8_t* profile, uint8_t* sbc); +int APS5_VABI sceCesUtf32ToSbc(uint32_t utf32, const uint8_t* profile, uint8_t* sbc); +int APS5_VABI sceCesUtf32beToSbc(const uint32_t* utf32, const uint8_t* profile, uint8_t* sbc); +int APS5_VABI sceCesUtf32leToSbc(const uint32_t* utf32, const uint8_t* profile, uint8_t* sbc); +int APS5_VABI sceCesUtf16StrToMbcsStr(void* context, const uint16_t* utf16, uint32_t utf16max, uint32_t* utf16Len, uint8_t* mbcs, uint32_t mbcsMax, uint32_t* mbcsLen); +int APS5_VABI sceCesUtf16StrGetMbcsLen(void* context, const uint16_t* utf16, uint32_t utf16max, uint32_t* utf16Len, uint32_t* mbcsLen); +int APS5_VABI sceCesMbcsStrToUtf16Str(void* context, const uint8_t* mbcs, uint32_t mbcsMax, uint32_t* mbcsLen, uint16_t* utf16, uint32_t utf16max, uint32_t* utf16Len); +int APS5_VABI sceCesMbcsStrGetUtf16Len(void* context, const uint8_t* mbcs, uint32_t mbcsMax, uint32_t* mbcsLen, uint32_t* utf16Len); +int APS5_VABI sceCesUtf32StrToMbcsStr(void* context, const uint32_t* utf32, uint32_t utf32max, uint32_t* utf32Len, uint8_t* mbcs, uint32_t mbcsMax, uint32_t* mbcsLen); +int APS5_VABI sceCesUtf32StrGetMbcsLen(void* context, const uint32_t* utf32, uint32_t utf32max, uint32_t* utf32Len, uint32_t* mbcsLen); +int APS5_VABI sceCesMbcsStrToUtf32Str(void* context, const uint8_t* mbcs, uint32_t mbcsMax, uint32_t* mbcsLen, uint32_t* utf32, uint32_t utf32max, uint32_t* utf32Len); +int APS5_VABI sceCesMbcsStrGetUtf32Len(void* context, const uint8_t* mbcs, uint32_t mbcsMax, uint32_t* mbcsLen, uint32_t* utf32Len); +void* APS5_VABI sceCesUcsProfileInitEucCnGb2312(void* sheet); +void* APS5_VABI sceCesUcsProfileInitGbkCp936(void* sheet); +void* APS5_VABI sceCesUcsProfileInitGb18030_2000(void* sheet); +void* APS5_VABI sceCesUcsProfileInitGb18030_2005(void* sheet); +int APS5_VABI sceCesEucCnToUcs2(const void* profile, const uint8_t* eucBuffer, uint32_t eucMax, uint32_t* eucSize, uint16_t* ucs2); +int APS5_VABI sceCesEucCnToUtf8(const void* profile, const uint8_t* eucBuffer, uint32_t eucMax, uint32_t* eucSize, uint8_t* utf8Buffer, uint32_t utf8Max, uint32_t* utf8Length); +int APS5_VABI sceCesEucCnToUtf16(const void* profile, const uint8_t* eucBuffer, uint32_t eucMax, uint32_t* eucSize, uint16_t* utf16Buffer, uint32_t utf16Max, uint32_t* utf16Length); +int APS5_VABI sceCesEucCnToUtf16be(const void* profile, const uint8_t* eucBuffer, uint32_t eucMax, uint32_t* eucSize, uint16_t* utf16Buffer, uint32_t utf16Max, uint32_t* utf16Length); +int APS5_VABI sceCesEucCnToUtf16le(const void* profile, const uint8_t* eucBuffer, uint32_t eucMax, uint32_t* eucSize, uint16_t* utf16Buffer, uint32_t utf16Max, uint32_t* utf16Length); +int APS5_VABI sceCesEucCnToUtf32(const void* profile, const uint8_t* eucBuffer, uint32_t eucMax, uint32_t* eucSize, uint32_t* utf32); +int APS5_VABI sceCesEucCnToUtf32be(const void* profile, const uint8_t* eucBuffer, uint32_t eucMax, uint32_t* eucSize, uint32_t* utf32); +int APS5_VABI sceCesEucCnToUtf32le(const void* profile, const uint8_t* eucBuffer, uint32_t eucMax, uint32_t* eucSize, uint32_t* utf32); +int APS5_VABI sceCesUcs2ToEucCn(uint16_t ucs2, const void* profile, uint8_t* eucBuffer, uint32_t eucMax, uint32_t* eucSize); +int APS5_VABI sceCesUtf8ToEucCn(const uint8_t* utf8Buffer, uint32_t utf8Max, uint32_t* utf8Length, const void* profile, uint8_t* eucBuffer, uint32_t eucMax, uint32_t* eucSize); +int APS5_VABI sceCesUtf16ToEucCn(const uint16_t* utf16Buffer, uint32_t utf16Max, uint32_t* utf16Length, const void* profile, uint8_t* eucBuffer, uint32_t eucMax, uint32_t* eucSize); +int APS5_VABI sceCesUtf16beToEucCn(const uint16_t* utf16Buffer, uint32_t utf16Max, uint32_t* utf16Length, const void* profile, uint8_t* eucBuffer, uint32_t eucMax, uint32_t* eucSize); +int APS5_VABI sceCesUtf16leToEucCn(const uint16_t* utf16Buffer, uint32_t utf16Max, uint32_t* utf16Length, const void* profile, uint8_t* eucBuffer, uint32_t eucMax, uint32_t* eucSize); +int APS5_VABI sceCesUtf32ToEucCn(uint32_t utf32, const void* profile, uint8_t* eucBuffer, uint32_t eucMax, uint32_t* eucSize); +int APS5_VABI sceCesUtf32beToEucCn(const uint32_t* utf32, const void* profile, uint8_t* eucBuffer, uint32_t eucMax, uint32_t* eucSize); +int APS5_VABI sceCesUtf32leToEucCn(const uint32_t* utf32, const void* profile, uint8_t* eucBuffer, uint32_t eucMax, uint32_t* eucSize); +int APS5_VABI sceCesGbToUcs2(const void* profile, const uint8_t* gbBuffer, uint32_t gbMax, uint32_t* gbSize, uint16_t* ucs2); +int APS5_VABI sceCesGbToUtf8(const void* profile, const uint8_t* gbBuffer, uint32_t gbMax, uint32_t* gbSize, uint8_t* utf8Buffer, uint32_t utf8Max, uint32_t* utf8Length); +int APS5_VABI sceCesGbToUtf16(const void* profile, const uint8_t* gbBuffer, uint32_t gbMax, uint32_t* gbSize, uint16_t* utf16Buffer, uint32_t utf16Max, uint32_t* utf16Length); +int APS5_VABI sceCesGbToUtf16be(const void* profile, const uint8_t* gbBuffer, uint32_t gbMax, uint32_t* gbSize, uint16_t* utf16Buffer, uint32_t utf16Max, uint32_t* utf16Length); +int APS5_VABI sceCesGbToUtf16le(const void* profile, const uint8_t* gbBuffer, uint32_t gbMax, uint32_t* gbSize, uint16_t* utf16Buffer, uint32_t utf16Max, uint32_t* utf16Length); +int APS5_VABI sceCesGbToUtf32(const void* profile, const uint8_t* gbBuffer, uint32_t gbMax, uint32_t* gbSize, uint32_t* utf32); +int APS5_VABI sceCesGbToUtf32be(const void* profile, const uint8_t* gbBuffer, uint32_t gbMax, uint32_t* gbSize, uint32_t* utf32); +int APS5_VABI sceCesGbToUtf32le(const void* profile, const uint8_t* gbBuffer, uint32_t gbMax, uint32_t* gbSize, uint32_t* utf32); +int APS5_VABI sceCesUcs2ToGb(uint16_t ucs2, const void* profile, uint8_t* gbBuffer, uint32_t gbMax, uint32_t* gbSize); +int APS5_VABI sceCesUtf8ToGb(const uint8_t* utf8Buffer, uint32_t utf8Max, uint32_t* utf8Length, const void* profile, uint8_t* gbBuffer, uint32_t gbMax, uint32_t* gbSize); +int APS5_VABI sceCesUtf16ToGb(const uint16_t* utf16Buffer, uint32_t utf16Max, uint32_t* utf16Length, const void* profile, uint8_t* gbBuffer, uint32_t gbMax, uint32_t* gbSize); +int APS5_VABI sceCesUtf16beToGb(const uint16_t* utf16Buffer, uint32_t utf16Max, uint32_t* utf16Length, const void* profile, uint8_t* gbBuffer, uint32_t gbMax, uint32_t* gbSize); +int APS5_VABI sceCesUtf16leToGb(const uint16_t* utf16Buffer, uint32_t utf16Max, uint32_t* utf16Length, const void* profile, uint8_t* gbBuffer, uint32_t gbMax, uint32_t* gbSize); +int APS5_VABI sceCesUtf32ToGb(uint32_t utf32, const void* profile, uint8_t* gbBuffer, uint32_t gbMax, uint32_t* gbSize); +int APS5_VABI sceCesUtf32beToGb(const uint32_t* utf32, const void* profile, uint8_t* gbBuffer, uint32_t gbMax, uint32_t* gbSize); +int APS5_VABI sceCesUtf32leToGb(const uint32_t* utf32, const void* profile, uint8_t* gbBuffer, uint32_t gbMax, uint32_t* gbSize); +int APS5_VABI sceCesEucKrToUcs2(const void* profile, const uint8_t* eucBuffer, uint32_t eucMax, uint32_t* eucSize, uint16_t* ucs2); +int APS5_VABI sceCesEucKrToUtf16(const void* profile, const uint8_t* eucBuffer, uint32_t eucMax, uint32_t* eucSize, uint16_t* utf16Buffer, uint32_t utf16Max, uint32_t* utf16Length); +int APS5_VABI sceCesEucKrToUtf16be(const void* profile, const uint8_t* eucBuffer, uint32_t eucMax, uint32_t* eucSize, uint16_t* utf16Buffer, uint32_t utf16Max, uint32_t* utf16Length); +int APS5_VABI sceCesEucKrToUtf16le(const void* profile, const uint8_t* eucBuffer, uint32_t eucMax, uint32_t* eucSize, uint16_t* utf16Buffer, uint32_t utf16Max, uint32_t* utf16Length); +int APS5_VABI sceCesEucKrToUtf32(const void* profile, const uint8_t* eucBuffer, uint32_t eucMax, uint32_t* eucSize, uint32_t* utf32); +int APS5_VABI sceCesEucKrToUtf32be(const void* profile, const uint8_t* eucBuffer, uint32_t eucMax, uint32_t* eucSize, uint32_t* utf32); +int APS5_VABI sceCesEucKrToUtf32le(const void* profile, const uint8_t* eucBuffer, uint32_t eucMax, uint32_t* eucSize, uint32_t* utf32); +int APS5_VABI sceCesUhcToUcs2(const void* profile, const uint8_t* uhcBuffer, uint32_t uhcMax, uint32_t* uhcSize, uint16_t* ucs2); +int APS5_VABI sceCesUhcToUtf16(const void* profile, const uint8_t* uhcBuffer, uint32_t uhcMax, uint32_t* uhcSize, uint16_t* utf16Buffer, uint32_t utf16Max, uint32_t* utf16Length); +int APS5_VABI sceCesUhcToUtf16be(const void* profile, const uint8_t* uhcBuffer, uint32_t uhcMax, uint32_t* uhcSize, uint16_t* utf16Buffer, uint32_t utf16Max, uint32_t* utf16Length); +int APS5_VABI sceCesUhcToUtf16le(const void* profile, const uint8_t* uhcBuffer, uint32_t uhcMax, uint32_t* uhcSize, uint16_t* utf16Buffer, uint32_t utf16Max, uint32_t* utf16Length); +int APS5_VABI sceCesUhcToUtf32(const void* profile, const uint8_t* uhcBuffer, uint32_t uhcMax, uint32_t* uhcSize, uint32_t* utf32); +int APS5_VABI sceCesUhcToUtf32be(const void* profile, const uint8_t* uhcBuffer, uint32_t uhcMax, uint32_t* uhcSize, uint32_t* utf32); +int APS5_VABI sceCesUhcToUtf32le(const void* profile, const uint8_t* uhcBuffer, uint32_t uhcMax, uint32_t* uhcSize, uint32_t* utf32); +int APS5_VABI sceCesBig5ToUcs2(const void* profile, const uint8_t* big5Buffer, uint32_t big5Max, uint32_t* big5Size, uint16_t* ucs2); +int APS5_VABI sceCesBig5ToUtf16(const void* profile, const uint8_t* big5Buffer, uint32_t big5Max, uint32_t* big5Size, uint16_t* utf16Buffer, uint32_t utf16Max, uint32_t* utf16Length); +int APS5_VABI sceCesBig5ToUtf16be(const void* profile, const uint8_t* big5Buffer, uint32_t big5Max, uint32_t* big5Size, uint16_t* utf16Buffer, uint32_t utf16Max, uint32_t* utf16Length); +int APS5_VABI sceCesBig5ToUtf16le(const void* profile, const uint8_t* big5Buffer, uint32_t big5Max, uint32_t* big5Size, uint16_t* utf16Buffer, uint32_t utf16Max, uint32_t* utf16Length); +int APS5_VABI sceCesBig5ToUtf32(const void* profile, const uint8_t* big5Buffer, uint32_t big5Max, uint32_t* big5Size, uint32_t* utf32); +int APS5_VABI sceCesBig5ToUtf32be(const void* profile, const uint8_t* big5Buffer, uint32_t big5Max, uint32_t* big5Size, uint32_t* utf32); +int APS5_VABI sceCesBig5ToUtf32le(const void* profile, const uint8_t* big5Buffer, uint32_t big5Max, uint32_t* big5Size, uint32_t* utf32); +int APS5_VABI sceCesUcs2ToEucKr(uint16_t ucs2, const void* profile, uint8_t* eucBuffer, uint32_t eucMax, uint32_t* eucSize); +int APS5_VABI sceCesUtf8ToEucKr(const uint8_t* utf8Buffer, uint32_t utf8Max, uint32_t* utf8Length, const void* profile, uint8_t* eucBuffer, uint32_t eucMax, uint32_t* eucSize); +int APS5_VABI sceCesUtf16ToEucKr(const uint16_t* utf16Buffer, uint32_t utf16Max, uint32_t* utf16Length, const void* profile, uint8_t* eucBuffer, uint32_t eucMax, uint32_t* eucSize); +int APS5_VABI sceCesUtf16beToEucKr(const uint16_t* utf16Buffer, uint32_t utf16Max, uint32_t* utf16Length, const void* profile, uint8_t* eucBuffer, uint32_t eucMax, uint32_t* eucSize); +int APS5_VABI sceCesUtf16leToEucKr(const uint16_t* utf16Buffer, uint32_t utf16Max, uint32_t* utf16Length, const void* profile, uint8_t* eucBuffer, uint32_t eucMax, uint32_t* eucSize); +int APS5_VABI sceCesUtf32ToEucKr(uint32_t utf32, const void* profile, uint8_t* eucBuffer, uint32_t eucMax, uint32_t* eucSize); +int APS5_VABI sceCesUtf32beToEucKr(const uint32_t* utf32, const void* profile, uint8_t* eucBuffer, uint32_t eucMax, uint32_t* eucSize); +int APS5_VABI sceCesUtf32leToEucKr(const uint32_t* utf32, const void* profile, uint8_t* eucBuffer, uint32_t eucMax, uint32_t* eucSize); +int APS5_VABI sceCesUcs2ToUhc(uint16_t ucs2, const void* profile, uint8_t* uhcBuffer, uint32_t uhcMax, uint32_t* uhcSize); +int APS5_VABI sceCesUtf8ToUhc(const uint8_t* utf8Buffer, uint32_t utf8Max, uint32_t* utf8Length, const void* profile, uint8_t* uhcBuffer, uint32_t uhcMax, uint32_t* uhcSize); +int APS5_VABI sceCesUtf16ToUhc(const uint16_t* utf16Buffer, uint32_t utf16Max, uint32_t* utf16Length, const void* profile, uint8_t* uhcBuffer, uint32_t uhcMax, uint32_t* uhcSize); +int APS5_VABI sceCesUtf16beToUhc(const uint16_t* utf16Buffer, uint32_t utf16Max, uint32_t* utf16Length, const void* profile, uint8_t* uhcBuffer, uint32_t uhcMax, uint32_t* uhcSize); +int APS5_VABI sceCesUtf16leToUhc(const uint16_t* utf16Buffer, uint32_t utf16Max, uint32_t* utf16Length, const void* profile, uint8_t* uhcBuffer, uint32_t uhcMax, uint32_t* uhcSize); +int APS5_VABI sceCesUtf32ToUhc(uint32_t utf32, const void* profile, uint8_t* uhcBuffer, uint32_t uhcMax, uint32_t* uhcSize); +int APS5_VABI sceCesUtf32beToUhc(const uint32_t* utf32, const void* profile, uint8_t* uhcBuffer, uint32_t uhcMax, uint32_t* uhcSize); +int APS5_VABI sceCesUtf32leToUhc(const uint32_t* utf32, const void* profile, uint8_t* uhcBuffer, uint32_t uhcMax, uint32_t* uhcSize); +int APS5_VABI sceCesUcs2ToBig5(uint16_t ucs2, const void* profile, uint8_t* big5Buffer, uint32_t big5Max, uint32_t* big5Size); +int APS5_VABI sceCesUtf8ToBig5(const uint8_t* utf8Buffer, uint32_t utf8Max, uint32_t* utf8Length, const void* profile, uint8_t* big5Buffer, uint32_t big5Max, uint32_t* big5Size); +int APS5_VABI sceCesUtf16ToBig5(const uint16_t* utf16Buffer, uint32_t utf16Max, uint32_t* utf16Length, const void* profile, uint8_t* big5Buffer, uint32_t big5Max, uint32_t* big5Size); +int APS5_VABI sceCesUtf16beToBig5(const uint16_t* utf16Buffer, uint32_t utf16Max, uint32_t* utf16Length, const void* profile, uint8_t* big5Buffer, uint32_t big5Max, uint32_t* big5Size); +int APS5_VABI sceCesUtf16leToBig5(const uint16_t* utf16Buffer, uint32_t utf16Max, uint32_t* utf16Length, const void* profile, uint8_t* big5Buffer, uint32_t big5Max, uint32_t* big5Size); +int APS5_VABI sceCesUtf32ToBig5(uint32_t utf32, const void* profile, uint8_t* big5Buffer, uint32_t big5Max, uint32_t* big5Size); +int APS5_VABI sceCesUtf32beToBig5(const uint32_t* utf32, const void* profile, uint8_t* big5Buffer, uint32_t big5Max, uint32_t* big5Size); +int APS5_VABI sceCesUtf32leToBig5(const uint32_t* utf32, const void* profile, uint8_t* big5Buffer, uint32_t big5Max, uint32_t* big5Size); +int APS5_VABI sceCesEucCnUcsProfileSetSbcs(void); +int APS5_VABI sceCesEucJpUcsProfileSetSbcs(void); +int APS5_VABI sceCesEucKrUcsProfileSetSbcs(void); +int APS5_VABI sceCesGbUcsProfileSet4ByteCharRange(void); +int APS5_VABI sceCesGbUcsProfileSetSbcs(void); +int APS5_VABI sceCesGbUcsProfileSetUdaMapping(void); +int APS5_VABI sceCesIso2022JpUcsProfileSetSbcs(void); +int APS5_VABI sceCesIso2022StrGetUcs2Len(void); +int APS5_VABI sceCesIso2022StrGetUtf16Len(void); +int APS5_VABI sceCesIso2022StrGetUtf32Len(void); +int APS5_VABI sceCesIso2022StrGetUtf8Len(void); +int APS5_VABI sceCesIso2022StrToUcs2Str(void); +int APS5_VABI sceCesIso2022StrToUtf16Str(void); +int APS5_VABI sceCesIso2022StrToUtf32Str(void); +int APS5_VABI sceCesIso2022StrToUtf8Str(void); +int APS5_VABI sceCesIso2022UcsContextInit(void); +int APS5_VABI sceCesIso2022UcsContextInitCopy(void); +int APS5_VABI sceCesJisGetLevel(void); +int APS5_VABI sceCesJiscsToUcs(void); +int APS5_VABI sceCesMbcsUcsSetMbcsReplacementCharCode(void); +int APS5_VABI sceCesMbcsUcsSetMbcsReplacementCharUCode(void); +int APS5_VABI sceCesRefersUcsProfileAscii(void); +int APS5_VABI sceCesRefersUcsProfileAsciiWithKatakana(void); +int APS5_VABI sceCesRefersUcsProfileBs4730(void); +int APS5_VABI sceCesRefersUcsProfileCp1253(void); +int APS5_VABI sceCesRefersUcsProfileCp1255(void); +int APS5_VABI sceCesRefersUcsProfileCp1257(void); +int APS5_VABI sceCesRefersUcsProfileCp857(void); +int APS5_VABI sceCesRefersUcsProfileCp858(void); +int APS5_VABI sceCesRefersUcsProfileCp864(void); +int APS5_VABI sceCesRefersUcsProfileCp869(void); +int APS5_VABI sceCesRefersUcsProfileCp874(void); +int APS5_VABI sceCesRefersUcsProfileGbT1988(void); +int APS5_VABI sceCesRefersUcsProfileGbT1988Tilde0x7e(void); +int APS5_VABI sceCesRefersUcsProfileIso8859_11(void); +int APS5_VABI sceCesRefersUcsProfileIso8859_3(void); +int APS5_VABI sceCesRefersUcsProfileIso8859_6(void); +int APS5_VABI sceCesRefersUcsProfileIso8859_7(void); +int APS5_VABI sceCesRefersUcsProfileIso8859_8(void); +int APS5_VABI sceCesRefersUcsProfileJisX0201(void); +int APS5_VABI sceCesRefersUcsProfileJisX0201Katakana(void); +int APS5_VABI sceCesRefersUcsProfileJisX0201Roman(void); +int APS5_VABI sceCesRefersUcsProfileJisX0201RomanTilde0x7e(void); +int APS5_VABI sceCesRefersUcsProfileJisX0201Tilde0x7e(void); +int APS5_VABI sceCesRefersUcsProfileKsX1003(void); +int APS5_VABI sceCesRefersUcsProfileKsX1003Tilde0x7e(void); +int APS5_VABI sceCesSJisUcsProfileSetSbcs(void); +int APS5_VABI sceCesUcs2StrGetIso2022Len(void); +int APS5_VABI sceCesUcs2StrToIso2022Str(void); +int APS5_VABI sceCesUcs2ToMbc(uint16_t ucs2, const void* profile, uint8_t* mbcBuffer, uint32_t mbcMax, uint32_t* mbcLen); +int APS5_VABI sceCesUcsProfileInitEucJis2004(void); +int APS5_VABI sceCesUcsProfileInitIso2022JpCp50221(void); +int APS5_VABI sceCesUcsProfileInitIso2022JpCp50222(void); +int APS5_VABI sceCesUcsProfileInitIso2022JpRfc1468(void); +int APS5_VABI sceCesUcsProfileInitSJis2004X0213(void); +int APS5_VABI sceCesUcsToJiscs(void); +int APS5_VABI sceCesUhcUcsProfileSetSbcs(void); +int APS5_VABI sceCesUtf16StrGetIso2022Len(void); +int APS5_VABI sceCesUtf16StrToIso2022Str(void); +int APS5_VABI sceCesUtf16ToMbc(const uint16_t* utf16Buffer, uint32_t utf16Max, uint32_t* utf16Len, const void* profile, uint8_t* mbcBuffer, uint32_t mbcMax, uint32_t* mbcLen); +int APS5_VABI sceCesUtf16beToMbc(const uint16_t* utf16Buffer, uint32_t utf16Max, uint32_t* utf16Len, const void* profile, uint8_t* mbcBuffer, uint32_t mbcMax, uint32_t* mbcLen); +int APS5_VABI sceCesUtf16leToMbc(const uint16_t* utf16Buffer, uint32_t utf16Max, uint32_t* utf16Len, const void* profile, uint8_t* mbcBuffer, uint32_t mbcMax, uint32_t* mbcLen); +int APS5_VABI sceCesUtf32StrGetIso2022Len(void); +int APS5_VABI sceCesUtf32StrToIso2022Str(void); +int APS5_VABI sceCesUtf32ToMbc(uint32_t utf32, const void* profile, uint8_t* mbcBuffer, uint32_t mbcMax, uint32_t* mbcLen); +int APS5_VABI sceCesUtf32beToMbc(const uint32_t* utf32, const void* profile, uint8_t* mbcBuffer, uint32_t mbcMax, uint32_t* mbcLen); +int APS5_VABI sceCesUtf32leToMbc(const uint32_t* utf32, const void* profile, uint8_t* mbcBuffer, uint32_t mbcMax, uint32_t* mbcLen); +int APS5_VABI sceCesUtf8StrGetIso2022Len(void); +int APS5_VABI sceCesUtf8StrToIso2022Str(void); +int APS5_VABI sceCesUtf8ToMbc(const uint8_t* utf8Buffer, uint32_t utf8Max, uint32_t* utf8Len, const void* profile, uint8_t* mbcBuffer, uint32_t mbcMax, uint32_t* mbcLen); +int APS5_VABI sceCesUcs2ToUtf8(uint16_t source, uint8_t* target, uint32_t capacity, uint32_t* targetLength); +int APS5_VABI sceCesUtf8ToUcs2(const uint8_t* source, uint32_t available, uint32_t* sourceLength, uint16_t* target); +int APS5_VABI sceCesUtf8ToUtf32(const uint8_t* source, uint32_t available, uint32_t* sourceLength, uint32_t* target); +int APS5_VABI sceCesUtf8ToUtf32be(const uint8_t* source, uint32_t available, uint32_t* sourceLength, uint32_t* target); +int APS5_VABI sceCesUtf8ToUtf32le(const uint8_t* source, uint32_t available, uint32_t* sourceLength, uint32_t* target); +int APS5_VABI sceCesUtf8ToUtf16(const uint8_t* source, uint32_t available, uint32_t* sourceLength, uint16_t* target, uint32_t capacity, uint32_t* targetLength); +int APS5_VABI sceCesUtf8ToUtf16be(const uint8_t* source, uint32_t available, uint32_t* sourceLength, uint16_t* target, uint32_t capacity, uint32_t* targetLength); +int APS5_VABI sceCesUtf8ToUtf16le(const uint8_t* source, uint32_t available, uint32_t* sourceLength, uint16_t* target, uint32_t capacity, uint32_t* targetLength); +int APS5_VABI sceCesUtf16ToUtf8(const uint16_t* source, uint32_t available, uint32_t* sourceLength, uint8_t* target, uint32_t capacity, uint32_t* targetLength); +int APS5_VABI sceCesUtf16beToUtf8(const uint16_t* source, uint32_t available, uint32_t* sourceLength, uint8_t* target, uint32_t capacity, uint32_t* targetLength); +int APS5_VABI sceCesUtf16leToUtf8(const uint16_t* source, uint32_t available, uint32_t* sourceLength, uint8_t* target, uint32_t capacity, uint32_t* targetLength); +int APS5_VABI sceCesUtf32ToUtf8(uint32_t source, uint8_t* target, uint32_t capacity, uint32_t* targetLength); +int APS5_VABI sceCesUtf32beToUtf8(const uint32_t* source, uint8_t* target, uint32_t capacity, uint32_t* targetLength); +int APS5_VABI sceCesUtf32leToUtf8(const uint32_t* source, uint8_t* target, uint32_t capacity, uint32_t* targetLength); + +} diff --git a/core/libs/prx/libSceCesCs/libSceCesCs.hpp b/core/libs/prx/libSceCesCs/libSceCesCs.hpp new file mode 100644 index 0000000000..d1bff8e93d --- /dev/null +++ b/core/libs/prx/libSceCesCs/libSceCesCs.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceCesCs/include/Api.hpp" diff --git a/core/libs/prx/libSceCommonDialog/Export.cpp b/core/libs/prx/libSceCommonDialog/Export.cpp index 47f9a84bb1..8d090d7d35 100644 --- a/core/libs/prx/libSceCommonDialog/Export.cpp +++ b/core/libs/prx/libSceCommonDialog/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceCommonDialog/include/Api.hpp" #include #include #include diff --git a/core/libs/prx/libSceCommonDialog/include/Api.hpp b/core/libs/prx/libSceCommonDialog/include/Api.hpp new file mode 100644 index 0000000000..50330e8aa4 --- /dev/null +++ b/core/libs/prx/libSceCommonDialog/include/Api.hpp @@ -0,0 +1,10 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceCommonDialogInitialize(void); +bool APS5_VABI sceCommonDialogIsUsed(void); + +} diff --git a/core/libs/prx/libSceCommonDialog/libSceCommonDialog.hpp b/core/libs/prx/libSceCommonDialog/libSceCommonDialog.hpp new file mode 100644 index 0000000000..2379b9c83f --- /dev/null +++ b/core/libs/prx/libSceCommonDialog/libSceCommonDialog.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceCommonDialog/include/Api.hpp" diff --git a/core/libs/prx/libSceCompanionHttpd/Export.cpp b/core/libs/prx/libSceCompanionHttpd/Export.cpp index 8d3a814f50..7941374a21 100644 --- a/core/libs/prx/libSceCompanionHttpd/Export.cpp +++ b/core/libs/prx/libSceCompanionHttpd/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceCompanionHttpd/include/Api.hpp" #include #include #include @@ -15,17 +16,8 @@ constexpr int CompanionHttpdErrorAlreadyStarted = static_cast(0x80E4000Au); constexpr int CompanionHttpdErrorNotStarted = static_cast(0x80E4000Bu); constexpr int CompanionHttpdErrorAlreadyRegistered = static_cast(0x80E4000Cu); -struct CompanionHttpdOptParam { - std::uint64_t reserved; - void* workMemory; - std::uint64_t workMemorySize; - std::uint8_t settings[0x40]; - const void* temporaryMountPoint; -}; static_assert(sizeof(CompanionHttpdOptParam) == 0x60); -using CompanionHttpdRequestCallback = int (*)(int, int, const void*, void*, void*); - struct CompanionHttpdState { std::mutex mutex; bool initialized = false; diff --git a/core/libs/prx/libSceCompanionHttpd/include/Api.hpp b/core/libs/prx/libSceCompanionHttpd/include/Api.hpp new file mode 100644 index 0000000000..6a7e2d194d --- /dev/null +++ b/core/libs/prx/libSceCompanionHttpd/include/Api.hpp @@ -0,0 +1,35 @@ +#pragma once + +#include "SceTypes.hpp" + +struct CompanionHttpdOptParam { + std::uint64_t reserved; + void* workMemory; + std::uint64_t workMemorySize; + std::uint8_t settings[0x40]; + const void* temporaryMountPoint; +}; + +using CompanionHttpdRequestCallback = int (*)(int, int, const void*, void*, void*); + +extern "C" { + +int APS5_VABI sceCompanionHttpdOptParamInitialize(CompanionHttpdOptParam* param); +int APS5_VABI sceCompanionHttpdInitialize(const CompanionHttpdOptParam* param); +int APS5_VABI sceCompanionHttpdTerminate(void); +int APS5_VABI sceCompanionHttpdRegisterRequestCallback(CompanionHttpdRequestCallback function, void* argument); +int APS5_VABI sceCompanionHttpdUnregisterRequestCallback(void); +int APS5_VABI sceCompanionHttpdStart(void); +int APS5_VABI sceCompanionHttpdStop(void); +int APS5_VABI sceCompanionHttpdGetEvent(void* event); +int APS5_VABI sceCompanionHttpdAddHeader(const char* key, const char* value, void* response); +int APS5_VABI sceCompanionHttpdSetStatus(int status, void* response); +int APS5_VABI sceCompanionHttpdSetBody(const char* body, std::uint64_t size, void* response); +int APS5_VABI sceCompanionHttpdGet2ndScreenStatus(void); +int APS5_VABI sceCompanionHttpdGetUserId(void); +int APS5_VABI sceCompanionHttpdInitialize2(void); +int APS5_VABI sceCompanionHttpdRegisterRequestBodyReceptionCallback(void); +int APS5_VABI sceCompanionHttpdRegisterRequestCallback2(void); +int APS5_VABI sceCompanionHttpdUnregisterRequestBodyReceptionCallback(void); + +} diff --git a/core/libs/prx/libSceCompanionHttpd/libSceCompanionHttpd.hpp b/core/libs/prx/libSceCompanionHttpd/libSceCompanionHttpd.hpp new file mode 100644 index 0000000000..9626d1bfa7 --- /dev/null +++ b/core/libs/prx/libSceCompanionHttpd/libSceCompanionHttpd.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceCompanionHttpd/include/Api.hpp" diff --git a/core/libs/prx/libSceCompanionUtil/Export.cpp b/core/libs/prx/libSceCompanionUtil/Export.cpp index 7a208122da..810abefbdc 100644 --- a/core/libs/prx/libSceCompanionUtil/Export.cpp +++ b/core/libs/prx/libSceCompanionUtil/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceCompanionUtil/include/Api.hpp" #include #include #include "SceTypes.hpp" @@ -5,7 +6,7 @@ extern "C" { -int APS5_VABI sceCompanionUtilGetEvent() { +int APS5_VABI sceCompanionUtilGetEvent(void* outEvent) { return static_cast(0x80AD0008); } diff --git a/core/libs/prx/libSceCompanionUtil/include/Api.hpp b/core/libs/prx/libSceCompanionUtil/include/Api.hpp new file mode 100644 index 0000000000..c71bbbf72b --- /dev/null +++ b/core/libs/prx/libSceCompanionUtil/include/Api.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceCompanionUtilGetEvent(void* outEvent); +int APS5_VABI sceCompanionUtilGetRemoteOskEvent(); +int APS5_VABI sceCompanionUtilInitialize(); +int APS5_VABI sceCompanionUtilOptParamInitialize(); +int APS5_VABI sceCompanionUtilTerminate(); + +} diff --git a/core/libs/prx/libSceCompanionUtil/libSceCompanionUtil.hpp b/core/libs/prx/libSceCompanionUtil/libSceCompanionUtil.hpp new file mode 100644 index 0000000000..e49fee6a03 --- /dev/null +++ b/core/libs/prx/libSceCompanionUtil/libSceCompanionUtil.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceCompanionUtil/include/Api.hpp" diff --git a/core/libs/prx/libSceComposite/Export.cpp b/core/libs/prx/libSceComposite/Export.cpp index ebf58fb725..a2e79ae3ed 100644 --- a/core/libs/prx/libSceComposite/Export.cpp +++ b/core/libs/prx/libSceComposite/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceComposite/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceComposite/include/Api.hpp b/core/libs/prx/libSceComposite/include/Api.hpp new file mode 100644 index 0000000000..0df26cb6bc --- /dev/null +++ b/core/libs/prx/libSceComposite/include/Api.hpp @@ -0,0 +1,86 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceCompositorAllocateIndex(); +int APS5_VABI sceCompositorCheckCrash(); +int APS5_VABI sceCompositorCommandGpuPerfBegin(); +int APS5_VABI sceCompositorCommandGpuPerfEnd(); +int APS5_VABI sceCompositorCreateIndirectRenderTarget(); +int APS5_VABI sceCompositorDeleteIndirectRenderTarget(); +int APS5_VABI sceCompositorFlush(); +int APS5_VABI sceCompositorFlushWithRepeat(); +int APS5_VABI sceCompositorGetAnotherProcessSystemAddress(); +int APS5_VABI sceCompositorGetAnotherProcessSystemSize(); +int APS5_VABI sceCompositorGetAnotherProcessVideoAddress(); +int APS5_VABI sceCompositorGetAnotherProcessVideoSize(); +int APS5_VABI sceCompositorGetCanvasHandle(); +int APS5_VABI sceCompositorGetClientList(); +int APS5_VABI sceCompositorGetDmemOffset(); +int APS5_VABI sceCompositorGetDummyAddress(); +int APS5_VABI sceCompositorGetDummySize(); +int APS5_VABI sceCompositorGetRemainedCommandNum(); +int APS5_VABI sceCompositorGetRenderTargetResolution(); +int APS5_VABI sceCompositorGetSystemAddress(); +int APS5_VABI sceCompositorGetSystemSize(); +int APS5_VABI sceCompositorGetVideoAddress(); +int APS5_VABI sceCompositorGetVideoSize(); +int APS5_VABI sceCompositorHandleProcessEvents(); +int APS5_VABI sceCompositorInit(); +int APS5_VABI sceCompositorInitWithProcessOrder(); +int APS5_VABI sceCompositorInsertThreadTraceMarker(); +int APS5_VABI sceCompositorIsDebugCaptureEnabled(); +int APS5_VABI sceCompositorIsReady4K(); +int APS5_VABI sceCompositorLockCommandBuffer(); +int APS5_VABI sceCompositorMakeCanvasHandle(); +int APS5_VABI sceCompositorMapAnotherProcess(); +int APS5_VABI sceCompositorMemoryPoolDecommit(); +int APS5_VABI sceCompositorPrivacyMaskPushArea(); +int APS5_VABI sceCompositorQuit(); +int APS5_VABI sceCompositorReleaseCommandBuffer(); +int APS5_VABI sceCompositorReleaseIndex(); +int APS5_VABI sceCompositorReleaseLocalStall(); +int APS5_VABI sceCompositorReserveCommandBuffer(); +int APS5_VABI sceCompositorResetZoomCommand(); +int APS5_VABI sceCompositorSetAgcCompositeCanvasCommand(); +int APS5_VABI sceCompositorSetAgcContextCommand(); +int APS5_VABI sceCompositorSetCompositeCanvasCommandInC(); +int APS5_VABI sceCompositorSetCursorImageAddress(); +int APS5_VABI sceCompositorSetDebugPositionCommand(); +int APS5_VABI sceCompositorSetEndOfFrameCommand(); +int APS5_VABI sceCompositorSetEventCommand(); +int APS5_VABI sceCompositorSetFilterType(); +int APS5_VABI sceCompositorSetFlipCommand2(); +int APS5_VABI sceCompositorSetGameSufaceControlCommand(); +int APS5_VABI sceCompositorSetGnmContextCommand(); +int APS5_VABI sceCompositorSetIndirectCanvasCommand(); +int APS5_VABI sceCompositorSetIndirectCompositionCommand(); +int APS5_VABI sceCompositorSetIndirectRenderTargetConfigCommand(); +int APS5_VABI sceCompositorSetInvisibleCanvasCommand(); +int APS5_VABI sceCompositorSetKeepDisplayBufferCommand(); +int APS5_VABI sceCompositorSetLocalStallCommand(); +int APS5_VABI sceCompositorSetMemoryCommand(); +int APS5_VABI sceCompositorSetPatchCommand(); +int APS5_VABI sceCompositorSetPostEventCommand(); +int APS5_VABI sceCompositorSetRepeatCommand(); +int APS5_VABI sceCompositorSetResolutionCommand(); +int APS5_VABI sceCompositorSetScalingLayoutInfo(); +int APS5_VABI sceCompositorSetSeparateContextCommand(); +int APS5_VABI sceCompositorSetSystemConfigWithMask(); +int APS5_VABI sceCompositorSetVideoOutMode(); +int APS5_VABI sceCompositorSetVirtualCanvasAgcContextCommand(); +int APS5_VABI sceCompositorSetVirtualCanvasCommandFooter(); +int APS5_VABI sceCompositorSetVirtualCanvasPatchCommand(); +int APS5_VABI sceCompositorSetVrMode(); +int APS5_VABI sceCompositorSetZoomCommand(); +int APS5_VABI sceCompositorSystemConfig(); +int APS5_VABI sceCompositorWaitEndOfRendering(); +int APS5_VABI sceCompositorWaitEvent(); +int APS5_VABI sceCompositorWaitPostEvent(); +int APS5_VABI sceCompsoitorGetGpuClock(); +int APS5_VABI sceCompsoitorGetProcessRenderingTime(); +int APS5_VABI sceCompsoitorGetRenderingTime(); + +} diff --git a/core/libs/prx/libSceComposite/libSceComposite.hpp b/core/libs/prx/libSceComposite/libSceComposite.hpp new file mode 100644 index 0000000000..2829781c84 --- /dev/null +++ b/core/libs/prx/libSceComposite/libSceComposite.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceComposite/include/Api.hpp" diff --git a/core/libs/prx/libSceCompositeExt/libSceCompositeExt.hpp b/core/libs/prx/libSceCompositeExt/libSceCompositeExt.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceCompositeExt/libSceCompositeExt.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceConnectAccountDialog/libSceConnectAccountDialog.hpp b/core/libs/prx/libSceConnectAccountDialog/libSceConnectAccountDialog.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceConnectAccountDialog/libSceConnectAccountDialog.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceContentDelete/Export.cpp b/core/libs/prx/libSceContentDelete/Export.cpp index 5f886b22a4..ecd7c66372 100644 --- a/core/libs/prx/libSceContentDelete/Export.cpp +++ b/core/libs/prx/libSceContentDelete/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceContentDelete/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceContentDelete/include/Api.hpp b/core/libs/prx/libSceContentDelete/include/Api.hpp new file mode 100644 index 0000000000..cabb8b7ac2 --- /dev/null +++ b/core/libs/prx/libSceContentDelete/include/Api.hpp @@ -0,0 +1,16 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceContentDeleteInitialize(const ContentDeleteInitParam* initParam); +int APS5_VABI sceContentDeleteByPath(const char* contentPath); +int APS5_VABI sceContentDeleteById(std::int64_t contentId); +int APS5_VABI sceContentDeleteByIdListForSf(const std::int64_t* contentIds, std::size_t count); +int APS5_VABI sceContentDeleteGlobalMstat(void); +int APS5_VABI sceContentDeleteMemoryInitialize(void); +int APS5_VABI sceContentDeleteMemoryTerminate(void); +int APS5_VABI sceContentDeleteTerminate(void); + +} diff --git a/core/libs/prx/libSceContentDelete/libSceContentDelete.hpp b/core/libs/prx/libSceContentDelete/libSceContentDelete.hpp new file mode 100644 index 0000000000..5fc5f90294 --- /dev/null +++ b/core/libs/prx/libSceContentDelete/libSceContentDelete.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceContentDelete/include/Api.hpp" diff --git a/core/libs/prx/libSceContentExport/Export.cpp b/core/libs/prx/libSceContentExport/Export.cpp index 0c5b205edf..975349f1e5 100644 --- a/core/libs/prx/libSceContentExport/Export.cpp +++ b/core/libs/prx/libSceContentExport/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceContentExport/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceContentExport/include/Api.hpp b/core/libs/prx/libSceContentExport/include/Api.hpp new file mode 100644 index 0000000000..97edfa3e73 --- /dev/null +++ b/core/libs/prx/libSceContentExport/include/Api.hpp @@ -0,0 +1,30 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceContentExportInit2(const ContentExportInitParam2* initParam); +int APS5_VABI sceContentExportFinish(std::int32_t expId); +int APS5_VABI sceContentExportFromData(std::int32_t expId, const ContentExportParam* param, std::size_t contentLength, ContentExportDataCallback callback, void* userData, char* path, std::size_t pathBufferLength); +int APS5_VABI sceContentExportFromFile(std::int32_t expId, const ContentExportParam* param, const char* sourcePath, char* path, std::size_t pathBufferLength); +int APS5_VABI sceContentExportFromFileWithThumbnail(std::int32_t expId, const ContentExportParam* param, const char* sourcePath, const char* thumbnailPath, char* path, std::size_t pathBufferLength); +int APS5_VABI sceContentExportAddToFavorites(std::int64_t contentId); +int APS5_VABI sceContentExportDataProvideFunction(void); +int APS5_VABI sceContentExportFree(void); +int APS5_VABI sceContentExportFrom(void); +int APS5_VABI sceContentExportFromFileForSf(std::int32_t expId, const ContentExportParam* param, const ContentExportSfParam* sfParam, const char* sourcePath, const char* thumbnailPath, char* path, std::size_t pathBufferLength); +int APS5_VABI sceContentExportFromFileWithContentIdList(std::int32_t expId, const ContentExportParam* param, const char* sourcePath, const char* thumbnailPath, const std::int64_t* contentIds, std::uint32_t contentCount, char* path, std::size_t pathBufferLength); +int APS5_VABI sceContentExportFromFileWithTitleIdList(std::int32_t expId, const ContentExportParam* param, const char* sourcePath, const char* thumbnailPath, const char* titleIdList, char* path, std::size_t pathBufferLength); +int APS5_VABI sceContentExportInit(const ContentExportInitParam* param); +int APS5_VABI sceContentExportMalloc(void); +int APS5_VABI sceContentExportRemoveFromFavorites(std::int64_t contentId); +int APS5_VABI sceContentExportRenameContent(std::int64_t contentId, const char* name); +int APS5_VABI sceContentExportValidateContents(const std::int64_t* contentIds, std::uint32_t count); +int APS5_VABI sceContentExportStart(void); +int APS5_VABI sceContentExportGetProgress(std::int32_t expId); +int APS5_VABI sceContentExportCancel(std::int32_t expId); +int APS5_VABI sceContentExportFromDataWithThumbnail(std::int32_t expId, const ContentExportParam* param, const ContentExportCallbackParam* contentCallbackParam, const char* thumbnailType, const ContentExportCallbackParam* thumbnailCallbackParam, char* path, std::size_t pathBufferLength); +int APS5_VABI sceContentExportTerm(void); + +} diff --git a/core/libs/prx/libSceContentExport/libSceContentExport.hpp b/core/libs/prx/libSceContentExport/libSceContentExport.hpp new file mode 100644 index 0000000000..a7887a9290 --- /dev/null +++ b/core/libs/prx/libSceContentExport/libSceContentExport.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceContentExport/include/Api.hpp" diff --git a/core/libs/prx/libSceContentListController/libSceContentListController.hpp b/core/libs/prx/libSceContentListController/libSceContentListController.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceContentListController/libSceContentListController.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceContentSearch/Export.cpp b/core/libs/prx/libSceContentSearch/Export.cpp index ac200672de..0fbd052c73 100644 --- a/core/libs/prx/libSceContentSearch/Export.cpp +++ b/core/libs/prx/libSceContentSearch/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceContentSearch/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceContentSearch/include/Api.hpp b/core/libs/prx/libSceContentSearch/include/Api.hpp new file mode 100644 index 0000000000..b54e8efb17 --- /dev/null +++ b/core/libs/prx/libSceContentSearch/include/Api.hpp @@ -0,0 +1,31 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceContentSearchInit(const ContentSearchInitParam* initParam); +int APS5_VABI sceContentSearchCloseMetadata(std::int32_t metadataId); +int APS5_VABI sceContentSearchGetMetadataFieldInfo(std::int32_t metadataId, const char* field, std::int32_t* metadataType, std::int32_t* size); +int APS5_VABI sceContentSearchGetMetadataValue(std::int32_t metadataId, const char* field, void* value); +int APS5_VABI sceContentSearchOpenMetadata(const char* filePath, std::int32_t* metadataId); +int APS5_VABI sceContentSearchSearchContent(const ContentSearchContentColumnSet* columnSet, std::uint32_t columnSetLength, const ContentSearchContentOrderByCondition* orderByConditions, std::uint32_t orderByConditionsLength, std::uint32_t offset, std::uint32_t limit, std::int64_t* numOfContent, void* infos, std::int64_t* lastUpdateId); +int APS5_VABI sceContentSearchGetContentLastUpdateId(std::int64_t* lastUpdateId); +int APS5_VABI sceContentSearchOpenMetadataByContentId(std::int64_t contentId, std::int32_t* metadataId); +int APS5_VABI sceContentSearchGetTotalContentSize(const ContentSearchContentColumnSet* columnSet, std::uint32_t columnSetLength, std::int64_t* size, std::int64_t* lastUpdateId); +int APS5_VABI sceContentSearchGetNumOfContent(const ContentSearchContentColumnSet* columnSet, std::uint32_t columnSetLength, std::int64_t* numOfContent, std::int64_t* lastUpdateId); +int APS5_VABI sceContentSearchTerm(void); +int APS5_VABI sceContentBinderEnd(); +int APS5_VABI sceContentBinderGetNumOfDifference(); +int APS5_VABI sceContentBinderInitialize(); +int APS5_VABI sceContentBinderIsUpdated(); +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 sceContentSearchSearchApplication(); + +} diff --git a/core/libs/prx/libSceContentSearch/libSceContentSearch.hpp b/core/libs/prx/libSceContentSearch/libSceContentSearch.hpp new file mode 100644 index 0000000000..79d8740064 --- /dev/null +++ b/core/libs/prx/libSceContentSearch/libSceContentSearch.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceContentSearch/include/Api.hpp" diff --git a/core/libs/prx/libSceConvertKeycode/Export.cpp b/core/libs/prx/libSceConvertKeycode/Export.cpp index 0aa1387305..f96e2deca1 100644 --- a/core/libs/prx/libSceConvertKeycode/Export.cpp +++ b/core/libs/prx/libSceConvertKeycode/Export.cpp @@ -1,3 +1,5 @@ +#include "prx/libSceConvertKeycode/include/Api.hpp" +#include "prx/libSceUserService/UserService.hpp" #include #include #include @@ -10,12 +12,6 @@ #include "prx/libkernel/AppMetadata/include/AppMetadata.hpp" #include -extern "C" { -int APS5_VABI sceUserServiceGetKeyboardType(int32_t userId, int32_t* type); -int APS5_VABI sceUserServiceGetJapaneseInputType(int32_t userId, int32_t* type); -int APS5_VABI sceUserServiceGetTraditionalChineseInputType(int32_t userId, int32_t* type); -} - namespace { constexpr int kErrInvalidAddress = static_cast(0x80BC0031u); constexpr std::array BaseVirtualKeys = { @@ -2306,7 +2302,6 @@ constexpr std::array KoreanFinal = { 12593, 12594, 12595, 12596, 12597, 12598, 12599, 12601, 12602, 12603, 12604, 12605, 12606, 12607, 12608, 12609, 12610, 12612, 12613, 12614, 12615, 12616, 12618, 12619, 12620, 12621, 12622 }; - std::size_t CharacterLayout(std::uint32_t type, std::uint32_t state) { constexpr std::array layouts = {18, 7, 0, 1, 14, 8, 29, 17, 9, 25, 24, 23, 10, 11, 16, 26, 27, 12, 1, 19, 28, 3, 3, 1, 1, 1, 1, 1, 1, 1, 14, 32, 14, 34, 35, 36, 37, 1, 1}; const bool imeMode = (state & 0x4000000u) != 0; diff --git a/core/libs/prx/libSceConvertKeycode/include/Api.hpp b/core/libs/prx/libSceConvertKeycode/include/Api.hpp new file mode 100644 index 0000000000..437b5117c5 --- /dev/null +++ b/core/libs/prx/libSceConvertKeycode/include/Api.hpp @@ -0,0 +1,12 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceConvertKeycodeGetImeKeyboardType(int32_t userId, uint32_t* type); +int APS5_VABI sceConvertKeycodeGetVirtualKeycode(std::uint16_t keycode, std::uint32_t keyboardType, std::uint16_t* virtualKeycode); +int APS5_VABI sceConvertKeycodeGetCharacterFromKeyboardData(const KeyboardData* keyData, std::int32_t index, std::uint32_t state, std::uint32_t keyboardType, char16_t* character); +int APS5_VABI sceConvertKeycodeGetCharacter(std::uint16_t keycode, std::uint32_t state, std::uint32_t type, char16_t* character); + +} diff --git a/core/libs/prx/libSceConvertKeycode/libSceConvertKeycode.hpp b/core/libs/prx/libSceConvertKeycode/libSceConvertKeycode.hpp new file mode 100644 index 0000000000..45c6357f44 --- /dev/null +++ b/core/libs/prx/libSceConvertKeycode/libSceConvertKeycode.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceConvertKeycode/include/Api.hpp" diff --git a/core/libs/prx/libSceCtrlp/libSceCtrlp.hpp b/core/libs/prx/libSceCtrlp/libSceCtrlp.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceCtrlp/libSceCtrlp.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceCustomMusicAudioOut/Export.cpp b/core/libs/prx/libSceCustomMusicAudioOut/Export.cpp index a383508620..04ed029ae6 100644 --- a/core/libs/prx/libSceCustomMusicAudioOut/Export.cpp +++ b/core/libs/prx/libSceCustomMusicAudioOut/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceCustomMusicAudioOut/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceCustomMusicAudioOut/include/Api.hpp b/core/libs/prx/libSceCustomMusicAudioOut/include/Api.hpp new file mode 100644 index 0000000000..934f42befc --- /dev/null +++ b/core/libs/prx/libSceCustomMusicAudioOut/include/Api.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceCustomMusicAudioOutFinalize(); +int APS5_VABI sceCustomMusicAudioOutGetAllMusicVolume(); +int APS5_VABI sceCustomMusicAudioOutGetMuted(); +int APS5_VABI sceCustomMusicAudioOutGetVolume(); +int APS5_VABI sceCustomMusicAudioOutSetAllMusicVolume(); + +} diff --git a/core/libs/prx/libSceCustomMusicAudioOut/libSceCustomMusicAudioOut.hpp b/core/libs/prx/libSceCustomMusicAudioOut/libSceCustomMusicAudioOut.hpp new file mode 100644 index 0000000000..387b464246 --- /dev/null +++ b/core/libs/prx/libSceCustomMusicAudioOut/libSceCustomMusicAudioOut.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceCustomMusicAudioOut/include/Api.hpp" diff --git a/core/libs/prx/libSceCustomMusicCore/Export.cpp b/core/libs/prx/libSceCustomMusicCore/Export.cpp index fa0c494e42..65b3aaccac 100644 --- a/core/libs/prx/libSceCustomMusicCore/Export.cpp +++ b/core/libs/prx/libSceCustomMusicCore/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceCustomMusicCore/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceCustomMusicCore/include/Api.hpp b/core/libs/prx/libSceCustomMusicCore/include/Api.hpp new file mode 100644 index 0000000000..478406741d --- /dev/null +++ b/core/libs/prx/libSceCustomMusicCore/include/Api.hpp @@ -0,0 +1,26 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceCustomMusicCoreBgmClose(); +int APS5_VABI sceCustomMusicCoreBgmOpen(); +int APS5_VABI sceCustomMusicCoreBgmOpen2(); +int APS5_VABI sceCustomMusicCoreBgmOutput(); +int APS5_VABI sceCustomMusicCoreBgmSetAudioVolume(); +int APS5_VABI sceCustomMusicCoreBgmStart(); +int APS5_VABI sceCustomMusicCoreBgmStop(); +int APS5_VABI sceCustomMusicCoreGetBgmAuthorityStatus(); +int APS5_VABI sceCustomMusicCoreGetHdcpStatus(); +int APS5_VABI sceCustomMusicCoreGetSystemAudioVolume(); +int APS5_VABI sceCustomMusicCorePostEvent(); +int APS5_VABI sceCustomMusicCoreSendEvent(); +int APS5_VABI sceCustomMusicCoreSendMulticastEvent(); +int APS5_VABI sceCustomMusicCoreSendSpMessage(); +int APS5_VABI sceCustomMusicCoreSetSystemAudioVolume(); +int APS5_VABI sceCustomMusicCoreStartOperation(); +int APS5_VABI sceCustomMusicCoreStartOperation2(); +int APS5_VABI sceCustomMusicCoreStopOperation(); + +} diff --git a/core/libs/prx/libSceCustomMusicCore/libSceCustomMusicCore.hpp b/core/libs/prx/libSceCustomMusicCore/libSceCustomMusicCore.hpp new file mode 100644 index 0000000000..e7d4cf7206 --- /dev/null +++ b/core/libs/prx/libSceCustomMusicCore/libSceCustomMusicCore.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceCustomMusicCore/include/Api.hpp" diff --git a/core/libs/prx/libSceCustomMusicSysCallWrapper/Export.cpp b/core/libs/prx/libSceCustomMusicSysCallWrapper/Export.cpp index ee9009496a..e64d1e4444 100644 --- a/core/libs/prx/libSceCustomMusicSysCallWrapper/Export.cpp +++ b/core/libs/prx/libSceCustomMusicSysCallWrapper/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceCustomMusicSysCallWrapper/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceCustomMusicSysCallWrapper/include/Api.hpp b/core/libs/prx/libSceCustomMusicSysCallWrapper/include/Api.hpp new file mode 100644 index 0000000000..63ad57d532 --- /dev/null +++ b/core/libs/prx/libSceCustomMusicSysCallWrapper/include/Api.hpp @@ -0,0 +1,9 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceCustomMusicSelect(); + +} diff --git a/core/libs/prx/libSceCustomMusicSysCallWrapper/libSceCustomMusicSysCallWrapper.hpp b/core/libs/prx/libSceCustomMusicSysCallWrapper/libSceCustomMusicSysCallWrapper.hpp new file mode 100644 index 0000000000..22ad944a67 --- /dev/null +++ b/core/libs/prx/libSceCustomMusicSysCallWrapper/libSceCustomMusicSysCallWrapper.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceCustomMusicSysCallWrapper/include/Api.hpp" diff --git a/core/libs/prx/libSceDataTransfer/Export.cpp b/core/libs/prx/libSceDataTransfer/Export.cpp index 43fb2a1574..5c993b6dfb 100644 --- a/core/libs/prx/libSceDataTransfer/Export.cpp +++ b/core/libs/prx/libSceDataTransfer/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceDataTransfer/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceDataTransfer/include/Api.hpp b/core/libs/prx/libSceDataTransfer/include/Api.hpp new file mode 100644 index 0000000000..f04a12fef4 --- /dev/null +++ b/core/libs/prx/libSceDataTransfer/include/Api.hpp @@ -0,0 +1,68 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceDataTransferAbortFgTransfer(); +int APS5_VABI sceDataTransferAbortRequest(); +int APS5_VABI sceDataTransferAbortSearchPS4(); +int APS5_VABI sceDataTransferCheckBgTransferRunning(); +int APS5_VABI sceDataTransferGetFgTransferProgress(); +int APS5_VABI sceDataTransferGetPrepareFgTransferProgress(); +int APS5_VABI sceDataTransferInitialize(); +int APS5_VABI sceDataTransferRequestGetAppInfoPS4(); +int APS5_VABI sceDataTransferRequestGetSavedataInfoPS4(); +int APS5_VABI sceDataTransferRequestGetUsersPS4(); +int APS5_VABI sceDataTransferRequestLaunchPS4(); +int APS5_VABI sceDataTransferRequestPrepareFgTransfer(); +int APS5_VABI sceDataTransferRequestRebootAuthPS4(); +int APS5_VABI sceDataTransferRequestSearchPS4(); +int APS5_VABI sceDataTransferRequestStartFgTransfer(); +int APS5_VABI sceDataTransferRequestTransferTimePS4(); +int APS5_VABI sceDataTransferTargetAbortBindSavedata(); +int APS5_VABI sceDataTransferTargetAbortDeactivate(); +int APS5_VABI sceDataTransferTargetAbortEth0(); +int APS5_VABI sceDataTransferTargetAbortGetDeviceInfo(); +int APS5_VABI sceDataTransferTargetAbortGetDeviceInfoApplication(); +int APS5_VABI sceDataTransferTargetAbortGetTitles(); +int APS5_VABI sceDataTransferTargetAbortGetUsers(); +int APS5_VABI sceDataTransferTargetAbortLaunch(); +int APS5_VABI sceDataTransferTargetAbortPrepareTransfer(); +int APS5_VABI sceDataTransferTargetAbortPwrReq(); +int APS5_VABI sceDataTransferTargetAbortReboot(); +int APS5_VABI sceDataTransferTargetAbortSendSsoNew2Old(); +int APS5_VABI sceDataTransferTargetAbortSendSsoOld2New(); +int APS5_VABI sceDataTransferTargetAbortTransfer(); +int APS5_VABI sceDataTransferTargetAbortTransferSpeed(); +int APS5_VABI sceDataTransferTargetEventIsAuthReady(); +int APS5_VABI sceDataTransferTargetEventIsIPv6Ready(); +int APS5_VABI sceDataTransferTargetEventIsPwrReqReady(); +int APS5_VABI sceDataTransferTargetGetFailedUsers(); +int APS5_VABI sceDataTransferTargetGetRebootData(); +int APS5_VABI sceDataTransferTargetGetTransferProgress(); +int APS5_VABI sceDataTransferTargetRequestAbortSearch(); +int APS5_VABI sceDataTransferTargetRequestActivate(); +int APS5_VABI sceDataTransferTargetRequestAuth(); +int APS5_VABI sceDataTransferTargetRequestBindSavedata(); +int APS5_VABI sceDataTransferTargetRequestComplete(); +int APS5_VABI sceDataTransferTargetRequestCreateRebootData(); +int APS5_VABI sceDataTransferTargetRequestDeactivate(); +int APS5_VABI sceDataTransferTargetRequestEndTransfer(); +int APS5_VABI sceDataTransferTargetRequestGetDeviceInfo(); +int APS5_VABI sceDataTransferTargetRequestGetDeviceInfoApplication(); +int APS5_VABI sceDataTransferTargetRequestGetTitles(); +int APS5_VABI sceDataTransferTargetRequestGetUsers(); +int APS5_VABI sceDataTransferTargetRequestLaunch(); +int APS5_VABI sceDataTransferTargetRequestPrepareTransfer(); +int APS5_VABI sceDataTransferTargetRequestPrepareTransferProgress(); +int APS5_VABI sceDataTransferTargetRequestPwrReq(); +int APS5_VABI sceDataTransferTargetRequestReboot(); +int APS5_VABI sceDataTransferTargetRequestSearch(); +int APS5_VABI sceDataTransferTargetRequestSendSsoNew2Old(); +int APS5_VABI sceDataTransferTargetRequestSendSsoOld2New(); +int APS5_VABI sceDataTransferTargetRequestStartTransfer(); +int APS5_VABI sceDataTransferTargetRequestTransferSpeed(); +int APS5_VABI sceDataTransferTerminate(); + +} diff --git a/core/libs/prx/libSceDataTransfer/libSceDataTransfer.hpp b/core/libs/prx/libSceDataTransfer/libSceDataTransfer.hpp new file mode 100644 index 0000000000..dfa5f26f82 --- /dev/null +++ b/core/libs/prx/libSceDataTransfer/libSceDataTransfer.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceDataTransfer/include/Api.hpp" diff --git a/core/libs/prx/libSceDbg/libSceDbg.hpp b/core/libs/prx/libSceDbg/libSceDbg.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceDbg/libSceDbg.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceDbgAssist/libSceDbgAssist.hpp b/core/libs/prx/libSceDbgAssist/libSceDbgAssist.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceDbgAssist/libSceDbgAssist.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceDbgThreadSanitizer/Export.cpp b/core/libs/prx/libSceDbgThreadSanitizer/Export.cpp index f2bbed9a32..dcd840a54c 100644 --- a/core/libs/prx/libSceDbgThreadSanitizer/Export.cpp +++ b/core/libs/prx/libSceDbgThreadSanitizer/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceDbgThreadSanitizer/include/Api.hpp" #include "SceTypes.hpp" #include "prx/libc/include/General.hpp" diff --git a/core/libs/prx/libSceDbgThreadSanitizer/include/Api.hpp b/core/libs/prx/libSceDbgThreadSanitizer/include/Api.hpp new file mode 100644 index 0000000000..0e19a53fdc --- /dev/null +++ b/core/libs/prx/libSceDbgThreadSanitizer/include/Api.hpp @@ -0,0 +1,10 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +void APS5_VABI __tsan_acquire(void*); +void APS5_VABI __tsan_release(void*); + +} diff --git a/core/libs/prx/libSceDbgThreadSanitizer/libSceDbgThreadSanitizer.hpp b/core/libs/prx/libSceDbgThreadSanitizer/libSceDbgThreadSanitizer.hpp new file mode 100644 index 0000000000..e6ff7c3d4b --- /dev/null +++ b/core/libs/prx/libSceDbgThreadSanitizer/libSceDbgThreadSanitizer.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceDbgThreadSanitizer/include/Api.hpp" diff --git a/core/libs/prx/libSceDeci5/libSceDeci5.hpp b/core/libs/prx/libSceDeci5/libSceDeci5.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceDeci5/libSceDeci5.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceDeci5Appmp/libSceDeci5Appmp.hpp b/core/libs/prx/libSceDeci5Appmp/libSceDeci5Appmp.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceDeci5Appmp/libSceDeci5Appmp.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceDeci5CpComm/libSceDeci5CpComm.hpp b/core/libs/prx/libSceDeci5CpComm/libSceDeci5CpComm.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceDeci5CpComm/libSceDeci5CpComm.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceDeci5Ctrlp/libSceDeci5Ctrlp.hpp b/core/libs/prx/libSceDeci5Ctrlp/libSceDeci5Ctrlp.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceDeci5Ctrlp/libSceDeci5Ctrlp.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceDeci5Dbgp/libSceDeci5Dbgp.hpp b/core/libs/prx/libSceDeci5Dbgp/libSceDeci5Dbgp.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceDeci5Dbgp/libSceDeci5Dbgp.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceDeci5Drfp/libSceDeci5Drfp.hpp b/core/libs/prx/libSceDeci5Drfp/libSceDeci5Drfp.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceDeci5Drfp/libSceDeci5Drfp.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceDeci5Eventp/libSceDeci5Eventp.hpp b/core/libs/prx/libSceDeci5Eventp/libSceDeci5Eventp.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceDeci5Eventp/libSceDeci5Eventp.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceDeci5Fsmp/libSceDeci5Fsmp.hpp b/core/libs/prx/libSceDeci5Fsmp/libSceDeci5Fsmp.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceDeci5Fsmp/libSceDeci5Fsmp.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceDeci5Pgcmp/libSceDeci5Pgcmp.hpp b/core/libs/prx/libSceDeci5Pgcmp/libSceDeci5Pgcmp.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceDeci5Pgcmp/libSceDeci5Pgcmp.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceDeci5Rdrfp/libSceDeci5Rdrfp.hpp b/core/libs/prx/libSceDeci5Rdrfp/libSceDeci5Rdrfp.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceDeci5Rdrfp/libSceDeci5Rdrfp.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceDeci5Tsmp/libSceDeci5Tsmp.hpp b/core/libs/prx/libSceDeci5Tsmp/libSceDeci5Tsmp.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceDeci5Tsmp/libSceDeci5Tsmp.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceDeci5Ttyp/libSceDeci5Ttyp.hpp b/core/libs/prx/libSceDeci5Ttyp/libSceDeci5Ttyp.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceDeci5Ttyp/libSceDeci5Ttyp.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceDeci5UlpCommon/libSceDeci5UlpCommon.hpp b/core/libs/prx/libSceDeci5UlpCommon/libSceDeci5UlpCommon.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceDeci5UlpCommon/libSceDeci5UlpCommon.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceDepth/Export.cpp b/core/libs/prx/libSceDepth/Export.cpp index edfa2e580e..58c40c04fd 100644 --- a/core/libs/prx/libSceDepth/Export.cpp +++ b/core/libs/prx/libSceDepth/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceDepth/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceDepth/include/Api.hpp b/core/libs/prx/libSceDepth/include/Api.hpp new file mode 100644 index 0000000000..fae208c300 --- /dev/null +++ b/core/libs/prx/libSceDepth/include/Api.hpp @@ -0,0 +1,46 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceDepthCalculateRectificationInformation(void); +int APS5_VABI sceDepthDisableHeteroMode(void); +int APS5_VABI sceDepthEnableExtendedMode(void); +int APS5_VABI sceDepthEnableHeteroMode(void); +int APS5_VABI sceDepthEnableHeteroModeAndGenerateInformation(void); +int APS5_VABI sceDepthGetCalibrationData(void); +int APS5_VABI sceDepthGetImage(void); +int APS5_VABI sceDepthGetRectificationInformation(void); +int APS5_VABI sceDepthGetSrParameter(void); +int APS5_VABI sceDepthHandCandidateTrackerGetResult(void); +int APS5_VABI sceDepthHasCalibrationData(void); +int APS5_VABI sceDepthHeadCandidateDetectorGetResults(void); +int APS5_VABI sceDepthHeadCandidateTrackerGetResult(void); +int APS5_VABI sceDepthHeadCandidateTrackerSetValidationInformation(void); +int APS5_VABI sceDepthInitialize(void); +int APS5_VABI sceDepthLoadCalibrationData(void); +int APS5_VABI sceDepthQueryMemory(void); +int APS5_VABI sceDepthSaveInternalBuffers(void); +int APS5_VABI sceDepthSetCalibrationData(void); +int APS5_VABI sceDepthSetCommands(void); +int APS5_VABI sceDepthSetPostFilterParameter(void); +int APS5_VABI sceDepthSetPreFilterParameter(void); +int APS5_VABI sceDepthSetRectificationInformation(void); +int APS5_VABI sceDepthSetRoi(void); +int APS5_VABI sceDepthSetRoiset(void); +int APS5_VABI sceDepthSetSrParameter(void); +int APS5_VABI sceDepthSetSrTnrParameter(void); +int APS5_VABI sceDepthSubmit(void); +int APS5_VABI sceDepthTerminate(void); +int APS5_VABI sceDepthUpdate(void); +int APS5_VABI sceDepthValidateCurrentCalibrationData(void); +int APS5_VABI sceDepthWaitAndExecutePostProcess(void); +int APS5_VABI _sceDepthCalcHeteroAdjustParam(); +int APS5_VABI _sceDepthHeadCandidateTrackerGetInformation(); +int APS5_VABI _sceDepthHeadCandidateTrackerSetInformation(); +int APS5_VABI _sceDepthSetCameraFactoryCalibrationData(); +int APS5_VABI _sceDepthSetHeteroAdjustParam(); +int APS5_VABI _sceDepthSetHeteroMode(); + +} diff --git a/core/libs/prx/libSceDepth/libSceDepth.hpp b/core/libs/prx/libSceDepth/libSceDepth.hpp new file mode 100644 index 0000000000..8899705618 --- /dev/null +++ b/core/libs/prx/libSceDepth/libSceDepth.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceDepth/include/Api.hpp" diff --git a/core/libs/prx/libSceDepth2/Export.cpp b/core/libs/prx/libSceDepth2/Export.cpp index d043a5728d..18a122f40c 100644 --- a/core/libs/prx/libSceDepth2/Export.cpp +++ b/core/libs/prx/libSceDepth2/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceDepth2/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceDepth2/include/Api.hpp b/core/libs/prx/libSceDepth2/include/Api.hpp new file mode 100644 index 0000000000..97193eee0c --- /dev/null +++ b/core/libs/prx/libSceDepth2/include/Api.hpp @@ -0,0 +1,18 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceDepth2GetImage(void); +int APS5_VABI sceDepth2Initialize(void); +int APS5_VABI sceDepth2QueryMemory(void); +int APS5_VABI sceDepth2SaveInternalBuffers(void); +int APS5_VABI sceDepth2SetCameraFactoryCalibrationData(void); +int APS5_VABI sceDepth2SetCommand(void); +int APS5_VABI sceDepth2SetRoi(void); +int APS5_VABI sceDepth2Submit(void); +int APS5_VABI sceDepth2Terminate(void); +int APS5_VABI sceDepth2WaitAndExecutePostProcess(void); + +} diff --git a/core/libs/prx/libSceDepth2/libSceDepth2.hpp b/core/libs/prx/libSceDepth2/libSceDepth2.hpp new file mode 100644 index 0000000000..30a843bc1b --- /dev/null +++ b/core/libs/prx/libSceDepth2/libSceDepth2.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceDepth2/include/Api.hpp" diff --git a/core/libs/prx/libSceDipsw/Export.cpp b/core/libs/prx/libSceDipsw/Export.cpp index 3cddf792b2..a822968f7d 100644 --- a/core/libs/prx/libSceDipsw/Export.cpp +++ b/core/libs/prx/libSceDipsw/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceDipsw/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceDipsw/include/Api.hpp b/core/libs/prx/libSceDipsw/include/Api.hpp new file mode 100644 index 0000000000..655ebbc6de --- /dev/null +++ b/core/libs/prx/libSceDipsw/include/Api.hpp @@ -0,0 +1,17 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceKernelCheckDipsw(); +int APS5_VABI sceKernelInitializeDipsw(); +int APS5_VABI sceKernelIsAssistMode(); +int APS5_VABI sceKernelIsDevelopmentMode(); +int APS5_VABI sceKernelIsDisableRazor(); +int APS5_VABI sceKernelReadDipswData(); +int APS5_VABI sceKernelSetDipsw(); +int APS5_VABI sceKernelUnsetDipsw(); +int APS5_VABI sceKernelWriteDipswData(); + +} diff --git a/core/libs/prx/libSceDipsw/libSceDipsw.hpp b/core/libs/prx/libSceDipsw/libSceDipsw.hpp new file mode 100644 index 0000000000..6d1d472e8b --- /dev/null +++ b/core/libs/prx/libSceDipsw/libSceDipsw.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceDipsw/include/Api.hpp" diff --git a/core/libs/prx/libSceDiscId/Export.cpp b/core/libs/prx/libSceDiscId/Export.cpp index ef0373a67b..33a87a4698 100644 --- a/core/libs/prx/libSceDiscId/Export.cpp +++ b/core/libs/prx/libSceDiscId/Export.cpp @@ -1,11 +1,9 @@ +#include "prx/libSceDiscId/include/Api.hpp" #include #include #include "SceTypes.hpp" #include "prx/libc/include/General.hpp" -struct DiscId; -struct DiscId2; - extern "C" { int APS5_VABI sceDiscIdGet(DiscId* discId) { diff --git a/core/libs/prx/libSceDiscId/include/Api.hpp b/core/libs/prx/libSceDiscId/include/Api.hpp new file mode 100644 index 0000000000..52b6039516 --- /dev/null +++ b/core/libs/prx/libSceDiscId/include/Api.hpp @@ -0,0 +1,14 @@ +#pragma once + +#include "SceTypes.hpp" + +struct DiscId; + +struct DiscId2; + +extern "C" { + +int APS5_VABI sceDiscIdGet(DiscId* discId); +int APS5_VABI sceDiscIdGet2(DiscId2* discId, std::uint32_t flags); + +} diff --git a/core/libs/prx/libSceDiscId/libSceDiscId.hpp b/core/libs/prx/libSceDiscId/libSceDiscId.hpp new file mode 100644 index 0000000000..26273e4024 --- /dev/null +++ b/core/libs/prx/libSceDiscId/libSceDiscId.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceDiscId/include/Api.hpp" diff --git a/core/libs/prx/libSceDiscMap/Export.cpp b/core/libs/prx/libSceDiscMap/Export.cpp index 8fedde6365..7eea1e3999 100644 --- a/core/libs/prx/libSceDiscMap/Export.cpp +++ b/core/libs/prx/libSceDiscMap/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceDiscMap/include/Api.hpp" #include #include "SceTypes.hpp" #include "prx/libc/include/General.hpp" diff --git a/core/libs/prx/libSceDiscMap/include/Api.hpp b/core/libs/prx/libSceDiscMap/include/Api.hpp new file mode 100644 index 0000000000..392ba50981 --- /dev/null +++ b/core/libs/prx/libSceDiscMap/include/Api.hpp @@ -0,0 +1,11 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +std::int32_t APS5_VABI sceDiscMapIsRequestOnHDD(const char* path, std::int64_t offset, std::int64_t size, std::int32_t* result); +std::int32_t APS5_VABI sceDiscMapUnknown_ioKMruft1ek(const char* path, std::int64_t offset, std::int64_t size, std::uint64_t* flags, std::uint64_t* out1, std::uint64_t* out2); +int APS5_VABI sceDiscMapGetPackageSize(std::int64_t fflags, int* ret1, int* ret2); + +} diff --git a/core/libs/prx/libSceDiscMap/libSceDiscMap.hpp b/core/libs/prx/libSceDiscMap/libSceDiscMap.hpp new file mode 100644 index 0000000000..e380270d79 --- /dev/null +++ b/core/libs/prx/libSceDiscMap/libSceDiscMap.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceDiscMap/include/Api.hpp" diff --git a/core/libs/prx/libSceDolbyVision/libSceDolbyVision.hpp b/core/libs/prx/libSceDolbyVision/libSceDolbyVision.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceDolbyVision/libSceDolbyVision.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceDseehx/Export.cpp b/core/libs/prx/libSceDseehx/Export.cpp index 43fce06ef6..b54b261746 100644 --- a/core/libs/prx/libSceDseehx/Export.cpp +++ b/core/libs/prx/libSceDseehx/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceDseehx/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceDseehx/include/Api.hpp b/core/libs/prx/libSceDseehx/include/Api.hpp new file mode 100644 index 0000000000..de8de8649b --- /dev/null +++ b/core/libs/prx/libSceDseehx/include/Api.hpp @@ -0,0 +1,12 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceDseehxConvert(); +int APS5_VABI sceDseehxExtInit(); +int APS5_VABI sceDseehxFlush(); +int APS5_VABI sceDseehxInit(); + +} diff --git a/core/libs/prx/libSceDseehx/libSceDseehx.hpp b/core/libs/prx/libSceDseehx/libSceDseehx.hpp new file mode 100644 index 0000000000..a70d9c176e --- /dev/null +++ b/core/libs/prx/libSceDseehx/libSceDseehx.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceDseehx/include/Api.hpp" diff --git a/core/libs/prx/libSceDtcpIp/libSceDtcpIp.hpp b/core/libs/prx/libSceDtcpIp/libSceDtcpIp.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceDtcpIp/libSceDtcpIp.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceDtsEnc/Export.cpp b/core/libs/prx/libSceDtsEnc/Export.cpp index 06a9bc9f32..058fb9d21b 100644 --- a/core/libs/prx/libSceDtsEnc/Export.cpp +++ b/core/libs/prx/libSceDtsEnc/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceDtsEnc/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceDtsEnc/include/Api.hpp b/core/libs/prx/libSceDtsEnc/include/Api.hpp new file mode 100644 index 0000000000..c58f777bab --- /dev/null +++ b/core/libs/prx/libSceDtsEnc/include/Api.hpp @@ -0,0 +1,15 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceDtsEncCreateEncoder(); +int APS5_VABI sceDtsEncDeleteEncoder(); +int APS5_VABI sceDtsEncEncode(); +int APS5_VABI sceDtsEncEncodeAsync(); +int APS5_VABI sceDtsEncFlush(); +int APS5_VABI sceDtsEncIsEncoding(); +int APS5_VABI sceDtsEncWaitEncode(); + +} diff --git a/core/libs/prx/libSceDtsEnc/libSceDtsEnc.hpp b/core/libs/prx/libSceDtsEnc/libSceDtsEnc.hpp new file mode 100644 index 0000000000..c8fe34a7d9 --- /dev/null +++ b/core/libs/prx/libSceDtsEnc/libSceDtsEnc.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceDtsEnc/include/Api.hpp" diff --git a/core/libs/prx/libSceEditMp4/Export.cpp b/core/libs/prx/libSceEditMp4/Export.cpp index 9bafeb8142..cc4aed4a43 100644 --- a/core/libs/prx/libSceEditMp4/Export.cpp +++ b/core/libs/prx/libSceEditMp4/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceEditMp4/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceEditMp4/include/Api.hpp b/core/libs/prx/libSceEditMp4/include/Api.hpp new file mode 100644 index 0000000000..219759f5bf --- /dev/null +++ b/core/libs/prx/libSceEditMp4/include/Api.hpp @@ -0,0 +1,17 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceEditMp4Abort(); +int APS5_VABI sceEditMp4Edit(); +int APS5_VABI sceEditMp4GetStatus(); +int APS5_VABI sceEditMp4Initialize(); +int APS5_VABI sceEditMp4InitializeParam(); +int APS5_VABI sceEditMp4QueryMemSize(); +int APS5_VABI sceEditMp4SetFinishCallback(); +int APS5_VABI sceEditMp4Terminate(); +int APS5_VABI sceEditMp4Unite(); + +} diff --git a/core/libs/prx/libSceEditMp4/libSceEditMp4.hpp b/core/libs/prx/libSceEditMp4/libSceEditMp4.hpp new file mode 100644 index 0000000000..d19448ddb3 --- /dev/null +++ b/core/libs/prx/libSceEditMp4/libSceEditMp4.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceEditMp4/include/Api.hpp" diff --git a/core/libs/prx/libSceEmbeddedTts/libSceEmbeddedTts.hpp b/core/libs/prx/libSceEmbeddedTts/libSceEmbeddedTts.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceEmbeddedTts/libSceEmbeddedTts.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceEmbeddedTtsCoreG3/libSceEmbeddedTtsCoreG3.hpp b/core/libs/prx/libSceEmbeddedTtsCoreG3/libSceEmbeddedTtsCoreG3.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceEmbeddedTtsCoreG3/libSceEmbeddedTtsCoreG3.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceErrorDialog/Export.cpp b/core/libs/prx/libSceErrorDialog/Export.cpp index d3c922f2b1..5d6ed9d85e 100644 --- a/core/libs/prx/libSceErrorDialog/Export.cpp +++ b/core/libs/prx/libSceErrorDialog/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceErrorDialog/include/Api.hpp" #include #include #include diff --git a/core/libs/prx/libSceErrorDialog/include/Api.hpp b/core/libs/prx/libSceErrorDialog/include/Api.hpp new file mode 100644 index 0000000000..3b12339095 --- /dev/null +++ b/core/libs/prx/libSceErrorDialog/include/Api.hpp @@ -0,0 +1,16 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceErrorDialogInitialize(void); +int APS5_VABI sceErrorDialogOpen(const void* param); +int APS5_VABI sceErrorDialogUpdateStatus(void); +int APS5_VABI sceErrorDialogGetStatus(void); +int APS5_VABI sceErrorDialogClose(void); +int APS5_VABI sceErrorDialogTerminate(void); +int APS5_VABI sceErrorDialogOpenDetail(); +int APS5_VABI sceErrorDialogOpenWithReport(); + +} diff --git a/core/libs/prx/libSceErrorDialog/libSceErrorDialog.hpp b/core/libs/prx/libSceErrorDialog/libSceErrorDialog.hpp new file mode 100644 index 0000000000..9681a99ea5 --- /dev/null +++ b/core/libs/prx/libSceErrorDialog/libSceErrorDialog.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceErrorDialog/include/Api.hpp" diff --git a/core/libs/prx/libSceEsvm/Export.cpp b/core/libs/prx/libSceEsvm/Export.cpp index 54def11467..cbef694c99 100644 --- a/core/libs/prx/libSceEsvm/Export.cpp +++ b/core/libs/prx/libSceEsvm/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceEsvm/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceEsvm/include/Api.hpp b/core/libs/prx/libSceEsvm/include/Api.hpp new file mode 100644 index 0000000000..d11b339d0e --- /dev/null +++ b/core/libs/prx/libSceEsvm/include/Api.hpp @@ -0,0 +1,11 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceEsvmAppAudioSyncCreateContext(); +int APS5_VABI sceEsvmAppAudioSyncFlush(); +int APS5_VABI sceEsvmSyncVideo(); + +} diff --git a/core/libs/prx/libSceEsvm/libSceEsvm.hpp b/core/libs/prx/libSceEsvm/libSceEsvm.hpp new file mode 100644 index 0000000000..015c133208 --- /dev/null +++ b/core/libs/prx/libSceEsvm/libSceEsvm.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceEsvm/include/Api.hpp" diff --git a/core/libs/prx/libSceEsvmEngine/Export.cpp b/core/libs/prx/libSceEsvmEngine/Export.cpp index 6667c6812b..1ffc3f6398 100644 --- a/core/libs/prx/libSceEsvmEngine/Export.cpp +++ b/core/libs/prx/libSceEsvmEngine/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceEsvmEngine/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceEsvmEngine/include/Api.hpp b/core/libs/prx/libSceEsvmEngine/include/Api.hpp new file mode 100644 index 0000000000..a99c298234 --- /dev/null +++ b/core/libs/prx/libSceEsvmEngine/include/Api.hpp @@ -0,0 +1,27 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceEsvmEngineDestroyMediaKeySystemAccess(); +int APS5_VABI sceEsvmEngineMediaKeySessionClose(); +int APS5_VABI sceEsvmEngineMediaKeySessionGenerateRequest(); +int APS5_VABI sceEsvmEngineMediaKeySessionGetExpiration(); +int APS5_VABI sceEsvmEngineMediaKeySessionGetKeyStatuses(); +int APS5_VABI sceEsvmEngineMediaKeySessionGetSessionId(); +int APS5_VABI sceEsvmEngineMediaKeySessionLoad(); +int APS5_VABI sceEsvmEngineMediaKeySessionRemove(); +int APS5_VABI sceEsvmEngineMediaKeySessionSetEventHandler(); +int APS5_VABI sceEsvmEngineMediaKeySessionUpdate(); +int APS5_VABI sceEsvmEngineMediaKeySystemAccessCreateMediaKeys(); +int APS5_VABI sceEsvmEngineMediaKeySystemAccessDestroyMediaKeys(); +int APS5_VABI sceEsvmEngineMediaKeySystemAccessGetConfiguration(); +int APS5_VABI sceEsvmEngineMediaKeySystemAccessSetCdmStorageConfig(); +int APS5_VABI sceEsvmEngineMediaKeysCreateSession(); +int APS5_VABI sceEsvmEngineMediaKeysDestroySession(); +int APS5_VABI sceEsvmEngineMediaKeysSetEventHandler(); +int APS5_VABI sceEsvmEngineMediaKeysSetServerCertificate(); +int APS5_VABI sceEsvmEngineRequestMediaKeySystemAccess(); + +} diff --git a/core/libs/prx/libSceEsvmEngine/libSceEsvmEngine.hpp b/core/libs/prx/libSceEsvmEngine/libSceEsvmEngine.hpp new file mode 100644 index 0000000000..c8bc3ef97c --- /dev/null +++ b/core/libs/prx/libSceEsvmEngine/libSceEsvmEngine.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceEsvmEngine/include/Api.hpp" diff --git a/core/libs/prx/libSceFiber/Export.cpp b/core/libs/prx/libSceFiber/Export.cpp index e214387ae3..4d3e54f5f4 100644 --- a/core/libs/prx/libSceFiber/Export.cpp +++ b/core/libs/prx/libSceFiber/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceFiber/include/Api.hpp" #include #include #include "SceTypes.hpp" @@ -42,8 +43,6 @@ static constexpr std::uint32_t FIBER_FLAG_SET_FPU_REGISTERS = 0x100; static constexpr std::uint32_t FIBER_DEFAULT_MXCSR = 0x9fc0; static constexpr std::uint16_t FIBER_DEFAULT_FPU_CONTROL = 0x037f; -using GuestFiberEntry = FiberEntry; - // A fiber that is switching away stays Suspending until its context is saved; whoever runs next // on that host thread publishes Suspended. Fibers migrate between threads, so a resumer must never // see Suspended before the saved stack pointer is valid. diff --git a/core/libs/prx/libSceFiber/include/Api.hpp b/core/libs/prx/libSceFiber/include/Api.hpp new file mode 100644 index 0000000000..e9cef9744c --- /dev/null +++ b/core/libs/prx/libSceFiber/include/Api.hpp @@ -0,0 +1,26 @@ +#pragma once + +#include "SceTypes.hpp" + +using GuestFiberEntry = FiberEntry; + +extern "C" { + +int32_t APS5_VABI _sceFiberInitializeImpl_nid_postfix(FiberObject* object, const char* name, GuestFiberEntry entry, uint64_t argOnInitialize, void* addrContext, uint64_t sizeContext, const void* optParam, uint32_t buildVersion); +int32_t APS5_VABI sceFiberFinalize(FiberObject* object); +int32_t APS5_VABI sceFiberRun_nid_postfix(FiberObject* object, uint64_t argOnRun, uint64_t* argOnReturn); +int32_t APS5_VABI sceFiberSwitch(FiberObject* object, uint64_t argOnRun, uint64_t* argOnRunOut); +int32_t APS5_VABI sceFiberReturnToThread(uint64_t argOnReturn, uint64_t* argOnRun); +int32_t APS5_VABI sceFiberGetSelf(FiberObject** fiber); +int32_t APS5_VABI sceFiberGetInfo(FiberObject* object, FiberInfo* fiberInfo); +int32_t APS5_VABI sceFiberRename(FiberObject* object, const char* name); +int32_t APS5_VABI sceFiberOptParamInitialize(FiberOptParam* optParam); +int32_t APS5_VABI sceFiberGetThreadFramePointerAddress(uint64_t* addrFramePointer); +int32_t APS5_VABI _sceFiberGetThreadFramePointerAddress(uint64_t* addrFramePointer); +int32_t APS5_VABI sceFiberStartContextSizeCheck(uint32_t flags); +int32_t APS5_VABI sceFiberStopContextSizeCheck(void); +int32_t APS5_VABI _sceFiberAttachContextAndRun(FiberObject* object, void* addrContext, uint64_t sizeContext, uint64_t argOnRun, uint64_t* argOnReturn); +int32_t APS5_VABI _sceFiberAttachContextAndSwitch(FiberObject* object, void* addrContext, uint64_t sizeContext, uint64_t argOnRun, uint64_t* argOnRunOut); +int32_t APS5_VABI _sceFiberInitializeWithInternalOptionImpl(FiberObject* object, const char* name, GuestFiberEntry entry, uint64_t argOnInitialize, void* addrContext, uint64_t sizeContext, const FiberOptParam* optParam, uint32_t flags, uint32_t buildVersion); + +} diff --git a/core/libs/prx/libSceFiber/libSceFiber.hpp b/core/libs/prx/libSceFiber/libSceFiber.hpp new file mode 100644 index 0000000000..1a16c725b6 --- /dev/null +++ b/core/libs/prx/libSceFiber/libSceFiber.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceFiber/include/Api.hpp" diff --git a/core/libs/prx/libSceFios2/Export.cpp b/core/libs/prx/libSceFios2/Export.cpp index eeedc28190..b97176c204 100644 --- a/core/libs/prx/libSceFios2/Export.cpp +++ b/core/libs/prx/libSceFios2/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceFios2/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceFios2/include/Api.hpp b/core/libs/prx/libSceFios2/include/Api.hpp new file mode 100644 index 0000000000..354858a01d --- /dev/null +++ b/core/libs/prx/libSceFios2/include/Api.hpp @@ -0,0 +1,176 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceFiosArchiveGetDecompressorThreadCount(); +int APS5_VABI sceFiosArchiveGetMountBufferSize(); +int APS5_VABI sceFiosArchiveGetMountBufferSizeSync(); +int APS5_VABI sceFiosArchiveMount(); +int APS5_VABI sceFiosArchiveMountSync(); +int APS5_VABI sceFiosArchiveMountWithOrder(); +int APS5_VABI sceFiosArchiveMountWithOrderSync(); +int APS5_VABI sceFiosArchiveSetDecompressorThreadCount(); +int APS5_VABI sceFiosArchiveUnmount(); +int APS5_VABI sceFiosArchiveUnmountSync(); +int APS5_VABI sceFiosCacheContainsFileRangeSync(); +int APS5_VABI sceFiosCacheContainsFileSync(); +int APS5_VABI sceFiosCacheFlushFileRangeSync(); +int APS5_VABI sceFiosCacheFlushFileSync(); +int APS5_VABI sceFiosCacheFlushSync(); +int APS5_VABI sceFiosCachePrefetchFH(); +int APS5_VABI sceFiosCachePrefetchFHRange(); +int APS5_VABI sceFiosCachePrefetchFHRangeSync(); +int APS5_VABI sceFiosCachePrefetchFHSync(); +int APS5_VABI sceFiosCachePrefetchFile(); +int APS5_VABI sceFiosCachePrefetchFileRange(); +int APS5_VABI sceFiosCachePrefetchFileRangeSync(); +int APS5_VABI sceFiosCachePrefetchFileSync(); +int APS5_VABI sceFiosCancelAllOps(); +int APS5_VABI sceFiosClearTimeStamps(); +int APS5_VABI sceFiosCloseAllFiles(); +int APS5_VABI sceFiosDHClose(); +int APS5_VABI sceFiosDHCloseSync(); +int APS5_VABI sceFiosDHGetPath(); +int APS5_VABI sceFiosDHOpen(); +int APS5_VABI sceFiosDHOpenSync(); +int APS5_VABI sceFiosDHRead(); +int APS5_VABI sceFiosDHReadSync(); +int APS5_VABI sceFiosDLLInitialize(); +int APS5_VABI sceFiosDLLTerminate(); +int APS5_VABI sceFiosDateFromComponents(); +int APS5_VABI sceFiosDateGetCurrent(); +int APS5_VABI sceFiosDateToComponents(); +int APS5_VABI sceFiosDeallocatePassthruFH(); +int APS5_VABI sceFiosDebugDumpDH(); +int APS5_VABI sceFiosDebugDumpDate(); +int APS5_VABI sceFiosDebugDumpError(); +int APS5_VABI sceFiosDebugDumpFH(); +int APS5_VABI sceFiosDebugDumpOp(); +int APS5_VABI sceFiosDelete(); +int APS5_VABI sceFiosDeleteSync(); +int APS5_VABI sceFiosDirectoryCreate(); +int APS5_VABI sceFiosDirectoryCreateSync(); +int APS5_VABI sceFiosDirectoryCreateWithMode(); +int APS5_VABI sceFiosDirectoryCreateWithModeSync(); +int APS5_VABI sceFiosDirectoryDelete(); +int APS5_VABI sceFiosDirectoryDeleteSync(); +int APS5_VABI sceFiosDirectoryExists(); +int APS5_VABI sceFiosDirectoryExistsSync(); +int APS5_VABI sceFiosExists(); +int APS5_VABI sceFiosExistsSync(); +int APS5_VABI sceFiosFHClose(); +int APS5_VABI sceFiosFHCloseSync(); +int APS5_VABI sceFiosFHGetOpenParams(); +int APS5_VABI sceFiosFHGetPath(); +int APS5_VABI sceFiosFHGetSize(); +int APS5_VABI sceFiosFHOpen(); +int APS5_VABI sceFiosFHOpenSync(); +int APS5_VABI sceFiosFHOpenWithMode(); +int APS5_VABI sceFiosFHOpenWithModeSync(); +int APS5_VABI sceFiosFHPread(); +int APS5_VABI sceFiosFHPreadSync(); +int APS5_VABI sceFiosFHPreadv(); +int APS5_VABI sceFiosFHPreadvSync(); +int APS5_VABI sceFiosFHPwrite(); +int APS5_VABI sceFiosFHPwriteSync(); +int APS5_VABI sceFiosFHPwritev(); +int APS5_VABI sceFiosFHPwritevSync(); +int APS5_VABI sceFiosFHRead(); +int APS5_VABI sceFiosFHReadSync(); +int APS5_VABI sceFiosFHReadv(); +int APS5_VABI sceFiosFHReadvSync(); +int APS5_VABI sceFiosFHSeek(); +int APS5_VABI sceFiosFHStat(); +int APS5_VABI sceFiosFHStatSync(); +int APS5_VABI sceFiosFHSync(); +int APS5_VABI sceFiosFHSyncSync(); +int APS5_VABI sceFiosFHTell(); +int APS5_VABI sceFiosFHToFileno(); +int APS5_VABI sceFiosFHTruncate(); +int APS5_VABI sceFiosFHTruncateSync(); +int APS5_VABI sceFiosFHWrite(); +int APS5_VABI sceFiosFHWriteSync(); +int APS5_VABI sceFiosFHWritev(); +int APS5_VABI sceFiosFHWritevSync(); +int APS5_VABI sceFiosFileDelete(); +int APS5_VABI sceFiosFileDeleteSync(); +int APS5_VABI sceFiosFileExists(); +int APS5_VABI sceFiosFileExistsSync(); +int APS5_VABI sceFiosFileGetSize(); +int APS5_VABI sceFiosFileGetSizeSync(); +int APS5_VABI sceFiosFileRead(); +int APS5_VABI sceFiosFileReadSync(); +int APS5_VABI sceFiosFileTruncate(); +int APS5_VABI sceFiosFileTruncateSync(); +int APS5_VABI sceFiosFileWrite(); +int APS5_VABI sceFiosFileWriteSync(); +int APS5_VABI sceFiosFilenoToFH(); +int APS5_VABI sceFiosGetAllDHs(); +int APS5_VABI sceFiosGetAllFHs(); +int APS5_VABI sceFiosGetAllOps(); +int APS5_VABI sceFiosGetDefaultOpAttr(); +int APS5_VABI sceFiosGetGlobalDefaultOpAttr(); +int APS5_VABI sceFiosGetSuspendCount(); +int APS5_VABI sceFiosGetThreadDefaultOpAttr(); +int APS5_VABI sceFiosIOFilterAdd(); +int APS5_VABI sceFiosIOFilterCache(); +int APS5_VABI sceFiosIOFilterGetInfo(); +int APS5_VABI sceFiosIOFilterPsarcDearchiver(); +int APS5_VABI sceFiosIOFilterRemove(); +int APS5_VABI sceFiosInitialize(); +int APS5_VABI sceFiosIsIdle(); +int APS5_VABI sceFiosIsInitialized(); +int APS5_VABI sceFiosIsSuspended(); +int APS5_VABI sceFiosIsValidHandle(); +int APS5_VABI sceFiosOpCancel(); +int APS5_VABI sceFiosOpDelete(); +int APS5_VABI sceFiosOpGetActualCount(); +int APS5_VABI sceFiosOpGetAttr(); +int APS5_VABI sceFiosOpGetBuffer(); +int APS5_VABI sceFiosOpGetError(); +int APS5_VABI sceFiosOpGetOffset(); +int APS5_VABI sceFiosOpGetPath(); +int APS5_VABI sceFiosOpGetRequestCount(); +int APS5_VABI sceFiosOpIsCancelled(); +int APS5_VABI sceFiosOpIsDone(); +int APS5_VABI sceFiosOpReschedule(); +int APS5_VABI sceFiosOpRescheduleWithPriority(); +int APS5_VABI sceFiosOpSetBuffer(); +int APS5_VABI sceFiosOpSyncWait(); +int APS5_VABI sceFiosOpSyncWaitForIO(); +int APS5_VABI sceFiosOpWait(); +int APS5_VABI sceFiosOpWaitUntil(); +int APS5_VABI sceFiosOverlayAdd(); +int APS5_VABI sceFiosOverlayGetInfo(); +int APS5_VABI sceFiosOverlayGetList(); +int APS5_VABI sceFiosOverlayModify(); +int APS5_VABI sceFiosOverlayRemove(); +int APS5_VABI sceFiosOverlayResolveSync(); +int APS5_VABI sceFiosPathNormalize(); +int APS5_VABI sceFiosPathcmp(); +int APS5_VABI sceFiosPathncmp(); +int APS5_VABI sceFiosPrintTimeStamps(); +int APS5_VABI sceFiosPrintf(); +int APS5_VABI sceFiosRename(); +int APS5_VABI sceFiosRenameSync(); +int APS5_VABI sceFiosResolve(); +int APS5_VABI sceFiosResolveSync(); +int APS5_VABI sceFiosResume(); +int APS5_VABI sceFiosSaveTimeStamp(); +int APS5_VABI sceFiosSetGlobalDefaultOpAttr(); +int APS5_VABI sceFiosSetThreadDefaultOpAttr(); +int APS5_VABI sceFiosShutdownAndCancelOps(); +int APS5_VABI sceFiosStat(); +int APS5_VABI sceFiosStatSync(); +int APS5_VABI sceFiosSuspend(); +int APS5_VABI sceFiosTerminate(); +int APS5_VABI sceFiosTimeGetCurrent(); +int APS5_VABI sceFiosTimeIntervalFromNanoseconds(); +int APS5_VABI sceFiosTimeIntervalToNanoseconds(); +int APS5_VABI sceFiosTraceTimestamp(); +int APS5_VABI sceFiosUpdateParameters(); +int APS5_VABI sceFiosVprintf(); + +} diff --git a/core/libs/prx/libSceFios2/libSceFios2.hpp b/core/libs/prx/libSceFios2/libSceFios2.hpp new file mode 100644 index 0000000000..5f164953f7 --- /dev/null +++ b/core/libs/prx/libSceFios2/libSceFios2.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceFios2/include/Api.hpp" diff --git a/core/libs/prx/libSceFont-module/libSceFont-module.hpp b/core/libs/prx/libSceFont-module/libSceFont-module.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceFont-module/libSceFont-module.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceFont.native/libSceFont.native.hpp b/core/libs/prx/libSceFont.native/libSceFont.native.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceFont.native/libSceFont.native.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceFont/CMakeLists.txt b/core/libs/prx/libSceFont/CMakeLists.txt index cec16f879b..9d7e177cb1 100644 --- a/core/libs/prx/libSceFont/CMakeLists.txt +++ b/core/libs/prx/libSceFont/CMakeLists.txt @@ -16,6 +16,33 @@ if(BUILD_TESTING) set_tests_properties(guest_font guest_system_font PROPERTIES ENVIRONMENT_MODIFICATION "PATH=path_list_prepend:$") endif() + add_test_executable(guest_font_metrics_tests ${LIBS_INCLUDE_DIR}/tests/GuestFontMetrics.cpp) + target_include_directories(guest_font_metrics_tests PRIVATE ${LIBS_INCLUDE_DIR}) + target_link_libraries(guest_font_metrics_tests PRIVATE libSceFont libSceFontFt libc) + configure_windows_unwind(guest_font_metrics_tests) + add_test(NAME guest_font_metrics COMMAND guest_font_metrics_tests) + if(WIN32) + set_tests_properties(guest_font_metrics PROPERTIES ENVIRONMENT_MODIFICATION + "PATH=path_list_prepend:$") + endif() + add_test_executable(guest_font_style_information_tests ${LIBS_INCLUDE_DIR}/tests/GuestFontStyleInformation.cpp) + target_include_directories(guest_font_style_information_tests PRIVATE ${LIBS_INCLUDE_DIR}) + target_link_libraries(guest_font_style_information_tests PRIVATE libSceFont libSceFontFt libc) + configure_windows_unwind(guest_font_style_information_tests) + add_test(NAME guest_font_style_information COMMAND guest_font_style_information_tests) + if(WIN32) + set_tests_properties(guest_font_style_information PROPERTIES ENVIRONMENT_MODIFICATION + "PATH=path_list_prepend:$") + endif() + add_test_executable(guest_font_outline_profile_tests ${LIBS_INCLUDE_DIR}/tests/GuestFontOutlineProfile.cpp) + target_include_directories(guest_font_outline_profile_tests PRIVATE ${LIBS_INCLUDE_DIR}) + target_link_libraries(guest_font_outline_profile_tests PRIVATE libSceFont libSceFontFt libc) + configure_windows_unwind(guest_font_outline_profile_tests) + add_test(NAME guest_font_outline_profile COMMAND guest_font_outline_profile_tests) + if(WIN32) + set_tests_properties(guest_font_outline_profile PROPERTIES ENVIRONMENT_MODIFICATION + "PATH=path_list_prepend:$") + endif() add_test_executable(guest_font_writing_line_tests ${LIBS_INCLUDE_DIR}/tests/GuestFontWritingLine.cpp) target_include_directories(guest_font_writing_line_tests PRIVATE ${LIBS_INCLUDE_DIR}) target_link_libraries(guest_font_writing_line_tests PRIVATE libSceFont libc) diff --git a/core/libs/prx/libSceFont/include/Api.hpp b/core/libs/prx/libSceFont/include/Api.hpp new file mode 100644 index 0000000000..bdb0f3f449 --- /dev/null +++ b/core/libs/prx/libSceFont/include/Api.hpp @@ -0,0 +1,329 @@ +#pragma once + +#include "prx/libSceFont/include/FontTypes.hpp" +#include "SceTypes.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct FontGraphicsDevice; + +struct FontGraphicsDeviceParam; + +struct FontGraphicsService; + +struct FontGraphicsServiceParam; + +struct FontWords; + +struct FontGlyphSupport; + +struct FontOutlineProfile; + +struct FontMetrics; + +struct FontStyleInformation; + +struct FontGlyphExpandBufferState; + +struct FontGraphicsResource; + +struct FontGraphicsFrame; + +struct FontGraphicsDesignResource; + +struct FontGraphicsDesign; + +struct FontGraphicsCanvas; + +struct FontGraphicsCanvasSequence; + +struct FontGraphicsSurface; + +struct FontGraphicsSurfaceTexture; + +struct FontGraphicsFill; + +struct FontGraphicsRegion { + float x; + float y; + float width; + float height; + std::uint32_t flags; + std::uint32_t tag; + float outerRadius; + float innerRadius; +}; + +struct FontGraphicsFillMethod { + std::int32_t mode; + std::int32_t type; + std::uint32_t flags; + std::uint32_t tag; + std::byte reserved[16]; +}; + +struct FontGraphicsFillPlot { + float mapping[4]; + const FontGraphicsRegion* region; + std::uint16_t tag; + std::uint16_t reserved26; + std::uint16_t layout; + std::uint8_t flags; + std::byte reserved[33]; +}; + +struct FontGraphicsFillRates { + float mapping[4]; + const FontGraphicsFill* fill; + std::uint16_t tag; + std::uint16_t effect; + std::uint16_t layout; + std::uint8_t flags; + std::byte reserved[33]; +}; + +struct FontGraphicsPoolUsage { + std::uint32_t capacity; + std::uint32_t used; + std::uint32_t available; + std::uint32_t peak; + std::int32_t change; +}; + +struct FontGraphicsMemoryUsage { + FontGraphicsPoolUsage storage; + FontGraphicsPoolUsage allocations; + void* address; +}; + +struct FontGraphicsDeviceUsage { + FontGraphicsMemoryUsage first; + FontGraphicsMemoryUsage second; +}; + +extern "C" { + +int APS5_VABI sceFontMemoryInit(FontMemory* memory, void* regionAddress, std::uint32_t regionSize, const FontMemoryInterface* iface, void* mspaceObject, FontMemoryDestroyFunction destroyCallback, void* destroyObject); +int APS5_VABI sceFontMemoryTerm(FontMemory* memory); +int APS5_VABI sceFontCreateLibraryWithEdition(const FontMemory* memory, const void* createParams, std::uint64_t edition, FontLibrary* pLibrary); +int APS5_VABI sceFontCreateLibrary(const FontMemory* memory, const void* createParams, FontLibrary* pLibrary); +int APS5_VABI sceFontDestroyLibrary(FontLibrary* pLibrary); +int APS5_VABI sceFontCreateRendererWithEdition(const FontMemory* memory, const void* createParams, std::uint64_t edition, FontRenderer* pRenderer); +int APS5_VABI sceFontCreateRenderer(const FontMemory* memory, const void* createParams, FontRenderer* pRenderer); +int APS5_VABI sceFontDestroyRenderer(FontRenderer* pRenderer); +int APS5_VABI sceFontRendererGetOutlineBufferSize(FontRenderer fontRenderer, std::uint32_t* size); +int APS5_VABI sceFontRendererResetOutlineBuffer(FontRenderer fontRenderer); +int APS5_VABI sceFontRendererSetOutlineBufferPolicy(FontRenderer fontRenderer, std::uint64_t bufferPolicy, std::uint32_t basalSize, std::uint32_t limitSize); +int APS5_VABI sceFontGetPixelResolution(FontLibrary library, std::uint32_t* subPixelCount); +int APS5_VABI sceFontAttachDeviceCacheBuffer(FontLibrary library, void* buffer, std::uint32_t size); +int APS5_VABI sceFontClearDeviceCache(FontLibrary library); +int APS5_VABI sceFontDettachDeviceCacheBuffer(FontLibrary library, void** buffer, std::uint32_t* size); +int APS5_VABI sceFontSupportExternalFonts(FontLibrary library, std::uint32_t fontMax, std::uint32_t formats); +int APS5_VABI sceFontSupportSystemFonts(FontLibrary library); +int APS5_VABI sceFontSetFontsOpenMode(FontLibrary library, std::uint32_t openMode); +int APS5_VABI sceFontOpenFontMemory(FontLibrary library, const void* fontAddress, std::uint32_t fontSize, const FontOpenDetail* openDetail, FontHandle* pFontHandle); +int APS5_VABI sceFontOpenFontFile(FontLibrary library, const char* path, std::uint32_t openMode, const FontOpenDetail* openDetail, FontHandle* pFontHandle); +int APS5_VABI sceFontOpenFontInstance(FontHandle fontHandle, FontHandle setupFont, FontHandle* pFontHandle); +int APS5_VABI sceFontOpenFontSet(FontLibrary library, std::uint32_t fontSetType, std::uint32_t openMode, const FontOpenDetail* openDetail, FontHandle* pFontHandle); +int APS5_VABI sceFontCloseFont(FontHandle fontHandle); +int APS5_VABI sceFontGetLibrary(FontHandle fontHandle, FontLibrary* pLibrary); +int APS5_VABI sceFontGetFontGlyphsCount(FontHandle fontHandle, std::uint32_t* glyphsCount); +int APS5_VABI sceFontGetCharGlyphCode(FontHandle fontHandle, std::uint32_t code, std::uint32_t* glyphCode); +int APS5_VABI sceFontGetFontResolution(FontHandle fontHandle, std::uint32_t* pResolution, float* pScalePixel); +int APS5_VABI sceFontBindRenderer(FontHandle fontHandle, FontRenderer renderer); +int APS5_VABI sceFontRebindRenderer(FontHandle fontHandle); +int APS5_VABI sceFontUnbindRenderer(FontHandle fontHandle); +int APS5_VABI sceFontGetCharGlyphMetrics(FontHandle fontHandle, std::uint32_t code, FontGlyphMetrics* metrics); +int APS5_VABI sceFontGetRenderCharGlyphMetrics(FontHandle fontHandle, std::uint32_t code, FontGlyphMetrics* metrics); +int APS5_VABI sceFontGetHorizontalLayout(FontHandle fontHandle, FontHorizontalLayout* layout); +int APS5_VABI sceFontGetVerticalLayout(FontHandle fontHandle, FontVerticalLayout* layout); +int APS5_VABI sceFontGetKerning(FontHandle fontHandle, std::uint32_t preCode, std::uint32_t code, FontKerning* kerning); +int APS5_VABI sceFontGetRenderScaledKerning(FontHandle fontHandle, std::uint32_t preCode, std::uint32_t code, FontKerning* kerning); +int APS5_VABI sceFontRenderCharGlyphImage(FontHandle fontHandle, std::uint32_t code, FontRenderSurface* surface, float x, float y, FontGlyphMetrics* metrics, FontRenderOutput* result); +int APS5_VABI sceFontRenderCharGlyphImageHorizontal(FontHandle fontHandle, std::uint32_t code, FontRenderSurface* surface, float x, float y, FontGlyphMetrics* metrics, FontRenderOutput* result); +int APS5_VABI sceFontRenderCharGlyphImageVertical(FontHandle fontHandle, std::uint32_t code, FontRenderSurface* surface, float x, float y, FontGlyphMetrics* metrics, FontRenderOutput* result); +void APS5_VABI sceFontRenderSurfaceInit(FontRenderSurface* renderSurface, void* buffer, int bufWidthByte, int pixelSizeByte, int widthPixel, int heightPixel); +void APS5_VABI sceFontRenderSurfaceSetScissor(FontRenderSurface* renderSurface, int x0, int y0, int w, int h); +int APS5_VABI sceFontRenderSurfaceSetStyleFrame(FontRenderSurface* renderSurface, FontStyleFrame* styleFrame); +int APS5_VABI sceFontGenerateCharGlyph(FontHandle fontHandle, std::uint32_t code, const FontGenerateGlyphDetail* detail, FontGlyph* pGlyph); +int APS5_VABI sceFontDeleteGlyph(const FontMemory* memory, FontGlyph* pGlyph); +int APS5_VABI sceFontGlyphDefineAttribute(FontGlyph glyph, std::int32_t attribute, std::int32_t* previousAttribute); +int APS5_VABI sceFontGlyphGetAttribute(FontGlyph glyph, int attribute, int* nowAttribute); +int APS5_VABI sceFontGlyphGetGlyphForm(FontGlyph glyph); +int APS5_VABI sceFontGlyphGetMetricsForm(FontGlyph glyph); +int APS5_VABI sceFontGlyphGetScalePixel(FontGlyph glyph, float* w, float* h); +const FontGlyphMetrics* APS5_VABI sceFontGlyphRefersMetrics(FontGlyph glyph); +const FontGlyphMetricsHorizontal* APS5_VABI sceFontGlyphRefersMetricsHorizontal(FontGlyph glyph); +const FontGlyphMetricsHorizontalAdvance* APS5_VABI sceFontGlyphRefersMetricsHorizontalAdvance(FontGlyph glyph); +const FontGlyphMetricsHorizontalX* APS5_VABI sceFontGlyphRefersMetricsHorizontalX(FontGlyph glyph); +FontGlyphOutline* APS5_VABI sceFontGlyphRefersOutline(FontGlyph glyph); +int APS5_VABI sceFontDefineAttribute(FontHandle fontHandle, int attribute, int* oldAttribute); +int APS5_VABI sceFontGetAttribute(FontHandle fontHandle, int attribute, int* nowAttribute); +int APS5_VABI sceFontSetScriptLanguage(FontHandle fontHandle, int fontScript, int fontLanguage); +int APS5_VABI sceFontGetScriptLanguage(FontHandle fontHandle, int fontScript, int* fontLanguage); +int APS5_VABI sceFontSetTypographicDesign(FontHandle fontHandle, int typographic, int feature); +int APS5_VABI sceFontGetTypographicDesign(FontHandle fontHandle, int typographic, int* feature); +int APS5_VABI sceFontSetScalePixel(FontHandle fontHandle, float w, float h); +int APS5_VABI sceFontSetScalePoint(FontHandle fontHandle, float w, float h); +int APS5_VABI sceFontSetResolutionDpi(FontHandle fontHandle, std::uint32_t hDpi, std::uint32_t vDpi); +int APS5_VABI sceFontSetEffectSlant(FontHandle fontHandle, float slantRatio); +int APS5_VABI sceFontSetEffectWeight(FontHandle fontHandle, float weightXScale, float weightYScale, std::uint32_t mode); +int APS5_VABI sceFontGetScalePixel(FontHandle fontHandle, float* w, float* h); +int APS5_VABI sceFontGetScalePoint(FontHandle fontHandle, float* w, float* h); +int APS5_VABI sceFontGetResolutionDpi(FontHandle fontHandle, std::uint32_t* hDpi, std::uint32_t* vDpi); +int APS5_VABI sceFontGetEffectSlant(FontHandle fontHandle, float* slantRatio); +int APS5_VABI sceFontGetEffectWeight(FontHandle fontHandle, float* weightXScale, float* weightYScale, std::uint32_t* mode); +int APS5_VABI sceFontSetupRenderScalePixel(FontHandle fontHandle, float w, float h); +int APS5_VABI sceFontSetupRenderScalePoint(FontHandle fontHandle, float w, float h); +int APS5_VABI sceFontSetupRenderEffectSlant(FontHandle fontHandle, float slantRatio); +int APS5_VABI sceFontSetupRenderEffectWeight(FontHandle fontHandle, float weightXScale, float weightYScale, std::uint32_t mode); +int APS5_VABI sceFontGetRenderScalePixel(FontHandle fontHandle, float* w, float* h); +int APS5_VABI sceFontGetRenderScalePoint(FontHandle fontHandle, float* w, float* h); +int APS5_VABI sceFontGetRenderEffectSlant(FontHandle fontHandle, float* slantRatio); +int APS5_VABI sceFontGetRenderEffectWeight(FontHandle fontHandle, float* weightXScale, float* weightYScale, std::uint32_t* mode); +int APS5_VABI sceFontStyleFrameInit(FontStyleFrame* styleFrame); +int APS5_VABI sceFontStyleFrameSetScalePixel(FontStyleFrame* styleFrame, float w, float h); +int APS5_VABI sceFontStyleFrameSetScalePoint(FontStyleFrame* styleFrame, float w, float h); +int APS5_VABI sceFontStyleFrameSetResolutionDpi(FontStyleFrame* styleFrame, std::uint32_t hDpi, std::uint32_t vDpi); +int APS5_VABI sceFontStyleFrameSetEffectSlant(FontStyleFrame* styleFrame, float slantRatio); +int APS5_VABI sceFontStyleFrameSetEffectWeight(FontStyleFrame* styleFrame, float weightXScale, float weightYScale, std::uint32_t mode); +int APS5_VABI sceFontStyleFrameUnsetScale(FontStyleFrame* styleFrame); +int APS5_VABI sceFontStyleFrameUnsetEffectSlant(FontStyleFrame* styleFrame); +int APS5_VABI sceFontStyleFrameUnsetEffectWeight(FontStyleFrame* styleFrame); +int APS5_VABI sceFontStyleFrameGetScalePixel(const FontStyleFrame* styleFrame, float* w, float* h); +int APS5_VABI sceFontStyleFrameGetScalePoint(const FontStyleFrame* styleFrame, float* w, float* h); +int APS5_VABI sceFontStyleFrameGetResolutionDpi(const FontStyleFrame* styleFrame, std::uint32_t* hDpi, std::uint32_t* vDpi); +int APS5_VABI sceFontStyleFrameGetEffectSlant(const FontStyleFrame* styleFrame, float* slantRatio); +int APS5_VABI sceFontStyleFrameGetEffectWeight(const FontStyleFrame* styleFrame, float* weightXScale, float* weightYScale, std::uint32_t* mode); +int APS5_VABI sceFontTextSourceInit(FontTextSource* textSource, const void* textAddress, std::uint32_t textSizeByte, FontTextParseFunction textParser, void* textObject); +int APS5_VABI sceFontTextSourceRewind(FontTextSource* textSource); +int APS5_VABI sceFontTextSourceSetDefaultFont(FontTextSource* textSource, FontHandle defaultFont); +int APS5_VABI sceFontTextSourceSetWritingForm(FontTextSource* textSource, std::int32_t writingForm); +int APS5_VABI sceFontCreateString(const FontMemory* fontMemory, FontTextSource* textSource, const FontCreateStringDetail* detail, FontString* pFontString); +int APS5_VABI sceFontDestroyString(FontString* pFontString); +std::uint32_t APS5_VABI sceFontStringGetTerminateCode(FontString fontString); +void* APS5_VABI sceFontStringGetTerminateOrder(FontString fontString); +int APS5_VABI sceFontStringGetWritingForm(FontString fontString); +FontTextCharacter* APS5_VABI sceFontStringRefersTextCharacters(FontString fontString, std::uint32_t* characterCount); +const FontTextCharacter* APS5_VABI sceFontStringRefersRenderCharacters(FontString fontString, FontTextCharacter* startCharacter, FontTextCharacter* lastCharacter, std::uint32_t* characterCount); +int APS5_VABI sceFontCharacterGetBidiLevel(const FontTextCharacter* textCharacter, int* bidiLevel); +int APS5_VABI sceFontCharacterGetSyllableStringState(const FontTextCharacter* textCharacter, int* syllableStringState); +int APS5_VABI sceFontCharacterGetTextFontCode(const FontTextCharacter* textCharacter, FontHandle* pFontHandle, std::uint32_t* textCode); +int APS5_VABI sceFontCharacterGetTextOrder(const FontTextCharacter* textCharacter, void** pTextOrder); +std::uint32_t APS5_VABI sceFontCharacterLooksFormatCharacters(const FontTextCharacter* textCharacter); +std::uint32_t APS5_VABI sceFontCharacterLooksWhiteSpace(const FontTextCharacter* textCharacter); +FontTextCharacter* APS5_VABI sceFontCharacterRefersTextBack(const FontTextCharacter* textCharacter); +FontTextCharacter* APS5_VABI sceFontCharacterRefersTextNext(const FontTextCharacter* textCharacter); +FontTextCodes* APS5_VABI sceFontCharactersRefersTextCodes(const FontTextCharacter* textCharacter, const FontTextCharacter* termCharacter, FontTextCodes* textCodes); +FontTextCodes* APS5_VABI sceFontTextCodesStepNext(FontTextCodes* textCodesStep); +FontTextCodes* APS5_VABI sceFontTextCodesStepBack(FontTextCodes* textCodesStep); +int APS5_VABI sceFontWritingInit(FontWriting* fontWriting, FontString fontString, const FontTextCharacter* fontCharacter); +int APS5_VABI sceFontWritingGetRenderMetrics(FontWriting* fontWriting, FontWritingMetrics* writingMetrics); +const FontWritingStep* APS5_VABI sceFontWritingRefersRenderStep(FontWriting* fontWriting); +FontTextCharacter* APS5_VABI sceFontWritingRefersRenderStepCharacter(FontWriting* fontWriting, const FontWritingLetterStep** pLetterStep); +int APS5_VABI sceFontWritingSetMaskInvisible(FontWriting* fontWriting, std::int32_t mask); +int APS5_VABI sceFontControl(std::int32_t command, void* object, std::uintptr_t argument); +int APS5_VABI sceFontCreateGraphicsDevice(const FontMemory* memory, const FontGraphicsDeviceParam* param, FontGraphicsDevice** device); +int APS5_VABI sceFontCreateGraphicsService(const FontMemory* memory, const FontGraphicsServiceParam* param, FontGraphicsService** service); +int APS5_VABI sceFontCreateGraphicsServiceWithEdition(const FontMemory* memory, const FontGraphicsServiceParam* param, std::uint64_t unusedSlot, FontGraphicsService** service); +int APS5_VABI sceFontCreateWords(const FontMemory* memory, FontTextSource* source, std::uint64_t unusedSlot, FontWords** words); +int APS5_VABI sceFontDestroyGraphicsDevice(FontGraphicsDevice** device); +int APS5_VABI sceFontDestroyGraphicsService(FontGraphicsService** service); +int APS5_VABI sceFontDestroyWords(FontWords** words); +int APS5_VABI sceFontGetFontGlyphsOutlineProfile(FontHandle font, FontOutlineProfile* profile); +int APS5_VABI sceFontGetFontMetrics(FontHandle font, std::uint32_t mode, FontMetrics* metrics); +int APS5_VABI sceFontGetFontStyleInformation(FontHandle font, FontStyleInformation* information); +int APS5_VABI sceFontGetGlyphExpandBufferState(FontHandle font, FontGlyphExpandBufferState* state); +int APS5_VABI sceFontGlyphRenderImage(FontGlyph glyph, const FontStyleFrame* styleFrame, FontRenderer renderer, FontRenderSurface* surface, float x, float y, FontGlyphMetrics* metrics, FontRenderOutput* output); +int APS5_VABI sceFontGlyphRenderImageHorizontal(FontGlyph glyph, const FontStyleFrame* styleFrame, FontRenderer renderer, FontRenderSurface* surface, float x, float y, FontGlyphMetrics* metrics, FontRenderOutput* output); +int APS5_VABI sceFontGlyphRenderImageVertical(FontGlyph glyph, const FontStyleFrame* styleFrame, FontRenderer renderer, FontRenderSurface* surface, float x, float y, FontGlyphMetrics* metrics, FontRenderOutput* output); +int APS5_VABI sceFontGraphicsBeginFrame(FontGraphicsFrame* frame, std::uint64_t flags, FontGraphicsResource** resource); +int APS5_VABI sceFontGraphicsDrawingCancel(FontGraphicsFrame** frame); +int APS5_VABI sceFontGraphicsDrawingFinish(FontGraphicsFrame** frame, FontGraphicsDevice* device); +int APS5_VABI sceFontGraphicsEndFrame(FontGraphicsFrame* frame); +int APS5_VABI sceFontGraphicsExchangeResource(FontGraphicsResource* resource, FontGraphicsDesignResource* replacement, FontGraphicsDesignResource** previous); +int APS5_VABI sceFontGraphicsFillMethodInit(FontGraphicsFillMethod* method, std::int32_t mode, std::int32_t type); +int APS5_VABI sceFontGraphicsFillPlotInit(FontGraphicsFillPlot* plot, const FontGraphicsRegion* region); +int APS5_VABI sceFontGraphicsFillPlotSetLayout(FontGraphicsFillPlot* plot, std::int32_t first, std::int32_t second); +int APS5_VABI sceFontGraphicsFillPlotSetMapping(FontGraphicsFillPlot* plot, float first, float second, float third, float fourth); +int APS5_VABI sceFontGraphicsFillRatesInit(FontGraphicsFillRates* rates, const FontGraphicsFill* fill, std::uint32_t effect); +int APS5_VABI sceFontGraphicsFillRatesSetFillEffect(FontGraphicsFillRates* rates, const FontGraphicsFill* fill, std::uint32_t effect); +int APS5_VABI sceFontGraphicsFillRatesSetLayout(FontGraphicsFillRates* rates, std::int32_t first, std::int32_t second); +int APS5_VABI sceFontGraphicsFillRatesSetMapping(FontGraphicsFillRates* rates, float first, float second, float third, float fourth); +int APS5_VABI sceFontGraphicsGetDeviceUsage(FontGraphicsDevice* device, FontGraphicsDeviceUsage* usage); +int APS5_VABI sceFontGraphicsRegionInit(FontGraphicsRegion* region, float x, float y, float width, float height); +int APS5_VABI sceFontGraphicsRegionInitCircular(FontGraphicsRegion* region, float centerX, float centerY, float outerRadius, float innerRadius); +int APS5_VABI sceFontGraphicsRegionInitRoundish(FontGraphicsRegion* region, float x, float y, float width, float height, float outerRadius, float innerRadius, std::uint32_t flags); +int APS5_VABI sceFontGraphicsRelease(void** object); +int APS5_VABI sceFontGraphicsRenderResource(FontGraphicsFrame* frame, FontGraphicsDesignResource* design, float x, float y, FontGraphicsResource** resource); +int APS5_VABI sceFontGraphicsSetFramePolicy(FontGraphicsResource* resource, std::int32_t policy, std::uint32_t value); +int APS5_VABI sceFontGraphicsSetupClipping(FontGraphicsResource* resource, const FontGraphicsRegion* region); +int APS5_VABI sceFontGraphicsSetupColorRates(FontGraphicsResource* resource, float red, float green, float blue, float alpha); +int APS5_VABI sceFontGraphicsSetupFillMethod(FontGraphicsResource* resource, const FontGraphicsFillMethod* method); +int APS5_VABI sceFontGraphicsSetupFillRates(FontGraphicsResource* resource, const FontGraphicsFillRates* rates); +int APS5_VABI sceFontGraphicsSetupGlyphFill(FontGraphicsResource* resource, const FontGraphicsFill* fill); +int APS5_VABI sceFontGraphicsSetupGlyphFillPlot(FontGraphicsResource* resource, const FontGraphicsFillPlot* plot); +int APS5_VABI sceFontGraphicsSetupHandleDefault(FontGraphicsResource* resource, std::uint64_t flags); +int APS5_VABI sceFontGraphicsSetupLocation(FontGraphicsResource* resource, float x, float y); +int APS5_VABI sceFontGraphicsSetupPositioning(FontGraphicsResource* resource, std::uint32_t flags, float x, float y); +int APS5_VABI sceFontGraphicsSetupRotation(FontGraphicsResource* resource, float angle, float pivotX, float pivotY); +int APS5_VABI sceFontGraphicsSetupScaling(FontGraphicsResource* resource, float scaleX, float scaleY, float pivotX, float pivotY); +int APS5_VABI sceFontGraphicsSetupShapeFill(FontGraphicsResource* resource, const FontGraphicsFill* fill); +int APS5_VABI sceFontGraphicsSetupShapeFillPlot(FontGraphicsResource* resource, const FontGraphicsFillPlot* plot); +int APS5_VABI sceFontGraphicsStructureCanvas(FontGraphicsDevice* device, std::uint32_t width, std::uint32_t height, std::int32_t format, FontGraphicsCanvas** canvas); +int APS5_VABI sceFontGraphicsStructureCanvasSequence(FontGraphicsDevice* device, FontGraphicsCanvas* canvas, const FontGraphicsSurface* surface, std::uint64_t flags, FontGraphicsCanvasSequence** sequence); +int APS5_VABI sceFontGraphicsStructureDesign(FontGraphicsDevice* device, std::int32_t format, FontGraphicsDesign** design); +int APS5_VABI sceFontGraphicsStructureDesignResource(FontGraphicsDevice* device, FontGraphicsDesign* design, FontGraphicsDesignResource** resource); +int APS5_VABI sceFontGraphicsStructureSurfaceTexture(FontGraphicsDevice* device, const FontGraphicsSurface* surface, FontGraphicsSurfaceTexture** texture); +int APS5_VABI sceFontGraphicsUpdateClipping(FontGraphicsResource* resource, const FontGraphicsRegion* region); +int APS5_VABI sceFontGraphicsUpdateColorRates(FontGraphicsResource* resource, float red, float green, float blue, float alpha); +int APS5_VABI sceFontGraphicsUpdateFillMethod(FontGraphicsResource* resource, const FontGraphicsFillMethod* method); +int APS5_VABI sceFontGraphicsUpdateFillRates(FontGraphicsResource* resource, const FontGraphicsFillRates* rates); +int APS5_VABI sceFontGraphicsUpdateGlyphFill(FontGraphicsResource* resource, const FontGraphicsFill* fill); +int APS5_VABI sceFontGraphicsUpdateGlyphFillPlot(FontGraphicsResource* resource, const FontGraphicsFillPlot* plot); +int APS5_VABI sceFontGraphicsUpdateLocation(FontGraphicsResource* resource, float x, float y); +int APS5_VABI sceFontGraphicsUpdatePositioning(FontGraphicsResource* resource, std::uint32_t flags, float x, float y); +int APS5_VABI sceFontGraphicsUpdateRotation(FontGraphicsResource* resource, float angle, float pivotX, float pivotY); +int APS5_VABI sceFontGraphicsUpdateScaling(FontGraphicsResource* resource, float scaleX, float scaleY, float pivotX, float pivotY); +int APS5_VABI sceFontGraphicsUpdateShapeFill(FontGraphicsResource* resource, const FontGraphicsFill* fill); +int APS5_VABI sceFontGraphicsUpdateShapeFillPlot(FontGraphicsResource* resource, const FontGraphicsFillPlot* plot); +int APS5_VABI sceFontSupportGlyphs(const FontGlyphSupport* support); +int APS5_VABI sceFontWordsFindWordCharacters(FontWords* words, FontTextCharacter* firstCharacter, FontTextCharacter* endCharacter, FontTextCharacter** lastCharacter, FontTextCharacter** nextCharacter); +int APS5_VABI sceFontGraphicsDrawupFillTextureImageObject(FontGraphicsFrame* frame, const void* data, std::uint32_t dataSize, float x, float y, float width, float height, FontGraphicsFill** fill); +int APS5_VABI sceFontGraphicsDrawupFillTexturePatternObject(FontGraphicsFrame* frame, const void* data, std::uint32_t dataSize, std::uint32_t firstMode, std::uint32_t secondMode, std::int32_t firstCount, std::int32_t firstLayout, std::int32_t secondLayout, std::int32_t secondCount, FontGraphicsFill** fill); +int APS5_VABI sceFontCreateWritingLine(const FontMemory* memory, std::int32_t writingForm, const void* writingLineDetail, void** pWritingLine); +int APS5_VABI sceFontDestroyWritingLine(void** pWritingLine); +int APS5_VABI sceFontWritingLineClear(void* writingLine); +int APS5_VABI sceFontWritingLineWritesOrder(void* writingLine, std::uint64_t writingAttribute, const FontWritingMetrics* writingMetrics, void* writingOrderer); +const FontWritingLineStep* APS5_VABI sceFontWritingLineRefersRenderStep(void* writingLine); +int APS5_VABI sceFontWritingLineGetRenderMetrics(void* writingLine, FontWritingMetrics* writingMetrics); +int APS5_VABI sceFontWritingLineGetOrderingSpace(void* writingLine, float* advanceSpace, float* headSpace, float* inlineSpace, float* tailSpace); + +} diff --git a/core/libs/prx/libSceFont/include/FontDriver.hpp b/core/libs/prx/libSceFont/include/FontDriver.hpp index 35b8d3d533..70b562b215 100644 --- a/core/libs/prx/libSceFont/include/FontDriver.hpp +++ b/core/libs/prx/libSceFont/include/FontDriver.hpp @@ -208,6 +208,9 @@ using DriverGlyphsCountFunction = int (APS5_VABI*)(FontObj* fontObj, std::uint32 using DriverGlyphIndexFunction = int (APS5_VABI*)(FontObj* fontObj, std::uint32_t codepoint, std::uint32_t* outGlyphIndex); using DriverSetCharWithDpiFunction = int (APS5_VABI*)(FontObj* fontObj, std::uint32_t dpiX, std::uint32_t dpiY, float scaleX, float scaleY, float* outScaleX, float* outScaleY); using DriverSetCharDefaultDpiFunction = int (APS5_VABI*)(FontObj* fontObj, float scaleX, float scaleY, float* outScaleX, float* outScaleY); +using DriverFontMetricsFunction = int (APS5_VABI*)(FontObj* fontObj, std::uint32_t form, FontMetrics* outMetrics); +using DriverOutlineProfileFunction = int (APS5_VABI*)(FontObj* fontObj, FontOutlineProfile* outProfile); +using DriverStyleInformationFunction = int (APS5_VABI*)(FontObj* fontObj, FontStyleInformation* outInformation); using DriverComputeLayoutFunction = int (APS5_VABI*)(FontObj* fontObj, const StyleStateBlock* style, std::uint8_t* outWords); using DriverLoadGlyphCachedFunction = int (APS5_VABI*)(FontObj* fontObj, std::uint32_t glyphIndex, std::int32_t mode, std::uint64_t* outWords); using DriverGetGlyphMetricsFunction = int (APS5_VABI*)(FontObj* fontObj, std::uint32_t* optParam2, std::uint8_t mode, std::uint8_t* outParams, FontGlyphMetrics* outMetrics); @@ -225,16 +228,17 @@ struct SysDriver { std::uint8_t reserved_0x30[0x08]; DriverOpenFunction open; DriverCloseFunction close; - std::uint8_t reserved_0x48[0x08]; + DriverStyleInformationFunction style_information; DriverScaleFunction scale; std::uint8_t reserved_0x58[0x08]; DriverMetricFunction metric; DriverGlyphsCountFunction glyphs_count; - std::uint8_t reserved_0x70[0x08]; + DriverOutlineProfileFunction outline_profile; DriverGlyphIndexFunction glyph_index; DriverSetCharWithDpiFunction set_char_with_dpi; DriverSetCharDefaultDpiFunction set_char_default_dpi; - std::uint8_t reserved_0x90[0x10]; + std::uint8_t reserved_0x90[0x08]; + DriverFontMetricsFunction font_metrics; DriverComputeLayoutFunction compute_layout; DriverLoadGlyphCachedFunction load_glyph_cached; std::uint8_t reserved_0xb0[0x08]; @@ -341,8 +345,11 @@ static_assert(offsetof(FontLibNative, list_head) == 0xE0); static_assert(sizeof(SysDriver) == 0x120); static_assert(offsetof(SysDriver, pixel_resolution) == 0x10); static_assert(offsetof(SysDriver, open) == 0x38); +static_assert(offsetof(SysDriver, style_information) == 0x48); static_assert(offsetof(SysDriver, scale) == 0x50); +static_assert(offsetof(SysDriver, outline_profile) == 0x70); static_assert(offsetof(SysDriver, glyph_index) == 0x78); +static_assert(offsetof(SysDriver, font_metrics) == 0x98); static_assert(offsetof(SysDriver, compute_layout) == 0xA0); static_assert(offsetof(SysDriver, get_glyph_metrics) == 0xB8); static_assert(offsetof(SysDriver, apply_glyph_adjust) == 0xE0); diff --git a/core/libs/prx/libSceFont/include/FontInternal.hpp b/core/libs/prx/libSceFont/include/FontInternal.hpp index 54c173835e..da4a70b28a 100644 --- a/core/libs/prx/libSceFont/include/FontInternal.hpp +++ b/core/libs/prx/libSceFont/include/FontInternal.hpp @@ -133,6 +133,9 @@ int ComputeHorizontalLayout(FontHandle handle, const StyleStateBlock* style, std int ComputeVerticalLayout(FontHandle handle, const StyleStateBlock* style, std::uint8_t* outWords); int GetCharGlyphMetrics(FontHandle handle, std::uint32_t code, FontGlyphMetrics* metrics, bool useCachedStyle, float* usedScaleW = nullptr, float* usedScaleH = nullptr); int RenderCharGlyphImageCore(FontHandle handle, std::uint32_t code, FontRenderSurface* surface, float x, float y, FontGlyphMetrics* metrics, FontRenderOutput* result); +int ComputeFontMetrics(FontHandle handle, std::uint32_t form, FontMetrics* metrics); +int ComputeFontStyleInformation(FontHandle handle, FontStyleInformation* information); +int ComputeFontGlyphsOutlineProfile(FontHandle handle, FontOutlineProfile* profile); } diff --git a/core/libs/prx/libSceFont/include/FontTypes.hpp b/core/libs/prx/libSceFont/include/FontTypes.hpp index eb1a548bb4..6507485349 100644 --- a/core/libs/prx/libSceFont/include/FontTypes.hpp +++ b/core/libs/prx/libSceFont/include/FontTypes.hpp @@ -423,12 +423,55 @@ struct FontVerticalLayout { float decorationSpan; }; +struct FontMetrics { + std::uint32_t form; + float ascender; + float descender; + float lineGap; + float maxAdvance; + float verticalDescender; + float verticalAscender; + float xMin; + float yMin; + float xMax; + float yMax; + float emWidth; + float emHeight; + float effectWeightX; + float effectWeightY; + float slantRatio; +}; + +struct FontOutlineProfile { + std::uint32_t maxContours; + std::uint32_t maxPoints; + std::uint32_t maxCompositeContours; + std::uint32_t maxCompositePoints; +}; + +struct FontStyleInformation { + const char* familyName; + const char* styleName; + std::uint16_t styleFlags; + std::uint16_t weight; + std::uint16_t width; + std::uint16_t layoutFlags; +}; + static_assert(sizeof(FontHandleOpaque) == 0x100); static_assert(sizeof(FontMemory) == 0x40); static_assert(sizeof(FontMemoryInterface) == 0x30); static_assert(sizeof(FontOpenDetail) == 0x20); static_assert(sizeof(FontGlyphMetrics) == 0x20); static_assert(sizeof(FontKerning) == 0x10); +static_assert(sizeof(FontMetrics) == 0x40); +static_assert(offsetof(FontMetrics, maxAdvance) == 0x10); +static_assert(offsetof(FontMetrics, xMin) == 0x1C); +static_assert(offsetof(FontMetrics, emWidth) == 0x2C); +static_assert(offsetof(FontMetrics, effectWeightX) == 0x34); +static_assert(sizeof(FontStyleInformation) == 0x18); +static_assert(sizeof(FontOutlineProfile) == 0x10); +static_assert(offsetof(FontStyleInformation, styleFlags) == 0x10); static_assert(sizeof(FontGlyphImageMetrics) == 0x18); static_assert(sizeof(FontGenerateGlyphDetail) == 0x20); static_assert(sizeof(FontResultStage) == 0x18); diff --git a/core/libs/prx/libSceFont/libSceFont.hpp b/core/libs/prx/libSceFont/libSceFont.hpp new file mode 100644 index 0000000000..c39c48d023 --- /dev/null +++ b/core/libs/prx/libSceFont/libSceFont.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceFont/include/Api.hpp" diff --git a/core/libs/prx/libSceFont/src/Layout.cpp b/core/libs/prx/libSceFont/src/Layout.cpp index 8bce6e00c2..d297840675 100644 --- a/core/libs/prx/libSceFont/src/Layout.cpp +++ b/core/libs/prx/libSceFont/src/Layout.cpp @@ -530,3 +530,109 @@ bool Font::BuildTrueOutline(GeneratedGlyph& glyph) { glyph.outlineInitialized = true; return true; } + +int Font::ComputeFontMetrics(FontHandle handle, std::uint32_t form, FontMetrics* metrics) { + auto* font = GetNativeFont(handle); + auto* library = font ? static_cast(font->library) : nullptr; + if (!library || !FontContext(library, font)) return SCE_FONT_ERROR_INVALID_FONT_HANDLE; + const SysDriver* driver = library->sys_driver; + if (!driver || !driver->set_char_with_dpi || !driver->set_char_default_dpi || !driver->font_metrics) return SCE_FONT_ERROR_INVALID_FONT_HANDLE; + const std::uint32_t fontId = font->open_info.ctx_entry_index; + if (static_cast(fontId) < 0) { + metrics->form = form; + metrics->ascender = 0.0f; + metrics->descender = 0.0f; + metrics->lineGap = 0.0f; + metrics->maxAdvance = 0.0f; + metrics->verticalDescender = 0.0f; + metrics->verticalAscender = 0.0f; + return SCE_FONT_OK; + } + const std::uint32_t modeLow = font->flags & 0x0Fu; + FontObj* head = nullptr; + std::uint32_t lockWord = 0; + auto* entry = AcquireFontCtxEntry(FontContext(library, font), fontId, modeLow, &head, &lockWord); + if (!entry) return SCE_FONT_ERROR_INVALID_FONT_HANDLE; + FontObj* match = FindSubFont(head, font->open_info.sub_font_index); + int rc = SCE_FONT_ERROR_FATAL; + if ((lockWord & OPEN_BIT) != 0 && (lockWord & COUNT_MASK) != 0 && match) { + float scaleX = font->style.scale_w; + float scaleY = font->style.scale_h; + match->font_handle = handle; + match->shift_units_x = 0; + match->shift_units_y = 0; + rc = SetDriverCharSize(driver, match, &font->style, scaleX, scaleY); + if (rc == SCE_FONT_OK) rc = driver->font_metrics(match, form, metrics); + } + ReleaseFontCtxEntryLock(entry, modeLow, lockWord); + return rc == SCE_FONT_OK ? rc : SCE_FONT_ERROR_INVALID_FONT_HANDLE; +} + +int Font::ComputeFontStyleInformation(FontHandle handle, FontStyleInformation* information) { + auto* font = GetNativeFont(handle); + auto* library = static_cast(font->library); + if (!library) return SCE_FONT_ERROR_INVALID_FONT_HANDLE; + if (!information) return SCE_FONT_ERROR_INVALID_PARAMETER; + if (const auto* record = static_cast(font->open_info.fontset_record)) { + std::memcpy(&information->familyName, record + 8, sizeof(information->familyName)); + std::memcpy(&information->styleName, record + 16, sizeof(information->styleName)); + information->styleFlags = record[4]; + information->weight = static_cast(record[5] * 100); + information->width = record[6]; + information->layoutFlags = record[7]; + return SCE_FONT_OK; + } + const SysDriver* driver = library->sys_driver; + auto* context = FontContext(library, font); + if (!driver || !driver->style_information || !context) return SCE_FONT_ERROR_FATAL; + const std::uint32_t modeLow = font->flags & 0x0Fu; + FontObj* head = nullptr; + std::uint32_t lockWord = 0; + auto* entry = AcquireFontCtxEntry(context, font->open_info.ctx_entry_index, modeLow, &head, &lockWord); + if (!entry) return SCE_FONT_ERROR_FATAL; + FontObj* match = FindSubFont(head, font->open_info.sub_font_index); + int rc = SCE_FONT_ERROR_FATAL; + if ((lockWord & OPEN_BIT) != 0 && (lockWord & COUNT_MASK) != 0 && match) { + match->font_handle = handle; + rc = driver->style_information(match, information); + information->weight = static_cast(information->weight * 100); + } + ReleaseFontCtxEntryLock(entry, modeLow, lockWord); + return rc; +} + +int Font::ComputeFontGlyphsOutlineProfile(FontHandle handle, FontOutlineProfile* profile) { + auto* font = GetNativeFont(handle); + if (!font || font->magic != HANDLE_MAGIC) { + if (profile) *profile = {}; + return SCE_FONT_ERROR_INVALID_FONT_HANDLE; + } + if (!profile) return SCE_FONT_ERROR_INVALID_PARAMETER; + *profile = {}; + auto* library = static_cast(font->library); + auto* context = library ? FontContext(library, font) : nullptr; + if (!context) return SCE_FONT_ERROR_INVALID_FONT_HANDLE; + const std::uint32_t fontId = font->open_info.ctx_entry_index; + if (static_cast(fontId) < 0) return SCE_FONT_OK; + const SysDriver* driver = library->sys_driver; + if (!driver || !driver->outline_profile) return SCE_FONT_ERROR_FATAL; + const std::uint32_t modeLow = font->flags & 0x0Fu; + FontObj* head = nullptr; + std::uint32_t lockWord = 0; + auto* entry = AcquireFontCtxEntry(context, fontId, modeLow, &head, &lockWord); + if (!entry) return SCE_FONT_ERROR_FATAL; + FontObj* match = FindSubFont(head, font->open_info.sub_font_index); + int rc = SCE_FONT_ERROR_FATAL; + FontOutlineProfile faceProfile{}; + if ((lockWord & OPEN_BIT) != 0 && (lockWord & COUNT_MASK) != 0 && match) { + match->font_handle = handle; + rc = driver->outline_profile(match, &faceProfile); + } + ReleaseFontCtxEntryLock(entry, modeLow, lockWord); + if (rc != SCE_FONT_OK) return rc; + profile->maxContours = std::max(profile->maxContours, faceProfile.maxContours); + profile->maxPoints = std::max(profile->maxPoints, faceProfile.maxPoints); + profile->maxCompositeContours = std::max(profile->maxCompositeContours, faceProfile.maxCompositeContours); + profile->maxCompositePoints = std::max(profile->maxCompositePoints, faceProfile.maxCompositePoints); + return SCE_FONT_OK; +} diff --git a/core/libs/prx/libSceFont/src/Library.cpp b/core/libs/prx/libSceFont/src/Library.cpp index 4d8adbac7e..54d3f48d0c 100644 --- a/core/libs/prx/libSceFont/src/Library.cpp +++ b/core/libs/prx/libSceFont/src/Library.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceFont/include/Api.hpp" // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later diff --git a/core/libs/prx/libSceFont/src/Open.cpp b/core/libs/prx/libSceFont/src/Open.cpp index 0963b98ba0..62d33f609e 100644 --- a/core/libs/prx/libSceFont/src/Open.cpp +++ b/core/libs/prx/libSceFont/src/Open.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceFont/include/Api.hpp" // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later diff --git a/core/libs/prx/libSceFont/src/Render.cpp b/core/libs/prx/libSceFont/src/Render.cpp index 1f97674eb4..0647f2192e 100644 --- a/core/libs/prx/libSceFont/src/Render.cpp +++ b/core/libs/prx/libSceFont/src/Render.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceFont/include/Api.hpp" // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -158,6 +159,63 @@ int APS5_VABI sceFontGetHorizontalLayout(FontHandle fontHandle, FontHorizontalLa return SCE_FONT_OK; } +int APS5_VABI sceFontGetFontMetrics(FontHandle fontHandle, std::uint32_t form, FontMetrics* metrics) { + auto* font = GetNativeFont(fontHandle); + std::uint32_t fontLock = 0; + if (font && font->magic == HANDLE_MAGIC && AcquireFontLock(font, fontLock)) { + if (!metrics) { + ReleaseFontLock(font, fontLock); + return SCE_FONT_ERROR_INVALID_FONT_HANDLE; + } + const int rc = ComputeFontMetrics(fontHandle, form, metrics); + ReleaseFontLock(font, fontLock); + if (rc == SCE_FONT_OK) return rc; + } + if (metrics) { + *metrics = {}; + metrics->effectWeightX = 1.0f; + metrics->effectWeightY = 1.0f; + } + return SCE_FONT_ERROR_INVALID_FONT_HANDLE; +} + +int APS5_VABI sceFontGetFontStyleInformation(FontHandle fontHandle, FontStyleInformation* information) { + auto* font = GetNativeFont(fontHandle); + std::uint32_t fontLock = 0; + int rc = SCE_FONT_ERROR_INVALID_FONT_HANDLE; + if (font && font->magic == HANDLE_MAGIC && AcquireFontLock(font, fontLock)) { + rc = ComputeFontStyleInformation(fontHandle, information); + ReleaseFontLock(font, fontLock); + if (rc == SCE_FONT_OK) return rc; + } + if (information) { + information->familyName = ""; + information->styleName = ""; + information->styleFlags = 0; + information->weight = 0; + information->width = 0; + information->layoutFlags = 0; + } + return rc; +} + +int APS5_VABI sceFontGetFontGlyphsOutlineProfile(FontHandle fontHandle, FontOutlineProfile* profile) { + auto* font = GetNativeFont(fontHandle); + std::uint32_t fontLock = 0; + int rc = SCE_FONT_ERROR_INVALID_FONT_HANDLE; + if (font && font->magic == HANDLE_MAGIC) { + if (!profile) return SCE_FONT_ERROR_INVALID_PARAMETER; + if (font->open_info.fontset_record) NotImplemented_nid_no_patch(__func__); + if (AcquireFontLock(font, fontLock)) { + rc = ComputeFontGlyphsOutlineProfile(fontHandle, profile); + ReleaseFontLock(font, fontLock); + if (rc == SCE_FONT_OK) return rc; + } + } + if (profile) *profile = {}; + return rc; +} + int APS5_VABI sceFontGetVerticalLayout(FontHandle fontHandle, FontVerticalLayout* layout) { int rc = SCE_FONT_ERROR_INVALID_FONT_HANDLE; auto* font = GetNativeFont(fontHandle); diff --git a/core/libs/prx/libSceFont/src/Style.cpp b/core/libs/prx/libSceFont/src/Style.cpp index 13df9555e0..fcb40847fe 100644 --- a/core/libs/prx/libSceFont/src/Style.cpp +++ b/core/libs/prx/libSceFont/src/Style.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceFont/include/Api.hpp" // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later diff --git a/core/libs/prx/libSceFont/src/Text.cpp b/core/libs/prx/libSceFont/src/Text.cpp index afc8a452f7..a729f8c503 100644 --- a/core/libs/prx/libSceFont/src/Text.cpp +++ b/core/libs/prx/libSceFont/src/Text.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceFont/include/Api.hpp" // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -20,6 +21,7 @@ constexpr std::uint16_t FONT_STRING_MAGIC = 0x0F05; constexpr std::uint16_t FONT_WRITING_MAGIC = 0x0F06; constexpr std::uint16_t CREATE_STRING_DETAIL_ID = 0x0FD4; constexpr std::uint32_t WRITING_FORM_HORIZONTAL = 0x10; +constexpr std::uint32_t WRITING_FORM_HORIZONTAL_RTL = 0x11; constexpr std::uint32_t WRITING_FORM_HORIZONTAL_LTR = 0x12; constexpr std::int32_t PARSER_RESULT_ERROR = -1; constexpr std::int32_t PARSER_RESULT_TERMINATE = 0; @@ -143,6 +145,37 @@ FontTextCharacter* TextCharacters(FontStringData* data) { return data && data->storage && !data->storage->characters.empty() ? data->storage->characters.data() : nullptr; } +bool IsRightToLeftLetter(std::uint32_t code) { + if ((code >= 0x0660u && code <= 0x0669u) || (code >= 0x06F0u && code <= 0x06F9u)) return false; + return (code >= 0x0590u && code <= 0x08FFu) || (code >= 0xFB1Du && code <= 0xFDFFu) || (code >= 0xFE70u && code <= 0xFEFFu) || + (code >= 0x10800u && code <= 0x10FFFu) || (code >= 0x1E800u && code <= 0x1EFFFu); +} + +bool IsDirectionNeutral(std::uint32_t code) { + return code < 0x41u || (code >= 0x5Bu && code <= 0x60u) || (code >= 0x7Bu && code <= 0xBFu) || code == 0xD7u || code == 0xF7u || + (code >= 0x2000u && code <= 0x2BFFu) || (code >= 0x3000u && code <= 0x3004u) || (code >= 0xFF00u && code <= 0xFF20u); +} + +std::uint32_t DefaultStringForm(const std::vector& characters) { + std::uint32_t isolateDepth = 0; + for (const FontTextCharacter& character : characters) { + const std::uint32_t code = character.characterCode; + if (code >= 0x2066u && code <= 0x2068u) { + ++isolateDepth; + continue; + } + if (code == 0x2069u) { + if (isolateDepth != 0) --isolateDepth; + continue; + } + if (isolateDepth != 0) continue; + if (code == 0x200Eu) return WRITING_FORM_HORIZONTAL_LTR; + if (code == 0x200Fu || IsRightToLeftLetter(code)) return WRITING_FORM_HORIZONTAL_RTL; + if (!IsDirectionNeutral(code)) return WRITING_FORM_HORIZONTAL_LTR; + } + return WRITING_FORM_HORIZONTAL_LTR; +} + std::uint32_t LevelOf(const FontTextCharacter* character) { return static_cast((character->flags >> 24) & 0xFFu); } @@ -326,6 +359,7 @@ int APS5_VABI sceFontCreateString(const FontMemory* fontMemory, FontTextSource* fontMemory->iface->dealloc(fontMemory->mspace_handle, raw); return state; } + if (data->writingForm == WRITING_FORM_HORIZONTAL) data->writingForm = DefaultStringForm(data->storage->characters); LinkCharacters(data->storage->characters); data->textCount = static_cast(data->storage->characters.size()); data->renderCount = data->textCount; diff --git a/core/libs/prx/libSceFont/src/Unimplemented.cpp b/core/libs/prx/libSceFont/src/Unimplemented.cpp index c98c47a93e..44417ee184 100644 --- a/core/libs/prx/libSceFont/src/Unimplemented.cpp +++ b/core/libs/prx/libSceFont/src/Unimplemented.cpp @@ -1,40 +1,10 @@ +#include "prx/libSceFont/include/Api.hpp" // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #include "prx/libc/include/General.hpp" #include "prx/libSceFont/include/FontTypes.hpp" -struct FontGraphicsDevice; -struct FontGraphicsDeviceParam; -struct FontGraphicsService; -struct FontGraphicsServiceParam; -struct FontWords; -struct FontGlyphSupport; -struct FontOutlineProfile; -struct FontMetrics; -struct FontStyleInformation; -struct FontGlyphExpandBufferState; -struct FontGraphicsResource; -struct FontGraphicsFrame; -struct FontGraphicsDesignResource; -struct FontGraphicsDesign; -struct FontGraphicsCanvas; -struct FontGraphicsCanvasSequence; -struct FontGraphicsSurface; -struct FontGraphicsSurfaceTexture; -struct FontGraphicsFill; - -struct FontGraphicsRegion { - float x; - float y; - float width; - float height; - std::uint32_t flags; - std::uint32_t tag; - float outerRadius; - float innerRadius; -}; - static_assert(sizeof(FontGraphicsRegion) == 32); static_assert(offsetof(FontGraphicsRegion, x) == 0); static_assert(offsetof(FontGraphicsRegion, y) == 4); @@ -45,14 +15,6 @@ static_assert(offsetof(FontGraphicsRegion, tag) == 20); static_assert(offsetof(FontGraphicsRegion, outerRadius) == 24); static_assert(offsetof(FontGraphicsRegion, innerRadius) == 28); -struct FontGraphicsFillMethod { - std::int32_t mode; - std::int32_t type; - std::uint32_t flags; - std::uint32_t tag; - std::byte reserved[16]; -}; - static_assert(sizeof(FontGraphicsFillMethod) == 32); static_assert(offsetof(FontGraphicsFillMethod, mode) == 0); static_assert(offsetof(FontGraphicsFillMethod, type) == 4); @@ -60,16 +22,6 @@ static_assert(offsetof(FontGraphicsFillMethod, flags) == 8); static_assert(offsetof(FontGraphicsFillMethod, tag) == 12); static_assert(offsetof(FontGraphicsFillMethod, reserved) == 16); -struct FontGraphicsFillPlot { - float mapping[4]; - const FontGraphicsRegion* region; - std::uint16_t tag; - std::uint16_t reserved26; - std::uint16_t layout; - std::uint8_t flags; - std::byte reserved[33]; -}; - static_assert(sizeof(FontGraphicsFillPlot) == 64); static_assert(offsetof(FontGraphicsFillPlot, mapping) == 0); static_assert(offsetof(FontGraphicsFillPlot, region) == 16); @@ -79,16 +31,6 @@ static_assert(offsetof(FontGraphicsFillPlot, layout) == 28); static_assert(offsetof(FontGraphicsFillPlot, flags) == 30); static_assert(offsetof(FontGraphicsFillPlot, reserved) == 31); -struct FontGraphicsFillRates { - float mapping[4]; - const FontGraphicsFill* fill; - std::uint16_t tag; - std::uint16_t effect; - std::uint16_t layout; - std::uint8_t flags; - std::byte reserved[33]; -}; - static_assert(sizeof(FontGraphicsFillRates) == 64); static_assert(offsetof(FontGraphicsFillRates, mapping) == 0); static_assert(offsetof(FontGraphicsFillRates, fill) == 16); @@ -98,14 +40,6 @@ static_assert(offsetof(FontGraphicsFillRates, layout) == 28); static_assert(offsetof(FontGraphicsFillRates, flags) == 30); static_assert(offsetof(FontGraphicsFillRates, reserved) == 31); -struct FontGraphicsPoolUsage { - std::uint32_t capacity; - std::uint32_t used; - std::uint32_t available; - std::uint32_t peak; - std::int32_t change; -}; - static_assert(sizeof(FontGraphicsPoolUsage) == 20); static_assert(offsetof(FontGraphicsPoolUsage, capacity) == 0); static_assert(offsetof(FontGraphicsPoolUsage, used) == 4); @@ -113,27 +47,15 @@ static_assert(offsetof(FontGraphicsPoolUsage, available) == 8); static_assert(offsetof(FontGraphicsPoolUsage, peak) == 12); static_assert(offsetof(FontGraphicsPoolUsage, change) == 16); -struct FontGraphicsMemoryUsage { - FontGraphicsPoolUsage storage; - FontGraphicsPoolUsage allocations; - void* address; -}; - static_assert(sizeof(FontGraphicsMemoryUsage) == 48); static_assert(offsetof(FontGraphicsMemoryUsage, storage) == 0); static_assert(offsetof(FontGraphicsMemoryUsage, allocations) == 20); static_assert(offsetof(FontGraphicsMemoryUsage, address) == 40); -struct FontGraphicsDeviceUsage { - FontGraphicsMemoryUsage first; - FontGraphicsMemoryUsage second; -}; - static_assert(sizeof(FontGraphicsDeviceUsage) == 96); static_assert(offsetof(FontGraphicsDeviceUsage, first) == 0); static_assert(offsetof(FontGraphicsDeviceUsage, second) == 48); - #pragma GCC visibility push(default) extern "C" { @@ -179,21 +101,6 @@ int APS5_VABI sceFontDestroyWords(FontWords** words) { } -int APS5_VABI sceFontGetFontGlyphsOutlineProfile(FontHandle font, FontOutlineProfile* profile) { - NotImplemented_nid_no_patch(__func__); - return 0; -} - -int APS5_VABI sceFontGetFontMetrics(FontHandle font, std::uint32_t mode, FontMetrics* metrics) { - NotImplemented_nid_no_patch(__func__); - return 0; -} - -int APS5_VABI sceFontGetFontStyleInformation(FontHandle font, FontStyleInformation* information) { - NotImplemented_nid_no_patch(__func__); - return 0; -} - int APS5_VABI sceFontGetGlyphExpandBufferState(FontHandle font, FontGlyphExpandBufferState* state) { NotImplemented_nid_no_patch(__func__); return 0; diff --git a/core/libs/prx/libSceFont/src/WritingLine.cpp b/core/libs/prx/libSceFont/src/WritingLine.cpp index 7365c1f418..95771489a0 100644 --- a/core/libs/prx/libSceFont/src/WritingLine.cpp +++ b/core/libs/prx/libSceFont/src/WritingLine.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceFont/include/Api.hpp" #include #include #include diff --git a/core/libs/prx/libSceFontFt-module/libSceFontFt-module.hpp b/core/libs/prx/libSceFontFt-module/libSceFontFt-module.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceFontFt-module/libSceFontFt-module.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceFontFt/Export.cpp b/core/libs/prx/libSceFontFt/Export.cpp index 628a572b94..c376b1c590 100644 --- a/core/libs/prx/libSceFontFt/Export.cpp +++ b/core/libs/prx/libSceFontFt/Export.cpp @@ -1,15 +1,12 @@ +#include "prx/libSceFontFt/include/Api.hpp" // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later - #include "prx/libSceFontFt/include/FontFtDriver.hpp" #include "prx/libc/include/General.hpp" #pragma GCC visibility push(default) -struct FontFtAliases; -struct FontFtGlyphSelection; - extern "C" { const Font::SysDriver* APS5_VABI sceFontSelectLibraryFt(int value) { diff --git a/core/libs/prx/libSceFontFt/include/Api.hpp b/core/libs/prx/libSceFontFt/include/Api.hpp new file mode 100644 index 0000000000..b31e84ae16 --- /dev/null +++ b/core/libs/prx/libSceFontFt/include/Api.hpp @@ -0,0 +1,35 @@ +#pragma once + +#include "prx/libSceFont/include/FontTypes.hpp" +#include "prx/libSceFont/include/FontDriver.hpp" +#include "SceTypes.hpp" + +struct FontFtAliases; + +struct FontFtGlyphSelection; + +extern "C" { + +const Font::SysDriver* APS5_VABI sceFontSelectLibraryFt(int value); +const Font::RendererSelection* APS5_VABI sceFontSelectRendererFt(int value); +int APS5_VABI sceFontFtInitAliases(FontFtAliases** aliases); +int APS5_VABI sceFontFtSetAliasFont(const char* alias, std::uint32_t fontId); +int APS5_VABI sceFontFtSetAliasPath(const char* alias, const char* path); +int APS5_VABI sceFontFtSupportBdf(FontLibrary library); +int APS5_VABI sceFontFtSupportCid(FontLibrary library); +int APS5_VABI sceFontFtSupportFontFormats(FontLibrary library, std::uint32_t formats); +int APS5_VABI sceFontFtSupportOpenType(FontLibrary library); +int APS5_VABI sceFontFtSupportOpenTypeOtf(FontLibrary library); +int APS5_VABI sceFontFtSupportOpenTypeTtf(FontLibrary library); +int APS5_VABI sceFontFtSupportPcf(FontLibrary library); +int APS5_VABI sceFontFtSupportPfr(FontLibrary library); +int APS5_VABI sceFontFtSupportSystemFonts(FontLibrary library); +int APS5_VABI sceFontFtSupportTrueType(FontLibrary library); +int APS5_VABI sceFontFtSupportTrueTypeGx(FontLibrary library); +int APS5_VABI sceFontFtSupportType1(FontLibrary library); +int APS5_VABI sceFontFtSupportType42(FontLibrary library); +int APS5_VABI sceFontFtSupportWinFonts(FontLibrary library); +int APS5_VABI sceFontFtTermAliases(FontFtAliases** aliases); +const FontFtGlyphSelection* APS5_VABI sceFontSelectGlyphsFt(std::int32_t selector); + +} diff --git a/core/libs/prx/libSceFontFt/libSceFontFt.hpp b/core/libs/prx/libSceFontFt/libSceFontFt.hpp new file mode 100644 index 0000000000..a14b5f23e0 --- /dev/null +++ b/core/libs/prx/libSceFontFt/libSceFontFt.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceFontFt/include/Api.hpp" diff --git a/core/libs/prx/libSceFontFt/src/Driver.cpp b/core/libs/prx/libSceFontFt/src/Driver.cpp index a4561830ea..7ac80488ea 100644 --- a/core/libs/prx/libSceFontFt/src/Driver.cpp +++ b/core/libs/prx/libSceFontFt/src/Driver.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceFontFt/include/Api.hpp" // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -777,6 +778,143 @@ std::uint64_t APS5_VABI RendererQuery(RendererNative* renderer, std::uint8_t* pa return 0; } +float ScaledUnits(std::int64_t units, std::int64_t fixed16) { + return FromF26Dot6(RoundMulFixed(units, fixed16)); +} + +void StoreVerticalFontMetrics(FT_Face face, const TT_OS2* os2, std::int64_t xShift, std::int64_t yShift, FontMetrics* metrics) { + const auto xScale = static_cast(face->size->metrics.x_scale); + const auto yScale = static_cast(face->size->metrics.y_scale); + const auto unitsPerEm = static_cast(static_cast(face->units_per_EM)); + const auto* vhea = static_cast(FT_Get_Sfnt_Table(face, FT_SFNT_VHEA)); + if (vhea) { + const std::int64_t minTop = vhea->min_Top_Side_Bearing; + metrics->ascender = ScaledUnits(minTop + yShift, yScale); + metrics->descender = ScaledUnits(static_cast(vhea->yMax_Extent) + yShift, yScale); + metrics->lineGap = 0.0f; + if (vhea->Version >= 0x110000 && vhea->Line_Gap != 0) { + metrics->lineGap = FromF26Dot6(RoundMulFixed(vhea->Line_Gap, xScale) - TruncFixed(unitsPerEm * xScale)); + } + metrics->verticalDescender = ScaledUnits(static_cast(vhea->Descender) + xShift, xScale); + const std::int64_t ascender = os2 ? os2->sTypoAscender : static_cast(minTop + face->bbox.yMax); + metrics->verticalAscender = ScaledUnits(ascender + yShift, yScale); + } else { + std::int64_t ascender = 0; + if (os2) { + ascender = os2->sTypoAscender; + metrics->ascender = ScaledUnits(ascender - face->bbox.yMax, yScale); + metrics->descender = ScaledUnits(ascender - face->bbox.yMin, yScale); + metrics->lineGap = 0.0f; + } else { + const std::int32_t lineGap = face->height - face->ascender + face->descender; + const std::int32_t halfGap = lineGap / 2; + metrics->ascender = ScaledUnits(halfGap, yScale); + metrics->descender = ScaledUnits(face->ascender - face->descender + halfGap, yScale); + metrics->lineGap = ScaledUnits(lineGap, xScale); + ascender = face->ascender + halfGap; + } + metrics->verticalAscender = ScaledUnits(ascender + yShift, yScale); + metrics->verticalDescender = ScaledUnits(-static_cast(unitsPerEm / 2), xScale); + } + metrics->maxAdvance = ScaledUnits(face->max_advance_height, yScale); +} + +std::uint32_t StoreHorizontalFontMetrics(FT_Face face, const TT_OS2* os2, std::uint32_t form, std::int64_t xShift, std::int64_t yShift, FontMetrics* metrics) { + const auto xScale = static_cast(face->size->metrics.x_scale); + const auto yScale = static_cast(face->size->metrics.y_scale); + const auto* hhea = static_cast(FT_Get_Sfnt_Table(face, FT_SFNT_HHEA)); + metrics->verticalDescender = 0.0f; + metrics->verticalAscender = 0.0f; + bool fromHorizontalHeader = form == 1 || ((form == 2 || form == 3) && !os2); + if (form == 2 && os2) { + metrics->ascender = ScaledUnits(static_cast(os2->sTypoAscender) + yShift, yScale); + metrics->descender = ScaledUnits(static_cast(os2->sTypoDescender) + yShift, yScale); + metrics->lineGap = ScaledUnits(os2->sTypoLineGap, yScale); + fromHorizontalHeader = metrics->ascender == 0.0f && metrics->descender == 0.0f; + } else if (form == 3 && os2) { + metrics->ascender = ScaledUnits(static_cast(os2->usWinAscent) + yShift, yScale); + metrics->descender = FromF26Dot6(-RoundMulFixed(static_cast(os2->usWinDescent) - yShift, yScale)); + metrics->lineGap = hhea ? ScaledUnits(hhea->Line_Gap, yScale) : 0.0f; + fromHorizontalHeader = metrics->ascender == metrics->descender; + } + if (fromHorizontalHeader) { + form = 1; + if (hhea) { + metrics->ascender = ScaledUnits(static_cast(hhea->Ascender) + yShift, yScale); + metrics->descender = ScaledUnits(static_cast(hhea->Descender) + yShift, yScale); + metrics->lineGap = ScaledUnits(hhea->Line_Gap, yScale); + } else { + metrics->ascender = ScaledUnits(static_cast(face->ascender) + yShift, yScale); + metrics->descender = ScaledUnits(static_cast(face->descender) + yShift, yScale); + metrics->lineGap = 0.0f; + } + } + metrics->maxAdvance = ScaledUnits(static_cast(face->max_advance_width) + xShift, xScale); + return form; +} + +int APS5_VABI LibraryGetFontMetrics(FontObj* obj, std::uint32_t form, FontMetrics* metrics) { + const FT_Face face = obj ? FaceOf(obj) : nullptr; + if (!face || !face->size || !metrics) return SCE_FONT_ERROR_FATAL; + const auto xScale = static_cast(face->size->metrics.x_scale); + const auto yScale = static_cast(face->size->metrics.y_scale); + const std::int64_t xShift = obj->shift_cache_x; + const std::int64_t yShift = obj->shift_cache_y; + const auto* os2 = static_cast(FT_Get_Sfnt_Table(face, FT_SFNT_OS2)); + if (os2 && os2->version == 0xFFFF) os2 = nullptr; + if (form == 4) { + StoreVerticalFontMetrics(face, os2, xShift, yShift, metrics); + } else { + form = StoreHorizontalFontMetrics(face, os2, form, xShift, yShift, metrics); + } + metrics->xMin = ScaledUnits(static_cast(face->bbox.xMin) + xShift, xScale); + metrics->yMin = ScaledUnits(static_cast(face->bbox.yMin) + yShift, yScale); + metrics->xMax = ScaledUnits(static_cast(face->bbox.xMax) + xShift, xScale); + metrics->yMax = ScaledUnits(static_cast(face->bbox.yMax) + yShift, yScale); + const auto unitsPerEm = static_cast(static_cast(face->units_per_EM)); + metrics->emWidth = FromF26Dot6(TruncFixed(unitsPerEm * xScale)); + metrics->emHeight = FromF26Dot6(TruncFixed(unitsPerEm * yScale)); + const auto* handle = reinterpret_cast(obj->font_handle); + metrics->effectWeightX = handle ? handle->style.effect_weight_x : 0.0f; + metrics->effectWeightY = handle ? handle->style.effect_weight_y : 0.0f; + metrics->slantRatio = handle ? handle->style.slant_ratio : 0.0f; + metrics->form = form; + return SCE_FONT_OK; +} + +int APS5_VABI LibraryGetOutlineProfile(FontObj* obj, FontOutlineProfile* profile) { + const FT_Face face = obj ? FaceOf(obj) : nullptr; + if (!face) return SCE_FONT_ERROR_INVALID_FONT_HANDLE; + const auto* maxp = static_cast(FT_Get_Sfnt_Table(face, FT_SFNT_MAXP)); + if (!maxp) throw std::runtime_error("FontFt: outline profile of a face without a maxp table"); + if (maxp->version < 0x10000) return SCE_FONT_ERROR_NO_SUPPORT_FUNCTION; + profile->maxContours = maxp->maxContours; + profile->maxPoints = maxp->maxPoints; + profile->maxCompositeContours = maxp->maxCompositeContours; + profile->maxCompositePoints = maxp->maxCompositePoints; + return SCE_FONT_OK; +} + +std::uint16_t WeightClass(std::uint16_t weight) { + return weight >= 100 && weight <= 900 && weight % 100 == 0 ? static_cast(weight / 100) : 0; +} + +int APS5_VABI LibraryGetFontStyleInformation(FontObj* obj, FontStyleInformation* information) { + const FT_Face face = obj ? FaceOf(obj) : nullptr; + if (!face || !information) return SCE_FONT_ERROR_FATAL; + const auto* header = static_cast(FT_Get_Sfnt_Table(face, FT_SFNT_HEAD)); + if (!header) throw std::runtime_error("FontFt: style information of a face without a head table"); + const auto* os2 = static_cast(FT_Get_Sfnt_Table(face, FT_SFNT_OS2)); + if (os2 && os2->version == 0xFFFF) os2 = nullptr; + information->familyName = face->family_name; + information->styleName = face->style_name; + information->styleFlags = static_cast(face->style_flags & (FT_STYLE_FLAG_ITALIC | FT_STYLE_FLAG_BOLD)); + information->weight = os2 ? WeightClass(os2->usWeightClass) : 0; + information->width = os2 && os2->usWidthClass < 10 ? os2->usWidthClass : 0; + information->layoutFlags = static_cast(1 + (header->Font_Direction < 0 ? 1 : 0) + (FT_HAS_VERTICAL(face) ? 0x80 : 0)); + return SCE_FONT_OK; +} + SysDriver MakeDriverTable() { SysDriver driver{}; driver.pixel_resolution = &LibraryGetPixelResolution; @@ -791,6 +929,9 @@ SysDriver MakeDriverTable() { driver.glyph_index = &LibraryGetGlyphIndex; driver.set_char_with_dpi = &LibrarySetCharSizeWithDpi; driver.set_char_default_dpi = &LibrarySetCharSizeDefaultDpi; + driver.font_metrics = &LibraryGetFontMetrics; + driver.style_information = &LibraryGetFontStyleInformation; + driver.outline_profile = &LibraryGetOutlineProfile; driver.compute_layout = &LibraryComputeLayout; driver.compute_layout_alt = &LibraryComputeLayoutAlt; driver.load_glyph_cached = &LibraryLoadGlyphCached; diff --git a/core/libs/prx/libSceFontGs/libSceFontGs.hpp b/core/libs/prx/libSceFontGs/libSceFontGs.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceFontGs/libSceFontGs.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceFreeType/CMakeLists.txt b/core/libs/prx/libSceFreeType/CMakeLists.txt index 4fec867345..fb0affb25c 100644 --- a/core/libs/prx/libSceFreeType/CMakeLists.txt +++ b/core/libs/prx/libSceFreeType/CMakeLists.txt @@ -7,6 +7,7 @@ add_library(libSceFreeType SHARED EXCLUDE_FROM_ALL src/GuestObjects.cpp src/Names.cpp src/Trigonometry.cpp + src/OutlineDecompose.cpp ) target_include_directories(libSceFreeType PRIVATE ${LIBS_INCLUDE_DIR}) target_link_libraries(libSceFreeType PRIVATE freetype) diff --git a/core/libs/prx/libSceFreeType/Export.cpp b/core/libs/prx/libSceFreeType/Export.cpp index 29fd059381..3d5bedd2f4 100644 --- a/core/libs/prx/libSceFreeType/Export.cpp +++ b/core/libs/prx/libSceFreeType/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceFreeType/include/Api.hpp" #include "prx/libSceFreeType/include/GuestObjects.hpp" #include FT_OUTLINE_H #include "prx/libc/include/FilesystemError.hpp" @@ -113,6 +114,13 @@ int APS5_VABI FT_Done_FreeType_nid_postfix(GuestLibrary* library) { return error; } +int APS5_VABI FT_Select_Size_nid_postfix(GuestFaceRec* face, std::int32_t strikeIndex) { + GuestFace* owner = FaceOf(face); + const FT_Error error = FT_Select_Size(owner ? owner->host : nullptr, strikeIndex); + if (owner) SyncSize(*owner); + return error; +} + int APS5_VABI FT_New_Face_nid_postfix(GuestLibrary* library, const char* filepathname, std::int64_t face_index, GuestFaceRec** aface) { if (!filepathname) return FT_Err_Invalid_Argument; const std::int64_t faceIndex = OpenFaceIndex(face_index); @@ -276,6 +284,19 @@ int APS5_VABI FT_Render_Glyph_nid_postfix(GuestGlyphSlotRec* slot, std::int32_t return error; } +int APS5_VABI FT_Outline_Copy_nid_postfix(const GuestOutline* source, GuestOutline* target) { + if (!source || !target) return FT_Err_Invalid_Outline; + if (source->n_points != target->n_points || source->n_contours != target->n_contours) return FT_Err_Invalid_Argument; + if (source == target) return FT_Err_Ok; + if (source->n_points) { + std::memmove(target->points, source->points, source->n_points * sizeof(GuestVector)); + std::memmove(target->tags, source->tags, source->n_points * sizeof(unsigned char)); + } + if (source->n_contours) std::memmove(target->contours, source->contours, source->n_contours * sizeof(std::uint16_t)); + target->flags = (source->flags & ~FT_OUTLINE_OWNER) | (target->flags & FT_OUTLINE_OWNER); + return FT_Err_Ok; +} + int APS5_VABI FT_Select_Charmap_nid_postfix(GuestFaceRec* face, std::int32_t encoding) { GuestFace* owner = FaceOf(face); const FT_Error error = FT_Select_Charmap(owner ? owner->host : nullptr, static_cast(encoding)); diff --git a/core/libs/prx/libSceFreeType/include/Api.hpp b/core/libs/prx/libSceFreeType/include/Api.hpp new file mode 100644 index 0000000000..090056032a --- /dev/null +++ b/core/libs/prx/libSceFreeType/include/Api.hpp @@ -0,0 +1,67 @@ +#pragma once + +#include "prx/libSceFreeType/include/GuestList.hpp" +#include "prx/libSceFreeType/include/GuestFreeType.hpp" +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI FT_Init_FreeType_nid_postfix(FreeType::GuestLibrary** alibrary); +int APS5_VABI FT_Done_FreeType_nid_postfix(FreeType::GuestLibrary* library); +int APS5_VABI FT_New_Face_nid_postfix(FreeType::GuestLibrary* library, const char* filepathname, std::int64_t faceIndex, FreeType::GuestFaceRec** aface); +int APS5_VABI FT_New_Memory_Face_nid_postfix(FreeType::GuestLibrary* library, const unsigned char* fileBase, std::int64_t fileSize, std::int64_t faceIndex, FreeType::GuestFaceRec** aface); +int APS5_VABI FT_Done_Face_nid_postfix(FreeType::GuestFaceRec* face); +int APS5_VABI FT_Select_Size_nid_postfix(FreeType::GuestFaceRec* face, std::int32_t strikeIndex); +int APS5_VABI FT_Set_Pixel_Sizes_nid_postfix(FreeType::GuestFaceRec* face, std::uint32_t pixelWidth, std::uint32_t pixelHeight); +int APS5_VABI FT_Set_Char_Size_nid_postfix(FreeType::GuestFaceRec* face, std::int64_t charWidth, std::int64_t charHeight, std::uint32_t horizontalResolution, std::uint32_t verticalResolution); +std::uint32_t APS5_VABI FT_Get_Char_Index_nid_postfix(FreeType::GuestFaceRec* face, std::uint64_t charcode); +int APS5_VABI FT_Get_Kerning_nid_postfix(FreeType::GuestFaceRec* face, std::uint32_t leftGlyph, std::uint32_t rightGlyph, std::uint32_t kernMode, FreeType::GuestVector* kerning); +int APS5_VABI FT_Load_Glyph_nid_postfix(FreeType::GuestFaceRec* face, std::uint32_t glyphIndex, std::int32_t loadFlags); +int APS5_VABI FT_Get_Gasp_nid_postfix(FreeType::GuestFaceRec* face, std::uint32_t ppem); +int APS5_VABI FT_Get_CID_Registry_Ordering_Supplement_nid_postfix(FreeType::GuestFaceRec* face, const char** registry, const char** ordering, std::int32_t* supplement); +int APS5_VABI FT_Get_CID_Is_Internally_CID_Keyed_nid_postfix(FreeType::GuestFaceRec* face, std::uint8_t* isCid); +int APS5_VABI FT_Get_CID_From_Glyph_Index_nid_postfix(FreeType::GuestFaceRec* face, std::uint32_t glyphIndex, std::uint32_t* cid); +int APS5_VABI FT_Load_Char_nid_postfix(FreeType::GuestFaceRec* face, std::uint64_t charCode, std::int32_t loadFlags); +int APS5_VABI FT_Outline_Get_Orientation_nid_postfix(FreeType::GuestOutline* outline); +int APS5_VABI FT_Outline_Copy_nid_postfix(const FreeType::GuestOutline* source, FreeType::GuestOutline* target); +int APS5_VABI FT_Outline_Decompose_nid_postfix(FreeType::GuestOutline* outline, const FreeType::GuestOutlineFuncs* functions, void* user); +int APS5_VABI FT_Render_Glyph_nid_postfix(FreeType::GuestGlyphSlotRec* slot, std::int32_t renderMode); +int APS5_VABI FT_Select_Charmap_nid_postfix(FreeType::GuestFaceRec* face, std::int32_t encoding); +int APS5_VABI FT_Set_Charmap_nid_postfix(FreeType::GuestFaceRec* face, FreeType::GuestCharMapRec* charmap); +std::uint64_t APS5_VABI FT_Get_First_Char_nid_postfix(FreeType::GuestFaceRec* face, std::uint32_t* glyphIndex); +std::uint64_t APS5_VABI FT_Get_Next_Char_nid_postfix(FreeType::GuestFaceRec* face, std::uint64_t charcode, std::uint32_t* glyphIndex); +void APS5_VABI FT_Set_Transform_nid_postfix(FreeType::GuestFaceRec* face, const FreeType::GuestMatrix* matrix, const FreeType::GuestVector* delta); +int APS5_VABI FT_Get_Charmap_Index_nid_postfix(FreeType::GuestCharMapRec* charmap); +std::uint64_t APS5_VABI FT_Get_CMap_Language_ID_nid_postfix(FreeType::GuestCharMapRec* charmap); +std::int64_t APS5_VABI FT_Get_CMap_Format_nid_postfix(FreeType::GuestCharMapRec* charmap); +const char* APS5_VABI FT_Get_X11_Font_Format_nid_postfix(FreeType::GuestFaceRec* face); +std::uint16_t APS5_VABI FT_Get_FSType_Flags_nid_postfix(FreeType::GuestFaceRec* face); +FreeType::GuestListNodeRec* APS5_VABI FT_List_Find_nid_postfix(FreeType::GuestListRec* list, void* data); +void APS5_VABI FT_List_Add_nid_postfix(FreeType::GuestListRec* list, FreeType::GuestListNodeRec* node); +void APS5_VABI FT_List_Insert_nid_postfix(FreeType::GuestListRec* list, FreeType::GuestListNodeRec* node); +void APS5_VABI FT_List_Remove_nid_postfix(FreeType::GuestListRec* list, FreeType::GuestListNodeRec* node); +void APS5_VABI FT_List_Up_nid_postfix(FreeType::GuestListRec* list, FreeType::GuestListNodeRec* node); +int APS5_VABI FT_List_Iterate_nid_postfix(FreeType::GuestListRec* list, FreeType::GuestListIterator iterator, void* user); +void APS5_VABI FT_List_Finalize_nid_postfix(FreeType::GuestListRec* list, FreeType::GuestListDestructor destroy, FreeType::GuestMemoryRec* memory, void* user); +int APS5_VABI FT_Get_Glyph_Name_nid_postfix(FreeType::GuestFaceRec* face, std::uint32_t glyphIndex, void* buffer, std::uint32_t bufferSize); +std::uint32_t APS5_VABI FT_Get_Name_Index_nid_postfix(FreeType::GuestFaceRec* face, const char* glyphName); +const char* APS5_VABI FT_Get_Postscript_Name_nid_postfix(FreeType::GuestFaceRec* face); +std::uint32_t APS5_VABI FT_Get_Sfnt_Name_Count_nid_postfix(FreeType::GuestFaceRec* face); +int APS5_VABI FT_Get_Sfnt_Name_nid_postfix(FreeType::GuestFaceRec* face, std::uint32_t index, FreeType::GuestSfntName* name); +int APS5_VABI FT_Outline_Check_nid_postfix(FreeType::GuestOutline* outline); +void APS5_VABI FT_Outline_Get_CBox_nid_postfix(const FreeType::GuestOutline* outline, FreeType::GuestBBox* box); +void APS5_VABI FT_Outline_Translate_nid_postfix(const FreeType::GuestOutline* outline, std::int64_t xOffset, std::int64_t yOffset); +void APS5_VABI FT_Outline_Reverse_nid_postfix(FreeType::GuestOutline* outline); +int APS5_VABI FT_Request_Size_nid_postfix(FreeType::GuestFaceRec* face, const FreeType::GuestSizeRequestRec* request); + +void APS5_VABI FT_Bitmap_New_nid_postfix(FreeType::GuestBitmap* bitmap); +int APS5_VABI FT_Bitmap_Copy_nid_postfix(FreeType::GuestLibrary* library, const FreeType::GuestBitmap* source, FreeType::GuestBitmap* target); +int APS5_VABI FT_Bitmap_Convert_nid_postfix(FreeType::GuestLibrary* library, const FreeType::GuestBitmap* source, FreeType::GuestBitmap* target, std::int32_t alignment); +int APS5_VABI FT_Bitmap_Done_nid_postfix(FreeType::GuestLibrary* library, FreeType::GuestBitmap* bitmap); +std::int64_t APS5_VABI FT_Cos_nid_postfix(std::int64_t angle); +std::int64_t APS5_VABI FT_Sin_nid_postfix(std::int64_t angle); +std::int64_t APS5_VABI FT_Tan_nid_postfix(std::int64_t angle); +void APS5_VABI FT_Vector_Unit_nid_postfix(FreeType::GuestVector* vector, std::int64_t angle); +std::int64_t APS5_VABI FT_Angle_Diff_nid_postfix(std::int64_t first, std::int64_t second); + +} diff --git a/core/libs/prx/libSceFreeType/include/GuestFreeType.hpp b/core/libs/prx/libSceFreeType/include/GuestFreeType.hpp index bddbb33246..51acae2148 100644 --- a/core/libs/prx/libSceFreeType/include/GuestFreeType.hpp +++ b/core/libs/prx/libSceFreeType/include/GuestFreeType.hpp @@ -8,6 +8,8 @@ namespace FreeType { +struct GuestLibrary; + struct GuestGeneric { void* data; void (APS5_VABI *finalizer)(void*); @@ -113,6 +115,15 @@ struct GuestOutline { std::int32_t flags; }; +struct GuestOutlineFuncs { + int (APS5_VABI *move_to)(const GuestVector*, void*); + int (APS5_VABI *line_to)(const GuestVector*, void*); + int (APS5_VABI *conic_to)(const GuestVector*, const GuestVector*, void*); + int (APS5_VABI *cubic_to)(const GuestVector*, const GuestVector*, const GuestVector*, void*); + std::int32_t shift; + std::int64_t delta; +}; + struct GuestGlyphSlotRec { void* library; void* face; @@ -183,6 +194,7 @@ static_assert(sizeof(GuestSizeRec) == 88 && offsetof(GuestSizeRec, metrics) == 2 static_assert(sizeof(GuestSizeRequestRec) == 32 && offsetof(GuestSizeRequestRec, width) == 8 && offsetof(GuestSizeRequestRec, height) == 16); static_assert(offsetof(GuestSizeRequestRec, horiResolution) == 24 && offsetof(GuestSizeRequestRec, vertResolution) == 28); static_assert(sizeof(GuestBitmap) == 40 && offsetof(GuestBitmap, buffer) == 16 && offsetof(GuestBitmap, palette) == 32); +static_assert(sizeof(GuestOutlineFuncs) == 48 && offsetof(GuestOutlineFuncs, shift) == 32 && offsetof(GuestOutlineFuncs, delta) == 40); static_assert(sizeof(GuestOutline) == 40 && offsetof(GuestOutline, points) == 8 && offsetof(GuestOutline, flags) == 32); static_assert(offsetof(GuestGlyphSlotRec, glyph_index) == 0x18 && offsetof(GuestGlyphSlotRec, metrics) == 0x30); static_assert(offsetof(GuestGlyphSlotRec, advance) == 0x80 && offsetof(GuestGlyphSlotRec, format) == 0x90); diff --git a/core/libs/prx/libSceFreeType/libSceFreeType.hpp b/core/libs/prx/libSceFreeType/libSceFreeType.hpp new file mode 100644 index 0000000000..e1970ef93b --- /dev/null +++ b/core/libs/prx/libSceFreeType/libSceFreeType.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceFreeType/include/Api.hpp" diff --git a/core/libs/prx/libSceFreeType/src/Charmap.cpp b/core/libs/prx/libSceFreeType/src/Charmap.cpp index c6a776664e..6f7ee76773 100644 --- a/core/libs/prx/libSceFreeType/src/Charmap.cpp +++ b/core/libs/prx/libSceFreeType/src/Charmap.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceFreeType/include/Api.hpp" #include "prx/libSceFreeType/include/GuestObjects.hpp" #include "prx/libc/include/general/VabiMacros.hpp" diff --git a/core/libs/prx/libSceFreeType/src/FaceInfo.cpp b/core/libs/prx/libSceFreeType/src/FaceInfo.cpp index 6810256751..a5969dcbfa 100644 --- a/core/libs/prx/libSceFreeType/src/FaceInfo.cpp +++ b/core/libs/prx/libSceFreeType/src/FaceInfo.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceFreeType/include/Api.hpp" #include "prx/libSceFreeType/include/GuestObjects.hpp" #include "prx/libc/include/general/VabiMacros.hpp" diff --git a/core/libs/prx/libSceFreeType/src/List.cpp b/core/libs/prx/libSceFreeType/src/List.cpp index ff3deb8272..45a1872a31 100644 --- a/core/libs/prx/libSceFreeType/src/List.cpp +++ b/core/libs/prx/libSceFreeType/src/List.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceFreeType/include/Api.hpp" #include "prx/libSceFreeType/include/GuestList.hpp" #include "prx/libc/include/GuestArena.hpp" diff --git a/core/libs/prx/libSceFreeType/src/Names.cpp b/core/libs/prx/libSceFreeType/src/Names.cpp index 23d3b8ad8f..02e1f9f39c 100644 --- a/core/libs/prx/libSceFreeType/src/Names.cpp +++ b/core/libs/prx/libSceFreeType/src/Names.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceFreeType/include/Api.hpp" #include "prx/libSceFreeType/include/GuestObjects.hpp" #include "prx/libc/include/GuestArena.hpp" #include "prx/libc/include/general/VabiMacros.hpp" diff --git a/core/libs/prx/libSceFreeType/src/Outline.cpp b/core/libs/prx/libSceFreeType/src/Outline.cpp index 1725531f3a..8c9892ad30 100644 --- a/core/libs/prx/libSceFreeType/src/Outline.cpp +++ b/core/libs/prx/libSceFreeType/src/Outline.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceFreeType/include/Api.hpp" #include "prx/libSceFreeType/include/GuestFreeType.hpp" #include "prx/libc/include/general/VabiMacros.hpp" diff --git a/core/libs/prx/libSceFreeType/src/OutlineDecompose.cpp b/core/libs/prx/libSceFreeType/src/OutlineDecompose.cpp new file mode 100644 index 0000000000..2304dc5a9b --- /dev/null +++ b/core/libs/prx/libSceFreeType/src/OutlineDecompose.cpp @@ -0,0 +1,130 @@ +#include "prx/libSceFreeType/include/GuestFreeType.hpp" + +#include +#include FT_FREETYPE_H + +#include +#include +#include + +using namespace FreeType; + +namespace { + +std::int64_t Scale(std::int64_t value, std::int32_t shift, std::int64_t delta) { + if (shift < 0 || shift >= 63) { + throw std::runtime_error("FT_Outline_Decompose: a shift outside 0-62 is not implemented"); + } + constexpr auto minimum = std::numeric_limits::min(); + constexpr auto maximum = std::numeric_limits::max(); + const std::int64_t factor = std::int64_t{1} << shift; + if (value < minimum / factor || value > maximum / factor) { + throw std::runtime_error("FT_Outline_Decompose: overflowing coordinate scaling is not implemented"); + } + const std::int64_t scaled = value * factor; + if ((delta > 0 && scaled < minimum + delta) || (delta < 0 && scaled > maximum + delta)) { + throw std::runtime_error("FT_Outline_Decompose: overflowing coordinate translation is not implemented"); + } + return scaled - delta; +} + +GuestVector Scale(GuestVector point, std::int32_t shift, std::int64_t delta) { + return {Scale(point.x, shift, delta), Scale(point.y, shift, delta)}; +} + +std::int64_t Midpoint(std::int64_t first, std::int64_t second) { + if ((second > 0 && first > std::numeric_limits::max() - second) || + (second < 0 && first < std::numeric_limits::min() - second)) { + throw std::runtime_error("FT_Outline_Decompose: overflowing midpoint arithmetic is not implemented"); + } + return (first + second) / 2; +} + +GuestVector Midpoint(GuestVector first, GuestVector second) { + return {Midpoint(first.x, second.x), Midpoint(first.y, second.y)}; +} + +} + +extern "C" int APS5_VABI FT_Outline_Decompose_nid_postfix(GuestOutline* outline, const GuestOutlineFuncs* functions, void* user) { + if (!outline) return FT_Err_Invalid_Outline; + if (!functions) return FT_Err_Invalid_Argument; + const std::int32_t shift = functions->shift; + const std::int64_t delta = functions->delta; + std::int32_t previousEnd = -1; + for (std::uint32_t contour = 0; contour < outline->n_contours; ++contour) { + const std::int32_t first = previousEnd + 1; + const std::int32_t last = outline->contours[contour]; + if (last < first) return FT_Err_Invalid_Outline; + previousEnd = last; + auto* points = outline->points; + auto* tags = outline->tags; + std::int32_t limit = last; + std::int32_t point = first; + GuestVector start = Scale(points[first], shift, delta); + const GuestVector end = Scale(points[last], shift, delta); + const int firstTag = tags[first] & 3; + if (firstTag == FT_CURVE_TAG_CUBIC) return FT_Err_Invalid_Outline; + if (firstTag == FT_CURVE_TAG_CONIC) { + if ((tags[last] & 3) == FT_CURVE_TAG_ON) { + start = end; + --limit; + } else { + start = Midpoint(start, end); + } + --point; + } + int error = functions->move_to(&start, user); + if (error != 0) return error; + bool closed = false; + while (point < limit) { + ++point; + const int tag = tags[point] & 3; + if (tag == FT_CURVE_TAG_ON) { + const GuestVector to = Scale(points[point], shift, delta); + error = functions->line_to(&to, user); + if (error != 0) return error; + } else if (tag == FT_CURVE_TAG_CONIC) { + GuestVector control = Scale(points[point], shift, delta); + while (true) { + if (point == limit) { + error = functions->conic_to(&control, &start, user); + closed = true; + break; + } + ++point; + const int nextTag = tags[point] & 3; + const GuestVector next = Scale(points[point], shift, delta); + if (nextTag == FT_CURVE_TAG_ON) { + error = functions->conic_to(&control, &next, user); + break; + } + if (nextTag != FT_CURVE_TAG_CONIC) return FT_Err_Invalid_Outline; + const GuestVector middle = Midpoint(control, next); + error = functions->conic_to(&control, &middle, user); + if (error != 0) return error; + control = next; + } + if (error != 0) return error; + } else { + if (point + 1 > limit || (tags[point + 1] & 3) != FT_CURVE_TAG_CUBIC) return FT_Err_Invalid_Outline; + const GuestVector control1 = Scale(points[point], shift, delta); + const GuestVector control2 = Scale(points[point + 1], shift, delta); + point += 2; + if (point <= limit) { + const GuestVector to = Scale(points[point], shift, delta); + error = functions->cubic_to(&control1, &control2, &to, user); + } else { + error = functions->cubic_to(&control1, &control2, &start, user); + closed = true; + } + if (error != 0) return error; + } + } + if (!closed) { + error = functions->line_to(&start, user); + if (error != 0) return error; + } + } + return 0; +} diff --git a/core/libs/prx/libSceFreeType/src/SizeRequest.cpp b/core/libs/prx/libSceFreeType/src/SizeRequest.cpp index 6ef487fa6a..e70ea25111 100644 --- a/core/libs/prx/libSceFreeType/src/SizeRequest.cpp +++ b/core/libs/prx/libSceFreeType/src/SizeRequest.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceFreeType/include/Api.hpp" #include "prx/libSceFreeType/include/GuestObjects.hpp" #include "prx/libc/include/General.hpp" diff --git a/core/libs/prx/libSceFreeTypeOl/libSceFreeTypeOl.hpp b/core/libs/prx/libSceFreeTypeOl/libSceFreeTypeOl.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceFreeTypeOl/libSceFreeTypeOl.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceFreeTypeOptOl/libSceFreeTypeOptOl.hpp b/core/libs/prx/libSceFreeTypeOptOl/libSceFreeTypeOptOl.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceFreeTypeOptOl/libSceFreeTypeOptOl.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceFreeTypeOt/libSceFreeTypeOt.hpp b/core/libs/prx/libSceFreeTypeOt/libSceFreeTypeOt.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceFreeTypeOt/libSceFreeTypeOt.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceFsInternalForVsh/Export.cpp b/core/libs/prx/libSceFsInternalForVsh/Export.cpp index 4a393cfbb7..75159006f0 100644 --- a/core/libs/prx/libSceFsInternalForVsh/Export.cpp +++ b/core/libs/prx/libSceFsInternalForVsh/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceFsInternalForVsh/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceFsInternalForVsh/include/Api.hpp b/core/libs/prx/libSceFsInternalForVsh/include/Api.hpp new file mode 100644 index 0000000000..15f7c8533c --- /dev/null +++ b/core/libs/prx/libSceFsInternalForVsh/include/Api.hpp @@ -0,0 +1,184 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceBdSchedCancelBackgroundCopyRequest(); +int APS5_VABI sceBdSchedCancelPrioritizedBackgroundCopyRequest(); +int APS5_VABI sceBdSchedConfigure(); +int APS5_VABI sceBdSchedConfigure2(); +int APS5_VABI sceBdSchedDeconfigure(); +int APS5_VABI sceBdSchedGetBackgroundCopyRequest(); +int APS5_VABI sceBdSchedGetExtentMap(); +int APS5_VABI sceBdSchedGetPrioritizedBackgroundCopyRequest(); +int APS5_VABI sceBdSchedGetState(); +int APS5_VABI sceBdSchedSetBackgroundCopyRequest(); +int APS5_VABI sceBdSchedSetDiscIdentity(); +int APS5_VABI sceBdSchedSetPrioritizedBackgroundCopyRequest(); +int APS5_VABI sceBdSchedStartGame(); +int APS5_VABI sceBdSchedStartRipping(); +int APS5_VABI sceBdSchedStopScheduling(); +int APS5_VABI sceFsBfsCheckCleanFlag(); +int APS5_VABI sceFsBindApplication(); +int APS5_VABI sceFsBindPackages(); +int APS5_VABI sceFsCheckFormat(); +int APS5_VABI sceFsCheckSingleUser(); +int APS5_VABI sceFsCreateExfatPartition(); +int APS5_VABI sceFsCreatePfsSaveDataImage(); +int APS5_VABI sceFsCreatePfsTrophyDataImage(); +int APS5_VABI sceFsCreatePprPfsTrophyDataImage(); +int APS5_VABI sceFsDeviceAlignedPread(); +int APS5_VABI sceFsDeviceAlignedPwrite(); +int APS5_VABI sceFsDevpfsA53IocGetBuildMetadataStatus(); +int APS5_VABI sceFsDevpfsCancelWaitEvent(); +int APS5_VABI sceFsDevpfsCreateForVSH(); +int APS5_VABI sceFsDevpfsDeleteForVSH(); +int APS5_VABI sceFsDevpfsDeregisterEvent(); +int APS5_VABI sceFsDevpfsEventComplete(); +int APS5_VABI sceFsDevpfsEventResponseComplete(); +int APS5_VABI sceFsDevpfsFetchMetaEntry(); +int APS5_VABI sceFsDevpfsFsck(); +int APS5_VABI sceFsDevpfsInitFetchMetaEntryCtx(); +int APS5_VABI sceFsDevpfsMountForFSMP(); +int APS5_VABI sceFsDevpfsRegisterEvent(); +int APS5_VABI sceFsDevpfsWaitEvent(); +int APS5_VABI sceFsDrfsRegisterSocket(); +int APS5_VABI sceFsDrfsResumeSocket(); +int APS5_VABI sceFsErriCtl(); +int APS5_VABI sceFsErriGetState(); +int APS5_VABI sceFsExfatMkfsExternalHdd(); +int APS5_VABI sceFsExfatfsMkfs(); +int APS5_VABI sceFsExtUSBSchedDestroy(); +int APS5_VABI sceFsExtUSBSchedInsert(); +int APS5_VABI sceFsExtUSBSchedInsertForHDD(); +int APS5_VABI sceFsExternalStorageDeconfigure(); +int APS5_VABI sceFsExternalStorageGetRawDevice(); +int APS5_VABI sceFsExternalStorageInitialize(); +int APS5_VABI sceFsExternalStorageVerifyMetadata(); +int APS5_VABI sceFsGetAttribute(); +int APS5_VABI sceFsGetClusterStatistics(); +int APS5_VABI sceFsGetDeviceSectorsize(); +int APS5_VABI sceFsGetFsMetadata(); +int APS5_VABI sceFsGetFsMetadataWithProgress(); +int APS5_VABI sceFsGetSmrInfo(); +int APS5_VABI sceFsGschedCtl(); +int APS5_VABI sceFsISSchedConfigCurrentThread(); +int APS5_VABI sceFsISSchedConfigDescriptor(); +int APS5_VABI sceFsISSchedConfigThread(); +int APS5_VABI sceFsISSchedMapStat(); +int APS5_VABI sceFsISSchedResultToPriority(); +int APS5_VABI sceFsISSchedResultToSlot(); +int APS5_VABI sceFsISSchedStatCurrentThread(); +int APS5_VABI sceFsISSchedStatDescriptor(); +int APS5_VABI sceFsISSchedStatThread(); +int APS5_VABI sceFsISSchedUnmapStat(); +int APS5_VABI sceFsInitCreatePfsSaveDataOpt(); +int APS5_VABI sceFsInitCreatePfsTrophyDataOpt(); +int APS5_VABI sceFsInitMountDownloadDataOpt(); +int APS5_VABI sceFsInitMountGamePkgOpt(); +int APS5_VABI sceFsInitMountLwfsCompatOpt(); +int APS5_VABI sceFsInitMountLwfsOpt(); +int APS5_VABI sceFsInitMountPprPkgOpt(); +int APS5_VABI sceFsInitMountSaveDataOpt(); +int APS5_VABI sceFsInitMountTrophyDataOpt(); +int APS5_VABI sceFsInitUmountDownloadDataOpt(); +int APS5_VABI sceFsInitUmountGamePkgOpt(); +int APS5_VABI sceFsInitUmountLwfsCompatOpt(); +int APS5_VABI sceFsInitUmountLwfsOpt(); +int APS5_VABI sceFsInitUmountPprPkgOpt(); +int APS5_VABI sceFsInitUmountSaveDataOpt(); +int APS5_VABI sceFsInitUmountTrophyDataOpt(); +int APS5_VABI sceFsInitWorkspaceFileMetadataParam(); +int APS5_VABI sceFsLvdAttach(); +int APS5_VABI sceFsLvdAttach2(); +int APS5_VABI sceFsLvdAttachPartiallyCryptedDownloadData(); +int APS5_VABI sceFsLvdAttachSingleDefaultImage(); +int APS5_VABI sceFsLvdAttachSingleImage(); +int APS5_VABI sceFsLvdDetach(); +int APS5_VABI sceFsLvdDisableLayer(); +int APS5_VABI sceFsLvdEnableLayer(); +int APS5_VABI sceFsLvdSetDiscIdentity(); +int APS5_VABI sceFsLvdWaitResumed(); +int APS5_VABI sceFsMlfsMount(); +int APS5_VABI sceFsMlfsMountWithFlags(); +int APS5_VABI sceFsMlfsUmount(); +int APS5_VABI sceFsMountDownloadData(); +int APS5_VABI sceFsMountGamePkg(); +int APS5_VABI sceFsMountLwfs(); +int APS5_VABI sceFsMountLwfsCompat(); +int APS5_VABI sceFsMountPartiallyCryptedDownloadData(); +int APS5_VABI sceFsMountPprPkg(); +int APS5_VABI sceFsMountSaveData(); +int APS5_VABI sceFsMountTrophyData(); +int APS5_VABI sceFsNsfsAddOverlayToNamespace(); +int APS5_VABI sceFsNsfsMountWithFlags(); +int APS5_VABI sceFsNsfsSetGlobalExclude(); +int APS5_VABI sceFsNsfsUmount(); +int APS5_VABI sceFsPartitionTrim(); +int APS5_VABI sceFsReserveCluster(); +int APS5_VABI sceFsSetAttribute(); +int APS5_VABI sceFsSetClusterCacheSize(); +int APS5_VABI sceFsSetFileReservedTotal(); +int APS5_VABI sceFsSetSystemReserveSize(); +int APS5_VABI sceFsSetWorkspaceFileHash(); +int APS5_VABI sceFsStatWorkspace(); +int APS5_VABI sceFsSysStorageGetStatus(); +int APS5_VABI sceFsTransactionCancel(); +int APS5_VABI sceFsTransactionSaveDataInitMountOpt(); +int APS5_VABI sceFsTransactionSaveDataMount(); +int APS5_VABI sceFsTransactionStart(); +int APS5_VABI sceFsTrophyImageError(); +int APS5_VABI sceFsUfsAllocateAdditionalContents(); +int APS5_VABI sceFsUfsAllocateAligned(); +int APS5_VABI sceFsUfsAllocateDownloadData(); +int APS5_VABI sceFsUfsAllocateGameImage(); +int APS5_VABI sceFsUfsAllocatePatchImage(); +int APS5_VABI sceFsUfsAllocateSaveData(); +int APS5_VABI sceFsUfsAllocateTrophyData(); +int APS5_VABI sceFsUfsCheckCleanFlag(); +int APS5_VABI sceFsUfsCheckFixedCylinderGroupSize(); +int APS5_VABI sceFsUfsCollectTelemetry(); +int APS5_VABI sceFsUfsCollectTelemetry2(); +int APS5_VABI sceFsUfsDirectWrite(); +int APS5_VABI sceFsUfsEstimateZoneCapacityForUser(); +int APS5_VABI sceFsUfsExtendFile(); +int APS5_VABI sceFsUfsFsck(); +int APS5_VABI sceFsUfsFsckWithMM(); +int APS5_VABI sceFsUfsGetExtentMap(); +int APS5_VABI sceFsUfsGrowLwfs(); +int APS5_VABI sceFsUfsGrowfs(); +int APS5_VABI sceFsUfsHideBlocksFromUser(); +int APS5_VABI sceFsUfsInitalizeSparseFile(); +int APS5_VABI sceFsUfsLargewriteFsck(); +int APS5_VABI sceFsUfsLargewriteFsckWithMM(); +int APS5_VABI sceFsUfsMkLwfs(); +int APS5_VABI sceFsUfsMkfs(); +int APS5_VABI sceFsUfsMkfsForExternalHDD(); +int APS5_VABI sceFsUfsMkfsForSystem(); +int APS5_VABI sceFsUfsMkfsWithFixedCylinderGroupSize(); +int APS5_VABI sceFsUfsReallocateSparseFile(); +int APS5_VABI sceFsUfsRecryptBlocks(); +int APS5_VABI sceFsUfsRecryptGetState(); +int APS5_VABI sceFsUfsRecryptIsUnfinished(); +int APS5_VABI sceFsUfsRecryptSyncMetadata(); +int APS5_VABI sceFsUfsSeekHoleInFile(); +int APS5_VABI sceFsUfsStopOperation(); +int APS5_VABI sceFsUmountDownloadData(); +int APS5_VABI sceFsUmountGamePkg(); +int APS5_VABI sceFsUmountLwfs(); +int APS5_VABI sceFsUmountLwfsCompat(); +int APS5_VABI sceFsUmountSaveData(); +int APS5_VABI sceFsUmountTrophyData(); +int APS5_VABI sceFsUmountWorkspace(); +int APS5_VABI sceFsUnbindApplication(); +int APS5_VABI sceFsUnbindPackages(); +int APS5_VABI sceFsWsCreate(); +int APS5_VABI sceFsWsDelete(); +int APS5_VABI sceFsWsFetchFileMetadata(); +int APS5_VABI sceFsWsFsck(); +int APS5_VABI sceFsWsGetStatus(); +int APS5_VABI sceFsWsMount(); +int APS5_VABI sceFsWsUmount(); + +} diff --git a/core/libs/prx/libSceFsInternalForVsh/libSceFsInternalForVsh.hpp b/core/libs/prx/libSceFsInternalForVsh/libSceFsInternalForVsh.hpp new file mode 100644 index 0000000000..bba8925b6e --- /dev/null +++ b/core/libs/prx/libSceFsInternalForVsh/libSceFsInternalForVsh.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceFsInternalForVsh/include/Api.hpp" diff --git a/core/libs/prx/libSceGLSlimVSH/libSceGLSlimVSH.hpp b/core/libs/prx/libSceGLSlimVSH/libSceGLSlimVSH.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceGLSlimVSH/libSceGLSlimVSH.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceGameCustomDataDialog/Export.cpp b/core/libs/prx/libSceGameCustomDataDialog/Export.cpp index 594d4adfac..48093e841d 100644 --- a/core/libs/prx/libSceGameCustomDataDialog/Export.cpp +++ b/core/libs/prx/libSceGameCustomDataDialog/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceGameCustomDataDialog/include/Api.hpp" #include #include #include diff --git a/core/libs/prx/libSceGameCustomDataDialog/include/Api.hpp b/core/libs/prx/libSceGameCustomDataDialog/include/Api.hpp new file mode 100644 index 0000000000..20d28826e7 --- /dev/null +++ b/core/libs/prx/libSceGameCustomDataDialog/include/Api.hpp @@ -0,0 +1,17 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceGameCustomDataDialogInitialize(void); +int APS5_VABI sceGameCustomDataDialogOpenA(const void* param); +int APS5_VABI sceGameCustomDataDialogUpdateStatus(void); +int APS5_VABI sceGameCustomDataDialogGetStatus(void); +int APS5_VABI sceGameCustomDataDialogGetResultA(void* result); +int APS5_VABI sceGameCustomDataDialogClose(void); +int APS5_VABI sceGameCustomDataDialogTerminate(void); +int APS5_VABI sceGameCustomDataDialogGetResult(); +int APS5_VABI sceGameCustomDataDialogOpen(); + +} diff --git a/core/libs/prx/libSceGameCustomDataDialog/libSceGameCustomDataDialog.hpp b/core/libs/prx/libSceGameCustomDataDialog/libSceGameCustomDataDialog.hpp new file mode 100644 index 0000000000..c5267d6b1a --- /dev/null +++ b/core/libs/prx/libSceGameCustomDataDialog/libSceGameCustomDataDialog.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceGameCustomDataDialog/include/Api.hpp" diff --git a/core/libs/prx/libSceGameLiveStreaming/Export.cpp b/core/libs/prx/libSceGameLiveStreaming/Export.cpp index 891a864574..d9e1f9a227 100644 --- a/core/libs/prx/libSceGameLiveStreaming/Export.cpp +++ b/core/libs/prx/libSceGameLiveStreaming/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceGameLiveStreaming/include/Api.hpp" #include #include #include "SceTypes.hpp" @@ -15,18 +16,6 @@ static constexpr int ErrorAlreadyInitialized = static_cast(0x80A00003); static constexpr int ErrorNotInitialized = static_cast(0x80A00004); static constexpr std::size_t ProgramInfoSize = 0x134C; -struct GameLiveStreamingProgramInfo; - -struct GameLiveStreamingStatus2 { - std::int32_t userId; - bool isOnAir; - std::uint8_t align[3]; - std::uint32_t spectatorCounts; - std::uint32_t textMessageCounts; - std::uint32_t commandMessageCounts; - std::uint32_t broadcastVideoResolution; - std::uint8_t reserved[48]; -}; static_assert(sizeof(GameLiveStreamingStatus2) == 72); extern "C" { @@ -108,7 +97,7 @@ int APS5_VABI sceGameLiveStreamingSetMaxBitrate(void) { return 0; } -int APS5_VABI sceGameLiveStreamingGetCurrentStatus(void) { +int APS5_VABI sceGameLiveStreamingGetCurrentStatus(GameLiveStreamingStatus* status) { NotImplemented_nid_no_patch(__func__); return 0; } diff --git a/core/libs/prx/libSceGameLiveStreaming/include/Api.hpp b/core/libs/prx/libSceGameLiveStreaming/include/Api.hpp new file mode 100644 index 0000000000..28b744e492 --- /dev/null +++ b/core/libs/prx/libSceGameLiveStreaming/include/Api.hpp @@ -0,0 +1,78 @@ +#pragma once + +#include "SceTypes.hpp" +#include +#include + +struct GameLiveStreamingProgramInfo; + +struct GameLiveStreamingStatus { + std::uint8_t opaque00[12]; + std::uint8_t reserved[60]; +}; + +static_assert(offsetof(GameLiveStreamingStatus, reserved) == 0x0C); +static_assert(sizeof(GameLiveStreamingStatus) == 0x48); + +struct GameLiveStreamingStatus2 { + std::int32_t userId; + bool isOnAir; + std::uint8_t align[3]; + std::uint32_t spectatorCounts; + std::uint32_t textMessageCounts; + std::uint32_t commandMessageCounts; + std::uint32_t broadcastVideoResolution; + std::uint8_t reserved[48]; +}; + +extern "C" { + +int APS5_VABI sceGameLiveStreamingInitialize(size_t heapSize); +int APS5_VABI sceGameLiveStreamingTerminate(void); +int APS5_VABI sceGameLiveStreamingGetCurrentStatus2(GameLiveStreamingStatus2* status); +int APS5_VABI sceGameLiveStreamingGetProgramInfo(GameLiveStreamingProgramInfo* info); +int APS5_VABI sceGameLiveStreamingScreenInitialize(void); +int APS5_VABI sceGameLiveStreamingScreenInitializeSeparateModeParameter(void); +int APS5_VABI sceGameLiveStreamingScreenTerminate(void); +int APS5_VABI sceGameLiveStreamingScreenCloseSeparateMode(void); +int APS5_VABI sceGameLiveStreamingScreenConfigureSeparateMode(void); +int APS5_VABI sceGameLiveStreamingScreenOpenSeparateMode(void); +int APS5_VABI sceGameLiveStreamingScreenSetMode(void); +int APS5_VABI sceGameLiveStreamingPermitLiveStreaming(void); +int APS5_VABI sceGameLiveStreamingSetMaxBitrate(void); +int APS5_VABI sceGameLiveStreamingGetCurrentStatus(GameLiveStreamingStatus* status); +int APS5_VABI sceGameLiveStreamingEnableSocialFeedback(void); +int APS5_VABI sceGameLiveStreamingGetSocialFeedbackMessagesCount(void); +int APS5_VABI sceGameLiveStreamingGetSocialFeedbackMessages(void); +int APS5_VABI sceGameLiveStreamingPermitServerSideRecording(void); +int APS5_VABI sceGameLiveStreamingSetMetadata(void); +int APS5_VABI sceGameLiveStreamingSetSpoilerTag(void); +int APS5_VABI sceGameLiveStreamingClearSpoilerTag(void); +int APS5_VABI sceGameLiveStreamingSetPresetSocialFeedbackCommands(void); +int APS5_VABI sceGameLiveStreamingClearPresetSocialFeedbackCommands(void); +int APS5_VABI sceGameLiveStreamingSetPresetSocialFeedbackCommandsDescription(void); +int APS5_VABI sceGameLiveStreamingClearSocialFeedbackMessages(void); +int APS5_VABI sceGameLiveStreamingPostSocialMessage(void); +int APS5_VABI sceGameLiveStreamingSetCameraFrameSetting(void); +int APS5_VABI sceGameLiveStreamingSetServiceProviderPermission(void); +int APS5_VABI sceGameLiveStreamingSetDefaultServiceProviderPermission(void); +int APS5_VABI sceGameLiveStreamingSetInvitationSessionId(void); +int APS5_VABI sceGameLiveStreamingStartGenerateStandbyScreenResource(void); +int APS5_VABI sceGameLiveStreamingStopGenerateStandbyScreenResource(void); +int APS5_VABI sceGameLiveStreamingRegisterCallback(void); +int APS5_VABI sceGameLiveStreamingUnregisterCallback(void); +int APS5_VABI sceGameLiveStreamingCheckCallback(void); +int APS5_VABI sceGameLiveStreamingSetStandbyScreenResource(void); +int APS5_VABI sceGameLiveStreamingGetCurrentBroadcastScreenLayout(void); +int APS5_VABI sceGameLiveStreamingLaunchLiveViewer(void); +int APS5_VABI sceGameLiveStreamingLaunchLiveViewerA(void); +int APS5_VABI sceGameLiveStreamingSetGuardAreas(void); +int APS5_VABI sceGameLiveStreamingStartSocialFeedbackMessageFiltering(void); +int APS5_VABI sceGameLiveStreamingStopSocialFeedbackMessageFiltering(void); +int APS5_VABI sceGameLiveStreamingApplySocialFeedbackMessageFilter(void); +int APS5_VABI sceGameLiveStreamingSetLinkCommentPreset(void); +int APS5_VABI sceGameLiveStreamingStartDebugBroadcast(void); +int APS5_VABI sceGameLiveStreamingStopDebugBroadcast(void); +int APS5_VABI sceGameLiveStreamingEnableLiveStreaming(bool isEnableLiveStreaming); + +} diff --git a/core/libs/prx/libSceGameLiveStreaming/libSceGameLiveStreaming.hpp b/core/libs/prx/libSceGameLiveStreaming/libSceGameLiveStreaming.hpp new file mode 100644 index 0000000000..65b14e5bdf --- /dev/null +++ b/core/libs/prx/libSceGameLiveStreaming/libSceGameLiveStreaming.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceGameLiveStreaming/include/Api.hpp" diff --git a/core/libs/prx/libSceGameUpdate/Export.cpp b/core/libs/prx/libSceGameUpdate/Export.cpp index f8527db000..dfcb3d1383 100644 --- a/core/libs/prx/libSceGameUpdate/Export.cpp +++ b/core/libs/prx/libSceGameUpdate/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceGameUpdate/include/Api.hpp" #include #include #include diff --git a/core/libs/prx/libSceGameUpdate/include/Api.hpp b/core/libs/prx/libSceGameUpdate/include/Api.hpp new file mode 100644 index 0000000000..2de12ef941 --- /dev/null +++ b/core/libs/prx/libSceGameUpdate/include/Api.hpp @@ -0,0 +1,15 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceGameUpdateAbortRequest(int requestId); +int APS5_VABI sceGameUpdateCheck(int requestId, const GameUpdateCheckParam* param, GameUpdateCheckResult* result); +int APS5_VABI sceGameUpdateCreateRequest(void); +int APS5_VABI sceGameUpdateDeleteRequest(int requestId); +int APS5_VABI sceGameUpdateGetAddcontLatestVersion(uint32_t serviceLabel, const NpUnifiedEntitlementLabel* entitlementLabel, GameUpdateAddcontVersionInfo* info); +int APS5_VABI sceGameUpdateInitialize(void); +int APS5_VABI sceGameUpdateTerminate(void); + +} diff --git a/core/libs/prx/libSceGameUpdate/libSceGameUpdate.hpp b/core/libs/prx/libSceGameUpdate/libSceGameUpdate.hpp new file mode 100644 index 0000000000..9807085ba6 --- /dev/null +++ b/core/libs/prx/libSceGameUpdate/libSceGameUpdate.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceGameUpdate/include/Api.hpp" diff --git a/core/libs/prx/libSceGic/Export.cpp b/core/libs/prx/libSceGic/Export.cpp index 6fff8198ce..2c4656fad6 100644 --- a/core/libs/prx/libSceGic/Export.cpp +++ b/core/libs/prx/libSceGic/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceGic/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceGic/include/Api.hpp b/core/libs/prx/libSceGic/include/Api.hpp new file mode 100644 index 0000000000..889405a588 --- /dev/null +++ b/core/libs/prx/libSceGic/include/Api.hpp @@ -0,0 +1,9 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceGicGetValue(); + +} diff --git a/core/libs/prx/libSceGic/libSceGic.hpp b/core/libs/prx/libSceGic/libSceGic.hpp new file mode 100644 index 0000000000..1f60bb76a8 --- /dev/null +++ b/core/libs/prx/libSceGic/libSceGic.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceGic/include/Api.hpp" diff --git a/core/libs/prx/libSceGifParser/libSceGifParser.hpp b/core/libs/prx/libSceGifParser/libSceGifParser.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceGifParser/libSceGifParser.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceGnmDriverCompat1/libSceGnmDriverCompat1.hpp b/core/libs/prx/libSceGnmDriverCompat1/libSceGnmDriverCompat1.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceGnmDriverCompat1/libSceGnmDriverCompat1.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceGnmDriverForNeoMode/Export.cpp b/core/libs/prx/libSceGnmDriverForNeoMode/Export.cpp index 4bddc78a76..b09d2a8a87 100644 --- a/core/libs/prx/libSceGnmDriverForNeoMode/Export.cpp +++ b/core/libs/prx/libSceGnmDriverForNeoMode/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceGnmDriverForNeoMode/include/Api.hpp" #include #include #include diff --git a/core/libs/prx/libSceGnmDriverForNeoMode/include/Api.hpp b/core/libs/prx/libSceGnmDriverForNeoMode/include/Api.hpp new file mode 100644 index 0000000000..f9ecf8db4c --- /dev/null +++ b/core/libs/prx/libSceGnmDriverForNeoMode/include/Api.hpp @@ -0,0 +1,126 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceGnmBeginWorkload(std::uint32_t stream, std::uint64_t* workload); +int APS5_VABI sceGnmComputeWaitOnAddress(std::uint32_t* cmdbuf, std::uint32_t size, std::uint64_t address, std::uint32_t mask, std::uint32_t compare, std::uint32_t reference); +int APS5_VABI sceGnmComputeWaitSemaphore(std::uint32_t* cmdbuf, std::uint32_t size, std::uint64_t semaphoreAddress, std::uint32_t flags); +int APS5_VABI sceGnmCreateWorkloadStream(std::uint64_t name, std::uint32_t* stream); +int APS5_VABI sceGnmDebugModuleReset(void); +int APS5_VABI sceGnmDebugReset(void); +int APS5_VABI sceGnmDestroyWorkloadStream(void); +int APS5_VABI sceGnmDingDongForWorkload(void); +int APS5_VABI sceGnmDispatchDirect(std::uint32_t* cmdbuf, std::uint32_t size, std::uint32_t threadsX, std::uint32_t threadsY, std::uint32_t threadsZ, std::uint32_t flags); +int APS5_VABI sceGnmDispatchIndirect(std::uint32_t* cmdbuf, std::uint32_t size, std::uint32_t dataOffset, std::uint32_t flags); +int APS5_VABI sceGnmDispatchIndirectOnMec(std::uint32_t* cmdbuf, std::uint32_t size, std::uint64_t args, std::uint32_t modifier); +int APS5_VABI sceGnmDrawIndex(std::uint32_t* cmdbuf, std::uint32_t size, std::uint32_t indexCount, std::uint64_t indexAddress, std::uint32_t flags, std::uint32_t); +int APS5_VABI sceGnmDrawIndexAuto(std::uint32_t* cmdbuf, std::uint32_t size, std::uint32_t indexCount, std::uint32_t flags); +int APS5_VABI sceGnmDrawIndexIndirect(std::uint32_t* cmdbuf, std::uint32_t size, std::uint32_t dataOffset, std::uint32_t stage, std::uint32_t vertexSgpr, std::uint32_t instanceSgpr, std::uint32_t flags); +int APS5_VABI sceGnmDrawIndexIndirectCountMulti(std::uint32_t* cmdbuf, std::uint32_t size, std::uint32_t dataOffset, std::uint32_t maxCount, std::uint64_t countAddress, std::uint32_t stage, std::uint32_t vertexSgpr, std::uint32_t instanceSgpr, std::uint32_t flags); +int APS5_VABI sceGnmDrawIndexIndirectMulti(std::uint32_t* cmdbuf, std::uint32_t size, std::uint32_t dataOffset, std::uint32_t maxCount, std::uint32_t stage, std::uint32_t vertexSgpr, std::uint32_t instanceSgpr, std::uint32_t flags); +int APS5_VABI sceGnmDrawIndexMultiInstanced(void); +int APS5_VABI sceGnmDrawIndexOffset(std::uint32_t* cmdbuf, std::uint32_t size, std::uint32_t indexOffset, std::uint32_t indexCount, std::uint32_t flags); +int APS5_VABI sceGnmDrawIndirect(std::uint32_t* cmdbuf, std::uint32_t size, std::uint32_t dataOffset, std::uint32_t stage, std::uint32_t vertexSgpr, std::uint32_t instanceSgpr, std::uint32_t flags); +int APS5_VABI sceGnmDrawIndirectCountMulti(std::uint32_t* cmdbuf, std::uint32_t size, std::uint32_t dataOffset, std::uint32_t maxCount, std::uint64_t countAddress, std::uint32_t stage, std::uint32_t vertexSgpr, std::uint32_t instanceSgpr, std::uint32_t flags); +int APS5_VABI sceGnmDrawIndirectMulti(std::uint32_t* cmdbuf, std::uint32_t size, std::uint32_t dataOffset, std::uint32_t maxCount, std::uint32_t stage, std::uint32_t vertexSgpr, std::uint32_t instanceSgpr, std::uint32_t flags); +int APS5_VABI sceGnmDrawInitDefaultHardwareState(std::uint32_t* cmdbuf, std::uint32_t size); +int APS5_VABI sceGnmDrawInitDefaultHardwareState200(std::uint32_t* cmdbuf, std::uint32_t size); +int APS5_VABI sceGnmDrawInitDefaultHardwareState350(std::uint32_t* cmdbuf, std::uint32_t size); +int APS5_VABI sceGnmDrawInitToDefaultContextState(std::uint32_t* cmdbuf, std::uint32_t size); +int APS5_VABI sceGnmDrawInitToDefaultContextState400(std::uint32_t* cmdbuf, std::uint32_t size); +int APS5_VABI sceGnmDrawInitToDefaultContextStateInternalCommand(void); +int APS5_VABI sceGnmDrawInitToDefaultContextStateInternalSize(void); +int APS5_VABI sceGnmDrawOpaqueAuto(void); +int APS5_VABI sceGnmDriverInternalRetrieveGnmInterface(void); +int APS5_VABI sceGnmDriverInternalRetrieveGnmInterfaceForGpuDebugger(void); +int APS5_VABI sceGnmDriverInternalRetrieveGnmInterfaceForReplay(void); +int APS5_VABI sceGnmDriverInternalRetrieveGnmInterfaceForResourceRegistration(void); +int APS5_VABI sceGnmDriverInternalRetrieveGnmInterfaceForValidation(void); +int APS5_VABI sceGnmDriverInternalVirtualQuery(void); +int APS5_VABI sceGnmDriverTraceInProgress(void); +int APS5_VABI sceGnmEndWorkload(std::uint64_t workload); +int APS5_VABI sceGnmFindResources(void); +int APS5_VABI sceGnmFindResourcesPublic(void); +int APS5_VABI sceGnmGetCoredumpAddress(void); +int APS5_VABI sceGnmGetCoredumpMode(void); +int APS5_VABI sceGnmGetCoredumpProtectionFaultTimestamp(void); +int APS5_VABI sceGnmGetDbgGcHandle(void); +int APS5_VABI sceGnmGetGpuBlockStatus(void); +int APS5_VABI sceGnmGetGpuCoreClockFrequency(void); +int APS5_VABI sceGnmGetGpuInfoStatus(void); +int APS5_VABI sceGnmGetLastWaitedAddress(void); +int APS5_VABI sceGnmGetNumTcaUnits(void); +int APS5_VABI sceGnmGetOffChipTessellationBufferSize(void); +int APS5_VABI sceGnmGetOwnerName(void); +int APS5_VABI sceGnmGetPhysicalCounterFromVirtualized(void); +int APS5_VABI sceGnmGetProtectionFaultTimeStamp(void); +int APS5_VABI sceGnmGetResourceBaseAddressAndSizeInBytes(void); +int APS5_VABI sceGnmGetResourceName(void); +int APS5_VABI sceGnmGetResourceRegistrationBuffers(void); +int APS5_VABI sceGnmGetResourceShaderGuid(void); +int APS5_VABI sceGnmGetResourceType(void); +int APS5_VABI sceGnmGetResourceUserData(void); +int APS5_VABI sceGnmGetShaderProgramBaseAddress(void); +int APS5_VABI sceGnmGetShaderStatus(void); +int APS5_VABI sceGnmGpuPaDebugEnter(void); +int APS5_VABI sceGnmGpuPaDebugLeave(void); +int APS5_VABI sceGnmInsertDingDongMarker(std::uint32_t* cmdbuf, std::uint32_t size); +int APS5_VABI sceGnmInsertThreadTraceMarker(void); +int APS5_VABI sceGnmIsCoredumpValid(void); +int APS5_VABI sceGnmLogicalTcaUnitToPhysical(void); +int APS5_VABI sceGnmMapComputeQueueWithPriority(void); +int APS5_VABI sceGnmPaDisableFlipCallbacks(void); +int APS5_VABI sceGnmPaEnableFlipCallbacks(void); +int APS5_VABI sceGnmPaHeartbeat(void); +int APS5_VABI sceGnmQueryResourceRegistrationUserMemoryRequirements(void); +int APS5_VABI sceGnmRaiseUserExceptionEvent(void); +int APS5_VABI sceGnmRegisterGdsResource(void); +int APS5_VABI sceGnmRegisterGnmLiveCallbackConfig(void); +int APS5_VABI sceGnmRegisterOwner(void); +int APS5_VABI sceGnmRegisterOwnerForSystem(void); +int APS5_VABI sceGnmRegisterResource(void); +int APS5_VABI sceGnmRequestFlipAndSubmitDoneForWorkload(void); +int APS5_VABI sceGnmResetVgtControl(std::uint32_t* cmdbuf, std::uint32_t size); +int APS5_VABI sceGnmSdmaClose(void); +int APS5_VABI sceGnmSdmaConstFill(void); +int APS5_VABI sceGnmSdmaCopyLinear(void); +int APS5_VABI sceGnmSdmaCopyTiled(void); +int APS5_VABI sceGnmSdmaCopyWindow(void); +int APS5_VABI sceGnmSdmaFlush(void); +int APS5_VABI sceGnmSdmaGetMinCmdSize(void); +int APS5_VABI sceGnmSdmaOpen(void); +int APS5_VABI sceGnmSetCsShaderWithModifier(std::uint32_t* cmdbuf, std::uint32_t size, const std::uint32_t* regs, std::uint32_t modifier); +int APS5_VABI sceGnmSetEmbeddedPsShader(std::uint32_t* cmdbuf, std::uint32_t, std::uint32_t shaderId, std::uint32_t); +int APS5_VABI sceGnmSetEmbeddedVsShader(std::uint32_t* cmdbuf, std::uint32_t, std::uint32_t shaderId, std::uint32_t); +int APS5_VABI sceGnmSetPsShader350(std::uint32_t* cmdbuf, std::uint32_t size, const std::uint32_t* regs); +int APS5_VABI sceGnmSetResourceRegistrationUserMemory(void); +int APS5_VABI sceGnmSetResourceUserData(void); +int APS5_VABI sceGnmSetSpiEnableSqCounters(void); +int APS5_VABI sceGnmSetSpiEnableSqCountersForUnitInstance(void); +int APS5_VABI sceGnmSetVgtControl(std::uint32_t* cmdbuf, std::uint32_t size, std::uint32_t primGroupSizeMinusOne, std::uint32_t partialVsWaveMode, std::uint32_t switchOnlyOnEop); +int APS5_VABI sceGnmSetWaveLimitMultiplier(void); +int APS5_VABI sceGnmSetWaveLimitMultipliers(void); +int APS5_VABI sceGnmSubmitAndFlipCommandBuffersForWorkload(void); +int APS5_VABI sceGnmSubmitCommandBuffersForWorkload(void); +int APS5_VABI sceGnmUnregisterAllResourcesForOwner(void); +int APS5_VABI sceGnmUnregisterOwnerAndResources(void); +int APS5_VABI sceGnmUnregisterResource(void); +int APS5_VABI sceGnmUpdateGsShader(std::uint32_t* cmdbuf, std::uint32_t size, const std::uint32_t* regs); +int APS5_VABI sceGnmUpdateHsShader(std::uint32_t* cmdbuf, std::uint32_t size, const std::uint32_t* regs, std::uint32_t lsHsConfig); +int APS5_VABI sceGnmUpdatePsShader(std::uint32_t* cmdbuf, std::uint32_t size, const std::uint32_t* regs); +int APS5_VABI sceGnmUpdatePsShader350(std::uint32_t* cmdbuf, std::uint32_t size, const std::uint32_t* regs); +int APS5_VABI sceGnmUpdateVsShader(std::uint32_t* cmdbuf, std::uint32_t size, const std::uint32_t* regs, std::uint32_t modifier); +int APS5_VABI sceGnmValidateDisableDiagnostics(void); +int APS5_VABI sceGnmValidateDisableDiagnostics2(void); +int APS5_VABI sceGnmValidateDispatchCommandBuffers(void); +int APS5_VABI sceGnmValidateDrawCommandBuffers(void); +int APS5_VABI sceGnmValidateGetDiagnosticInfo(void); +int APS5_VABI sceGnmValidateGetDiagnostics(void); +int APS5_VABI sceGnmValidateGetVersion(void); +int APS5_VABI sceGnmValidateOnSubmitEnabled(void); +int APS5_VABI sceGnmValidateResetState(void); +int APS5_VABI sceGnmValidationRegisterMemoryCheckCallback(void); + +} diff --git a/core/libs/prx/libSceGnmDriverForNeoMode/libSceGnmDriverForNeoMode.hpp b/core/libs/prx/libSceGnmDriverForNeoMode/libSceGnmDriverForNeoMode.hpp new file mode 100644 index 0000000000..ebeb3b8bad --- /dev/null +++ b/core/libs/prx/libSceGnmDriverForNeoMode/libSceGnmDriverForNeoMode.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceGnmDriverForNeoMode/include/Api.hpp" diff --git a/core/libs/prx/libSceGpuCapture/libSceGpuCapture.hpp b/core/libs/prx/libSceGpuCapture/libSceGpuCapture.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceGpuCapture/libSceGpuCapture.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceGpuTrace/libSceGpuTrace.hpp b/core/libs/prx/libSceGpuTrace/libSceGpuTrace.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceGpuTrace/libSceGpuTrace.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceGvMp4Parser/libSceGvMp4Parser.hpp b/core/libs/prx/libSceGvMp4Parser/libSceGvMp4Parser.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceGvMp4Parser/libSceGvMp4Parser.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceHand/libSceHand.hpp b/core/libs/prx/libSceHand/libSceHand.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceHand/libSceHand.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceHandTracker/libSceHandTracker.hpp b/core/libs/prx/libSceHandTracker/libSceHandTracker.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceHandTracker/libSceHandTracker.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceHdrScopes/libSceHdrScopes.hpp b/core/libs/prx/libSceHdrScopes/libSceHdrScopes.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceHdrScopes/libSceHdrScopes.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceHeadTracker/libSceHeadTracker.hpp b/core/libs/prx/libSceHeadTracker/libSceHeadTracker.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceHeadTracker/libSceHeadTracker.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceHidControl/Export.cpp b/core/libs/prx/libSceHidControl/Export.cpp index c3bfd0d3ed..bb7329027a 100644 --- a/core/libs/prx/libSceHidControl/Export.cpp +++ b/core/libs/prx/libSceHidControl/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceHidControl/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceHidControl/include/Api.hpp b/core/libs/prx/libSceHidControl/include/Api.hpp new file mode 100644 index 0000000000..ca9e12b806 --- /dev/null +++ b/core/libs/prx/libSceHidControl/include/Api.hpp @@ -0,0 +1,48 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceHidControlEnableMicBeamForming(void); +int APS5_VABI sceHidControlSetAllVibrationMute(void); +int APS5_VABI sceHidControlSetVibrationTriggerEffectWeakForce(void); +int APS5_VABI sceHidControlIsForceUpdateNeeded(void); +int APS5_VABI sceHidControlSetRemoteMergeProcess(void); +int APS5_VABI sceHidControlSetCollaboInputSettingOverrideProcess(void); +int APS5_VABI sceHidControlSetForceAdvancedVibrationMode(void); +int APS5_VABI sceHidControlPswUpdateIsUpdateNeeded(void); +int APS5_VABI sceHidControlPswUpdateIsUpdateNeededForMultiDevice(void); +int APS5_VABI sceHidControlPswUpdateIsReady(void); +int APS5_VABI sceHidControlPswUpdateStart(void); +int APS5_VABI sceHidControlPswUpdateGetStatus(void); +int APS5_VABI sceHidControlPswUpdateSendData(void); +int APS5_VABI sceHidControlPswUpdateSendAppendixData(void); +int APS5_VABI sceHidControlPswUpdateGetReconnectStatus(void); +int APS5_VABI sceHidControlPswUpdateGetDeviceFirmwareUpdateTelemetryData(void); +int APS5_VABI sceHidControlGetPswState(void); +int APS5_VABI sceHidControlGetPswBatteryState(void); +int APS5_VABI sceHidControlSetPswDeviceName(void); +int APS5_VABI sceHidControlGetPswDeviceName(void); +int APS5_VABI sceHidControlSetPswConsoleMute(void); +int APS5_VABI sceHidControlSetPswSpeakerVolume(void); +int APS5_VABI sceHidControlSetPswSidetoneLevel(void); +int APS5_VABI sceHidControlGetPswSidetoneLevel(void); +int APS5_VABI sceHidControlSetPswEqPresetSelection(void); +int APS5_VABI sceHidControlGetPswEqPresetSelection(void); +int APS5_VABI sceHidControlSetPswEqPresetName(void); +int APS5_VABI sceHidControlGetPswEqPresetName(void); +int APS5_VABI sceHidControlSetPswEqBandValues(void); +int APS5_VABI sceHidControlGetPswEqBandValues(void); +int APS5_VABI sceHidControlGetPswAllEqBandValues(void); +int APS5_VABI sceHidControlSetPswResetSettings(void); +int APS5_VABI sceHidControlSetPswNetworkLocale(void); +int APS5_VABI sceHidControlGetPswNetworkLocale(void); +int APS5_VABI sceHidControlGetPswDeviceNameForNearby(void); +int APS5_VABI sceHidControlConnectPswDeviceForNearby(void); +int APS5_VABI sceHidControlGetPswDeviceInfo(void); +int APS5_VABI sceHidControlSetPswCommand(void); +int APS5_VABI sceHidControlGetPswCommand(void); +int APS5_VABI sceHidControlGetPswDeviceIdFromIdxAdd(void); + +} diff --git a/core/libs/prx/libSceHidControl/libSceHidControl.hpp b/core/libs/prx/libSceHidControl/libSceHidControl.hpp new file mode 100644 index 0000000000..6a943525cb --- /dev/null +++ b/core/libs/prx/libSceHidControl/libSceHidControl.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceHidControl/include/Api.hpp" diff --git a/core/libs/prx/libSceHmd/Export.cpp b/core/libs/prx/libSceHmd/Export.cpp index d32073ea63..c859361ee4 100644 --- a/core/libs/prx/libSceHmd/Export.cpp +++ b/core/libs/prx/libSceHmd/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceHmd/include/Api.hpp" #include "Hmd.hpp" #include "prx/libc/include/ApplicationHeap.hpp" #include "prx/libc/include/General.hpp" @@ -8,56 +9,12 @@ #include #include -struct HmdDistortionCommandParameter; -struct HmdWideNearDistortionCommandParameter; -struct Hmd2dVrCommandParameter; - -struct HmdCommandBuffer { - const std::uint32_t* commands; - std::uint32_t dwordCount; -}; - static_assert(sizeof(HmdCommandBuffer) == 16); static_assert(offsetof(HmdCommandBuffer, dwordCount) == 8); -struct HmdReprojectionFrameParameter; -struct HmdReprojectionWideNearParameter; -struct HmdReprojection2dVrParameter; -struct HmdReprojectionPose; -struct HmdReprojectionOverlayParameter; -struct HmdReprojectionSubmissionParameter; -struct HmdReprojectionInitializeParameter; -struct HmdReprojectionMultilayerParameter; -struct HmdDeviceInformation; -struct HmdDistortionParameters; -struct HmdInertialSensorData; -struct HmdStatusReport; - -struct HmdFieldOfView { - float angles[4]; -}; - -struct HmdAssemblyError { - float offsets[4]; -}; - static_assert(sizeof(HmdFieldOfView) == 16); static_assert(sizeof(HmdAssemblyError) == 16); -struct HmdVr2dData; -struct HmdPuPositionParameter; -struct HmdOpticalParameter; -struct HmdCrashDumpInfo; -struct HmdScreenOutputParameter; -struct HmdScreenFadeParameter; -struct HmdScreenStatus; -struct HmdCaptureInitializeParameter; -struct HmdCaptureInfo; -struct HmdLiveCaptureParameter; -struct HmdReprojectionDebugInfo; -struct HmdReprojectionMultilayerDebugInfo; -struct HmdReprojectionCallbackParameter; - namespace { std::atomic initialized{false}; @@ -101,60 +58,20 @@ std::int32_t Vr2dCommandArguments(const Hmd2dVrCommandParameter* parameter, cons } -struct HmdEyeDistances { - std::uint32_t left; - std::uint32_t right; -}; - -struct HmdEyeOffset { - float x; - float y; - float z; -}; - -struct HmdMirroringAspect { - std::uint16_t reserved0; - std::int16_t aspect; - std::uint16_t reserved1; - std::uint16_t reserved2; -}; - -struct HmdMirroringAspectDebug { - std::uint16_t values[5]; - std::uint8_t mode; -}; - static_assert(sizeof(HmdMirroringAspectDebug) == 12); static_assert(offsetof(HmdMirroringAspectDebug, mode) == 10); static_assert(sizeof(HmdMirroringAspect) == 8); static_assert(offsetof(HmdMirroringAspect, aspect) == 2); -using HmdEventCallback = void (APS5_VABI *)(std::uint32_t events); - -struct HmdDfuData { - const void* data; - std::uint32_t size; - std::uint32_t mode; -}; - static_assert(sizeof(HmdDfuData) == 16); static_assert(offsetof(HmdDfuData, size) == 8); static_assert(offsetof(HmdDfuData, mode) == 12); -struct HmdScreenData { - const void* data; - std::int32_t size; -}; - static_assert(sizeof(HmdScreenData) == 16); static_assert(offsetof(HmdScreenData, size) == 8); static_assert(sizeof(HmdEyeDistances) == 8); static_assert(sizeof(HmdEyeOffset) == 12); -struct HmdLedData { - std::uint8_t values[9]; -}; - static_assert(sizeof(HmdLedData) == 9); extern "C" { diff --git a/core/libs/prx/libSceHmd/Hmd.hpp b/core/libs/prx/libSceHmd/Hmd.hpp index 22f812c774..e535975c5e 100644 --- a/core/libs/prx/libSceHmd/Hmd.hpp +++ b/core/libs/prx/libSceHmd/Hmd.hpp @@ -52,14 +52,25 @@ static_assert(offsetof(DeviceInformation, hmuMount) == 24); } -struct HmdFieldOfView; -struct HmdEyeOffset; +struct HmdFieldOfView { + float angles[4]; +}; +struct HmdEyeOffset { + float x; + float y; + float z; +}; struct HmdInertialSensorData; -struct HmdAssemblyError; +struct HmdAssemblyError { + float offsets[4]; +}; struct HmdDistortionCommandParameter; struct HmdWideNearDistortionCommandParameter; struct Hmd2dVrCommandParameter; -struct HmdCommandBuffer; +struct HmdCommandBuffer { + const std::uint32_t* commands; + std::uint32_t dwordCount; +}; extern "C" { std::int32_t APS5_VABI sceHmdInitialize(const Hmd::InitializeParam* param); diff --git a/core/libs/prx/libSceHmd/include/Api.hpp b/core/libs/prx/libSceHmd/include/Api.hpp new file mode 100644 index 0000000000..3feeb6eb93 --- /dev/null +++ b/core/libs/prx/libSceHmd/include/Api.hpp @@ -0,0 +1,232 @@ +#pragma once + +#include "SceTypes.hpp" +#include "prx/libSceHmd/Hmd.hpp" + +struct HmdCaptureInfo; + +struct HmdCaptureInitializeParameter; + +struct HmdCrashDumpInfo; + +struct HmdDeviceInformation; + +struct HmdDfuData { + const void* data; + std::uint32_t size; + std::uint32_t mode; +}; + +struct HmdDistortionParameters; + +using HmdEventCallback = void (APS5_VABI *)(std::uint32_t events); + +struct HmdEyeDistances { + std::uint32_t left; + std::uint32_t right; +}; + + + +struct HmdLedData { + std::uint8_t values[9]; +}; + +struct HmdLiveCaptureParameter; + +struct HmdMirroringAspect { + std::uint16_t reserved0; + std::int16_t aspect; + std::uint16_t reserved1; + std::uint16_t reserved2; +}; + +struct HmdMirroringAspectDebug { + std::uint16_t values[5]; + std::uint8_t mode; +}; + +struct HmdOpticalParameter; + +struct HmdPuPositionParameter; + +struct HmdReprojection2dVrParameter; + +struct HmdReprojectionCallbackParameter; + +struct HmdReprojectionDebugInfo; + +struct HmdReprojectionFrameParameter; + +struct HmdReprojectionInitializeParameter; + +struct HmdReprojectionMultilayerDebugInfo; + +struct HmdReprojectionMultilayerParameter; + +struct HmdReprojectionOverlayParameter; + +struct HmdReprojectionPose; + +struct HmdReprojectionSubmissionParameter; + +struct HmdReprojectionWideNearParameter; + +struct HmdScreenData { + const void* data; + std::int32_t size; +}; + +struct HmdScreenFadeParameter; + +struct HmdScreenOutputParameter; + +struct HmdScreenStatus; + +struct HmdStatusReport; + +struct HmdVr2dData; + +extern "C" { + +int APS5_VABI sceHmdInternalGetPUVersion(std::uint32_t* version); +int APS5_VABI sceHmdInternalEventInitialize(void); +int APS5_VABI sceHmdInternalSetVirtualDisplaySize(std::uint8_t size); +int APS5_VABI sceHmdInternalSocialScreenSetOutput(std::uint32_t output, const HmdScreenOutputParameter* parameter); +int APS5_VABI sceHmdInternalGetVirtualDisplayDepth(std::uint8_t* depth); +int APS5_VABI sceHmdInternalGetEyeStatus(std::int32_t handle, HmdEyeOffset* left, HmdEyeOffset* right); +int APS5_VABI sceHmdInternalAnotherScreenOpen(void); +int APS5_VABI sceHmdReprojectionUnsetCallback(void); +int APS5_VABI sceHmdInternalSetCrashReportCommand(std::uint8_t command); +int APS5_VABI sceHmdInternalGetDebugTextMode(std::uint8_t* mode); +int APS5_VABI sceHmdInternalRegisterEventCallback(HmdEventCallback callback); +int APS5_VABI sceHmdReprojectionStartWideNear(const HmdReprojectionWideNearParameter* parameter, const HmdReprojectionPose* pose, std::uint64_t flipArg, const void* reserved); +int APS5_VABI sceHmdInternalGetPUSerialNumber(char* serialNumber); +int APS5_VABI sceHmdInternalGetDebugSocialScreenMode(std::uint8_t* mode); +int APS5_VABI sceHmdInternalSetM2LedBrightness(std::int32_t handle, std::uint32_t ledMask, const std::uint8_t* brightness); +int APS5_VABI sceHmdInternalSetIPD(std::int32_t mode, HmdEyeDistances distances); +int APS5_VABI sceHmdInternalMirroringModeSetAspect(const HmdMirroringAspect* aspect); +int APS5_VABI sceHmdInternalDfuGetStatus(std::uint64_t* status); +int APS5_VABI sceHmdInternalAnotherScreenSendVideo(const HmdScreenData* data); +int APS5_VABI sceHmdInternalGetRequiredPUPVersion(std::uint32_t* firstVersion, std::uint32_t* secondVersion); +int APS5_VABI sceHmdReprojectionSetCallback(const HmdReprojectionCallbackParameter* parameter); +int APS5_VABI sceHmdInternalDfuCheckAfterPvt(std::uint8_t* afterPvt); +int APS5_VABI sceHmdInternalResetInertialSensor(void); +int APS5_VABI sceHmdReprojectionSetUserEventStart(std::int64_t eventQueue, std::int32_t eventId); +int APS5_VABI sceHmdDistortionSetOutputMinColor(float red, float green, float blue); +int APS5_VABI sceHmdInternalSetVirtualDisplayDepth(std::uint8_t depth); +int APS5_VABI sceHmdGetDistortionWorkMemoryAlign(void); +int APS5_VABI sceHmdReprojectionStartMultilayer(const HmdReprojectionMultilayerParameter* layers, std::uint32_t layerCount, const HmdReprojectionSubmissionParameter* submission, const HmdReprojectionPose* pose, std::uint64_t flipArg, const void* reserved); +int APS5_VABI sceHmdInternalPushVr2dData(const HmdVr2dData* data); +int APS5_VABI sceHmdReprojectionClearUserEventEnd(void); +int APS5_VABI sceHmdInternalGetIPD(HmdEyeDistances* distances); +int APS5_VABI sceHmdInternalSetVRMode(std::int32_t enabled); +int APS5_VABI sceHmdInternalCrashReportReadDataSize(std::uint32_t* dataSize); +int APS5_VABI sceHmdInternalGetVr2dData(HmdVr2dData* data); +int APS5_VABI sceHmdInternalAnotherScreenSendAudio(const HmdScreenData* data); +int APS5_VABI sceHmdInternalGetPuPositionParam(HmdPuPositionParameter* parameter); +int APS5_VABI sceHmdReprojectionInitializeCapture(const HmdCaptureInitializeParameter* parameter); +int APS5_VABI sceHmdInternalSetDebugSocialScreenMode(std::uint8_t mode); +int APS5_VABI sceHmdInternalGetHmuPowerStatusForDebug(std::uint8_t* status); +int APS5_VABI sceHmdGetDistortionWorkMemorySize(void); +int APS5_VABI sceHmdReprojectionSetDisplayBuffers(std::int32_t videoOutHandle, std::int32_t firstBufferIndex, std::int32_t secondBufferIndex, const void* reserved); +int APS5_VABI sceHmdInternalAnotherScreenSetFadeAndSwitch(const HmdScreenFadeParameter* parameter); +int APS5_VABI sceHmdInternalCreateSharedMemory(void); +int APS5_VABI sceHmdInternalMirroringModeSetAspectDebug(const HmdMirroringAspectDebug* aspect); +int APS5_VABI sceHmdInternalGetPuBuildNumber(std::uint32_t* buildNumber); +int APS5_VABI sceHmdDistortionGetCompoundEyeCorrectionCommand(void); +int APS5_VABI sceHmdInternalSetS3dPassMode(std::uint8_t mode); +int APS5_VABI sceHmdReprojectionStopCapture(HmdCaptureInfo* info); +int APS5_VABI sceHmdInternalMmapGetSensorCalibrationData(void* buffer, std::uint32_t size); +int APS5_VABI sceHmdInternalGetDebugMode(std::uint8_t* mode); +int APS5_VABI sceHmdReprojectionSetOutputMinColor(float red, float green, float blue); +int APS5_VABI sceHmdInternalSetPortConnection(std::uint64_t connection); +int APS5_VABI sceHmdReprojectionDebugGetLastInfo(HmdReprojectionDebugInfo* info); +int APS5_VABI sceHmdInternalSetM2LedOn(std::int32_t handle, std::uint32_t ledMask, std::uint32_t brightness); +int APS5_VABI sceHmdReprojectionAddDisplayBuffer(std::int32_t bufferIndex, const void* reserved); +int APS5_VABI sceHmdInternalSetIpdSettingEnableForSystemService(std::uint8_t enabled); +int APS5_VABI sceHmdInternalSetLedOn(std::int32_t handle, std::uint32_t ledMask); +int APS5_VABI sceHmdInternal3dAudioSendData(std::int32_t port, const void* data, std::int32_t size); +int APS5_VABI sceHmdReprojectionInitialize(const HmdReprojectionInitializeParameter* parameter, std::uint32_t mode, const void* reserved); +int APS5_VABI sceHmdInternalGetDeviceInformationByHandle(std::int32_t handle, HmdDeviceInformation* information); +int APS5_VABI sceHmdReprojectionStopLiveCapture(void); +int APS5_VABI sceHmdInternalAnotherScreenClose(void); +int APS5_VABI sceHmdInternalCrashReportReadData(void* buffer, std::uint32_t* bytesRead, std::uint32_t bufferSize); +int APS5_VABI sceHmdInternalGetDeviceInformation(HmdDeviceInformation* information); +int APS5_VABI sceHmdReprojectionStartCapture(void); +int APS5_VABI sceHmdInternalGetDefaultLedData(std::int32_t handle, std::uint32_t* mask, HmdLedData* data); +int APS5_VABI sceHmdInternalDfuClose(void); +int APS5_VABI sceHmdInternalSetHmuPowerControl(std::uint8_t control); +int APS5_VABI sceHmdInternalBindDeviceWithUserId(std::int32_t handle, std::int32_t userId); +int APS5_VABI sceHmdInternalGetHmuSerialNumber(std::uint8_t* serialNumber); +int APS5_VABI sceHmdInternalCheckS3dPassModeAvailable(bool* available); +int APS5_VABI sceHmdInternalAnotherScreenGetAudioStatus(HmdScreenStatus* status); +int APS5_VABI sceHmdInternalSeparateModeGetAudioStatus(HmdScreenStatus* status); +int APS5_VABI sceHmdReprojectionStartLiveCapture(const HmdLiveCaptureParameter* parameter); +int APS5_VABI sceHmdReprojectionFinalize(void); +int APS5_VABI sceHmdInternalSocialScreenSetFadeAndSwitch(const HmdScreenFadeParameter* parameter); +int APS5_VABI sceHmdInternalDfuStart(void); +int APS5_VABI sceHmdInternalSetVirtualDisplayHeight(std::uint8_t height); +int APS5_VABI sceHmdDistortionInitialize(void* workMemory); +int APS5_VABI sceHmdInternalDfuSetMode(std::uint32_t mode); +int APS5_VABI sceHmdInternalSetForcedCrash(std::uint8_t mode); +int APS5_VABI sceHmdInternalDfuCheckPartialUpdateAvailable(bool* available); +int APS5_VABI sceHmdInternalSeparateModeClose(void); +int APS5_VABI sceHmdInternalSetDebugTextMode(std::uint8_t mode); +int APS5_VABI sceHmdInternalCrashReportClose(void); +int APS5_VABI sceHmdInternalSetHmuPowerControlForDebug(std::uint8_t control); +int APS5_VABI sceHmdInternalGetVirtualDisplayHeight(std::uint8_t* height); +int APS5_VABI sceHmdReprojectionStart(const HmdReprojectionFrameParameter* parameter, const HmdReprojectionPose* pose, std::uint64_t flipArg, const void* reserved); +int APS5_VABI sceHmdInternalResetLedForVsh(void); +int APS5_VABI sceHmdInternalDfuOpen(void); +int APS5_VABI sceHmdInternalSetDebugMode(std::uint8_t mode); +int APS5_VABI sceHmdInternalCrashReportCancel(void); +int APS5_VABI sceHmdInternalSeparateModeGetVideoStatus(HmdScreenStatus* status); +int APS5_VABI sceHmdInternalCheckDeviceModelMk3(bool* isMk3); +int APS5_VABI sceHmdSetVr2dEnable(std::int32_t enabled); +int APS5_VABI sceHmdInternalSetSidetone(std::uint8_t level); +int APS5_VABI sceHmdInternalSeparateModeOpen(void); +int APS5_VABI sceHmdInternalMmapGetModeId(std::uint32_t* modeId); +int APS5_VABI sceHmdInternalDfuSendSize(std::int32_t size); +int APS5_VABI sceHmdReprojectionStartMultilayer2(const HmdReprojectionMultilayerParameter* layers, std::uint32_t layerCount, const HmdReprojectionSubmissionParameter* submission, std::uint64_t flipArg, const void* reserved); +int APS5_VABI sceHmdInternalSetDeviceConnection(std::uint64_t connection); +int APS5_VABI sceHmdInternalGetVirtualDisplaySize(std::uint8_t* size); +int APS5_VABI sceHmdReprojectionUnsetDisplayBuffers(void); +int APS5_VABI sceHmdInternalGetHmuOpticalParam(HmdOpticalParameter* parameter); +int APS5_VABI sceHmdInternalSeparateModeSendVideo(const HmdScreenData* data); +int APS5_VABI sceHmdInternalResetLedForVrTracker(void); +int APS5_VABI sceHmdReprojectionStartWithOverlay(const HmdReprojectionFrameParameter* parameter, const HmdReprojectionPose* pose, std::uint64_t flipArg, const HmdReprojectionOverlayParameter* overlay, const void* reserved); +int APS5_VABI sceHmdReprojectionSetUserEventEnd(std::int64_t eventQueue, std::int32_t eventId); +int APS5_VABI sceHmdInternalCrashReportOpen(void); +int APS5_VABI sceHmdInternalSetDemoMode(std::uint8_t mode); +int APS5_VABI sceHmdReprojectionStartWideNearWithOverlay(const HmdReprojectionWideNearParameter* parameter, const HmdReprojectionPose* pose, std::uint64_t flipArg, const HmdReprojectionOverlayParameter* overlay, const void* reserved); +int APS5_VABI sceHmdGetDistortionParams(HmdDistortionParameters* parameters); +int APS5_VABI sceHmdInternalDfuSend(const HmdDfuData* data); +int APS5_VABI sceHmdReprojectionClearUserEventStart(void); +int APS5_VABI sceHmdInternalSetUserType(std::uint8_t userType); +int APS5_VABI sceHmdInternalGetDemoMode(std::uint8_t* mode); +int APS5_VABI sceHmdInternalMapSharedMemory(void); +int APS5_VABI sceHmdInternalGetCrashDumpInfo(HmdCrashDumpInfo* info); +int APS5_VABI sceHmdInternalGetTv4kCapability(std::uint8_t* capability); +int APS5_VABI sceHmdInternalDfuReset(void); +int APS5_VABI sceHmdReprojectionStart2dVr(const HmdReprojection2dVrParameter* parameter, std::uint64_t flipArg, const void* reserved); +int APS5_VABI sceHmdInternalMmapGetCount(void); +int APS5_VABI sceHmdInternalSetDefaultLedData(std::int32_t handle, std::uint32_t mask, const HmdLedData* data); +int APS5_VABI sceHmdInternal3dAudioClose(std::int32_t port); +int APS5_VABI sceHmdInternalSetBrightness(std::uint8_t brightness); +int APS5_VABI sceHmdInternalSocialScreenGetFadeState(std::int32_t* state); +int APS5_VABI sceHmdInternalSeparateModeSendAudio(const HmdScreenData* data); +int APS5_VABI sceHmdInternalGetStatusReport(std::int32_t handle, HmdStatusReport* report); +int APS5_VABI sceHmdInternalGetBrightness(std::uint8_t* brightness); +int APS5_VABI sceHmdReprojectionFinalizeCapture(void); +int APS5_VABI sceHmdInternalSetPortStatus(std::uint64_t status); +int APS5_VABI sceHmdReprojectionStop(void); +int APS5_VABI sceHmdInternalAnotherScreenGetVideoStatus(HmdScreenStatus* status); +int APS5_VABI sceHmdInternal3dAudioOpen(std::int32_t port); +int APS5_VABI sceHmdInternalAnotherScreenGetFadeState(std::int32_t* state); +int APS5_VABI sceHmdInternalSetDebugGpo(std::uint32_t value); +int APS5_VABI sceHmdInternalGetIpdSettingEnableForSystemService(std::uint8_t* enabled); +int APS5_VABI sceHmdReprojectionDebugGetLastInfoMultilayer(HmdReprojectionMultilayerDebugInfo* info); +int APS5_VABI sceHmdInternalGetPuRevision(std::uint32_t* revision); + +} diff --git a/core/libs/prx/libSceHmd/libSceHmd.hpp b/core/libs/prx/libSceHmd/libSceHmd.hpp new file mode 100644 index 0000000000..fb3f263602 --- /dev/null +++ b/core/libs/prx/libSceHmd/libSceHmd.hpp @@ -0,0 +1,4 @@ +#pragma once + +#include "prx/libSceHmd/Hmd.hpp" +#include "prx/libSceHmd/include/Api.hpp" diff --git a/core/libs/prx/libSceHmd2/Export.cpp b/core/libs/prx/libSceHmd2/Export.cpp index d744bf2741..82c55782b7 100644 --- a/core/libs/prx/libSceHmd2/Export.cpp +++ b/core/libs/prx/libSceHmd2/Export.cpp @@ -1,3 +1,5 @@ +#include "prx/libSceHmd2/include/Api.hpp" +#include "prx/libSceHmd2/Hmd2.hpp" #include "Hmd2.hpp" #include "prx/libc/include/general/ExportMacros.hpp" #include "prx/libc/include/ApplicationHeap.hpp" @@ -13,25 +15,6 @@ namespace Hmd2 { -struct ReprojectionStatus; -struct ReprojectionOutput { - std::uint32_t textureDescriptor[8]; -}; - -struct ReprojectionInitializeParameter { - void* workMemory; - void* displayMemory; - std::int32_t threadPriority; - std::uint32_t threadAffinity; - std::uint32_t queueParameter24; - std::uint32_t queueParameter28; - std::uint32_t renderingMode; - std::uint32_t reserved36; - void* auxiliaryMemory; - std::uint32_t timingInterval; - std::uint32_t reserved52[5]; -}; - static_assert(sizeof(ReprojectionOutput) == 32); static_assert(sizeof(ReprojectionInitializeParameter) == 72); static_assert(offsetof(ReprojectionInitializeParameter, threadPriority) == 16); @@ -39,28 +22,6 @@ static_assert(offsetof(ReprojectionInitializeParameter, threadAffinity) == 20); static_assert(offsetof(ReprojectionInitializeParameter, renderingMode) == 32); static_assert(offsetof(ReprojectionInitializeParameter, auxiliaryMemory) == 40); static_assert(offsetof(ReprojectionInitializeParameter, timingInterval) == 48); -struct ReprojectionLayer; -struct ReprojectionBufferedLayer; - -struct ReprojectionOption { - std::uint32_t size; - std::uint32_t flags; - std::uint32_t reserved[30]; -}; - -struct ReprojectionParameter { - const ReprojectionLayer* layers; - std::int32_t layerCount; - std::uint8_t padding[4]; - const ReprojectionOption* option; -}; - -struct ReprojectionBufferedParameter { - const ReprojectionBufferedLayer* layers; - std::int32_t layerCount; - std::uint8_t padding[4]; - const ReprojectionOption* option; -}; static_assert(sizeof(ReprojectionOption) == 128); static_assert(sizeof(ReprojectionParameter) == 24); @@ -68,88 +29,12 @@ static_assert(sizeof(ReprojectionBufferedParameter) == 24); static_assert(offsetof(ReprojectionParameter, option) == 16); static_assert(offsetof(ReprojectionBufferedParameter, option) == 16); - -struct MirroringParameter { - void* workMemory; - void* displayMemory; -}; - -struct MirroringOption { - std::uint32_t mode; - std::uint32_t reserved[7]; -}; - static_assert(sizeof(MirroringParameter) == 16); static_assert(sizeof(MirroringOption) == 32); -struct GazeResultParameter { - std::uint32_t size; - std::int32_t handle; - std::uint8_t reserved[8]; -}; -struct GazeResult; -struct FoveatedRenderingResult { - std::uint32_t size; - std::int32_t status; - float direction[3]; - std::uint8_t reserved[4]; -}; - static_assert(sizeof(GazeResultParameter) == 16); static_assert(sizeof(FoveatedRenderingResult) == 24); static_assert(offsetof(FoveatedRenderingResult, direction) == 8); -struct GazeCalibrationData { - void* data; - std::int32_t size; -}; -struct GazeUserCalibrationData { - const void* data; - std::int32_t size; -}; -struct GazeUserCalibrationStatus { - std::int32_t status; - std::int32_t eye; - float point[3]; -}; -struct GazeRawData; -struct GazeObjectSelectionTransform { - float values[16]; -}; - -struct GazeObjectSelectionObject { - std::uint64_t id; - std::uint32_t enabled; - std::uint32_t reserved12; - GazeObjectSelectionTransform transform; - const GazeObjectSelectionTransform* boundingBoxes; - std::uint32_t boundingBoxCount; - std::uint32_t reserved92; -}; - -struct GazeObjectSelectionParameter { - std::uint32_t size; - std::uint32_t reserved4; - std::uint64_t reserved8; - std::uint64_t gazeTimestamp; - GazeObjectSelectionTransform transform; - std::uint32_t selectionMode; - std::uint32_t filterMode; - std::uint64_t timestamp; - const GazeObjectSelectionObject* objects; - std::uint32_t objectCount; - std::uint32_t reserved116; -}; - -struct GazeObjectSelectionResult { - std::uint32_t size; - std::uint32_t selected; - std::uint64_t objectId; - std::uint64_t gazeTimestamp; - std::uint32_t gazeValid; - float origin[3]; - float direction[3]; - float distance; -}; static_assert(sizeof(GazeObjectSelectionTransform) == 64); static_assert(sizeof(GazeObjectSelectionObject) == 96); @@ -168,28 +53,6 @@ static_assert(offsetof(GazeObjectSelectionResult, gazeTimestamp) == 16); static_assert(offsetof(GazeObjectSelectionResult, origin) == 28); static_assert(offsetof(GazeObjectSelectionResult, direction) == 40); static_assert(offsetof(GazeObjectSelectionResult, distance) == 52); -struct GazeObjectSelectionInitializeParameter { - std::uint32_t size; - std::uint32_t maxObjects; - void* memory; - std::uint32_t memorySize; - std::uint32_t reserved; -}; -struct GazeObjectSelectionMemoryParameter { - std::uint32_t size; - std::uint32_t maxObjects; -}; -struct GazeObjectSelectionMemoryInfo { - std::uint32_t size; - std::uint32_t memorySize; - std::uint64_t alignment; -}; - -struct CalibrationPoint { - float x; - float y; - float z; -}; static_assert(sizeof(CalibrationPoint) == 12); static_assert(sizeof(GazeCalibrationData) == 16); @@ -497,7 +360,6 @@ int APS5_VABI sceHmd2RpeorjectionSetParam() { return 0; } - std::int32_t APS5_VABI Hmd2BeforeInitializeZero() { return BeforeInitialize(0, __func__); } @@ -520,10 +382,6 @@ int APS5_VABI sceHmd2SetIpdOffset(std::uint8_t enabled, float offset) { } APS5_EXPORT("-kZT7X7OMg0", Hmd2BeforeInitializeZero); APS5_EXPORT("1ewLtng-SVk", Hmd2BeforeInitializeZero); -APS5_EXPORT("B0b8DeIUGes", Hmd2BeforeInitializeZero); -APS5_EXPORT("HclLg4Oj5yw", Hmd2BeforeInitializeZero); -APS5_EXPORT("VbEvrQXsZyY", Hmd2BeforeInitializeZero); -APS5_EXPORT("bB6MKZi5UCQ", Hmd2BeforeInitializeZero); APS5_EXPORT("OXQ1EDf02XU", Hmd2BeforeInitializeZero); APS5_EXPORT("IAxfMTvFm0M", Hmd2BeforeInitializeZero); APS5_EXPORT("qTJtAtaLeno", Hmd2BeforeInitializeZero); @@ -680,10 +538,6 @@ std::int32_t APS5_VABI Hmd2BeforeInitializeMinusOne() { } APS5_EXPORT("EAkv8Mqt33E", Hmd2BeforeInitializeMinusOne); APS5_EXPORT("Rv7bkmKvmz0", Hmd2BeforeInitializeMinusOne); -APS5_EXPORT("1oPZizn0SNA", Hmd2BeforeInitializeMinusOne); -APS5_EXPORT("TwCpE-nNrlo", Hmd2BeforeInitializeMinusOne); -APS5_EXPORT("jkqAeQfdtxw", Hmd2BeforeInitializeMinusOne); -APS5_EXPORT("+l0RQph81Z8", Hmd2BeforeInitializeMinusOne); APS5_EXPORT("qsmAtGw1Ncc", Hmd2BeforeInitializeMinusOne); APS5_EXPORT("uKhwYoMsIsA", Hmd2BeforeInitializeMinusOne); APS5_EXPORT("WNdaigr94dI", Hmd2BeforeInitializeMinusOne); @@ -691,6 +545,38 @@ APS5_EXPORT("P6S5ZVWf-H0", Hmd2BeforeInitializeMinusOne); APS5_EXPORT("sun6NWE1sdg", Hmd2BeforeInitializeMinusOne); APS5_EXPORT("--TFsJYXo04", Hmd2BeforeInitializeMinusOne); +std::int32_t APS5_VABI sceHmd2InternalTrackingOpen() { + return BeforeInitialize(0, __func__); +} + +std::int32_t APS5_VABI sceHmd2InternalTrackingClose() { + return BeforeInitialize(0, __func__); +} + +std::int32_t APS5_VABI sceHmd2InternalLedDetectorOpen() { + return BeforeInitialize(0, __func__); +} + +std::int32_t APS5_VABI sceHmd2InternalLedDetectorClose() { + return BeforeInitialize(0, __func__); +} + +std::int32_t APS5_VABI sceHmd2InternalTrackingStart() { + return BeforeInitialize(-1, __func__); +} + +std::int32_t APS5_VABI sceHmd2InternalTrackingStop() { + return BeforeInitialize(-1, __func__); +} + +std::int32_t APS5_VABI sceHmd2InternalLedDetectorStart() { + return BeforeInitialize(-1, __func__); +} + +std::int32_t APS5_VABI sceHmd2InternalLedDetectorStop() { + return BeforeInitialize(-1, __func__); +} + std::int32_t APS5_VABI Hmd2BeforeInitializeValue0400() { return BeforeInitialize(0x400, __func__); } @@ -989,7 +875,6 @@ std::int32_t APS5_VABI Hmd2CheckSecondThenError1002(const void* a0, const void* } APS5_EXPORT("W-ZIlUXcrNA", Hmd2CheckSecondThenError1002); - std::int32_t APS5_VABI Hmd2WriteStateTwo(void* a0) { if (a0 == nullptr) return Hmd2::ParameterNull; static constexpr std::uint8_t bytes[] = {0x02, 0x00, 0x00, 0x00, 0x00}; diff --git a/core/libs/prx/libSceHmd2/include/Api.hpp b/core/libs/prx/libSceHmd2/include/Api.hpp new file mode 100644 index 0000000000..141cd26128 --- /dev/null +++ b/core/libs/prx/libSceHmd2/include/Api.hpp @@ -0,0 +1,384 @@ +#pragma once + +#include "prx/libSceHmd2/Hmd2.hpp" +#include "SceTypes.hpp" +#include +#include +#include +#include + +namespace Hmd2 { + +struct ReprojectionStatus; + +} + +namespace Hmd2 { + +struct ReprojectionOutput { + std::uint32_t textureDescriptor[8]; +}; + +} + +namespace Hmd2 { + +struct ReprojectionInitializeParameter { + void* workMemory; + void* displayMemory; + std::int32_t threadPriority; + std::uint32_t threadAffinity; + std::uint32_t queueParameter24; + std::uint32_t queueParameter28; + std::uint32_t renderingMode; + std::uint32_t reserved36; + void* auxiliaryMemory; + std::uint32_t timingInterval; + std::uint32_t reserved52[5]; +}; + +} + +namespace Hmd2 { + +struct ReprojectionLayer; + +} + +namespace Hmd2 { + +struct ReprojectionBufferedLayer; + +} + +namespace Hmd2 { + +struct ReprojectionOption { + std::uint32_t size; + std::uint32_t flags; + std::uint32_t reserved[30]; +}; + +} + +namespace Hmd2 { + +struct ReprojectionParameter { + const ReprojectionLayer* layers; + std::int32_t layerCount; + std::uint8_t padding[4]; + const ReprojectionOption* option; +}; + +} + +namespace Hmd2 { + +struct ReprojectionBufferedParameter { + const ReprojectionBufferedLayer* layers; + std::int32_t layerCount; + std::uint8_t padding[4]; + const ReprojectionOption* option; +}; + +} + +namespace Hmd2 { + +struct MirroringParameter { + void* workMemory; + void* displayMemory; +}; + +} + +namespace Hmd2 { + +struct MirroringOption { + std::uint32_t mode; + std::uint32_t reserved[7]; +}; + +} + +namespace Hmd2 { + +struct GazeResultParameter { + std::uint32_t size; + std::int32_t handle; + std::uint8_t reserved[8]; +}; + +} + +namespace Hmd2 { + +struct GazeResult; + +} + +namespace Hmd2 { + +struct FoveatedRenderingResult { + std::uint32_t size; + std::int32_t status; + float direction[3]; + std::uint8_t reserved[4]; +}; + +} + +namespace Hmd2 { + +struct GazeCalibrationData { + void* data; + std::int32_t size; +}; + +} + +namespace Hmd2 { + +struct GazeUserCalibrationData { + const void* data; + std::int32_t size; +}; + +} + +namespace Hmd2 { + +struct GazeUserCalibrationStatus { + std::int32_t status; + std::int32_t eye; + float point[3]; +}; + +} + +namespace Hmd2 { + +struct GazeRawData; + +} + +namespace Hmd2 { + +struct GazeObjectSelectionTransform { + float values[16]; +}; + +} + +namespace Hmd2 { + +struct GazeObjectSelectionObject { + std::uint64_t id; + std::uint32_t enabled; + std::uint32_t reserved12; + GazeObjectSelectionTransform transform; + const GazeObjectSelectionTransform* boundingBoxes; + std::uint32_t boundingBoxCount; + std::uint32_t reserved92; +}; + +} + +namespace Hmd2 { + +struct GazeObjectSelectionParameter { + std::uint32_t size; + std::uint32_t reserved4; + std::uint64_t reserved8; + std::uint64_t gazeTimestamp; + GazeObjectSelectionTransform transform; + std::uint32_t selectionMode; + std::uint32_t filterMode; + std::uint64_t timestamp; + const GazeObjectSelectionObject* objects; + std::uint32_t objectCount; + std::uint32_t reserved116; +}; + +} + +namespace Hmd2 { + +struct GazeObjectSelectionResult { + std::uint32_t size; + std::uint32_t selected; + std::uint64_t objectId; + std::uint64_t gazeTimestamp; + std::uint32_t gazeValid; + float origin[3]; + float direction[3]; + float distance; +}; + +} + +namespace Hmd2 { + +struct GazeObjectSelectionInitializeParameter { + std::uint32_t size; + std::uint32_t maxObjects; + void* memory; + std::uint32_t memorySize; + std::uint32_t reserved; +}; + +} + +namespace Hmd2 { + +struct GazeObjectSelectionMemoryParameter { + std::uint32_t size; + std::uint32_t maxObjects; +}; + +} + +namespace Hmd2 { + +struct GazeObjectSelectionMemoryInfo { + std::uint32_t size; + std::uint32_t memorySize; + std::uint64_t alignment; +}; + +} + +namespace Hmd2 { + +struct CalibrationPoint { + float x; + float y; + float z; +}; + +} + +extern "C" { + +int APS5_VABI sceHmd2ReprojectionGetStatus(Hmd2::ReprojectionStatus* status); +int APS5_VABI sceHmd2GazeGetResult(const Hmd2::GazeResultParameter* param, Hmd2::GazeResult* result); +int APS5_VABI sceHmd2GazeGetResultForFoveatedRendering(const Hmd2::GazeResultParameter* param, Hmd2::FoveatedRenderingResult* result); +int APS5_VABI sceHmd2ReprojectionBeginFrame(std::uint64_t frameId); +int APS5_VABI sceHmd2ReprojectionDisableMirroring(); +int APS5_VABI sceHmd2ReprojectionDisableVrMode(); +int APS5_VABI sceHmd2ReprojectionEnableMirroring(const Hmd2::MirroringParameter* parameter); +int APS5_VABI sceHmd2ReprojectionEnableVrMode(std::uint64_t mode); +int APS5_VABI sceHmd2ReprojectionGetPredictedDisplayTime(std::uint64_t frameId, std::uint64_t* time); +int APS5_VABI sceHmd2ReprojectionInitialize(const Hmd2::ReprojectionInitializeParameter* parameter, const void* reserved); +int APS5_VABI sceHmd2ReprojectionSetAllowPositionalReprojection(std::uint8_t mode); +int APS5_VABI sceHmd2ReprojectionSetMirroringOption(const Hmd2::MirroringOption* option); +int APS5_VABI sceHmd2ReprojectionSetParam(std::uint32_t bufferSetId, std::uint64_t frameId, const Hmd2::ReprojectionParameter* parameter, std::uint64_t reserved); +int APS5_VABI sceHmd2ReprojectionSetParamWithBuffer(std::uint32_t bufferSetId, std::uint64_t frameId, const Hmd2::ReprojectionBufferedParameter* parameter, std::uint64_t reserved); +int APS5_VABI sceHmd2ReprojectionSetRenderConfig(std::uint64_t flags, std::uint64_t reserved, std::uint64_t reserved2); +int APS5_VABI sceHmd2ReprojectionSetTiming(std::int32_t timing); +int APS5_VABI sceHmd2ReprojectionTerminate(); +int APS5_VABI sceHmd2ReprojectionSeeThroughDraw(); +int APS5_VABI sceHmd2ReprojectionSeeThroughIC(); +int APS5_VABI sceHmd2ReprojectionVideoOutEq(); +int APS5_VABI sceHmd2ReprojectionWaitShader(); +int APS5_VABI sceHmd2SeeThroughCallbackGetPoseDataFunc(); +int APS5_VABI sceHmd2ReprojectionClear(); +int APS5_VABI sceHmd2ReprojectionSet(); +int APS5_VABI sceHmd2ReprojectionSetEventGpuEnd(KernelEqueue queue, std::int32_t eventId); +int APS5_VABI sceHmd2ReprojectionSetEventGpuStart(KernelEqueue queue, std::int32_t eventId); +int APS5_VABI sceHmd2RpeorjectionSetParam(); +std::int32_t APS5_VABI Hmd2BeforeInitializeZero(); +int APS5_VABI sceHmd2SetIpdOffset(std::uint8_t enabled, float offset); +int APS5_VABI sceHmd2GazeActivateGazeTracking(std::int32_t mode); +std::int32_t APS5_VABI Hmd2BeforeInitializeNotInitialized(); +std::int32_t APS5_VABI Hmd2BeforeInitializeError0004(); +int APS5_VABI sceHmd2GazeStartUserCalibration(); +int APS5_VABI sceHmd2GazeStopUserCalibration(); +int APS5_VABI sceHmd2GazeSetUserCalibrationPoint(Hmd2::CalibrationPoint point); +int APS5_VABI sceHmd2GazeSetEnabledEye(std::int32_t eye); +std::int32_t APS5_VABI Hmd2BeforeInitializeParameterNull(); +int APS5_VABI sceHmd2GazeGetCalibrationData(std::int32_t type, Hmd2::GazeCalibrationData* data); +int APS5_VABI sceHmd2GazeSetUserCalibrationData(const Hmd2::GazeUserCalibrationData* data); +int APS5_VABI sceHmd2GazeObjectSelectionInitialize(const Hmd2::GazeObjectSelectionInitializeParameter* parameter); +std::int32_t APS5_VABI Hmd2BeforeInitializeParameterInvalid(); +std::int32_t APS5_VABI Hmd2BeforeInitializeReprojectionNotInitialized(); +int APS5_VABI sceHmd2ReprojectionSetUserEventStart(KernelEqueue queue, std::int32_t eventId); +int APS5_VABI sceHmd2ReprojectionSetUserEventEnd(KernelEqueue queue, std::int32_t eventId); +int APS5_VABI sceHmd2ReprojectionClearUserEventStart(); +int APS5_VABI sceHmd2ReprojectionClearUserEventEnd(); +int APS5_VABI sceHmd2ReprojectionGetCurrentOutput(Hmd2::ReprojectionOutput* output); +std::int32_t APS5_VABI Hmd2BeforeInitializeError002C(); +int APS5_VABI sceHmd2GazeObjectSelectionTerminate(); +std::int32_t APS5_VABI Hmd2BeforeInitializeError1002(); +std::int32_t APS5_VABI Hmd2BeforeInitializeError1003(); +std::int32_t APS5_VABI Hmd2BeforeInitializeMinusOne(); +std::int32_t APS5_VABI Hmd2BeforeInitializeValue0400(); +std::int32_t APS5_VABI Hmd2BeforeInitializeValue20000(); +std::int32_t APS5_VABI sceHmd2InternalTrackingOpen(); +std::int32_t APS5_VABI sceHmd2InternalTrackingStart(); +std::int32_t APS5_VABI sceHmd2InternalTrackingStop(); +std::int32_t APS5_VABI sceHmd2InternalTrackingClose(); +std::int32_t APS5_VABI sceHmd2InternalLedDetectorOpen(); +std::int32_t APS5_VABI sceHmd2InternalLedDetectorStart(); +std::int32_t APS5_VABI sceHmd2InternalLedDetectorStop(); +std::int32_t APS5_VABI sceHmd2InternalLedDetectorClose(); +int APS5_VABI sceHmd2InternalSetPortStatus(void); +int APS5_VABI sceHmd2InternalLedDetectorStartBySlot(void); +int APS5_VABI sceHmd2InternalImageStartBySlot(void); +int APS5_VABI sceHmd2InternalSetPortConnection(void); +int APS5_VABI sceHmd2InternalSetCameraSeeThroughMode(void); +int APS5_VABI sceHmd2InternalSetFakeLensSeparationDistance(void); +int APS5_VABI sceHmd2InternalDfuSend(void); +int APS5_VABI sceHmd2InternalLedDetectorOpenBySlot(void); +int APS5_VABI sceHmd2InternalImageOpenBySlot(void); +int APS5_VABI sceHmd2InternalLedDetectorStopBySlot(void); +int APS5_VABI sceHmd2InternalSetDeviceConnection(void); +int APS5_VABI sceHmd2InternalLedDetectorCloseBySlot(void); +int APS5_VABI sceHmd2InternalSetSidetone(void); +int APS5_VABI sceHmd2InternalGetDeviceId(void); +int APS5_VABI sceHmd2InternalSetBrightness(void); +int APS5_VABI sceHmd2InternalImageStopBySlot(void); +int APS5_VABI sceHmd2InternalSetVibrationMode(void); +int APS5_VABI sceHmd2InternalGetVr2dData(void); +int APS5_VABI sceHmd2InternalImageCloseBySlot(void); +std::int32_t APS5_VABI Hmd2CheckFirstThenError0004(const void* a0); +int APS5_VABI sceHmd2GazeGetDeviceStatus(std::int32_t* status); +int APS5_VABI sceHmd2GazeGetUserCalibrationStatus(Hmd2::GazeUserCalibrationStatus* status); +std::int32_t APS5_VABI Hmd2CheckFirstThenZero(const void* a0); +int APS5_VABI sceHmd2SetFieldOfView(const Hmd2::FieldOfView* fieldOfView); +std::int32_t APS5_VABI Hmd2CheckFirstThenError1002(const void* a0); +std::int32_t APS5_VABI Hmd2CheckFirstThenMinusOne(const void* a0); +std::int32_t APS5_VABI Hmd2CheckFirstTwoThenParameterInvalid(const void* a0, const void* a1); +int APS5_VABI sceHmd2GazeObjectSelectionQueryMemory(const Hmd2::GazeObjectSelectionMemoryParameter* parameter, Hmd2::GazeObjectSelectionMemoryInfo* info); +int APS5_VABI sceHmd2GazeObjectSelectionGetSelectedObject(const Hmd2::GazeObjectSelectionParameter* parameter, Hmd2::GazeObjectSelectionResult* result); +std::int32_t APS5_VABI Hmd2CheckSecondThenError002C(const void* a0, const void* a1); +std::int32_t APS5_VABI Hmd2CheckFirstThenParameterInvalid(const void* a0); +std::int32_t APS5_VABI Hmd2CheckAllSixThenZero(const void* a0, const void* a1, const void* a2, const void* a3, const void* a4, const void* a5); +std::int32_t APS5_VABI Hmd2CheckSecondThenParameterInvalid(const void* a0, const void* a1); +int APS5_VABI sceHmd2GazeGetCalibrationDataMaxSize(std::int32_t type, std::uint32_t* size); +std::int32_t APS5_VABI Hmd2CheckFirstThenError800d0203(const void* a0); +std::int32_t APS5_VABI Hmd2CheckFirstThenError1003(const void* a0); +std::int32_t APS5_VABI Hmd2CheckFirstThenError1010(const void* a0); +std::int32_t APS5_VABI Hmd2CheckFirstTwoThenError1002(const void* a0, const void* a1); +std::int32_t APS5_VABI Hmd2CheckFirstTwoThenError1003(const void* a0, const void* a1); +std::int32_t APS5_VABI Hmd2CheckFirstAndThirdThenZero(const void* a0, const void* a1, const void* a2); +std::int32_t APS5_VABI Hmd2CheckFirstAndThirdThenError1003(const void* a0, const void* a1, const void* a2); +std::int32_t APS5_VABI Hmd2CheckSecondThenInvalidHandle(const void* a0, const void* a1); +int APS5_VABI sceHmd2GazeInsertRawDataWithHandle(std::int32_t handle, Hmd2::GazeRawData* data); +std::int32_t APS5_VABI Hmd2CheckSecondThenError1002(const void* a0, const void* a1); +std::int32_t APS5_VABI Hmd2WriteStateTwo(void* a0); +std::int32_t APS5_VABI Hmd2WriteSize0x2000Align0x100(std::uint64_t* a0, std::uint64_t* a1); +std::int32_t APS5_VABI Hmd2WriteFourConstants(void* a0); +std::int32_t APS5_VABI Hmd2WriteSixHalvesThenInvalidHandle(std::uint64_t a0, void* a1); +std::int32_t APS5_VABI Hmd2WriteTwelveHalvesThenInvalidHandle(std::uint64_t a0, void* a1); +std::int32_t APS5_VABI Hmd2SlotUpTo3CheckSecondThirdThenZero(std::uint64_t a0, const void* a1, const void* a2); +std::int32_t APS5_VABI Hmd2SlotUpTo1ThenError1002(std::uint64_t a0); +std::int32_t APS5_VABI Hmd2SlotUpTo1CheckSecondThenError1002(std::uint64_t a0, const void* a1); +std::int32_t APS5_VABI Hmd2SlotUpTo1ThenMinusOne(std::uint64_t a0); +std::int32_t APS5_VABI Hmd2SlotUpTo2ThenMinusOne(std::uint64_t a0); +std::int32_t APS5_VABI Hmd2SlotUpTo2ThenError1002(std::uint64_t a0); +std::int32_t APS5_VABI Hmd2SlotUpTo2ThenError1003(std::uint64_t a0); +std::int32_t APS5_VABI Hmd2SlotUpTo2CheckSecondThenError002C(std::uint64_t a0, const void* a1); +std::int32_t APS5_VABI Hmd2IndexZeroCheckSecondThenZero(std::uint64_t a0, const void* a1); + +} diff --git a/core/libs/prx/libSceHmd2/libSceHmd2.hpp b/core/libs/prx/libSceHmd2/libSceHmd2.hpp new file mode 100644 index 0000000000..0c3f869cc7 --- /dev/null +++ b/core/libs/prx/libSceHmd2/libSceHmd2.hpp @@ -0,0 +1,4 @@ +#pragma once + +#include "prx/libSceHmd2/Hmd2.hpp" +#include "prx/libSceHmd2/include/Api.hpp" diff --git a/core/libs/prx/libSceHmdSetupDialog/Export.cpp b/core/libs/prx/libSceHmdSetupDialog/Export.cpp index 571643bf02..156643bf24 100644 --- a/core/libs/prx/libSceHmdSetupDialog/Export.cpp +++ b/core/libs/prx/libSceHmdSetupDialog/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceHmdSetupDialog/include/Api.hpp" #include #include #include diff --git a/core/libs/prx/libSceHmdSetupDialog/include/Api.hpp b/core/libs/prx/libSceHmdSetupDialog/include/Api.hpp new file mode 100644 index 0000000000..abe27b70aa --- /dev/null +++ b/core/libs/prx/libSceHmdSetupDialog/include/Api.hpp @@ -0,0 +1,15 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceHmdSetupDialogInitialize(void); +int APS5_VABI sceHmdSetupDialogOpen(const void* param); +int APS5_VABI sceHmdSetupDialogUpdateStatus(void); +int APS5_VABI sceHmdSetupDialogGetStatus(void); +int APS5_VABI sceHmdSetupDialogGetResult(void* result); +int APS5_VABI sceHmdSetupDialogClose(void); +int APS5_VABI sceHmdSetupDialogTerminate(void); + +} diff --git a/core/libs/prx/libSceHmdSetupDialog/libSceHmdSetupDialog.hpp b/core/libs/prx/libSceHmdSetupDialog/libSceHmdSetupDialog.hpp new file mode 100644 index 0000000000..4b5986bfa2 --- /dev/null +++ b/core/libs/prx/libSceHmdSetupDialog/libSceHmdSetupDialog.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceHmdSetupDialog/include/Api.hpp" diff --git a/core/libs/prx/libSceHttp/Export.cpp b/core/libs/prx/libSceHttp/Export.cpp index 1b49b9b016..ad94bc3ba5 100644 --- a/core/libs/prx/libSceHttp/Export.cpp +++ b/core/libs/prx/libSceHttp/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceHttp/include/Http.hpp" #include #include #ifdef _WIN32 @@ -24,52 +25,23 @@ // No network is emulated: contexts, templates and requests can be created, but any request // that would touch the network fails with the library's network error. static std::atomic g_nextHandle{1}; -struct HttpConnectionStat; -struct HttpRequestStat; -using HttpCookieSendCallback = int (APS5_VABI *)(std::int32_t, const char*, const char*, void*); -using HttpSocketCreationCallback = void (APS5_VABI *)(std::int32_t, std::int32_t, void*); -using HttpRequestStatusCallback = void (APS5_VABI *)(int, int, void*); struct RequestStatusRegistration { HttpRequestStatusCallback callback; void* argument; }; static std::mutex g_statusMutex; static std::map g_statusCallbacks; -struct HttpCookieStats { - std::size_t usedBytes; - std::uint32_t cookieCount; - std::uint32_t reserved; - std::size_t peakUsedBytes; - std::uint32_t peakCookieCount; - std::uint32_t evictedCookieCount; -}; static_assert(sizeof(HttpCookieStats) == 32); static_assert(offsetof(HttpCookieStats, peakUsedBytes) == 16); -struct HttpMemoryPoolStats { - std::size_t poolSize; - std::size_t peakUsedSize; - std::size_t usedSize; -}; - -struct HttpRequestHeader { - const char* name; - const char* value; -}; - static_assert(sizeof(HttpMemoryPoolStats) == 24); static_assert(offsetof(HttpMemoryPoolStats, peakUsedSize) == 8); static_assert(offsetof(HttpMemoryPoolStats, usedSize) == 16); static_assert(sizeof(HttpRequestHeader) == 16); static_assert(offsetof(HttpRequestHeader, value) == 8); -struct HttpsCaList { - void* certs; - int certsNum; -}; - #ifdef _WIN32 struct HostMutex { SRWLOCK native = SRWLOCK_INIT; @@ -495,7 +467,6 @@ int APS5_VABI sceHttpSetChunkedTransferEnabled(int id, int enable) { return 0; } - int APS5_VABI sceHttpSetInflateGZIPEnabled(int id, int enable) { (void)id; if (static_cast(enable) > 1) return ERROR_INVALID_VALUE; diff --git a/core/libs/prx/libSceHttp/include/Http.hpp b/core/libs/prx/libSceHttp/include/Http.hpp new file mode 100644 index 0000000000..505be14652 --- /dev/null +++ b/core/libs/prx/libSceHttp/include/Http.hpp @@ -0,0 +1,157 @@ +#pragma once + +#include "SceTypes.hpp" + +struct HttpConnectionStat; +struct HttpRequestStat; + +struct HttpCookieStats { + std::size_t usedBytes; + std::uint32_t cookieCount; + std::uint32_t reserved; + std::size_t peakUsedBytes; + std::uint32_t peakCookieCount; + std::uint32_t evictedCookieCount; +}; + +struct HttpMemoryPoolStats { + std::size_t poolSize; + std::size_t peakUsedSize; + std::size_t usedSize; +}; + +struct HttpRequestHeader { + const char* name; + const char* value; +}; + +struct HttpsCaList { + void* certs; + int certsNum; +}; + +using HttpCookieSendCallback = int (APS5_VABI *)(std::int32_t, const char*, const char*, void*); + +using HttpSocketCreationCallback = void (APS5_VABI *)(std::int32_t, std::int32_t, void*); + +using HttpRequestStatusCallback = void (APS5_VABI *)(int, int, void*); + +extern "C" { + +int APS5_VABI sceHttpAbortRequest(int requestId); +int APS5_VABI sceHttpAbortRequestForce(int requestId); +int APS5_VABI sceHttpAddRequestHeader(int id, const char* name, const char* value, uint32_t mode); +int APS5_VABI sceHttpAuthCacheFlush(int httpCtxId); +int APS5_VABI sceHttpCookieFlush(int httpCtxId); +int APS5_VABI sceHttpCreateConnection(int tmplId, const char* serverName, const char* scheme, uint16_t port, int enableKeepAlive); +int APS5_VABI sceHttpCreateConnectionWithURL(int tmplId, const char* url, int enableKeepAlive); +int APS5_VABI sceHttpCreateEpoll(int httpCtxId, HttpEpollHandle* eh); +int APS5_VABI sceHttpCreateRequest(int connId, int method, const char* path, uint64_t contentLength); +int APS5_VABI sceHttpCreateRequestWithURL2(int connId, const char* method, const char* url, uint64_t contentLength); +int APS5_VABI sceHttpCreateTemplate(int httpCtxId, const char* userAgent, int httpVer, int isAutoProxyConf); +int APS5_VABI sceHttpDeleteConnection(int connId); +int APS5_VABI sceHttpDeleteRequest(int reqId); +int APS5_VABI sceHttpDeleteTemplate(int tmplId); +int APS5_VABI sceHttpDestroyEpoll(int httpCtxId, HttpEpollHandle eh); +int APS5_VABI sceHttpGetAllResponseHeaders(int requestId, char** header, size_t* headerSize); +int APS5_VABI sceHttpGetResponseContentLength(int requestId, int* result, uint64_t* contentLength); +int APS5_VABI sceHttpGetStatusCode(int requestId, int* statusCode); +int APS5_VABI sceHttpInit_nid_postfix(int memid, int sslCtxId, uint64_t poolSize); +int APS5_VABI sceHttpsDisableOption(int id, uint32_t sslFlags); +int APS5_VABI sceHttpSendRequest(int requestId, const void* postData, size_t size); +int APS5_VABI sceHttpSetAuthEnabled(int id, int enable); +int APS5_VABI sceHttpSetAuthInfoCallback(int id, HttpAuthInfoCallback callback, void* userArg); +int APS5_VABI sceHttpSetCookieEnabled(int id, int enable); +int APS5_VABI sceHttpSetAutoRedirect(int id, int enable); +int APS5_VABI sceHttpSetConnectTimeOut(int id, uint32_t usec); +int APS5_VABI sceHttpSetEpoll(int id, HttpEpollHandle eh, void* userArg); +int APS5_VABI sceHttpSetNonblock(int id, int enable); +int APS5_VABI sceHttpTrySetNonblock(int id, int enable); +int APS5_VABI sceHttpSetRecvTimeOut(int id, uint32_t usec); +int APS5_VABI sceHttpSetRecvBlockSize(int id, uint32_t blockSize); +int APS5_VABI sceHttpSetResponseHeaderMaxSize(int id, uint64_t headerSize); +int APS5_VABI sceHttpSetRequestContentLength(int requestId, uint64_t contentLength); +int APS5_VABI sceHttpSetResolveRetry(int id, int32_t retry); +int APS5_VABI sceHttpSetResolveTimeOut(int id, uint32_t usec); +int APS5_VABI sceHttpSetSendTimeOut(int id, uint32_t usec); +int APS5_VABI sceHttpsSetMinSslVersion(int id, uint32_t sslVersion); +int APS5_VABI sceHttpsSetSslCallback(int id, HttpsCallback cbfunc, void* userArg); +int APS5_VABI sceHttpTerm_nid_postfix(int httpCtxId); +int APS5_VABI sceHttpUnsetEpoll(int id); +int APS5_VABI sceHttpWaitRequest(HttpEpollHandle eh, HttpNBEvent* nbev, int maxevents, int timeout); +int APS5_VABI sceHttpCreateRequestWithURL(int connId, int method, const char* url, uint64_t contentLength); +int APS5_VABI sceHttpReadData(int requestId, void* data, size_t size); +int APS5_VABI sceHttpRedirectCacheFlush(int httpCtxId); +int APS5_VABI sceHttpSetChunkedTransferEnabled(int id, int enable); +int APS5_VABI sceHttpSetInflateGZIPEnabled(int id, int enable); +int APS5_VABI sceHttpSetRequestStatusCallback(int id, HttpRequestStatusCallback callback, void* argument); +int APS5_VABI sceHttpParseResponseHeader(const char* header, std::size_t headerLen, const char* fieldStr, const char** fieldValue, std::size_t* valueLen); +int APS5_VABI sceHttpCreateRequest2(int connId, const char* method, const char* path, uint64_t contentLength); +int APS5_VABI sceHttpsEnableOption(int id, uint32_t sslFlags); +int APS5_VABI sceHttpsLoadCert(int httpCtxId, int num, void* caList, void* cert, void* key); +int APS5_VABI sceHttpsUnloadCert(int httpCtxId); +int APS5_VABI sceHttpGetLastErrno(int requestId, int* errnoOut); +int APS5_VABI sceHttpsGetSslError(int id, int* errNum, uint32_t* detail); +int APS5_VABI sceHttpSetCookieRecvCallback(int id, HttpCookieRecvCallback cbfunc, void* userArg); +int APS5_VABI sceHttpsSetSslVersion(int id, int sslVersion); +int APS5_VABI sceHttpSetRedirectCallback(int id, HttpRedirectCallback cbfunc, void* userArg); +int APS5_VABI sceHttpAbortWaitRequest(HttpEpollHandle eh); +int APS5_VABI sceHttpsGetCaList(int httpCtxId, HttpsCaList* caList); +int APS5_VABI sceHttpsFreeCaList(int httpCtxId, HttpsCaList* caList); +int APS5_VABI sceHttpAuthCacheImport(int contextId, const void* buffer, std::size_t size); +int APS5_VABI sceHttpAuthCacheExport(int contextId, void* buffer, std::size_t size, std::size_t* requiredSize); +int APS5_VABI sceHttpDbgEnableProfile(void); +int APS5_VABI sceHttpDbgSetPrintf(void); +int APS5_VABI sceHttpDbgShowStat(void); +int APS5_VABI sceHttpGetMemoryPoolStats(int contextId, HttpMemoryPoolStats* stats); +int APS5_VABI sceHttpDbgShowConnectionStat(void); +int APS5_VABI sceHttpDbgShowRequestStat(void); +int APS5_VABI sceHttpDbgShowMemoryPoolStat(void); +int APS5_VABI sceHttpDbgGetConnectionStat(std::int32_t connectionId, HttpConnectionStat* stat); +int APS5_VABI sceHttpDbgGetRequestStat(std::int32_t requestId, HttpRequestStat* stat); +int APS5_VABI sceHttpAddRequestHeaderRaw(int id, const char* header, int mode); +int APS5_VABI sceHttpRemoveRequestHeader(int id, const char* name); +int APS5_VABI sceHttpGetAuthEnabled(int id, int* enable); +int APS5_VABI sceHttpSetEpollId(std::int32_t id, std::int32_t epollId, void* userArg); +int APS5_VABI sceHttpGetEpollId(std::int32_t id, std::int32_t* epollId, void** userArg); +int APS5_VABI sceHttpGetCookie(int contextId, const char* url, char* cookie, std::size_t* requiredSize, std::size_t size); +int APS5_VABI sceHttpGetCookieEnabled(int id, int* enable); +int APS5_VABI sceHttpAddCookie(int contextId, const char* url, const char* cookie, std::size_t size); +int APS5_VABI sceHttpSetCookieSendCallback(std::int32_t id, HttpCookieSendCallback callback, void* userArg); +int APS5_VABI sceHttpCookieExport(int contextId, void* buffer, std::size_t size, std::size_t* requiredSize); +int APS5_VABI sceHttpCookieImport(int contextId, const void* buffer, std::size_t size); +int APS5_VABI sceHttpSetCookieTotalMaxSize(int contextId, std::uint32_t size); +int APS5_VABI sceHttpSetCookieMaxSize(int contextId, std::uint32_t size); +int APS5_VABI sceHttpSetCookieMaxNum(int contextId, std::uint32_t count); +int APS5_VABI sceHttpSetCookieMaxNumPerDomain(int contextId, std::uint32_t count); +int APS5_VABI sceHttpGetCookieStats(int id, HttpCookieStats* stats); +int APS5_VABI sceHttpSetPriorityOption(int id, int priority); +int APS5_VABI sceHttpSetPolicyOption(int id, int policy); +int APS5_VABI sceHttpRequestGetAllHeaders(int requestId, HttpRequestHeader* headers, std::uint32_t* headerCount, char* contentLength, std::size_t* contentLengthSize); +int APS5_VABI sceHttpSetDefaultAcceptEncodingGZIPEnabled(int httpCtxId, int enable); +int APS5_VABI sceHttpSetProxy(int id, int, int, const char* hostname, std::uint16_t); +int APS5_VABI sceHttpSetSocketCreationCallback(std::int32_t id, HttpSocketCreationCallback callback, void* userArg); +int APS5_VABI sceHttpSetHttp09Enabled(int id, int enabled); +int APS5_VABI sceHttpGetRegisteredCtxIds(int contextId, int* netPoolId, int* sslContextId); +int APS5_VABI sceHttpGetConnectionStat(std::int32_t connectionId, HttpConnectionStat* stat); +int APS5_VABI sceHttpAddQuery(int id, const char* query); +int APS5_VABI sceHttpSetDelayBuildRequestEnabled(int id, int enabled); +int APS5_VABI sceHttpGetAutoRedirect(int id, int* enable); +int APS5_VABI sceHttpGetNonblock(int id, int* enable); +int APS5_VABI sceHttpTryGetNonblock(int id, int* enable); +int APS5_VABI sceHttpGetAcceptEncodingGZIPEnabled(int id, int* enable); +int APS5_VABI sceHttpSetAcceptEncodingGZIPEnabled(int id, int enable); +int APS5_VABI sceHttpGetEpoll(int id, HttpEpollHandle* epoll, void** argument); +int APS5_VABI sceHttpCacheRedirectedConnectionEnabled(int id, int enable); +int APS5_VABI sceHttpsEnableOptionPrivate(int id, std::uint32_t sslFlags); +int APS5_VABI sceHttpsDisableOptionPrivate(int id, std::uint32_t sslFlags); +int APS5_VABI sceHttpParseStatusLine(const char* statusLine, size_t lineLen, int32_t* httpMajorVer, int32_t* httpMinorVer, int32_t* responseCode, const char** reasonPhrase, size_t* phraseLen); +int APS5_VABI sceHttpUriBuild(char* out, size_t* requiredSize, size_t capacity, const SceHttpUriElement* element, uint32_t option); +int APS5_VABI sceHttpUriEscape(char* out, size_t* require, size_t prepare, const char* in); +int APS5_VABI sceHttpUriUnescape(char* out, size_t* requiredSize, size_t capacity, const char* input); +int APS5_VABI sceHttpUriMerge(char* mergedUrl, const char* url, const char* relativeUri, size_t* require, size_t prepare, uint32_t option); +int APS5_VABI sceHttpUriParse(SceHttpUriElement* out, const char* srcUrl, void* pool, size_t* require, size_t prepare); +int APS5_VABI sceHttpUriCopy(SceHttpUriElement* out, const SceHttpUriElement* src, void* pool, size_t prepare, size_t* require); +int APS5_VABI sceHttpUriSweepPath(char* dst, const char* src, size_t srcSize); + +} diff --git a/core/libs/prx/libSceHttp/libSceHttp.hpp b/core/libs/prx/libSceHttp/libSceHttp.hpp new file mode 100644 index 0000000000..69e0774038 --- /dev/null +++ b/core/libs/prx/libSceHttp/libSceHttp.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceHttp/include/Http.hpp" diff --git a/core/libs/prx/libSceHttp/src/Options.cpp b/core/libs/prx/libSceHttp/src/Options.cpp index 710b33311a..415c462ee4 100644 --- a/core/libs/prx/libSceHttp/src/Options.cpp +++ b/core/libs/prx/libSceHttp/src/Options.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceHttp/include/Http.hpp" #include "prx/libSceHttp/src/Options.hpp" #include "prx/libc/include/General.hpp" #include "prx/libSceHttp/src/HttpErrors.hpp" diff --git a/core/libs/prx/libSceHttp/src/Parse.cpp b/core/libs/prx/libSceHttp/src/Parse.cpp index 409e18cf1b..1662a05f43 100644 --- a/core/libs/prx/libSceHttp/src/Parse.cpp +++ b/core/libs/prx/libSceHttp/src/Parse.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceHttp/include/Http.hpp" #include #include #include diff --git a/core/libs/prx/libSceHttp/src/Uri.cpp b/core/libs/prx/libSceHttp/src/Uri.cpp index 2cf41f6f6b..f2c4f83d2d 100644 --- a/core/libs/prx/libSceHttp/src/Uri.cpp +++ b/core/libs/prx/libSceHttp/src/Uri.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceHttp/include/Http.hpp" #include #include #include @@ -10,8 +11,6 @@ #include "prx/libc/include/ApplicationHeap.hpp" #include "prx/libSceHttp/src/HttpErrors.hpp" -extern "C" int APS5_VABI sceHttpUriSweepPath(char* dst, const char* src, size_t srcSize); - namespace { constexpr uint32_t URI_BUILD_WITH_SCHEME = 0x01; diff --git a/core/libs/prx/libSceHttp2/Export.cpp b/core/libs/prx/libSceHttp2/Export.cpp index d97f8d6c6d..7cb14fc27a 100644 --- a/core/libs/prx/libSceHttp2/Export.cpp +++ b/core/libs/prx/libSceHttp2/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceHttp2/include/Http2.hpp" #include #include #include @@ -62,13 +63,6 @@ static bool HandleIsLive(int id) { return FindAnyHandle(id) != nullptr; } -struct Http2MemoryPoolStats { - size_t pool_size; - size_t max_inuse_size; - size_t current_inuse_size; - int32_t reserved; -}; - static std::mutex g_completionsMutex; static std::unordered_map> g_completions; @@ -104,11 +98,6 @@ static int CompleteAsync(const char* function, int req_id, const Http2AsyncOptio return 0; } -using Http2WebSocketTextCallback = void (APS5_VABI*)(std::int32_t requestId, const char* text, std::uint32_t flags, void* userData); -using Http2WebSocketDataCallback = void (APS5_VABI*)(std::int32_t requestId, const void* data, std::size_t dataSize, std::uint32_t flags, void* userData); -using Http2WebSocketCloseCallback = void (APS5_VABI*)(std::int32_t requestId, const std::uint16_t* status, const char* reason, std::uint32_t flags, void* userData); -using Http2WebSocketErrorCallback = void (APS5_VABI*)(std::int32_t requestId, std::int32_t error, void* userData); - extern "C" { int APS5_VABI sceHttp2AddRequestHeader(int id, const char* name, const char* value, uint32_t mode) { @@ -385,7 +374,6 @@ int APS5_VABI sceHttp2SetRequestNoContentLength(int id) { return 0; } - int APS5_VABI sceHttp2SetResolveRetry(int id, int32_t retry) { (void)id; (void)retry; diff --git a/core/libs/prx/libSceHttp2/include/Http2.hpp b/core/libs/prx/libSceHttp2/include/Http2.hpp new file mode 100644 index 0000000000..bf7b34e6a7 --- /dev/null +++ b/core/libs/prx/libSceHttp2/include/Http2.hpp @@ -0,0 +1,85 @@ +#pragma once + +#include "SceTypes.hpp" + +struct Http2MemoryPoolStats { + size_t pool_size; + size_t max_inuse_size; + size_t current_inuse_size; + int32_t reserved; +}; + +using Http2WebSocketTextCallback = void (APS5_VABI*)(std::int32_t requestId, const char* text, std::uint32_t flags, void* userData); + +using Http2WebSocketDataCallback = void (APS5_VABI*)(std::int32_t requestId, const void* data, std::size_t dataSize, std::uint32_t flags, void* userData); + +using Http2WebSocketCloseCallback = void (APS5_VABI*)(std::int32_t requestId, const std::uint16_t* status, const char* reason, std::uint32_t flags, void* userData); + +using Http2WebSocketErrorCallback = void (APS5_VABI*)(std::int32_t requestId, std::int32_t error, void* userData); + +extern "C" { + +int APS5_VABI sceHttp2AddRequestHeader(int id, const char* name, const char* value, uint32_t mode); +int APS5_VABI sceHttp2CreateRequestWithURL(int tmplId, const char* method, const char* url, uint64_t contentLength); +int APS5_VABI sceHttp2CreateTemplate(int libHttp2CtxId, const char* userAgent, int httpVer, int isAutoProxyConf); +int APS5_VABI sceHttp2DeleteRequest(int reqId); +int APS5_VABI sceHttp2DeleteTemplate(int tmplId); +int APS5_VABI sceHttp2GetAllResponseHeaders(int reqId, char** header, size_t* headerSize); +int APS5_VABI sceHttp2GetResponseContentLength(int reqId, int* result, uint64_t* contentLength); +int APS5_VABI sceHttp2GetStatusCode(int reqId, int* statusCode); +int APS5_VABI sceHttp2Init(int libnetMemId, int libsslCtxId, size_t poolSize, int maxConcurrentRequest); +int APS5_VABI sceHttp2ReadData(int reqId, void* data, size_t size); +int APS5_VABI sceHttp2ReadDataAsync(int reqId, void* data, size_t size, void* kqueueOption, void* option); +int APS5_VABI sceHttp2SendRequest(int reqId, const void* postData, size_t size); +int APS5_VABI sceHttp2SendRequestAsync(int reqId, const void* postData, size_t size, Http2AsyncOption* kqueueOption, void* option); +int APS5_VABI sceHttp2SetAuthEnabled(int id, int isEnable); +int APS5_VABI sceHttp2SetAutoRedirect(int id, int enable); +int APS5_VABI sceHttp2SetConnectionWaitTimeOut(int id, uint32_t usec); +int APS5_VABI sceHttp2SetConnectTimeOut(int id, uint32_t usec); +int APS5_VABI sceHttp2SetInflateGZIPEnabled(int id, int enable); +int APS5_VABI sceHttp2SetRecvTimeOut(int id, uint32_t usec); +int APS5_VABI sceHttp2SetRedirectCallback(int id, void* cbFunc, void* userArg); +int APS5_VABI sceHttp2SetRequestContentLength(int id, uint64_t contentLength); +int APS5_VABI sceHttp2SetResolveTimeOut(int id, uint32_t usec); +int APS5_VABI sceHttp2SetSendTimeOut(int id, uint32_t usec); +int APS5_VABI sceHttp2SetSslCallback(int id, void* cbFunc, void* userArg); +int APS5_VABI sceHttp2SetTimeOut(int id, uint32_t usec); +int APS5_VABI sceHttp2SslDisableOption(int id, uint32_t sslFlags); +int APS5_VABI sceHttp2SslEnableOption(int id, uint32_t sslFlags); +int APS5_VABI sceHttp2SetMinSslVersion(int id, uint32_t sslVersion); +int APS5_VABI sceHttp2Term(int libHttp2CtxId); +int APS5_VABI sceHttp2WaitAsync(int reqId, Http2AsyncResult* result, uint32_t* timeout, void* option); +int APS5_VABI sceHttp2AbortRequest(int reqId); +int APS5_VABI sceHttp2GetMemoryPoolStats(int libHttp2CtxId, Http2MemoryPoolStats* stats); +int APS5_VABI sceHttp2CookieFlush(int id); +int APS5_VABI sceHttp2CreateCookieBox(std::size_t poolSize); +int APS5_VABI sceHttp2DeleteCookieBox(int cookieBoxId); +int APS5_VABI sceHttp2SetCookieBox(int id, int cookieBoxId); +int APS5_VABI sceHttp2SetRequestNoContentLength(int id); +int APS5_VABI sceHttp2SetResolveRetry(int id, int32_t retry); +int APS5_VABI sceHttp2WebSocketCreateRequest(std::int32_t templateId, const char* url, Http2WebSocketTextCallback textCallback, Http2WebSocketDataCallback dataCallback, Http2WebSocketCloseCallback closeCallback, Http2WebSocketErrorCallback errorCallback, void* receiveBuffer, std::size_t receiveBufferSize, void* userData, const void* option); +int APS5_VABI sceHttp2WebSocketCloseAsync(std::int32_t requestId, const std::uint16_t* status, const char* reason, std::uint8_t flags, const Http2AsyncOption* asyncOption, const void* option); +int APS5_VABI sceHttp2WebSocketSendTextMessageAsync(std::int32_t requestId, const char* text, std::uint8_t flags, const Http2AsyncOption* asyncOption, const void* option); +int APS5_VABI sceHttp2WebSocketSendDataMessageAsync(std::int32_t requestId, const void* data, std::size_t dataSize, std::uint8_t flags, const Http2AsyncOption* asyncOption, const void* option); +int APS5_VABI sceHttp2WebSocketSetPingInterval(std::int32_t requestId, std::uint32_t intervalMicroseconds); +int APS5_VABI sceHttp2WebSocketSetPingTimeout(std::int32_t requestId, std::uint32_t timeoutMicroseconds); +int APS5_VABI sceHttp2AddCookie(void); +int APS5_VABI sceHttp2AuthCacheFlush(void); +int APS5_VABI sceHttp2CookieExport(void); +int APS5_VABI sceHttp2CookieImport(void); +int APS5_VABI sceHttp2GetAuthEnabled(void); +int APS5_VABI sceHttp2GetAutoRedirect(void); +int APS5_VABI sceHttp2GetCookie(void); +int APS5_VABI sceHttp2GetCookieBox(void); +int APS5_VABI sceHttp2GetCookieStats(void); +int APS5_VABI sceHttp2RedirectCacheFlush(void); +int APS5_VABI sceHttp2RemoveRequestHeader(void); +int APS5_VABI sceHttp2SetAuthInfoCallback(void); +int APS5_VABI sceHttp2SetCookieMaxNum(void); +int APS5_VABI sceHttp2SetCookieMaxNumPerDomain(void); +int APS5_VABI sceHttp2SetCookieMaxSize(void); +int APS5_VABI sceHttp2SetCookieRecvCallback(void); +int APS5_VABI sceHttp2SetCookieSendCallback(void); +int APS5_VABI sceHttp2SetPreSendCallback(void); + +} diff --git a/core/libs/prx/libSceHttp2/libSceHttp2.hpp b/core/libs/prx/libSceHttp2/libSceHttp2.hpp new file mode 100644 index 0000000000..d6ec538a09 --- /dev/null +++ b/core/libs/prx/libSceHttp2/libSceHttp2.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceHttp2/include/Http2.hpp" diff --git a/core/libs/prx/libSceHttpCache/Export.cpp b/core/libs/prx/libSceHttpCache/Export.cpp index 12a2497b87..d3bdbf753f 100644 --- a/core/libs/prx/libSceHttpCache/Export.cpp +++ b/core/libs/prx/libSceHttpCache/Export.cpp @@ -1,46 +1,9 @@ +#include "prx/libSceHttpCache/include/Api.hpp" #include #include #include "SceTypes.hpp" #include "prx/libc/include/General.hpp" -struct HttpCacheHeader { - const char* name; - const char* value; -}; - -struct HttpCacheRequest { - std::uint32_t method; - std::uint32_t reserved; - const char* url; - std::size_t headerCount; - const HttpCacheHeader* headers; -}; - -struct HttpCacheResponseHeader { - std::uint32_t statusCode; - std::uint32_t reserved; - std::size_t headerCount; - const HttpCacheHeader* headers; -}; - -struct HttpCacheResponse { - std::uint32_t statusCode; - std::uint32_t reserved; - std::size_t headerCount; - const HttpCacheHeader* headers; - std::uint64_t contentLength; -}; - -struct HttpCacheQuotaEntry { - const char* name; - std::uint64_t size; -}; - -struct HttpCacheQuota { - std::size_t count; - const HttpCacheQuotaEntry* entries; -}; - static_assert(sizeof(HttpCacheHeader) == 16); static_assert(sizeof(HttpCacheRequest) == 32); static_assert(offsetof(HttpCacheRequest, url) == 8); @@ -162,7 +125,6 @@ int APS5_VABI sceHttpCacheTerm(std::int32_t cacheId) { return 0; } - int APS5_VABI sceHttpCacheClearAllUserTags() { NotImplemented_nid_no_patch(__func__); return 0; diff --git a/core/libs/prx/libSceHttpCache/include/Api.hpp b/core/libs/prx/libSceHttpCache/include/Api.hpp new file mode 100644 index 0000000000..634bf42348 --- /dev/null +++ b/core/libs/prx/libSceHttpCache/include/Api.hpp @@ -0,0 +1,75 @@ +#pragma once + +#include "SceTypes.hpp" +#include +#include + +struct HttpCacheHeader { + const char* name; + const char* value; +}; + +struct HttpCacheRequest { + std::uint32_t method; + std::uint32_t reserved; + const char* url; + std::size_t headerCount; + const HttpCacheHeader* headers; +}; + +struct HttpCacheResponseHeader { + std::uint32_t statusCode; + std::uint32_t reserved; + std::size_t headerCount; + const HttpCacheHeader* headers; +}; + +struct HttpCacheResponse { + std::uint32_t statusCode; + std::uint32_t reserved; + std::size_t headerCount; + const HttpCacheHeader* headers; + std::uint64_t contentLength; +}; + +struct HttpCacheQuotaEntry { + const char* name; + std::uint64_t size; +}; + +struct HttpCacheQuota { + std::size_t count; + const HttpCacheQuotaEntry* entries; +}; + +extern "C" { + +int APS5_VABI sceHttpCacheClear(std::int32_t cacheId, std::int32_t userId, const char* tag); +int APS5_VABI sceHttpCacheClearAll(std::int32_t cacheId, std::int32_t userId); +int APS5_VABI sceHttpCacheCompleteRequest(std::int32_t requestId); +int APS5_VABI sceHttpCacheCreateRequest(std::int32_t cacheId, std::int32_t userId); +int APS5_VABI sceHttpCacheCreateRequestWithTag(std::int32_t cacheId, std::int32_t userId, const char* tag); +int APS5_VABI sceHttpCacheDeleteRequest(std::int32_t requestId); +int APS5_VABI sceHttpCacheInit(std::size_t poolSize); +int APS5_VABI sceHttpCacheReadData(std::int32_t requestId, std::size_t size, void* data); +int APS5_VABI sceHttpCacheRetrieve(std::int32_t requestId, const HttpCacheRequest* request, HttpCacheResponse* response, HttpCacheRequest* nextRequest, std::int32_t* result); +int APS5_VABI sceHttpCacheRetrieveWithMemoryPool(std::int32_t requestId, const HttpCacheRequest* request, HttpCacheResponse* response, HttpCacheRequest* nextRequest, std::int32_t* result, void* pool, std::size_t* requiredSize, std::size_t poolSize); +int APS5_VABI sceHttpCacheRevalidate(std::int32_t requestId, const HttpCacheResponseHeader* header, HttpCacheResponse* response, std::int32_t* result); +int APS5_VABI sceHttpCacheRevalidateWithMemoryPool(std::int32_t requestId, const HttpCacheResponseHeader* header, HttpCacheResponse* response, std::int32_t* result, void* pool, std::size_t* requiredSize, std::size_t poolSize); +int APS5_VABI sceHttpCacheSetCacheSharing(std::uint8_t enabled); +int APS5_VABI sceHttpCacheSetData(std::int32_t requestId, const void* data, std::size_t size); +int APS5_VABI sceHttpCacheSetQuota(std::int32_t cacheId, const HttpCacheQuota* quota); +int APS5_VABI sceHttpCacheSetResponseHeader(std::int32_t requestId, const HttpCacheResponseHeader* header); +int APS5_VABI sceHttpCacheSystemClearAll(const char* path); +int APS5_VABI sceHttpCacheSystemInit(const char* path); +int APS5_VABI sceHttpCacheSystemSendStatistics(); +int APS5_VABI sceHttpCacheSystemShutdown(); +int APS5_VABI sceHttpCacheSystemTerm(); +int APS5_VABI sceHttpCacheTerm(std::int32_t cacheId); +int APS5_VABI sceHttpCacheClearAllUserTags(); +int APS5_VABI sceHttpCacheClearCacheInfo(); +int APS5_VABI sceHttpCacheDebugSetUrl(); +int APS5_VABI sceHttpCacheRegisterCacheInfoUrl(); +int APS5_VABI sceHttpCacheRemoveTag(); + +} diff --git a/core/libs/prx/libSceHttpCache/libSceHttpCache.hpp b/core/libs/prx/libSceHttpCache/libSceHttpCache.hpp new file mode 100644 index 0000000000..1a210e0748 --- /dev/null +++ b/core/libs/prx/libSceHttpCache/libSceHttpCache.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceHttpCache/include/Api.hpp" diff --git a/core/libs/prx/libSceHubAppUtil/Export.cpp b/core/libs/prx/libSceHubAppUtil/Export.cpp index b4a5ae963d..2ed0d86fca 100644 --- a/core/libs/prx/libSceHubAppUtil/Export.cpp +++ b/core/libs/prx/libSceHubAppUtil/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceHubAppUtil/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceHubAppUtil/include/Api.hpp b/core/libs/prx/libSceHubAppUtil/include/Api.hpp new file mode 100644 index 0000000000..721784ffcb --- /dev/null +++ b/core/libs/prx/libSceHubAppUtil/include/Api.hpp @@ -0,0 +1,11 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceHubAppUtilDeeplinkToLiveDetailView(); +int APS5_VABI sceHubAppUtilDeeplinkToPSSubscriptions(); +int APS5_VABI sceHubAppUtilGetInstallationStatus(); + +} diff --git a/core/libs/prx/libSceHubAppUtil/libSceHubAppUtil.hpp b/core/libs/prx/libSceHubAppUtil/libSceHubAppUtil.hpp new file mode 100644 index 0000000000..6636d9db00 --- /dev/null +++ b/core/libs/prx/libSceHubAppUtil/libSceHubAppUtil.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceHubAppUtil/include/Api.hpp" diff --git a/core/libs/prx/libSceIcu/libSceIcu.hpp b/core/libs/prx/libSceIcu/libSceIcu.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceIcu/libSceIcu.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceIdu/Export.cpp b/core/libs/prx/libSceIdu/Export.cpp index def1b88f9a..753cc6aa8b 100644 --- a/core/libs/prx/libSceIdu/Export.cpp +++ b/core/libs/prx/libSceIdu/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceIdu/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceIdu/include/Api.hpp b/core/libs/prx/libSceIdu/include/Api.hpp new file mode 100644 index 0000000000..4e9d5daaaa --- /dev/null +++ b/core/libs/prx/libSceIdu/include/Api.hpp @@ -0,0 +1,16 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceIduGetEnv(); +int APS5_VABI sceIduInit(); +int APS5_VABI sceIduInstallPkg(); +int APS5_VABI sceIduIsAppInstalled(); +int APS5_VABI sceIduIsRifInstalled(); +int APS5_VABI sceIduIsStaffMode(); +int APS5_VABI sceIduReboot(); +int APS5_VABI sceIduTerm(); + +} diff --git a/core/libs/prx/libSceIdu/libSceIdu.hpp b/core/libs/prx/libSceIdu/libSceIdu.hpp new file mode 100644 index 0000000000..b899940205 --- /dev/null +++ b/core/libs/prx/libSceIdu/libSceIdu.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceIdu/include/Api.hpp" diff --git a/core/libs/prx/libSceImageUtil/libSceImageUtil.hpp b/core/libs/prx/libSceImageUtil/libSceImageUtil.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceImageUtil/libSceImageUtil.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceIme/Export.cpp b/core/libs/prx/libSceIme/Export.cpp index 9485063034..a6c3a3d181 100644 --- a/core/libs/prx/libSceIme/Export.cpp +++ b/core/libs/prx/libSceIme/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceIme/include/Api.hpp" #include #include #include @@ -15,25 +16,6 @@ #include "prx/libSceIme/include/ImeFilterText.hpp" #include "prx/libSceIme/include/ImeInput.hpp" -struct ImeVshContext; -struct ImeVshParameter; -struct ImePreeditMetaInfo; -struct ImeDictionaryWord; - -struct ImeVshCaretGeometry { - std::int32_t x; - std::int32_t y; - std::uint32_t height; - std::uint32_t index; -}; - -struct ImeVshTextGeometry { - std::int32_t x; - std::int32_t y; - std::uint32_t width; - std::uint32_t height; -}; - static_assert(sizeof(ImeEditText) == 64); static_assert(offsetof(ImeEvent, param) == 8); static_assert(sizeof(ImeVshCaretGeometry) == 16); diff --git a/core/libs/prx/libSceIme/include/Api.hpp b/core/libs/prx/libSceIme/include/Api.hpp new file mode 100644 index 0000000000..50ed144cfc --- /dev/null +++ b/core/libs/prx/libSceIme/include/Api.hpp @@ -0,0 +1,93 @@ +#pragma once + +#include "prx/libSceIme/include/ImeFilterText.hpp" +#include "SceTypes.hpp" + +struct ImeDictionaryWord; + +struct ImeVshContext; + +struct ImePreeditMetaInfo; + +struct ImeVshCaretGeometry { + std::int32_t x; + std::int32_t y; + std::uint32_t height; + std::uint32_t index; +}; + +struct ImeVshParameter; + +struct ImeVshTextGeometry { + std::int32_t x; + std::int32_t y; + std::uint32_t width; + std::uint32_t height; +}; + +extern "C" { + +int APS5_VABI sceImeOpen_nid_postfix(const Param* param, const ExtendedParam* extended); +int APS5_VABI sceImeClose_nid_postfix(void); +int APS5_VABI sceImeGetPanelPositionAndForm(PositionAndForm* form); +int APS5_VABI sceImeGetPanelSize(const Param* param, uint32_t* width, uint32_t* height); +int APS5_VABI sceImeKeyboardClose(int32_t userId); +int APS5_VABI sceImeKeyboardGetInfo(uint32_t resourceId, KeyboardInfo* info); +int APS5_VABI sceImeKeyboardGetResourceId(int32_t userId, KeyboardResourceIdArray* resourceIds); +int APS5_VABI sceImeKeyboardOpen(int32_t userId, const KeyboardParam* param); +int APS5_VABI sceImeKeyboardSetMode(int32_t userId, uint32_t mode); +int APS5_VABI sceImeFilterText(char16_t* dst, int32_t* outLength, uint32_t capacity, const ime_filter::FilterParam* param, const char16_t* src, uint32_t srcLength); +int APS5_VABI sceImeCheckFilterText(const void* param); +void APS5_VABI sceImeParamInit(Param* param); +int APS5_VABI sceImeSetCaret(const Caret* caret); +int APS5_VABI sceImeSetConsecutiveClauseConversionEnabled(std::uint8_t enabled); +int APS5_VABI sceImeSetText(const char16_t* text, uint32_t length); +int APS5_VABI sceImeSetTextGeometry(TextAreaMode mode, const TextGeometry* geometry); +int APS5_VABI sceImeUpdate(EventHandler handler); +int APS5_VABI sceImeVshOpen(ImeVshContext** context, const ImeVshParameter* parameter, const char16_t* text); +int APS5_VABI sceImeKeyboardUpdate(EventHandler handler); +int APS5_VABI sceImeVshUpdate(ImeVshContext* context); +int APS5_VABI sceImeVshUpdateContext(ImeVshContext* context, const char16_t* text, std::uint32_t caretIndex); +int APS5_VABI sceImeVshClearPreedit(ImeVshContext* context); +int APS5_VABI sceImeVshNotifySetText(ImeVshContext* context, const char16_t* text, std::uint32_t length); +int APS5_VABI sceImeVshSetCaretGeometry(ImeVshContext* context, const ImeVshCaretGeometry* geometry); +int APS5_VABI sceImeVshConfirmPreedit(ImeVshContext* context); +int APS5_VABI sceImeVshSetCaretIndexInPreedit(ImeVshContext* context, std::int32_t index); +int APS5_VABI sceImeVshSetPreeditGeometry(ImeVshContext* context, const ImeVshTextGeometry* geometry); +int APS5_VABI sceImeVshSetSelectGeometry(ImeVshContext* context, const ImeVshTextGeometry* geometry); +int APS5_VABI sceImeVshClose(ImeVshContext* context); +int APS5_VABI sceImeVshGetPanelPositionAndForm(ImeVshContext* context, PositionAndForm* form); +int APS5_VABI sceImeSetCandidateIndex(std::int32_t index); +int APS5_VABI sceImeConfirmCandidate(std::int32_t index); +int APS5_VABI sceImeDisableController(void); +int APS5_VABI sceImeSetVoiceDictationEnabled(bool enabled); +int APS5_VABI sceImeSetEditEventWithRemotePlayEnabled(bool enabled); +int APS5_VABI sceImeForTestFunction(void); +int APS5_VABI sceImeVshInformConfirmdString2(ImeVshContext* context, const char16_t* text, std::int32_t firstParameter, std::int32_t secondParameter, std::int32_t thirdParameter); +int APS5_VABI sceImeVshSetSelectionText(ImeVshContext* context, const char16_t* text, std::uint32_t length); +int APS5_VABI sceImeCheckUpdateTextInfo(ImeEditText* info, std::uint8_t repair); +int APS5_VABI sceImeCheckRemoteEventParam(ImeEvent* event, std::uint8_t repair); +int APS5_VABI sceImeKeyboardOpenInternal(std::int32_t userId, EventHandler handler, const KeyboardParam* param); +int APS5_VABI sceImeVshSetParam(ImeVshContext* context, const ImeVshParameter* parameter); +int APS5_VABI sceImeVshUpdateContext2(ImeVshContext* context, const char16_t* text, std::uint32_t caretIndex); +int APS5_VABI sceImeVshSendTextInfo(ImeVshContext* context, const void* info, std::uint32_t size); +int APS5_VABI sceImeVshInformConfirmdString(ImeVshContext* context, const char16_t* text, std::int32_t parameter); +int APS5_VABI sceImeVshNotifyCurrentTextInfo(ImeVshContext* context, const char16_t* text, std::int32_t caretIndex, std::int32_t preeditFirst, std::int32_t preeditSecond, std::int32_t selectionFirst, std::int32_t selectionSecond); +int APS5_VABI sceImeVshNotifyCurrentTextInfoForReconvertText(ImeVshContext* context, const char16_t* text, std::int32_t caretIndex, std::int32_t preeditFirst, std::int32_t preeditSecond, std::int32_t selectionFirst, std::int32_t selectionSecond, std::int32_t option); +int APS5_VABI sceImeVshNotifyDeleteText(ImeVshContext* context, const char16_t* text, std::int32_t length, std::int32_t parameter); +int APS5_VABI sceImeVshNotifyUpdateCaretText(ImeVshContext* context, const char16_t* text, std::int32_t length, std::int32_t parameter); +int APS5_VABI sceImeVshCheckAutoReConvertingPreeditText(ImeVshContext* context, const char16_t* text); +int APS5_VABI sceImeVshSetPanelPosition(ImeVshContext* context, float x, float y, std::int32_t horizontalAlignment, std::int32_t verticalAlignment); +int APS5_VABI sceImeVshNotifyPreeditMetaInfo(ImeVshContext* context, const ImePreeditMetaInfo* info); +int APS5_VABI sceImeConfigSet(std::uint64_t unusedArgument, std::uint64_t configuration, std::uint32_t key, std::uint32_t value); +int APS5_VABI sceImeConfigGet(std::uint64_t unusedArgument, std::uint64_t configuration, std::uint32_t key); +int APS5_VABI sceImeDicGetWords(std::int32_t userId, std::uint64_t dictionary, ImeDictionaryWord* words); +int APS5_VABI sceImeDicAddWord(std::int32_t userId, std::uint64_t dictionary, const ImeDictionaryWord* word); +int APS5_VABI sceImeDicDeleteWord(std::int32_t userId, std::uint64_t dictionary, const ImeDictionaryWord* word); +int APS5_VABI sceImeDicReplaceWord(std::int32_t userId, std::uint64_t dictionary, const ImeDictionaryWord* oldWord, const ImeDictionaryWord* newWord); +int APS5_VABI sceImeDicDeleteLearnDics(std::int32_t userId); +int APS5_VABI sceImeDicDeleteUserDics(std::int32_t userId); +int APS5_VABI FinalizeImeModule_nid_postfix(void); +int APS5_VABI InitializeImeModule_nid_postfix(void); + +} diff --git a/core/libs/prx/libSceIme/libSceIme.hpp b/core/libs/prx/libSceIme/libSceIme.hpp new file mode 100644 index 0000000000..01b649be31 --- /dev/null +++ b/core/libs/prx/libSceIme/libSceIme.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceIme/include/Api.hpp" diff --git a/core/libs/prx/libSceImeBackend/libSceImeBackend.hpp b/core/libs/prx/libSceImeBackend/libSceImeBackend.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceImeBackend/libSceImeBackend.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceImeDialog/Export.cpp b/core/libs/prx/libSceImeDialog/Export.cpp index c19acdd36a..94cdcf67c7 100644 --- a/core/libs/prx/libSceImeDialog/Export.cpp +++ b/core/libs/prx/libSceImeDialog/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceImeDialog/include/Api.hpp" #include #include #include @@ -198,7 +199,7 @@ int APS5_VABI sceImeDialogGetCurrentStarState(int64_t state) { return 0; } -int APS5_VABI sceImeDialogInitInternal(Param* param, ExtendedParam* extended) { +int APS5_VABI sceImeDialogInitInternal(const Param* param, const ExtendedParam* extended) { return sceImeDialogInit(param, extended); } @@ -207,7 +208,6 @@ int APS5_VABI sceImeDialogSetPanelPosition(int32_t, int32_t) { return g_dialog.status == StatusNone ? ErrorNotInUse : ErrorSuspending; } - int APS5_VABI sceImeDialogInitInternalWithSubInfo() { NotImplemented_nid_no_patch(__func__); return 0; diff --git a/core/libs/prx/libSceImeDialog/include/Api.hpp b/core/libs/prx/libSceImeDialog/include/Api.hpp new file mode 100644 index 0000000000..70f28051e4 --- /dev/null +++ b/core/libs/prx/libSceImeDialog/include/Api.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceImeDialogAbort(void); +int APS5_VABI sceImeDialogGetPanelPositionAndForm(PositionAndForm* form); +int APS5_VABI sceImeDialogGetPanelSize(const Param* param, uint32_t* width, uint32_t* height); +int APS5_VABI sceImeDialogGetPanelSizeExtended(const Param* param, const ExtendedParam* extended, uint32_t* width, uint32_t* height); +int APS5_VABI sceImeDialogGetResult(Result* result); +int APS5_VABI sceImeDialogGetStatus(void); +int APS5_VABI sceImeDialogInit(const Param* param, const ExtendedParam* extended); +int APS5_VABI sceImeDialogTerm(void); +int APS5_VABI sceImeDialogForTestFunction(); +int APS5_VABI sceImeDialogForceClose(void); +int APS5_VABI sceImeDialogGetCurrentStarState(int64_t state); +int APS5_VABI sceImeDialogInitInternal(const Param* param, const ExtendedParam* extended); +int APS5_VABI sceImeDialogSetPanelPosition(int32_t, int32_t); +int APS5_VABI sceImeDialogInitInternalWithSubInfo(); + +} diff --git a/core/libs/prx/libSceImeDialog/libSceImeDialog.hpp b/core/libs/prx/libSceImeDialog/libSceImeDialog.hpp new file mode 100644 index 0000000000..b9c6e0c899 --- /dev/null +++ b/core/libs/prx/libSceImeDialog/libSceImeDialog.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceImeDialog/include/Api.hpp" diff --git a/core/libs/prx/libSceInvitationDialog/Export.cpp b/core/libs/prx/libSceInvitationDialog/Export.cpp index 6292323d0c..9053e853ee 100644 --- a/core/libs/prx/libSceInvitationDialog/Export.cpp +++ b/core/libs/prx/libSceInvitationDialog/Export.cpp @@ -1,9 +1,10 @@ +#include "prx/libSceInvitationDialog/include/Api.hpp" #include "SceTypes.hpp" #include "prx/libc/include/General.hpp" extern "C" { -int APS5_VABI sceInvitationDialogGetResult() { +int APS5_VABI sceInvitationDialogGetResult(InvitationDialogResult* result) { NotImplemented_nid_no_patch(__func__); return 0; } diff --git a/core/libs/prx/libSceInvitationDialog/include/Api.hpp b/core/libs/prx/libSceInvitationDialog/include/Api.hpp new file mode 100644 index 0000000000..884ec82465 --- /dev/null +++ b/core/libs/prx/libSceInvitationDialog/include/Api.hpp @@ -0,0 +1,38 @@ +#pragma once + +#include "SceTypes.hpp" +#include +#include + +struct InvitationDialogRecipients { + std::uint32_t count; + NpOnlineId onlineIds[16]; +}; + +struct InvitationDialogResult { + std::uint8_t opaque00[8]; + std::int32_t errorCode; + std::uint32_t opaque0C; + InvitationDialogRecipients* recipients; + std::uint8_t reserved[32]; +}; + +static_assert(sizeof(NpOnlineId) == 20); +static_assert(offsetof(InvitationDialogRecipients, onlineIds) == 4); +static_assert(sizeof(InvitationDialogRecipients) == 324); +static_assert(offsetof(InvitationDialogResult, errorCode) == 0x08); +static_assert(offsetof(InvitationDialogResult, opaque0C) == 0x0C); +static_assert(offsetof(InvitationDialogResult, recipients) == 0x10); +static_assert(offsetof(InvitationDialogResult, reserved) == 0x18); +static_assert(sizeof(InvitationDialogResult) == 0x38); + +extern "C" { + +int APS5_VABI sceInvitationDialogGetResult(InvitationDialogResult* result); +int APS5_VABI sceInvitationDialogInitialize(); +int APS5_VABI sceInvitationDialogOpen(); +int APS5_VABI sceInvitationDialogTerminate(); +int APS5_VABI sceInvitationDialogUpdateStatus(); +int APS5_VABI sceInvitationDialogClose(void); + +} diff --git a/core/libs/prx/libSceInvitationDialog/libSceInvitationDialog.hpp b/core/libs/prx/libSceInvitationDialog/libSceInvitationDialog.hpp new file mode 100644 index 0000000000..52cc7b951a --- /dev/null +++ b/core/libs/prx/libSceInvitationDialog/libSceInvitationDialog.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceInvitationDialog/include/Api.hpp" diff --git a/core/libs/prx/libSceIpmi/Export.cpp b/core/libs/prx/libSceIpmi/Export.cpp index 238bb67ecf..993a1254b3 100644 --- a/core/libs/prx/libSceIpmi/Export.cpp +++ b/core/libs/prx/libSceIpmi/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceIpmi/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceIpmi/PendingExports.cpp b/core/libs/prx/libSceIpmi/PendingExports.cpp index 62a504bc35..5970f64dd6 100644 --- a/core/libs/prx/libSceIpmi/PendingExports.cpp +++ b/core/libs/prx/libSceIpmi/PendingExports.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceIpmi/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceIpmi/include/Api.hpp b/core/libs/prx/libSceIpmi/include/Api.hpp new file mode 100644 index 0000000000..200ce258ea --- /dev/null +++ b/core/libs/prx/libSceIpmi/include/Api.hpp @@ -0,0 +1,62 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceIpmiMgrGetIpcBlockerPid(void); +int APS5_VABI sceIpmiMgrGetIpcBlockerPidByAppId(void); +int APS5_VABI sceIpmiMgrPauseDump(void); +int APS5_VABI sceIpmiMgrRaiseExceptionToPid(void); +int APS5_VABI sceIpmiMgrStartDump(void); +int APS5_VABI _ZN4IPMI4impl11SessionImplC1Ev(void); +int APS5_VABI _ZN4IPMI6Client6Config14MsgQueueConfig20estimateMsgQueueSizeEmj(void); +int APS5_VABI _ZN4IPMI6Server12EventHandler21onAsyncMethodDispatchEPNS_7SessionEjjPvmS4_m(void); +int APS5_VABI _ZN4IPMI6Client6Config26SyncMethodInvocationConfigC1Ev(void); +int APS5_VABI _ZN4IPMI6Server12EventHandler20onSyncMethodDispatchEPNS_7SessionEjPvmmS4_m(void); +int APS5_VABI _ZN4IPMI7SessionD1Ev(void); +int APS5_VABI _ZN4IPMI4impl11SessionImpl9tryGetMsgEjPvPmm(void); +int APS5_VABI _ZN4IPMI6Server12EventHandler20onSyncMethodDispatchEPNS_7SessionEjPKNS_8DataInfoEjPNS_10BufferInfoEj(void); +int APS5_VABI _ZN4IPMI6Client6Config14MsgQueueConfigC1Ev(void); +int APS5_VABI _ZN4IPMI6ServerD2Ev(void); +int APS5_VABI _ZN4IPMI6ServerD0Ev(void); +int APS5_VABI _ZN4IPMI6Client6Config24estimateClientMemorySizeEv(void); +int APS5_VABI _ZN4IPMI6Server6createEPPS0_PKNS0_6ConfigEPvS6_(void); +int APS5_VABI _ZN4IPMI6Client6ConfigC2Ev(void); +int APS5_VABI _ZN4IPMI6Server12EventHandler15onSessionKilledEPNS_7SessionE(void); +int APS5_VABI _ZN4IPMI4impl11SessionImplD1Ev(void); +int APS5_VABI _ZN4IPMI4impl11SessionImpl27respondToAsyncMethodRequestEjiPKvm(void); +int APS5_VABI _ZN4IPMI6Client6Config27AsyncMethodInvocationConfigC2Ev(void); +int APS5_VABI _ZN4IPMI6Server12EventHandler21onAsyncMethodDispatchEPNS_7SessionEjjPKNS_8DataInfoEj(void); +int APS5_VABI _ZN4IPMI6ClientD2Ev(void); +int APS5_VABI _ZN4IPMI4impl11SessionImpl7sendMsgEjPKvmPj(void); +int APS5_VABI _ZN4IPMI6ClientC2Ev(void); +int APS5_VABI _ZN4IPMI7SessionD2Ev(void); +int APS5_VABI _ZNK4IPMI4impl11SessionImpl16isPeerPrivilegedEv(void); +int APS5_VABI _ZN4IPMI7SessionC2Ev(void); +int APS5_VABI _ZN4IPMI4impl11SessionImplD2Ev(void); +int APS5_VABI _ZN4IPMI6ClientD1Ev(void); +int APS5_VABI _ZN4IPMI6Server12EventHandlerD0Ev(void); +int APS5_VABI _ZN4IPMI7Session6Config25estimateSessionMemorySizeEv(void); +int APS5_VABI _ZNK4IPMI6Server6Config29estimateTempWorkingMemorySizeEv(void); +int APS5_VABI _ZN4IPMI4impl11SessionImplD0Ev(void); +int APS5_VABI _ZN4IPMI4impl11SessionImpl7destroyEv(void); +int APS5_VABI _ZN4IPMI6Client6Config27AsyncMethodInvocationConfigC1Ev(void); +int APS5_VABI _ZN4IPMI4impl11SessionImpl6getMsgEjPvPmmPj(void); +int APS5_VABI _ZN4IPMI4impl11SessionImpl27respondToAsyncMethodRequestEjjiPKNS_8DataInfoEj(void); +int APS5_VABI _ZN4IPMI6Server12EventHandlerD2Ev(void); +int APS5_VABI _ZN4IPMI6ClientD0Ev(void); +int APS5_VABI _ZN4IPMI6Client6createEPPS0_PKNS0_6ConfigEPvS6_(void); +int APS5_VABI _ZN4IPMI6ServerC2Ev(void); +int APS5_VABI _ZN4IPMI4impl11SessionImplC2Ev(void); +int APS5_VABI _ZN4IPMI7SessionD0Ev(void); +int APS5_VABI _ZN4IPMI6ServerD1Ev(void); +int APS5_VABI _ZN4IPMI6Server6ConfigC1Ev(void); +int APS5_VABI _ZN4IPMI6Server12EventHandlerD1Ev(void); +int APS5_VABI _ZN4IPMI4impl11SessionImpl9getServerEv(void); +int APS5_VABI _ZN4IPMI6Client6ConfigC1Ev(void); +int APS5_VABI _ZN4IPMI6Client6Config26SyncMethodInvocationConfigC2Ev(void); +int APS5_VABI _ZN4IPMI6Client6Config14MsgQueueConfigC2Ev(void); +int APS5_VABI _ZN4IPMI6Server6ConfigC2Ev(void); + +} diff --git a/core/libs/prx/libSceIpmi/libSceIpmi.hpp b/core/libs/prx/libSceIpmi/libSceIpmi.hpp new file mode 100644 index 0000000000..c7fc7c9a22 --- /dev/null +++ b/core/libs/prx/libSceIpmi/libSceIpmi.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceIpmi/include/Api.hpp" diff --git a/core/libs/prx/libSceJemspace/Export.cpp b/core/libs/prx/libSceJemspace/Export.cpp index 5dc318d1a1..c6a8018fa1 100644 --- a/core/libs/prx/libSceJemspace/Export.cpp +++ b/core/libs/prx/libSceJemspace/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceJemspace/include/Api.hpp" #include "SceTypes.hpp" #include "prx/libc/include/General.hpp" diff --git a/core/libs/prx/libSceJemspace/include/Api.hpp b/core/libs/prx/libSceJemspace/include/Api.hpp new file mode 100644 index 0000000000..5f280f8dcb --- /dev/null +++ b/core/libs/prx/libSceJemspace/include/Api.hpp @@ -0,0 +1,21 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceJemspaceCalloc(); +int APS5_VABI sceJemspaceCreate(); +int APS5_VABI sceJemspaceDestroy(); +int APS5_VABI sceJemspaceFree(); +int APS5_VABI sceJemspaceGetStats(); +int APS5_VABI sceJemspaceMalloc(); +int APS5_VABI sceJemspaceMallocUsableSize(); +int APS5_VABI sceJemspaceMemalign(); +int APS5_VABI sceJemspacePosixMemalign(); +int APS5_VABI sceJemspacePrintStats(); +int APS5_VABI sceJemspacePurge(); +int APS5_VABI sceJemspaceRealloc(); +int APS5_VABI sceJemspaceReallocalign(); + +} diff --git a/core/libs/prx/libSceJemspace/libSceJemspace.hpp b/core/libs/prx/libSceJemspace/libSceJemspace.hpp new file mode 100644 index 0000000000..efe1e331fb --- /dev/null +++ b/core/libs/prx/libSceJemspace/libSceJemspace.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceJemspace/include/Api.hpp" diff --git a/core/libs/prx/libSceJitBridge/libSceJitBridge.hpp b/core/libs/prx/libSceJitBridge/libSceJitBridge.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceJitBridge/libSceJitBridge.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceJobManager/CMakeLists.txt b/core/libs/prx/libSceJobManager/CMakeLists.txt index 4a88c6da6d..1364b0e64d 100644 --- a/core/libs/prx/libSceJobManager/CMakeLists.txt +++ b/core/libs/prx/libSceJobManager/CMakeLists.txt @@ -1,9 +1,24 @@ add_library(libSceJobManager SHARED EXCLUDE_FROM_ALL Export.cpp) target_include_directories(libSceJobManager PRIVATE ${LIBS_INCLUDE_DIR}) -target_link_libraries(libSceJobManager PRIVATE libSceAgc libSceAgcDriver) +target_link_libraries(libSceJobManager PRIVATE libSceAgc libSceAgcDriver libSceRazorCpu ulobjmgr) configure_windows_unwind(libSceJobManager) if(BUILD_TESTING) + add_test_executable(guest_job_manager_profiler_tests ${LIBS_INCLUDE_DIR}/tests/JobManagerProfiler.cpp Export.cpp) + target_include_directories(guest_job_manager_profiler_tests PRIVATE ${LIBS_INCLUDE_DIR} + ${ANYPS5_VULKAN_HEADERS_INCLUDE_DIR} ${ANYPS5_SPIRV_HEADERS_INCLUDE_DIR} + $) + target_compile_options(guest_job_manager_profiler_tests PRIVATE -msse4.2) + target_link_libraries(guest_job_manager_profiler_tests PRIVATE libSceAgc libSceAgcDriver libkernel libc ulobjmgr) + configure_windows_unwind(guest_job_manager_profiler_tests) + add_test(NAME guest_job_manager_profiler COMMAND guest_job_manager_profiler_tests) + add_test(NAME guest_job_manager_profiler_gpu COMMAND guest_job_manager_profiler_tests gpu) + set_tests_properties(guest_job_manager_profiler guest_job_manager_profiler_gpu PROPERTIES TIMEOUT 20) + set_tests_properties(guest_job_manager_profiler_gpu PROPERTIES SKIP_RETURN_CODE 77 ENVIRONMENT "ANYPS5_NO_SHADER_CACHE=1") + if(WIN32) + set_tests_properties(guest_job_manager_profiler guest_job_manager_profiler_gpu PROPERTIES ENVIRONMENT_MODIFICATION + "PATH=path_list_prepend:$") + endif() add_test_executable(job_manager_compute_progress_tests ${LIBS_INCLUDE_DIR}/tests/JobManagerComputeProgress.cpp) target_include_directories(job_manager_compute_progress_tests PRIVATE ${LIBS_INCLUDE_DIR}) target_link_libraries(job_manager_compute_progress_tests PRIVATE libc) @@ -14,22 +29,43 @@ if(BUILD_TESTING) set_tests_properties(guest_job_manager_compute_progress PROPERTIES ENVIRONMENT_MODIFICATION "PATH=path_list_prepend:$") endif() + add_test_executable(guest_job_manager_failure_tests ${LIBS_INCLUDE_DIR}/tests/JobManagerFailures.cpp Export.cpp) + target_include_directories(guest_job_manager_failure_tests PRIVATE ${LIBS_INCLUDE_DIR}) + target_link_libraries(guest_job_manager_failure_tests PRIVATE libSceAgc libSceAgcDriver libSceRazorCpu libkernel libc ulobjmgr) + configure_windows_unwind(guest_job_manager_failure_tests) + add_test(NAME guest_job_manager_failures COMMAND guest_job_manager_failure_tests) + set_tests_properties(guest_job_manager_failures PROPERTIES TIMEOUT 20) + if(WIN32) + set_tests_properties(guest_job_manager_failures PROPERTIES ENVIRONMENT_MODIFICATION + "PATH=path_list_prepend:$") + endif() + add_test_executable(guest_job_manager_registration_tests ${LIBS_INCLUDE_DIR}/tests/JobManagerRegistration.cpp Export.cpp) + target_include_directories(guest_job_manager_registration_tests PRIVATE ${LIBS_INCLUDE_DIR}) + target_link_libraries(guest_job_manager_registration_tests PRIVATE libSceAgc libSceAgcDriver libSceRazorCpu libkernel libc) + configure_windows_unwind(guest_job_manager_registration_tests) + add_test(NAME guest_job_manager_registration COMMAND guest_job_manager_registration_tests) + set_tests_properties(guest_job_manager_registration PROPERTIES TIMEOUT 20) + if(WIN32) + set_tests_properties(guest_job_manager_registration PROPERTIES ENVIRONMENT_MODIFICATION + "PATH=path_list_prepend:$") + endif() add_test_executable(guest_job_manager_tests ${LIBS_INCLUDE_DIR}/tests/GuestJobManager.cpp) target_include_directories(guest_job_manager_tests PRIVATE ${LIBS_INCLUDE_DIR}) target_link_libraries(guest_job_manager_tests PRIVATE libSceJobManager libSceAgc libSceAgcDriver libkernel libc) configure_windows_unwind(guest_job_manager_tests) - if(WIN32) + if(WIN32 OR CMAKE_SYSTEM_NAME STREQUAL "Linux") add_library(job_manager_reference SHARED EXCLUDE_FROM_ALL ${LIBS_INCLUDE_DIR}/tests/GuestJobManager.cpp ${LIBS_INCLUDE_DIR}/tests/JobManagerReference.cpp) target_include_directories(job_manager_reference PRIVATE ${LIBS_INCLUDE_DIR}) target_compile_definitions(job_manager_reference PRIVATE ANYPS5_JOB_MANAGER_REFERENCE) - target_link_libraries(job_manager_reference PRIVATE libkernel libc) + target_link_libraries(job_manager_reference PRIVATE libkernel libc ${CMAKE_DL_LIBS}) set_target_properties(job_manager_reference PROPERTIES PREFIX "" SUFFIX .prx - RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/tests) + RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/tests + LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/tests) configure_windows_unwind(job_manager_reference) endif() - foreach(testCase IN ITEMS memory validation dispatch ordering nested limits node_pool priority shutdown worker_policy worker_wake worker_wait worker_count worker_spin) + foreach(testCase IN ITEMS memory owned_state validation dispatch ordering nested limits node_pool priority shutdown worker_policy worker_wake worker_wait worker_count worker_spin shutdown_running shutdown_waiter shutdown_queued shutdown_destroy shutdown_partial shutdown_cross_wait concurrent_wait) add_test(NAME guest_job_manager_${testCase} COMMAND guest_job_manager_tests ${testCase}) set_tests_properties(guest_job_manager_${testCase} PROPERTIES TIMEOUT 20) if(WIN32) diff --git a/core/libs/prx/libSceJobManager/Export.cpp b/core/libs/prx/libSceJobManager/Export.cpp index 9030b82d22..0901e79c0f 100644 --- a/core/libs/prx/libSceJobManager/Export.cpp +++ b/core/libs/prx/libSceJobManager/Export.cpp @@ -1,55 +1,36 @@ +#include "prx/libSceRazorCpu/libSceRazorCpu.hpp" +#include "prx/ulobjmgr/ulobjmgr.hpp" +#include "prx/libkernel/Time/include/Time.hpp" +#include "prx/libkernel/include/Api.hpp" +#include "prx/libSceJobManager/include/Api.hpp" +#include "prx/libSceAgcDriver/Submit/include/Acb.hpp" +#include "prx/libSceAgcDriver/Eq/include/Event.hpp" +#include "prx/libSceAgc/Cb/include/Sync.hpp" +#include "prx/libSceAgc/Cb/include/Registers.hpp" +#include "prx/libSceAgc/Cb/include/Dispatch.hpp" +#include "prx/libSceAgc/Acb/include/Sync.hpp" +#include "prx/libSceAgc/Acb/include/Memory.hpp" +#include "prx/libSceAgc/Acb/include/Dispatch.hpp" +#include "prx/libSceAgc/Acb/include/Control.hpp" #include #include #include #include #include #include +#include #include -#include #include +#include #include +#include #include -#include -#include #include "SceTypes.hpp" #include "ComputeProgress.hpp" #include "prx/libc/include/General.hpp" #include "prx/libc/include/GuestArena.hpp" -extern "C" { -int APS5_VABI scePthreadAttrInit(PthreadAttr* attr); -int APS5_VABI scePthreadAttrDestroy(PthreadAttr* attr); -int APS5_VABI scePthreadAttrSetinheritsched(PthreadAttr* attr, int inheritSched); -int APS5_VABI scePthreadAttrSetschedparam(PthreadAttr* attr, const KernelSchedParam* param); -int APS5_VABI scePthreadAttrSetstacksize(PthreadAttr* attr, std::size_t stackSize); -int APS5_VABI scePthreadAttrSetaffinity(PthreadAttr* attr, KernelCpumask mask); -int APS5_VABI scePthreadCreate(Pthread* thread, const PthreadAttr* attr, PthreadEntry entry, void* arg, const char* name); -int APS5_VABI scePthreadJoin(Pthread thread, void** result); -std::uint64_t APS5_VABI sceKernelGetTscFrequency(); -int APS5_VABI sceKernelCreateEqueue(KernelEqueue* eq, const char* name); -int APS5_VABI sceKernelDeleteEqueue(KernelEqueue eq); -int APS5_VABI sceKernelWaitEqueue(KernelEqueue eq, KernelEvent* ev, int num, int* out, const KernelUseconds* timo); -int APS5_VABI sceKernelAddUserEventEdge(KernelEqueue eq, int id); -int APS5_VABI sceKernelTriggerUserEvent(KernelEqueue eq, int id, void* udata); -int APS5_VABI sceKernelGetEventFilter(const KernelEvent* ev); -std::uintptr_t APS5_VABI sceKernelGetEventId(const KernelEvent* ev); -int APS5_VABI sceAgcDriverAddEqEvent(KernelEqueue eq, int id, void* udata); -int APS5_VABI sceAgcDriverDeleteEqEvent(KernelEqueue eq, int id); -int APS5_VABI sceAgcDriverSubmitAcb(std::uint32_t queue, const Packet* packet); -std::uint32_t* APS5_VABI sceAgcAcbAcquireMem(CommandBuffer* buf, std::uint32_t gcrControl, const volatile void* base, std::uint64_t sizeBytes, std::uint32_t pollCycles); -std::uint32_t* APS5_VABI sceAgcCbSetShRegistersDirect(CommandBuffer* buf, const volatile ShaderRegister* regs, std::uint32_t numRegs); -std::uint32_t* APS5_VABI sceAgcCbSetShRegisterRangeDirect(CommandBuffer* buf, std::uint32_t offset, const std::uint32_t* values, std::uint32_t numValues); -std::uint32_t* APS5_VABI sceAgcAcbPushMarker(CommandBuffer* buf, const char* str, std::uint32_t color); -std::uint32_t* APS5_VABI sceAgcAcbPopMarker(CommandBuffer* buf); -std::uint32_t* APS5_VABI sceAgcCbDispatch(CommandBuffer* buf, std::uint32_t threadGroupX, std::uint32_t threadGroupY, std::uint32_t threadGroupZ, std::uint32_t modifier); -std::uint32_t* APS5_VABI sceAgcAcbDispatchIndirect(CommandBuffer* buf, const volatile void* indirectArguments, std::uint32_t modifier); -std::uint32_t* APS5_VABI sceAgcCbReleaseMem(CommandBuffer* buf, std::uint8_t action, std::uint16_t gcrControl, std::uint8_t dst, std::uint8_t cachePolicy, const volatile Label* address, std::uint8_t dataSelect, std::uint64_t data, std::uint16_t gdsOffset, std::uint16_t gdsSize, std::uint8_t interrupt, std::uint32_t interruptContextId); -std::uint32_t* APS5_VABI sceAgcAcbWaitRegMem(CommandBuffer* buf, std::uint8_t size, std::uint8_t compareFunction, std::uint8_t cachePolicy, const volatile void* address, std::uint64_t reference, std::uint64_t mask, std::uint32_t pollCycles); -std::uint32_t* APS5_VABI sceAgcAcbRewind(CommandBuffer* buf, std::uint32_t initialState); -std::uint32_t* APS5_VABI sceAgcAcbWriteData(CommandBuffer* buf, std::uint8_t dst, std::uint8_t cachePolicy, std::uint64_t address, const void* data, std::uint32_t numDwords, std::uint8_t increment, std::uint8_t writeConfirm); -} - namespace { constexpr int ManagerInvalidArgument = static_cast(0x81581000u); @@ -81,30 +62,6 @@ constexpr std::uint32_t FirstComputeQueue = 0x20; constexpr std::uint32_t UserDataRegister = 0x240; constexpr int UserEventFilter = -11; -struct MemorySizeQueryParams { - std::uint32_t version; - std::uint32_t workers; - std::uint32_t sequences; - std::uint32_t invocations; - std::uint32_t dispatches; - std::uint32_t syncPoints; - std::uint32_t waits; - std::uint32_t computeSequences; - std::uint64_t computeQueueMask; -}; - -struct ConfigParams { - std::uint32_t version; - std::uint32_t threadFlags; - std::uint32_t stackSize; - std::uint32_t priority; - const char* threadName; - std::uint32_t spinMicroseconds; - std::uint32_t computeAffinity; - std::uint32_t computePriority; - std::uint32_t reserved; -}; - constexpr ConfigParams DefaultConfig{0, 0x00021fff, 0x00010000, 0x2bc, nullptr, 0, 0x1fff, 0x100, 0}; struct BlockHeader { @@ -115,8 +72,6 @@ struct BlockHeader { std::uint32_t reserved; }; -using JobEntry = void (APS5_VABI*)(void* argument, std::uint32_t index); - std::uint64_t AlignUp(std::uint64_t value, std::uint64_t alignment) { return (value + alignment - 1) & ~(alignment - 1); } @@ -153,19 +108,51 @@ class Sequence; enum class ItemType { Dispatch, SyncPoint, Wait, Compute, ComputeIndirect }; struct Item { - ItemType type; + Item* next = nullptr; + Item* runnableNext = nullptr; Sequence* sequence; - JobEntry entry; - void* argument; - std::uint32_t count; - std::uint32_t handedOut; - std::uint32_t completed; - bool* passed; - const void* shader = nullptr; - std::array groups{}; - const void* indirectArguments = nullptr; - std::string name; - bool named = false; + struct Cpu { + JobEntry entry; + void* argument; + std::uint32_t count; + std::uint32_t handedOut; + std::uint32_t completed; + }; + struct Compute { + const void* shader; + void* userData; + union { + std::array groups; + const void* indirectArguments; + }; + }; + union { + Cpu cpu; + Compute gpu; + bool* passed; + }; + const char* name = nullptr; + ItemType type; + bool encoded = false; +}; + +static_assert(sizeof(Item) == NodeBytes); + +struct RunQueue { + Item* first = nullptr; + Item* last = nullptr; + + void Push(Item* item) { + item->runnableNext = nullptr; + if (last != nullptr) last->runnableNext = item; + else first = item; + last = item; + } + + void Pop() { + first = first->runnableNext; + if (first == nullptr) last = nullptr; + } }; struct Counters { @@ -175,27 +162,6 @@ struct Counters { std::uint32_t waits = 0; }; -class ISequence { -public: - APS5_VABI virtual int Dispatch(JobEntry entry, void* argument, std::uint32_t count, const char* name) = 0; - APS5_VABI virtual int SyncPoint() = 0; - APS5_VABI virtual int Wait() = 0; - APS5_VABI virtual void CompleteDestructor() {} - APS5_VABI virtual void DeletingDestructor() { throw std::runtime_error("libSceJobManager: a sequence was deleted by its caller"); } - APS5_VABI virtual int DispatchCompute(const void* shader, void* userData, std::int32_t x, std::int32_t y, std::int32_t z, const char* name) = 0; - APS5_VABI virtual int DispatchComputeIndirect(const void* shader, void* userData, const void* indirectArguments, const char* name) = 0; -}; - -class ISequenceFactory { -public: - APS5_VABI virtual int Create(ISequence** out, std::uint32_t invocations, std::uint32_t dispatches, std::uint32_t syncPoints, std::uint32_t waits, const char* name) = 0; - APS5_VABI virtual int Destroy(ISequence* sequence) = 0; - APS5_VABI virtual void CompleteDestructor() {} - APS5_VABI virtual void DeletingDestructor() { throw std::runtime_error("libSceJobManager: a sequence factory was deleted by its caller"); } - APS5_VABI virtual int CreateCompute(ISequence** out, std::uint32_t invocations, std::uint32_t dispatches, std::uint32_t syncPoints, std::uint32_t waits, const char* name) = 0; - APS5_VABI virtual int DestroyCompute(ISequence* sequence) = 0; -}; - class Sequence final : public ISequence { public: APS5_VABI int Dispatch(JobEntry entry, void* argument, std::uint32_t count, const char* name) override; @@ -204,26 +170,32 @@ public: APS5_VABI int DispatchCompute(const void* shader, void* userData, std::int32_t x, std::int32_t y, std::int32_t z, const char* name) override; APS5_VABI int DispatchComputeIndirect(const void* shader, void* userData, const void* indirectArguments, const char* name) override; - bool Open(Manager* owner, const Counters& limit, std::uint32_t runQueue); + bool Open(Manager* owner, const Counters& limit, std::uint32_t runQueue, const char* name); int WaitAndClose(std::uint32_t index); void Advance(); void DispatchCompleted(std::uint32_t invocations); void CollectCompute(); void SetComputeStorage(std::uint32_t* commands, std::size_t words, Label* completion); - bool Busy() const { return outstanding != 0; } + void CancelWaits(); Manager* manager = nullptr; bool open = false; bool compute = false; std::uint32_t queue = 0; + std::uint16_t profileId = 0; private: int Latch(int code); void RequireOpen() const; int WaitLocked(std::unique_lock& guard); int AppendCompute(Item item); + void Append(Item* item); + void RemoveWait(Item* item); void SubmitCompute(const Item& item); + void SubmitComputeAhead(Item* item); + void RetireCompute(); void FlushCompute(); + void Profile(std::uint16_t event); Counters limits; Counters submitted; @@ -231,18 +203,42 @@ private: std::uint32_t priority = 0; int error = 0; std::uint32_t outstanding = 0; - std::size_t cursor = 0; - std::deque items; + Item* reserved = nullptr; + Item* first = nullptr; + Item* last = nullptr; + Item* cursor = nullptr; std::condition_variable passed; Label* label = nullptr; JobManager::ComputeProgress progress; std::uint32_t pendingCompute = 0; + std::uint32_t activeCompute = 0; + std::uint32_t availableCompute = 0; bool batchStarted = false; + bool profileActive = false; + bool profileCpu = false; + bool profileGpuBarrier = false; + const char* profileName = nullptr; std::uint32_t* commandBegin = nullptr; std::size_t commandWords = 0; std::size_t commandUsed = 0; }; +static_assert(sizeof(Sequence) < SequenceBytes); + +struct alignas(64) SequenceSlot { + Sequence value; + std::array padding; +}; + +static_assert(sizeof(SequenceSlot) == SequenceBytes); + +struct WorkerSlot { + Pthread thread = nullptr; + std::array padding; +}; + +static_assert(sizeof(WorkerSlot) == ThreadRecordBytes); + class Factory final : public ISequenceFactory { public: APS5_VABI int Create(ISequence** out, std::uint32_t invocations, std::uint32_t dispatches, std::uint32_t syncPoints, std::uint32_t waits, const char* name) override; @@ -255,11 +251,14 @@ public: }; struct Manager { + std::uint32_t objectId = 0; + std::uint16_t profileId = 0; std::mutex lock; std::condition_variable work; + std::condition_variable quiesced; bool running = false; std::uint32_t blockedWaiters = 0; - std::uint32_t freeNodes = 0; + Item* freeNodes = nullptr; std::uint32_t freeSequences = 0; std::uint32_t persistentThreads = 0; std::uint32_t workerCount = 0; @@ -267,18 +266,24 @@ struct Manager { std::uint32_t wakeTokens = 0; std::uint64_t pendingInvocations = 0; std::uint64_t spinTicks = 0; - std::array, 2> runQueues; - std::vector sequences; - std::deque computeSequences; + std::array runQueues; + std::span sequences; + std::span computeSequences; std::uint32_t freeComputeSequences = 0; - std::vector computeQueues; + std::uint64_t computeQueues = 0; KernelEqueue computeEvents = 0; Pthread computeHandler = nullptr; std::array factories; std::array unifiedFactories; - std::vector workers; + std::span workers; + std::uint32_t activeWorkers = 0; + void* stateBegin = nullptr; + std::size_t stateBytes = 0; + std::span nodes; }; +static_assert(sizeof(Manager) <= StateEnd - StateOffset); + thread_local Manager* currentWorker = nullptr; void WakeWorkers(Manager& manager, std::uint32_t invocations, bool publisherCanRun = true) { @@ -291,14 +296,18 @@ Manager*& Implementation(void* self) { return *static_cast(self); } -bool TakeNode(Manager& manager) { - if (manager.freeNodes == 0) return false; - --manager.freeNodes; - return true; +Item* TakeNode(Manager& manager) { + Item* item = manager.freeNodes; + if (item != nullptr) { + manager.freeNodes = item->next; + *item = {}; + } + return item; } -void ReturnNodes(Manager& manager, std::uint32_t count) { - manager.freeNodes += count; +void ReturnNode(Manager& manager, Item* item) { + item->next = manager.freeNodes; + manager.freeNodes = item; } int Sequence::Latch(int code) { @@ -306,7 +315,12 @@ int Sequence::Latch(int code) { return code; } -bool Sequence::Open(Manager* owner, const Counters& limit, std::uint32_t runQueue) { +void Sequence::Profile(std::uint16_t event) { + const auto id = static_cast(profileId - (compute && event <= 2 ? manager->sequences.size() : 0)); + static_cast(sceRazorCpuJobManagerSequence(profileName, manager->profileId, id, event)); +} + +bool Sequence::Open(Manager* owner, const Counters& limit, std::uint32_t runQueue, const char* name) { manager = owner; limits = limit; submitted = {}; @@ -314,12 +328,21 @@ bool Sequence::Open(Manager* owner, const Counters& limit, std::uint32_t runQueu priority = runQueue; error = 0; outstanding = 0; - cursor = 0; - items.clear(); + cursor = nullptr; + first = nullptr; + last = nullptr; commandUsed = 0; batchStarted = false; - if (!TakeNode(*owner)) return false; + activeCompute = 0; + availableCompute = 0; + profileActive = false; + profileCpu = false; + profileGpuBarrier = false; + profileName = name; + reserved = TakeNode(*owner); + if (reserved == nullptr) return false; open = true; + Profile(1); return true; } @@ -327,34 +350,92 @@ void Sequence::RequireOpen() const { if (!open) throw std::runtime_error("libSceJobManager: a destroyed sequence was used"); } +void Sequence::Append(Item* item) { + item->next = nullptr; + if (last != nullptr) last->next = item; + else first = item; + last = item; + if (cursor == nullptr) cursor = item; +} + +void Sequence::RemoveWait(Item* item) { + Item* previous = nullptr; + for (Item* current = first; current != nullptr; current = current->next) { + if (current == item) { + if (previous != nullptr) previous->next = item->next; + else first = item->next; + if (last == item) last = previous; + if (cursor == item) cursor = item->next; + return; + } + previous = current; + } +} + void Sequence::Advance() { - while (cursor < items.size()) { - Item& item = items[cursor]; + while (cursor != nullptr) { + Item& item = *cursor; if (item.type == ItemType::Dispatch) { + if (profileGpuBarrier) { + Profile(4); + profileActive = false; + profileGpuBarrier = false; + } + if (!profileActive) Profile(3); + profileActive = true; + profileCpu = true; + if (!manager->running) return; ++outstanding; - ++cursor; - manager->runQueues[priority].push_back(&item); - manager->pendingInvocations -= item.count; - WakeWorkers(*manager, item.count); + cursor = item.next; + manager->runQueues[priority].Push(&item); + manager->pendingInvocations -= item.cpu.count; + WakeWorkers(*manager, item.cpu.count); continue; } if (item.type == ItemType::Compute || item.type == ItemType::ComputeIndirect) { + if (!manager->running) return; + if (!profileActive) Profile(3); + profileActive = true; + profileGpuBarrier = false; ++outstanding; - ++cursor; - SubmitCompute(item); + ++activeCompute; + cursor = item.next; + if (!item.encoded) { + SubmitCompute(item); + item.encoded = true; + } + RetireCompute(); continue; } FlushCompute(); - if (outstanding != 0) return; + if (outstanding != 0) { + if (item.type == ItemType::SyncPoint && !profileCpu && manager->running) SubmitComputeAhead(item.next); + return; + } if (item.type == ItemType::SyncPoint) { + if (profileCpu) { + Profile(4); + profileActive = false; + profileCpu = false; + } + profileGpuBarrier = profileActive; ++completed.syncPoints; - ++cursor; + cursor = item.next; continue; } + if (profileActive) Profile(4); + profileActive = false; + profileCpu = false; + profileGpuBarrier = false; bool* const waiter = item.passed; - const auto retired = static_cast(cursor); - items.erase(items.begin(), items.begin() + static_cast(retired + 1)); - cursor = 0; + while (first != &item) { + Item* retired = first; + first = first->next; + ReturnNode(*manager, retired); + } + first = item.next; + if (last == &item) last = nullptr; + cursor = first; commandUsed = 0; batchStarted = false; if (error == 0) { @@ -364,7 +445,6 @@ void Sequence::Advance() { --submitted.waits; completed = {}; } - ReturnNodes(*manager, retired); *waiter = true; passed.notify_all(); } @@ -377,7 +457,14 @@ void Sequence::DispatchCompleted(std::uint32_t invocations) { if (outstanding == 0) Advance(); } -int Sequence::Dispatch(JobEntry entry, void* argument, std::uint32_t count, const char*) { +void Sequence::CancelWaits() { + for (Item* item = first; item != nullptr; item = item->next) { + if (item->type == ItemType::Wait) *item->passed = true; + } + passed.notify_all(); +} + +int Sequence::Dispatch(JobEntry entry, void* argument, std::uint32_t count, const char* name) { if (entry == nullptr) return SequenceNullArgument; if (count == 0 || count > MaxInvocations) return SequenceOutOfRange; const std::lock_guard guard(manager->lock); @@ -387,15 +474,20 @@ int Sequence::Dispatch(JobEntry entry, void* argument, std::uint32_t count, cons submitted.invocations += count; ++submitted.dispatches; if (before.invocations + count > limits.invocations || before.dispatches >= limits.dispatches) return Latch(SequenceLimitExceeded); - if (!TakeNode(*manager)) return Latch(SequenceNoNodes); - items.push_back({ItemType::Dispatch, this, entry, argument, count, 0, 0, nullptr}); + Item* item = TakeNode(*manager); + if (item == nullptr) return Latch(SequenceNoNodes); + item->type = ItemType::Dispatch; + item->sequence = this; + item->name = name; + item->cpu = {entry, argument, count, 0, 0}; + Append(item); manager->pendingInvocations += count; Advance(); return 0; } void Sequence::SubmitCompute(const Item& item) { - const auto* bytes = static_cast(item.shader); + const auto* bytes = static_cast(item.gpu.shader); const ShaderRegister* registers = nullptr; const std::uint8_t* specials = nullptr; std::memcpy(®isters, bytes + 0x20, sizeof(registers)); @@ -403,9 +495,9 @@ void Sequence::SubmitCompute(const Item& item) { const std::uint32_t registerCount = bytes[0x5c]; std::uint32_t modifier = 0; std::memcpy(&modifier, specials + 0x10, sizeof(modifier)); - const auto userData = reinterpret_cast(item.argument); + const auto userData = reinterpret_cast(item.gpu.userData); const std::array userDataWords{static_cast(userData), static_cast(userData >> 32)}; - const auto capacity = std::min(commandWords - commandUsed, 64 + 3 * registerCount + item.name.size() / 4); + const auto capacity = std::min(commandWords - commandUsed, 64 + 3 * registerCount + (item.name != nullptr ? std::strlen(item.name) / 4 : 0)); auto* const words = commandBegin + commandUsed; CommandBuffer buffer{words, words + capacity, words, words + capacity, nullptr, nullptr, 0}; { @@ -413,13 +505,13 @@ void Sequence::SubmitCompute(const Item& item) { bool encoded = sceAgcAcbAcquireMem(&buffer, 0x20380u | (batchStarted ? 0u : 1u), nullptr, 0, 0x190) != nullptr; encoded = encoded && sceAgcCbSetShRegistersDirect(&buffer, registers, registerCount) != nullptr; encoded = encoded && sceAgcCbSetShRegisterRangeDirect(&buffer, UserDataRegister, userDataWords.data(), 2) != nullptr; - if (item.named) encoded = encoded && sceAgcAcbPushMarker(&buffer, item.name.c_str(), 0) != nullptr; + if (item.name != nullptr) encoded = encoded && sceAgcAcbPushMarker(&buffer, item.name, 0) != nullptr; if (item.type == ItemType::Compute) { - encoded = encoded && sceAgcCbDispatch(&buffer, item.groups[0], item.groups[1], item.groups[2], modifier) != nullptr; + encoded = encoded && sceAgcCbDispatch(&buffer, item.gpu.groups[0], item.gpu.groups[1], item.gpu.groups[2], modifier) != nullptr; } else { - encoded = encoded && sceAgcAcbDispatchIndirect(&buffer, item.indirectArguments, modifier) != nullptr; + encoded = encoded && sceAgcAcbDispatchIndirect(&buffer, item.gpu.indirectArguments, modifier) != nullptr; } - if (item.named) encoded = encoded && sceAgcAcbPopMarker(&buffer) != nullptr; + if (item.name != nullptr) encoded = encoded && sceAgcAcbPopMarker(&buffer) != nullptr; if (!encoded) throw std::runtime_error("libSceJobManager: a compute dispatch did not fit its command buffer"); } batchStarted = true; @@ -437,6 +529,21 @@ void Sequence::SetComputeStorage(std::uint32_t* commands, std::size_t words, Lab label->value = 0; } +void Sequence::SubmitComputeAhead(Item* item) { + while (item != nullptr) { + if (item->type == ItemType::Compute || item->type == ItemType::ComputeIndirect) { + if (!item->encoded) { + SubmitCompute(*item); + item->encoded = true; + } + } else { + FlushCompute(); + if (item->type != ItemType::SyncPoint) return; + } + item = item->next; + } +} + void Sequence::FlushCompute() { if (pendingCompute == 0) return; if (commandWords - commandUsed < 8) throw std::runtime_error("libSceJobManager: a compute completion did not fit its command buffer"); @@ -454,11 +561,19 @@ void Sequence::FlushCompute() { if (sceAgcDriverSubmitAcb(queue, &packet) != 0) throw std::runtime_error("libSceJobManager: sceAgcDriverSubmitAcb failed for a completion"); } +void Sequence::RetireCompute() { + const auto finished = std::min(activeCompute, availableCompute); + activeCompute -= finished; + availableCompute -= finished; + completed.dispatches += finished; + outstanding -= finished; +} + void Sequence::CollectCompute() { const auto finished = progress.Collect(label->value); if (finished == 0) return; - completed.dispatches += finished; - outstanding -= finished; + availableCompute += finished; + RetireCompute(); if (outstanding == 0) Advance(); } @@ -468,8 +583,10 @@ int Sequence::AppendCompute(Item item) { if (!compute) throw std::runtime_error("libSceJobManager: a compute dispatch was made on a CPU sequence"); if (error != 0) return SequenceInvalid; if (submitted.dispatches++ >= limits.dispatches) return Latch(SequenceLimitExceeded); - if (!TakeNode(*manager)) return Latch(SequenceNoNodes); - items.push_back(std::move(item)); + Item* stored = TakeNode(*manager); + if (stored == nullptr) return Latch(SequenceNoNodes); + *stored = item; + Append(stored); Advance(); return 0; } @@ -477,22 +594,26 @@ int Sequence::AppendCompute(Item item) { int Sequence::DispatchCompute(const void* shader, void* userData, std::int32_t x, std::int32_t y, std::int32_t z, const char* name) { if (shader == nullptr) return SequenceNullArgument; if (x <= 0 || y <= 0 || z <= 0) return SequenceOutOfRange; - Item item{ItemType::Compute, this, nullptr, userData, 0, 0, 0, nullptr}; - item.shader = shader; - item.groups = {static_cast(x), static_cast(y), static_cast(z)}; - item.named = name != nullptr; - if (item.named) item.name = name; - return AppendCompute(std::move(item)); + Item item{}; + item.type = ItemType::Compute; + item.sequence = this; + item.gpu.shader = shader; + item.gpu.userData = userData; + item.gpu.groups = {static_cast(x), static_cast(y), static_cast(z)}; + item.name = name; + return AppendCompute(item); } int Sequence::DispatchComputeIndirect(const void* shader, void* userData, const void* indirectArguments, const char* name) { if (shader == nullptr || indirectArguments == nullptr || (reinterpret_cast(indirectArguments) & 0x1f) != 0) return SequenceNullArgument; - Item item{ItemType::ComputeIndirect, this, nullptr, userData, 0, 0, 0, nullptr}; - item.shader = shader; - item.indirectArguments = indirectArguments; - item.named = name != nullptr; - if (item.named) item.name = name; - return AppendCompute(std::move(item)); + Item item{}; + item.type = ItemType::ComputeIndirect; + item.sequence = this; + item.gpu.shader = shader; + item.gpu.userData = userData; + item.gpu.indirectArguments = indirectArguments; + item.name = name; + return AppendCompute(item); } int Sequence::SyncPoint() { @@ -501,8 +622,11 @@ int Sequence::SyncPoint() { if (error != 0) return SequenceInvalid; const std::uint32_t before = submitted.syncPoints++; if (before >= limits.syncPoints) return Latch(SequenceLimitExceeded); - if (!TakeNode(*manager)) return Latch(SequenceNoNodes); - items.push_back({ItemType::SyncPoint, this, nullptr, nullptr, 0, 0, 0, nullptr}); + Item* item = TakeNode(*manager); + if (item == nullptr) return Latch(SequenceNoNodes); + item->type = ItemType::SyncPoint; + item->sequence = this; + Append(item); Advance(); return 0; } @@ -515,13 +639,19 @@ int Sequence::Wait() { int Sequence::WaitAndClose(std::uint32_t index) { std::unique_lock guard(manager->lock); const int result = WaitLocked(guard); - const auto remaining = static_cast(std::count_if(items.begin(), items.end(), [](const Item& item) { return item.type != ItemType::Wait; })); - ReturnNodes(*manager, remaining + 1); - items.clear(); + while (first != nullptr) { + Item* item = first; + first = item->next; + if (item->type != ItemType::Wait) ReturnNode(*manager, item); + } + ReturnNode(*manager, reserved); + reserved = nullptr; + last = nullptr; commandUsed = 0; - cursor = 0; + cursor = nullptr; outstanding = 0; open = false; + Profile(2); (compute ? manager->freeComputeSequences : manager->freeSequences) |= std::uint32_t{1} << index; return result; } @@ -536,17 +666,23 @@ int Sequence::WaitLocked(std::unique_lock& guard) { } ++manager->blockedWaiters; bool done = false; - items.push_back({ItemType::Wait, this, nullptr, nullptr, 0, 0, 0, &done}); + Item waiter{}; + waiter.type = ItemType::Wait; + waiter.sequence = this; + waiter.passed = &done; + Append(&waiter); Advance(); if (!done && currentWorker == manager) { std::uint64_t runnable = 0; for (const auto& queue : manager->runQueues) { - for (const Item* item : queue) runnable += item->count - item->handedOut; + for (const Item* item = queue.first; item != nullptr; item = item->runnableNext) runnable += item->cpu.count - item->cpu.handedOut; } WakeWorkers(*manager, static_cast(std::min(runnable, std::uint64_t{manager->workerCount})), false); } passed.wait(guard, [&done] { return done; }); + RemoveWait(&waiter); --manager->blockedWaiters; + manager->quiesced.notify_all(); return result; } @@ -556,15 +692,15 @@ bool ValidLimits(std::uint32_t invocations, std::uint32_t dispatches, std::uint3 } template -int CreateIn(Manager* manager, TSequences& sequences, std::uint32_t& free, std::uint32_t priority, ISequence** out, const Counters& limits) { +int CreateIn(Manager* manager, TSequences& sequences, std::uint32_t& free, std::uint32_t priority, ISequence** out, const Counters& limits, const char* name) { if (out == nullptr) return SequenceNullArgument; if (!ValidLimits(limits.invocations, limits.dispatches, limits.syncPoints, limits.waits)) return SequenceOutOfRange; const std::lock_guard guard(manager->lock); if (free == 0) return SequenceNoneFree; const int index = std::countr_zero(free); free &= ~(std::uint32_t{1} << index); - Sequence& sequence = sequences[static_cast(index)]; - if (!sequence.Open(manager, limits, priority)) return SequenceNoNodes; + Sequence& sequence = sequences[static_cast(index)].value; + if (!sequence.Open(manager, limits, priority, name)) return SequenceNoNodes; *out = &sequence; return 0; } @@ -576,25 +712,25 @@ int DestroyIn(Manager* manager, TSequences& sequences, const std::uint32_t& free { const std::lock_guard guard(manager->lock); for (; index < sequences.size(); ++index) { - if (&sequences[index] == sequence) break; + if (&sequences[index].value == sequence) break; } if (index == sequences.size() || (free & (std::uint32_t{1} << index)) != 0) return SequenceInvalid; - found = &sequences[index]; + found = &sequences[index].value; } static_cast(found->WaitAndClose(index)); return 0; } -int Factory::Create(ISequence** out, std::uint32_t invocations, std::uint32_t dispatches, std::uint32_t syncPoints, std::uint32_t waits, const char*) { - return CreateIn(manager, manager->sequences, manager->freeSequences, priority, out, {invocations, dispatches, syncPoints, waits}); +int Factory::Create(ISequence** out, std::uint32_t invocations, std::uint32_t dispatches, std::uint32_t syncPoints, std::uint32_t waits, const char* name) { + return CreateIn(manager, manager->sequences, manager->freeSequences, priority, out, {invocations, dispatches, syncPoints, waits}, name); } int Factory::Destroy(ISequence* sequence) { return DestroyIn(manager, manager->sequences, manager->freeSequences, sequence); } -int Factory::CreateCompute(ISequence** out, std::uint32_t invocations, std::uint32_t dispatches, std::uint32_t syncPoints, std::uint32_t waits, const char*) { - return CreateIn(manager, manager->computeSequences, manager->freeComputeSequences, priority, out, {invocations, dispatches, syncPoints, waits}); +int Factory::CreateCompute(ISequence** out, std::uint32_t invocations, std::uint32_t dispatches, std::uint32_t syncPoints, std::uint32_t waits, const char* name) { + return CreateIn(manager, manager->computeSequences, manager->freeComputeSequences, priority, out, {invocations, dispatches, syncPoints, waits}, name); } int Factory::DestroyCompute(ISequence* sequence) { @@ -610,7 +746,7 @@ void* APS5_VABI ComputeHandlerEntry(void* argument) { if (count <= 0) continue; if (sceKernelGetEventFilter(&event) == UserEventFilter && sceKernelGetEventId(&event) == 0) return nullptr; const std::lock_guard guard(manager.lock); - for (Sequence& sequence : manager.computeSequences) sequence.CollectCompute(); + for (SequenceSlot& slot : manager.computeSequences) slot.value.CollectCompute(); } } @@ -618,19 +754,25 @@ bool RunOne(Manager& manager, std::unique_lock& guard) { Item* item = nullptr; for (const std::size_t queue : {std::size_t{1}, std::size_t{0}}) { auto& pending = manager.runQueues[queue]; - if (pending.empty()) continue; - item = pending.front(); - if (item->handedOut + 1 == item->count) pending.pop_front(); + if (pending.first == nullptr) continue; + item = pending.first; + if (item->cpu.handedOut + 1 == item->cpu.count) pending.Pop(); break; } if (item == nullptr) return false; - const std::uint32_t index = item->handedOut++; - const JobEntry entry = item->entry; - void* const argument = item->argument; + const std::uint32_t index = item->cpu.handedOut++; + const JobEntry entry = item->cpu.entry; + void* const argument = item->cpu.argument; + const auto dispatchId = static_cast(item - manager.nodes.data()); guard.unlock(); + static_cast(sceRazorCpuJobManagerJob(manager.profileId, dispatchId, static_cast(index), 16)); entry(argument, index); + static_cast(sceRazorCpuJobManagerJob(manager.profileId, dispatchId, static_cast(index), 32)); guard.lock(); - if (++item->completed == item->count) item->sequence->DispatchCompleted(item->count); + if (++item->cpu.completed == item->cpu.count) { + static_cast(sceRazorCpuJobManagerDispatch(item->name, manager.profileId, item->sequence->profileId, dispatchId, static_cast(item->cpu.count), reinterpret_cast(entry), reinterpret_cast(argument))); + item->sequence->DispatchCompleted(item->cpu.count); + } return true; } @@ -661,6 +803,10 @@ void* APS5_VABI WorkerEntry(void* argument) { } struct WorkLayout { + std::uint64_t workers = 0; + std::uint64_t sequences = 0; + std::uint64_t stateEnd = 0; + std::uint64_t pool = 0; std::uint64_t commands = 0; std::uint64_t commandBytes = 0; std::uint64_t labels = 0; @@ -670,9 +816,12 @@ struct WorkLayout { WorkLayout LayoutFor(std::uint64_t memory, std::uint64_t size, std::uint32_t workers, std::uint32_t sequences, std::uint32_t computeQueues) { WorkLayout layout; const std::uint64_t end = memory + size; - std::uint64_t address = AlignUp(memory + StateEnd, 8) + workers * ThreadRecordBytes; + layout.workers = AlignUp(memory + StateEnd, 8); + std::uint64_t address = layout.workers + workers * ThreadRecordBytes; for (const std::uint64_t bytes : {std::uint64_t{0x100}, std::uint64_t{0x80}, std::uint64_t{0x80}, std::uint64_t{0x80}}) address = AlignUp(address, 64) + bytes; - address = AlignUp(address, 64) + (sequences + computeQueues) * SequenceBytes; + layout.sequences = AlignUp(address, 64); + address = layout.sequences + (sequences + computeQueues) * SequenceBytes; + layout.stateEnd = address; if (computeQueues != 0) { layout.commandBytes = ComputeCommandBudget(); layout.commands = AlignUp(address + ComputeContextBytes, 0x100); @@ -680,6 +829,7 @@ WorkLayout LayoutFor(std::uint64_t memory, std::uint64_t size, std::uint32_t wor address = layout.labels + 8 * std::uint64_t{computeQueues}; } address = AlignUp(address, 64); + layout.pool = address; if (address <= end) layout.nodes = static_cast(((end - address) / NodeBytes) & 0xffff); return layout; } @@ -692,6 +842,17 @@ int ValidateWorkers(const ConfigParams& config, std::uint32_t workers) { return 0; } +class ThreadAttributes { +public: + ThreadAttributes() { + if (scePthreadAttrInit(&value) != 0) throw std::runtime_error("libSceJobManager: scePthreadAttrInit failed"); + } + ~ThreadAttributes() { static_cast(scePthreadAttrDestroy(&value)); } + ThreadAttributes(const ThreadAttributes&) = delete; + ThreadAttributes& operator=(const ThreadAttributes&) = delete; + PthreadAttr value = nullptr; +}; + void StartWorkers(Manager& manager, const ConfigParams& config, std::uint32_t workers) { std::uint32_t remaining = config.threadFlags & 0x1fff; for (std::uint32_t index = 0; index < workers; ++index) { @@ -700,19 +861,19 @@ void StartWorkers(Manager& manager, const ConfigParams& config, std::uint32_t wo affinity = remaining & (~remaining + 1); remaining &= remaining - 1; } - const std::string name = config.threadName != nullptr ? std::string(config.threadName).substr(0, 31) : "SceJobManagerWorker" + std::to_string(index); + std::array name{}; + if (config.threadName != nullptr) std::snprintf(name.data(), name.size(), "%.31s", config.threadName); + else std::snprintf(name.data(), name.size(), "SceJobManagerWorker%u", index); const KernelSchedParam schedule{static_cast(config.priority)}; - PthreadAttr attributes = nullptr; - if (scePthreadAttrInit(&attributes) != 0) throw std::runtime_error("libSceJobManager: scePthreadAttrInit failed"); - if (scePthreadAttrSetinheritsched(&attributes, 0) != 0 || scePthreadAttrSetschedparam(&attributes, &schedule) != 0 || - scePthreadAttrSetstacksize(&attributes, config.stackSize) != 0 || scePthreadAttrSetaffinity(&attributes, affinity) != 0) { + ThreadAttributes attributes; + if (scePthreadAttrSetinheritsched(&attributes.value, 0) != 0 || scePthreadAttrSetschedparam(&attributes.value, &schedule) != 0 || + scePthreadAttrSetstacksize(&attributes.value, config.stackSize) != 0 || scePthreadAttrSetaffinity(&attributes.value, affinity) != 0) { throw std::runtime_error("libSceJobManager: a worker thread attribute was rejected"); } Pthread thread = nullptr; - const int created = scePthreadCreate(&thread, &attributes, WorkerEntry, &manager, name.c_str()); - scePthreadAttrDestroy(&attributes); + const int created = scePthreadCreate(&thread, &attributes.value, WorkerEntry, &manager, name.data()); if (created != 0) throw std::runtime_error("libSceJobManager: scePthreadCreate failed for a worker"); - manager.workers.push_back(thread); + manager.workers[manager.activeWorkers++].thread = thread; } } @@ -721,27 +882,67 @@ void StartCompute(Manager& manager, const WorkLayout& layout, std::uint32_t comp for (std::uint64_t mask = computeQueueMask; mask != 0; mask &= mask - 1) { const std::uint32_t queue = FirstComputeQueue + static_cast(std::countr_zero(mask)); if (sceAgcDriverAddEqEvent(manager.computeEvents, static_cast(queue), nullptr) != 0) throw std::runtime_error("libSceJobManager: sceAgcDriverAddEqEvent failed"); - manager.computeQueues.push_back(queue); + manager.computeQueues |= std::uint64_t{1} << (queue - FirstComputeQueue); } - manager.computeSequences.resize(computeSequences); + std::uint64_t availableQueues = computeQueueMask; for (std::uint32_t index = 0; index < computeSequences; ++index) { - manager.computeSequences[index].compute = true; - manager.computeSequences[index].queue = manager.computeQueues[index]; - manager.computeSequences[index].SetComputeStorage(reinterpret_cast(layout.commands + index * layout.commandBytes), + Sequence& sequence = manager.computeSequences[index].value; + sequence.compute = true; + sequence.queue = FirstComputeQueue + static_cast(std::countr_zero(availableQueues)); + availableQueues &= availableQueues - 1; + sequence.SetComputeStorage(reinterpret_cast(layout.commands + index * layout.commandBytes), static_cast(layout.commandBytes / 4), reinterpret_cast(layout.labels + index * sizeof(Label))); } manager.freeComputeSequences = computeSequences == MaxSequences ? ~std::uint32_t{0} : (std::uint32_t{1} << computeSequences) - 1; const KernelSchedParam schedule{static_cast(priority)}; - PthreadAttr attributes = nullptr; - if (scePthreadAttrInit(&attributes) != 0 || scePthreadAttrSetinheritsched(&attributes, 0) != 0 || scePthreadAttrSetschedparam(&attributes, &schedule) != 0 || - scePthreadAttrSetstacksize(&attributes, 0x4000) != 0 || scePthreadAttrSetaffinity(&attributes, affinity) != 0) { + ThreadAttributes attributes; + if (scePthreadAttrSetinheritsched(&attributes.value, 0) != 0 || scePthreadAttrSetschedparam(&attributes.value, &schedule) != 0 || + scePthreadAttrSetstacksize(&attributes.value, 0x4000) != 0 || scePthreadAttrSetaffinity(&attributes.value, affinity) != 0) { throw std::runtime_error("libSceJobManager: a compute handler thread attribute was rejected"); } - const int created = scePthreadCreate(&manager.computeHandler, &attributes, ComputeHandlerEntry, &manager, "SceJobManagerComputeEventHdlr"); - scePthreadAttrDestroy(&attributes); + const int created = scePthreadCreate(&manager.computeHandler, &attributes.value, ComputeHandlerEntry, &manager, "SceJobManagerComputeEventHdlr"); if (created != 0) throw std::runtime_error("libSceJobManager: scePthreadCreate failed for the compute handler"); } +void StopManager(Manager& manager) { + { + const std::lock_guard guard(manager.lock); + manager.running = false; + manager.work.notify_all(); + } + while (manager.activeWorkers != 0) { + if (scePthreadJoin(manager.workers[manager.activeWorkers - 1].thread, nullptr) != 0) throw std::runtime_error("sce::Job::JobManager::shutdown: scePthreadJoin failed"); + manager.workers[--manager.activeWorkers].thread = nullptr; + } + if (manager.computeHandler != nullptr) { + if (sceKernelAddUserEventEdge(manager.computeEvents, 0) != 0 || sceKernelTriggerUserEvent(manager.computeEvents, 0, nullptr) != 0) { + throw std::runtime_error("sce::Job::JobManager::shutdown: the compute handler could not be signalled"); + } + if (scePthreadJoin(manager.computeHandler, nullptr) != 0) throw std::runtime_error("sce::Job::JobManager::shutdown: scePthreadJoin failed"); + manager.computeHandler = nullptr; + } + if (manager.computeEvents != 0) { + for (std::uint64_t mask = manager.computeQueues; mask != 0; mask &= mask - 1) { + const auto queue = FirstComputeQueue + static_cast(std::countr_zero(mask)); + static_cast(sceAgcDriverDeleteEqEvent(manager.computeEvents, static_cast(queue))); + } + if (sceKernelDeleteEqueue(manager.computeEvents) != 0) throw std::runtime_error("sce::Job::JobManager::shutdown: sceKernelDeleteEqueue failed"); + manager.computeEvents = 0; + manager.computeQueues = 0; + } + std::unique_lock guard(manager.lock); + for (SequenceSlot& slot : manager.sequences) slot.value.CancelWaits(); + for (SequenceSlot& slot : manager.computeSequences) slot.value.CancelWaits(); + manager.quiesced.wait(guard, [&manager] { return manager.blockedWaiters == 0; }); +} + +void DestroyManager(Manager* manager) { + const GuestArena::HostWrite memory(manager->stateBegin, manager->stateBytes); + for (SequenceSlot& slot : manager->sequences) std::destroy_at(&slot); + for (SequenceSlot& slot : manager->computeSequences) std::destroy_at(&slot); + std::destroy_at(manager); +} + int Initialize(void* self, void* memory, std::uint64_t size, std::uint32_t workers, std::uint32_t sequences, std::uint32_t computeSequences, std::uint64_t computeQueueMask, const ConfigParams* config, bool unified) { if (Implementation(self) != nullptr) return ManagerAlreadyInitialized; if (memory == nullptr) return ManagerNullMemory; @@ -771,23 +972,60 @@ int Initialize(void* self, void* memory, std::uint64_t size, std::uint32_t worke const std::uint32_t handlerPriority = ownHandlerSettings ? settings.computePriority : 0x100; const std::uint32_t handlerAffinity = ownHandlerSettings ? settings.computeAffinity : 0x1fff; if (computeSequences != 0 && (handlerPriority < 0x100 || handlerPriority > 0x2ff || handlerAffinity == 0 || handlerAffinity > 0x1fff)) return ManagerInvalidArgument; - auto* manager = new Manager; + const GuestArena::HostWrite stateMemory(memory, static_cast(layout.stateEnd - base)); + const GuestArena::HostWrite nodeMemory(reinterpret_cast(layout.pool), layout.nodes * sizeof(Item)); + Manager* manager = std::construct_at(reinterpret_cast(base + StateOffset)); + manager->stateBegin = memory; + manager->stateBytes = static_cast(layout.stateEnd - base); + manager->nodes = {reinterpret_cast(layout.pool), layout.nodes}; + std::unique_ptr owner(manager, DestroyManager); manager->running = true; manager->workerCount = workers; manager->spinTicks = sceKernelGetTscFrequency() / 1000000 * settings.spinMicroseconds; - manager->freeNodes = layout.nodes - 1; + for (std::uint32_t index = 0; index < layout.nodes; ++index) std::construct_at(&manager->nodes[index]); + for (std::uint32_t index = layout.nodes; index > 1; --index) ReturnNode(*manager, &manager->nodes[index - 1]); manager->freeSequences = sequences == MaxSequences ? ~std::uint32_t{0} : (std::uint32_t{1} << sequences) - 1; - manager->sequences = std::vector(sequences); + manager->workers = {reinterpret_cast(layout.workers), workers}; + for (WorkerSlot& worker : manager->workers) std::construct_at(&worker); + auto* cpuSlots = reinterpret_cast(layout.sequences); + auto* computeSlots = cpuSlots + sequences; + for (std::uint32_t index = 0; index < sequences; ++index) { + std::construct_at(cpuSlots + index); + cpuSlots[index].value.profileId = static_cast(index); + manager->sequences = {cpuSlots, index + 1}; + } + for (std::uint32_t index = 0; index < computeSequences; ++index) { + std::construct_at(computeSlots + index); + computeSlots[index].value.profileId = static_cast(sequences + index); + manager->computeSequences = {computeSlots, index + 1}; + } for (std::uint32_t priority = 0; priority < 2; ++priority) { manager->factories[priority].manager = manager; manager->factories[priority].priority = priority; manager->unifiedFactories[priority].manager = manager; manager->unifiedFactories[priority].priority = priority; } - if (computeSequences != 0) StartCompute(*manager, layout, computeSequences, computeQueueMask, handlerPriority, handlerAffinity); - Implementation(self) = manager; - StartWorkers(*manager, settings, workers); - return 0; + try { + if (computeSequences != 0) StartCompute(*manager, layout, computeSequences, computeQueueMask, handlerPriority, handlerAffinity); + StartWorkers(*manager, settings, workers); + } catch (...) { + try { + StopManager(*manager); + } catch (...) { + Implementation(self) = owner.release(); + throw; + } + throw; + } + Implementation(self) = owner.release(); + const int result = _sceUlobjmgrRegisterObject_nid_postfix(base, 0x21, &manager->objectId); + std::uint32_t crc = 0; + for (std::uint32_t byte = 0; byte < sizeof(base); ++byte) { + crc ^= static_cast(base >> (byte * 8)); + for (std::uint32_t bit = 0; bit < 8; ++bit) crc = (crc >> 1) ^ (0x82f63b78u & (0u - (crc & 1))); + } + manager->profileId = static_cast(crc >> 16); + return result; } ISequenceFactory* FactoryFor(void* self, std::uint32_t priority, bool unified) { @@ -810,8 +1048,6 @@ void APS5_VABI _ZN3sce3Job10JobManagerC2Ev(void* self) { Implementation(self) = nullptr; } -int APS5_VABI _ZN3sce3Job10JobManager8shutdownEv(void* self); - void APS5_VABI _ZN3sce3Job10JobManagerD1Ev(void* self) { if (Implementation(self) != nullptr) { static_cast(_ZN3sce3Job10JobManager8shutdownEv(self)); @@ -820,6 +1056,7 @@ void APS5_VABI _ZN3sce3Job10JobManagerD1Ev(void* self) { void APS5_VABI _ZN3sce3Job10JobManagerD2Ev(void* self) { _ZN3sce3Job10JobManagerD1Ev(self); + } std::uint64_t APS5_VABI _ZN3sce3Job10JobManager27calculateRequiredMemorySizeEPKNS1_21MemorySizeQueryParamsE(const MemorySizeQueryParams* params) { @@ -862,28 +1099,15 @@ int APS5_VABI _ZN3sce3Job10JobManager10initializeEPvmjjPKNS1_12ConfigParamsE(voi int APS5_VABI _ZN3sce3Job10JobManager8shutdownEv(void* self) { Manager* manager = Implementation(self); if (manager == nullptr) return ManagerNotInitialized; + if (currentWorker == manager) throw std::runtime_error("sce::Job::JobManager::shutdown: a worker cannot join itself"); { const std::lock_guard guard(manager->lock); - if (manager->blockedWaiters != 0) throw std::runtime_error("sce::Job::JobManager::shutdown: a thread is still blocked in a sequence wait"); - for (const Sequence& sequence : manager->computeSequences) { - if (sequence.open && sequence.Busy()) throw std::runtime_error("sce::Job::JobManager::shutdown: a compute sequence still has work in flight"); - } manager->running = false; - manager->work.notify_all(); - } - for (const Pthread worker : manager->workers) { - if (scePthreadJoin(worker, nullptr) != 0) throw std::runtime_error("sce::Job::JobManager::shutdown: scePthreadJoin failed"); - } - if (manager->computeHandler != nullptr) { - if (sceKernelAddUserEventEdge(manager->computeEvents, 0) != 0 || sceKernelTriggerUserEvent(manager->computeEvents, 0, nullptr) != 0) { - throw std::runtime_error("sce::Job::JobManager::shutdown: the compute handler could not be signalled"); - } - if (scePthreadJoin(manager->computeHandler, nullptr) != 0) throw std::runtime_error("sce::Job::JobManager::shutdown: scePthreadJoin failed"); - for (const std::uint32_t queue : manager->computeQueues) static_cast(sceAgcDriverDeleteEqEvent(manager->computeEvents, static_cast(queue))); - if (sceKernelDeleteEqueue(manager->computeEvents) != 0) throw std::runtime_error("sce::Job::JobManager::shutdown: sceKernelDeleteEqueue failed"); } + StopManager(*manager); + static_cast(_sceUlobjmgrUnregisterObject_nid_postfix(manager->objectId)); Implementation(self) = nullptr; - delete manager; + DestroyManager(manager); return 0; } diff --git a/core/libs/prx/libSceJobManager/include/Api.hpp b/core/libs/prx/libSceJobManager/include/Api.hpp new file mode 100644 index 0000000000..f76c944d21 --- /dev/null +++ b/core/libs/prx/libSceJobManager/include/Api.hpp @@ -0,0 +1,78 @@ +#pragma once + +#include "SceTypes.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct MemorySizeQueryParams { + std::uint32_t version; + std::uint32_t workers; + std::uint32_t sequences; + std::uint32_t invocations; + std::uint32_t dispatches; + std::uint32_t syncPoints; + std::uint32_t waits; + std::uint32_t computeSequences; + std::uint64_t computeQueueMask; +}; + +struct ConfigParams { + std::uint32_t version; + std::uint32_t threadFlags; + std::uint32_t stackSize; + std::uint32_t priority; + const char* threadName; + std::uint32_t spinMicroseconds; + std::uint32_t computeAffinity; + std::uint32_t computePriority; + std::uint32_t reserved; +}; + +using JobEntry = void (APS5_VABI*)(void* argument, std::uint32_t index); + +class ISequence { +public: + APS5_VABI virtual int Dispatch(JobEntry entry, void* argument, std::uint32_t count, const char* name) = 0; + APS5_VABI virtual int SyncPoint() = 0; + APS5_VABI virtual int Wait() = 0; + APS5_VABI virtual void CompleteDestructor() {} + APS5_VABI virtual void DeletingDestructor() { throw std::runtime_error("libSceJobManager: a sequence was deleted by its caller"); } + APS5_VABI virtual int DispatchCompute(const void* shader, void* userData, std::int32_t x, std::int32_t y, std::int32_t z, const char* name) = 0; + APS5_VABI virtual int DispatchComputeIndirect(const void* shader, void* userData, const void* indirectArguments, const char* name) = 0; +}; + +class ISequenceFactory { +public: + APS5_VABI virtual int Create(ISequence** out, std::uint32_t invocations, std::uint32_t dispatches, std::uint32_t syncPoints, std::uint32_t waits, const char* name) = 0; + APS5_VABI virtual int Destroy(ISequence* sequence) = 0; + APS5_VABI virtual void CompleteDestructor() {} + APS5_VABI virtual void DeletingDestructor() { throw std::runtime_error("libSceJobManager: a sequence factory was deleted by its caller"); } + APS5_VABI virtual int CreateCompute(ISequence** out, std::uint32_t invocations, std::uint32_t dispatches, std::uint32_t syncPoints, std::uint32_t waits, const char* name) = 0; + APS5_VABI virtual int DestroyCompute(ISequence* sequence) = 0; +}; + +extern "C" { + +void APS5_VABI _ZN3sce3Job10JobManagerC1Ev(void* self); +void APS5_VABI _ZN3sce3Job10JobManagerC2Ev(void* self); +void APS5_VABI _ZN3sce3Job10JobManagerD1Ev(void* self); +void APS5_VABI _ZN3sce3Job10JobManagerD2Ev(void* self); +std::uint64_t APS5_VABI _ZN3sce3Job10JobManager27calculateRequiredMemorySizeEPKNS1_21MemorySizeQueryParamsE(const MemorySizeQueryParams* params); +int APS5_VABI _ZN3sce3Job10JobManager10initializeEPvmjjjmPKNS1_12ConfigParamsE(void* self, void* memory, std::uint64_t memorySize, std::uint32_t workers, std::uint32_t sequences, std::uint32_t computeSequences, std::uint64_t computeQueueMask, const ConfigParams* config); +int APS5_VABI _ZN3sce3Job10JobManager10initializeEPvmjjPKNS1_12ConfigParamsE(void* self, void* memory, std::uint64_t memorySize, std::uint32_t workers, std::uint32_t sequences, const ConfigParams* config); +int APS5_VABI _ZN3sce3Job10JobManager8shutdownEv(void* self); +ISequenceFactory* APS5_VABI _ZN3sce3Job10JobManager27getSequenceFactoryInterfaceENS1_8PriorityE(void* self, std::uint32_t priority); +ISequenceFactory* APS5_VABI _ZN3sce3Job10JobManager34getUnifiedSequenceFactoryInterfaceENS1_8PriorityE(void* self, std::uint32_t priority); +int APS5_VABI _ZN3sce3Job10JobManager24setPersistentThreadCountEj(void* self, std::uint32_t count); + +} diff --git a/core/libs/prx/libSceJobManager/libSceJobManager.hpp b/core/libs/prx/libSceJobManager/libSceJobManager.hpp new file mode 100644 index 0000000000..740c6ddc49 --- /dev/null +++ b/core/libs/prx/libSceJobManager/libSceJobManager.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceJobManager/include/Api.hpp" diff --git a/core/libs/prx/libSceJpegDec/Export.cpp b/core/libs/prx/libSceJpegDec/Export.cpp index aeddcbeb6c..d7d11c7277 100644 --- a/core/libs/prx/libSceJpegDec/Export.cpp +++ b/core/libs/prx/libSceJpegDec/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceJpegDec/include/Api.hpp" #include #include #include diff --git a/core/libs/prx/libSceJpegDec/include/Api.hpp b/core/libs/prx/libSceJpegDec/include/Api.hpp new file mode 100644 index 0000000000..0f0892be0a --- /dev/null +++ b/core/libs/prx/libSceJpegDec/include/Api.hpp @@ -0,0 +1,14 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int32_t APS5_VABI sceJpegDecCreate(const JpegDecCreateParam* param, void* memoryAddress, uint32_t memorySize, void** handle); +int32_t APS5_VABI sceJpegDecDecode(void* handle, const JpegDecDecodeParam* param, JpegDecImageInfo* imageInfo); +int32_t APS5_VABI sceJpegDecDelete(void* handle); +int32_t APS5_VABI sceJpegDecParseHeader(const JpegDecParseParam* param, JpegDecImageInfo* imageInfo); +int32_t APS5_VABI sceJpegDecQueryMemorySize(const JpegDecCreateParam* param); +int APS5_VABI sceJpegDecDecodeWithInputControl(); + +} diff --git a/core/libs/prx/libSceJpegDec/libSceJpegDec.hpp b/core/libs/prx/libSceJpegDec/libSceJpegDec.hpp new file mode 100644 index 0000000000..e1581fb344 --- /dev/null +++ b/core/libs/prx/libSceJpegDec/libSceJpegDec.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceJpegDec/include/Api.hpp" diff --git a/core/libs/prx/libSceJpegEnc/Export.cpp b/core/libs/prx/libSceJpegEnc/Export.cpp index a5801fcbeb..6a2407eebe 100644 --- a/core/libs/prx/libSceJpegEnc/Export.cpp +++ b/core/libs/prx/libSceJpegEnc/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceJpegEnc/include/Api.hpp" #include #include #include diff --git a/core/libs/prx/libSceJpegEnc/include/Api.hpp b/core/libs/prx/libSceJpegEnc/include/Api.hpp new file mode 100644 index 0000000000..25215e5d07 --- /dev/null +++ b/core/libs/prx/libSceJpegEnc/include/Api.hpp @@ -0,0 +1,12 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int32_t APS5_VABI sceJpegEncCreate(const JpegEncCreateParam* param, void* memory, uint32_t memorySize, void** handle); +int32_t APS5_VABI sceJpegEncDelete(void* handle); +int32_t APS5_VABI sceJpegEncEncode(void* handle, const JpegEncEncodeParam* param, JpegEncOutputInfo* outputInfo); +int32_t APS5_VABI sceJpegEncQueryMemorySize(const JpegEncCreateParam* param); + +} diff --git a/core/libs/prx/libSceJpegEnc/libSceJpegEnc.hpp b/core/libs/prx/libSceJpegEnc/libSceJpegEnc.hpp new file mode 100644 index 0000000000..a5548622ca --- /dev/null +++ b/core/libs/prx/libSceJpegEnc/libSceJpegEnc.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceJpegEnc/include/Api.hpp" diff --git a/core/libs/prx/libSceJpegParser/libSceJpegParser.hpp b/core/libs/prx/libSceJpegParser/libSceJpegParser.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceJpegParser/libSceJpegParser.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceJsc/libSceJsc.hpp b/core/libs/prx/libSceJsc/libSceJsc.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceJsc/libSceJsc.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceJscCompiler/libSceJscCompiler.hpp b/core/libs/prx/libSceJscCompiler/libSceJscCompiler.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceJscCompiler/libSceJscCompiler.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceJson/libSceJson.hpp b/core/libs/prx/libSceJson/libSceJson.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceJson/libSceJson.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceJson2/Export.cpp b/core/libs/prx/libSceJson2/Export.cpp index 9155bbed45..477b3d020f 100644 --- a/core/libs/prx/libSceJson2/Export.cpp +++ b/core/libs/prx/libSceJson2/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceJson2/include/Api.hpp" #include #include #include @@ -20,71 +21,14 @@ namespace { -enum ValueType : std::int32_t { - TypeNull = 0, - TypeBoolean = 1, - TypeInteger = 2, - TypeUInteger = 3, - TypeReal = 4, - TypeString = 5, - TypeArray = 6, - TypeObject = 7, -}; +using namespace SceJson2; constexpr int JsonErrorParse = static_cast(0x80848101); -struct Node; -struct Value { Node* node; }; -struct String { std::string* text; }; -struct Array { std::list* items; }; -struct Pair; -struct Object { std::list* items; }; -struct ArrayIteratorState { - std::list::iterator position; - std::list::iterator end; -}; -struct ArrayIterator { ArrayIteratorState* state; }; -struct ObjectIteratorState { - std::list* owner = nullptr; - std::list::iterator position{}; -}; -struct ObjectIterator { ObjectIteratorState* state; }; -struct Pair { - String key; - std::uint64_t reserved; - Value value; -}; static_assert(sizeof(Value) == 8 && sizeof(String) == 8 && sizeof(Array) == 8 && sizeof(Object) == 8); static_assert(sizeof(ArrayIterator) == 8 && sizeof(ObjectIterator) == 8); static_assert(offsetof(Pair, value) == 0x10); -using TypeMismatchHandler = const Value& (APS5_VABI*)(ValueType, const Value*, const Value*, void*); -using SpecialFloatHandler = Value* (APS5_VABI*)(Value*, std::int32_t, double, const Value*, void*, bool*); -using ElementAccessFailureHandler = void (APS5_VABI*)(int, const String*, const std::size_t*, const Value*, const Value*, void*); - -struct Handlers { - TypeMismatchHandler typeMismatch = nullptr; - void* typeMismatchContext = nullptr; - SpecialFloatHandler specialFloat = nullptr; - void* specialFloatContext = nullptr; - ElementAccessFailureHandler elementAccessFailure = nullptr; - void* elementAccessFailureContext = nullptr; -}; - -struct Node { - ValueType type = TypeNull; - bool boolean = false; - std::int64_t integer = 0; - std::uint64_t uinteger = 0; - double real = 0; - String string{}; - Array array{}; - Object object{}; - Handlers handlers{}; -}; - -using NullAccessCallback = const Value& (APS5_VABI*)(ValueType, const Value*, void*); - struct Globals { std::mutex mutex; NullAccessCallback callback = nullptr; @@ -375,8 +319,6 @@ Value& ObjectEntry(Object& object, const std::string& key) { } } -using ParserReadCallback = int (APS5_VABI*)(char&, void*); - class Parser { public: Parser(const char* text, std::size_t size, const Handlers& handlers) : text(text), end(text + size), handlers(handlers) {} @@ -550,10 +492,9 @@ private: skip(); if (peek() >= 0 && peek() == ']') { take(); --depth; return true; } for (;;) { - Value item{}; + auto& item = out.array.items->emplace_back(); Construct(item); item.node->handlers = handlers; - out.array.items->push_back(item); skip(); if (!value(*item.node)) return false; skip(); @@ -623,7 +564,6 @@ void* const JsonMemAllocatorVtable[] = { reinterpret_cast(&JsonMemAllocatorPureVirtual), reinterpret_cast(&JsonMemAllocatorPureVirtual), }; - } extern "C" { @@ -888,6 +828,7 @@ ObjectIterator* APS5_VABI _ZN3sce4Json6Object8iterator7advanceEm(ObjectIterator* if (self->state && self->state->owner) { while (count) { _ZN3sce4Json6Object8iteratorppEv(self); + --count; } } @@ -1098,7 +1039,6 @@ int APS5_VABI _ZNK3sce4Json5Value8toStringERNS0_6StringE(const Value* self, Stri return 0; } - int APS5_VABI _ZN3sce4Json6Parser5parseERNS0_5ValueEPFiRcPvES5_(Value* out, ParserReadCallback read, void* context) { if (read == nullptr) throw std::invalid_argument("sce::Json::Parser::parse: null read callback"); Parser parser(read, context, NodeOf(*out).handlers); @@ -1112,26 +1052,12 @@ int APS5_VABI _ZN3sce4Json6Parser5parseERNS0_5ValueEPKcm(Value* out, const char* return ParseValue(out, parser); } - -struct InitParameterRtti { - void* allocParam; - void* userData; - std::size_t fileBufferSize; -}; - void APS5_VABI _ZN3sce4Json17InitParameterRttiC1EPNS0_14AllocParamRttiEPvm(InitParameterRtti* self, void* allocParam, void* userData, std::size_t fileBufferSize) { self->allocParam = allocParam; self->userData = userData; self->fileBufferSize = fileBufferSize; } -struct InitParameter2 { - void* allocator; - void* userData; - std::size_t fileBufferSize; - std::int32_t specialFloatFormatType; - std::uint32_t reserved[3]; -}; static_assert(sizeof(InitParameter2) == 0x28 && offsetof(InitParameter2, specialFloatFormatType) == 0x18); void APS5_VABI _ZN3sce4Json14InitParameter2C1Ev(InitParameter2* self) { @@ -1141,6 +1067,7 @@ void APS5_VABI _ZN3sce4Json14InitParameter2C1Ev(InitParameter2* self) { void APS5_VABI _ZN3sce4Json14InitParameter2C2Ev(InitParameter2* self) { _ZN3sce4Json14InitParameter2C1Ev(self); + } void APS5_VABI _ZN3sce4Json14InitParameter212setAllocatorEPNS0_12MemAllocatorEPv(InitParameter2* self, void* allocator, void* userData) { @@ -1268,6 +1195,7 @@ ObjectIterator* APS5_VABI _ZN3sce4Json6Object6insertERKNS1_4PairE(ObjectIterator ArrayIterator* APS5_VABI _ZN3sce4Json5Array8iteratorppEi(ArrayIterator* result, ArrayIterator* self, int) { _ZN3sce4Json5Array8iteratorC1ERKS2_(result, self); _ZN3sce4Json5Array8iteratorppEv(self); + return result; } @@ -1290,6 +1218,7 @@ void APS5_VABI _ZN3sce4Json5Array8iteratorC1Ev(ArrayIterator* self) { ObjectIterator* APS5_VABI _ZN3sce4Json6Object8iteratorppEi(ObjectIterator* result, ObjectIterator* self, int) { auto state = self->state ? std::make_unique(*self->state) : nullptr; _ZN3sce4Json6Object8iteratorppEv(self); + result->state = state.release(); return result; } diff --git a/core/libs/prx/libSceJson2/include/Api.hpp b/core/libs/prx/libSceJson2/include/Api.hpp new file mode 100644 index 0000000000..630d23d193 --- /dev/null +++ b/core/libs/prx/libSceJson2/include/Api.hpp @@ -0,0 +1,347 @@ +#pragma once + +#include "SceTypes.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace SceJson2 { + +enum ValueType : std::int32_t { + TypeNull = 0, + TypeBoolean = 1, + TypeInteger = 2, + TypeUInteger = 3, + TypeReal = 4, + TypeString = 5, + TypeArray = 6, + TypeObject = 7, +}; + +} + +namespace SceJson2 { + +struct Node; + +} + +namespace SceJson2 { + +struct Value { Node* node; }; + +} + +namespace SceJson2 { + +struct String { std::string* text; }; + +} + +namespace SceJson2 { + +struct Array { std::list* items; }; + +} + +namespace SceJson2 { + +struct Pair; + +} + +namespace SceJson2 { + +struct Object { std::list* items; }; + +} + +namespace SceJson2 { + +struct ArrayIteratorState { + std::list::iterator position; + std::list::iterator end; +}; + +} + +namespace SceJson2 { + +struct ArrayIterator { ArrayIteratorState* state; }; + +} + +namespace SceJson2 { + +struct ObjectIteratorState { + std::list* owner = nullptr; + std::list::iterator position{}; +}; + +} + +namespace SceJson2 { + +struct ObjectIterator { ObjectIteratorState* state; }; + +} + +namespace SceJson2 { + +struct Pair { + String key; + std::uint64_t reserved; + Value value; +}; + +} + +namespace SceJson2 { + +using TypeMismatchHandler = const Value& (APS5_VABI*)(ValueType, const Value*, const Value*, void*); + +} + +namespace SceJson2 { + +using SpecialFloatHandler = Value* (APS5_VABI*)(Value*, std::int32_t, double, const Value*, void*, bool*); + +} + +namespace SceJson2 { + +using ElementAccessFailureHandler = void (APS5_VABI*)(int, const String*, const std::size_t*, const Value*, const Value*, void*); + +} + +namespace SceJson2 { + +struct Handlers { + TypeMismatchHandler typeMismatch = nullptr; + void* typeMismatchContext = nullptr; + SpecialFloatHandler specialFloat = nullptr; + void* specialFloatContext = nullptr; + ElementAccessFailureHandler elementAccessFailure = nullptr; + void* elementAccessFailureContext = nullptr; +}; + +} + +namespace SceJson2 { + +struct Node { + ValueType type = TypeNull; + bool boolean = false; + std::int64_t integer = 0; + std::uint64_t uinteger = 0; + double real = 0; + String string{}; + Array array{}; + Object object{}; + Handlers handlers{}; +}; + +} + +namespace SceJson2 { + +using NullAccessCallback = const Value& (APS5_VABI*)(ValueType, const Value*, void*); + +} + +namespace SceJson2 { + +using ParserReadCallback = int (APS5_VABI*)(char&, void*); + +} + +namespace SceJson2 { + +struct InitParameterRtti { + void* allocParam; + void* userData; + std::size_t fileBufferSize; +}; + +} + +namespace SceJson2 { + +struct InitParameter2 { + void* allocator; + void* userData; + std::size_t fileBufferSize; + std::int32_t specialFloatFormatType; + std::uint32_t reserved[3]; +}; + +} + +extern "C" { + +int APS5_VABI _ZN3sce4Json11InitializerC1Ev(void* self); +int APS5_VABI _ZN3sce4Json11InitializerD1Ev(void* self); +int APS5_VABI _ZN3sce4Json11Initializer10initializeEPKNS0_13InitParameterE(void* self, const void* parameter); +int APS5_VABI _ZN3sce4Json11Initializer9terminateEv(void* self); +int APS5_VABI _ZN3sce4Json11Initializer27setGlobalNullAccessCallBackEPFRKNS0_5ValueENS0_9ValueTypeEPS3_PvES7_(void* self, SceJson2::NullAccessCallback callback, void* context); +int APS5_VABI _ZN3sce4Json11Initializer27setGlobalNullAccessCallbackEPFRKNS0_5ValueENS0_9ValueTypeEPS3_PvES7_(void* self, SceJson2::NullAccessCallback callback, void* context); +void APS5_VABI _ZN3sce4Json12MemAllocatorC2Ev(void* self); +void APS5_VABI _ZN3sce4Json12MemAllocatorD2Ev(void* self); +void APS5_VABI _ZN3sce4Json6StringC1Ev(SceJson2::String* self); +void APS5_VABI _ZN3sce4Json6StringC1EPKc(SceJson2::String* self, const char* text); +void APS5_VABI _ZN3sce4Json6StringC1ERKS1_(SceJson2::String* self, const SceJson2::String* other); +void APS5_VABI _ZN3sce4Json6StringD1Ev(SceJson2::String* self); +SceJson2::String* APS5_VABI _ZN3sce4Json6StringaSERKS1_(SceJson2::String* self, const SceJson2::String* other); +const char* APS5_VABI _ZNK3sce4Json6String5c_strEv(const SceJson2::String* self); +bool APS5_VABI _ZNK3sce4Json6String5emptyEv(const SceJson2::String* self); +std::size_t APS5_VABI _ZNK3sce4Json6String6lengthEv(const SceJson2::String* self); +std::size_t APS5_VABI _ZNK3sce4Json6String4sizeEv(const SceJson2::String* self); +std::size_t APS5_VABI _ZNK3sce4Json6String8capacityEv(const SceJson2::String* self); +bool APS5_VABI _ZNK3sce4Json6StringeqEPKc(const SceJson2::String* self, const char* text); +bool APS5_VABI _ZNK3sce4Json6StringeqERKS1_(const SceJson2::String* self, const SceJson2::String* other); +void APS5_VABI _ZN3sce4Json6String5clearEv(SceJson2::String* self); +void APS5_VABI _ZN3sce4Json6String6resizeEm(SceJson2::String* self, std::size_t count); +void APS5_VABI _ZN3sce4Json6String7reserveEm(SceJson2::String* self, std::size_t capacity); +SceJson2::String* APS5_VABI _ZN3sce4Json6String6appendERKS1_(SceJson2::String* self, const SceJson2::String* other); +SceJson2::String* APS5_VABI _ZN3sce4Json6String6appendEPKc(SceJson2::String* self, const char* text); +SceJson2::String* APS5_VABI _ZN3sce4Json6String6appendEPKcm(SceJson2::String* self, const char* text, std::size_t length); +SceJson2::String* APS5_VABI _ZN3sce4Json6StringpLEPKc(SceJson2::String* self, const char* text); +SceJson2::String* APS5_VABI _ZN3sce4Json6StringpLEh(SceJson2::String* self, unsigned char ch); +SceJson2::String* APS5_VABI _ZNK3sce4Json6String6substrEmm(SceJson2::String* result, const SceJson2::String* self, std::size_t position, std::size_t length); +std::size_t APS5_VABI _ZNK3sce4Json6String4findEcm(const SceJson2::String* self, char character, std::size_t position); +std::size_t APS5_VABI _ZNK3sce4Json6String5rfindEcm(const SceJson2::String* self, char character, std::size_t position); +char APS5_VABI _ZNK3sce4Json6String2atEm(const SceJson2::String* self, std::size_t position); +std::size_t APS5_VABI _ZNK3sce4Json6String4findEPKcm(const SceJson2::String* self, const char* text, std::size_t position); +std::size_t APS5_VABI _ZNK3sce4Json6String4findEPKcmm(const SceJson2::String* self, const char* text, std::size_t position, std::size_t length); +std::size_t APS5_VABI _ZNK3sce4Json6String4findERKS1_m(const SceJson2::String* self, const SceJson2::String* other, std::size_t position); +std::size_t APS5_VABI _ZNK3sce4Json6String5rfindEPKcm(const SceJson2::String* self, const char* text, std::size_t position); +std::size_t APS5_VABI _ZNK3sce4Json6String5rfindEPKcmm(const SceJson2::String* self, const char* text, std::size_t position, std::size_t length); +std::size_t APS5_VABI _ZNK3sce4Json6String5rfindERKS1_m(const SceJson2::String* self, const SceJson2::String* other, std::size_t position); +int APS5_VABI _ZNK3sce4Json6String7compareEPKc(const SceJson2::String* self, const char* text); +int APS5_VABI _ZNK3sce4Json6String7compareERKS1_(const SceJson2::String* self, const SceJson2::String* other); +void APS5_VABI _ZN3sce4Json5ArrayC1Ev(SceJson2::Array* self); +void APS5_VABI _ZN3sce4Json5ArrayC1ERKS1_(SceJson2::Array* self, const SceJson2::Array* other); +void APS5_VABI _ZN3sce4Json5ArrayD1Ev(SceJson2::Array* self); +SceJson2::Array* APS5_VABI _ZN3sce4Json5ArrayaSERKS1_(SceJson2::Array* self, const SceJson2::Array* other); +void APS5_VABI _ZN3sce4Json5Array9push_backERKNS0_5ValueE(SceJson2::Array* self, const SceJson2::Value* value); +SceJson2::ArrayIterator* APS5_VABI _ZNK3sce4Json5Array5beginEv(SceJson2::ArrayIterator* result, const SceJson2::Array* self); +SceJson2::ArrayIterator* APS5_VABI _ZNK3sce4Json5Array3endEv(SceJson2::ArrayIterator* result, const SceJson2::Array* self); +bool APS5_VABI _ZNK3sce4Json5Array5emptyEv(const SceJson2::Array* self); +std::size_t APS5_VABI _ZNK3sce4Json5Array4sizeEv(const SceJson2::Array* self); +void APS5_VABI _ZN3sce4Json5Array5clearEv(SceJson2::Array* self); +const SceJson2::Value* APS5_VABI _ZNK3sce4Json5Array5frontEv(const SceJson2::Array* self); +const SceJson2::Value* APS5_VABI _ZNK3sce4Json5Array4backEv(const SceJson2::Array* self); +void APS5_VABI _ZN3sce4Json5Array9pop_frontEv(SceJson2::Array* self); +void APS5_VABI _ZN3sce4Json5Array8iteratorD1Ev(SceJson2::ArrayIterator* self); +SceJson2::ArrayIterator* APS5_VABI _ZN3sce4Json5Array8iteratorppEv(SceJson2::ArrayIterator* self); +SceJson2::Value* APS5_VABI _ZNK3sce4Json5Array8iteratordeEv(const SceJson2::ArrayIterator* self); +SceJson2::Value* APS5_VABI _ZNK3sce4Json5Array8iteratorptEv(const SceJson2::ArrayIterator* self); +bool APS5_VABI _ZNK3sce4Json5Array8iteratorneERKS2_(const SceJson2::ArrayIterator* self, const SceJson2::ArrayIterator* other); +void APS5_VABI _ZN3sce4Json5Array8iteratorC1ERKS2_(SceJson2::ArrayIterator* self, const SceJson2::ArrayIterator* other); +SceJson2::ArrayIterator* APS5_VABI _ZN3sce4Json5Array8iterator7advanceEm(SceJson2::ArrayIterator* self, std::size_t count); +void APS5_VABI _ZN3sce4Json6ObjectC1Ev(SceJson2::Object* self); +void APS5_VABI _ZN3sce4Json6ObjectC1ERKS1_(SceJson2::Object* self, const SceJson2::Object* other); +void APS5_VABI _ZN3sce4Json6ObjectD1Ev(SceJson2::Object* self); +SceJson2::Object* APS5_VABI _ZN3sce4Json6ObjectaSERKS1_(SceJson2::Object* self, const SceJson2::Object* other); +void APS5_VABI _ZN3sce4Json6Object5clearEv(SceJson2::Object* self); +SceJson2::Value* APS5_VABI _ZN3sce4Json6ObjectixERKNS0_6StringE(SceJson2::Object* self, const SceJson2::String* key); +SceJson2::ObjectIterator* APS5_VABI _ZNK3sce4Json6Object5beginEv(SceJson2::ObjectIterator* result, const SceJson2::Object* self); +SceJson2::ObjectIterator* APS5_VABI _ZNK3sce4Json6Object3endEv(SceJson2::ObjectIterator* result, const SceJson2::Object* self); +void APS5_VABI _ZN3sce4Json6Object8iteratorD1Ev(SceJson2::ObjectIterator* self); +SceJson2::ObjectIterator* APS5_VABI _ZN3sce4Json6Object8iteratorppEv(SceJson2::ObjectIterator* self); +SceJson2::Pair* APS5_VABI _ZNK3sce4Json6Object8iteratordeEv(const SceJson2::ObjectIterator* self); +SceJson2::Pair* APS5_VABI _ZNK3sce4Json6Object8iteratorptEv(const SceJson2::ObjectIterator* self); +SceJson2::ObjectIterator* APS5_VABI _ZNK3sce4Json6Object4findERKNS0_6StringE(SceJson2::ObjectIterator* result, const SceJson2::Object* self, const SceJson2::String* key); +bool APS5_VABI _ZNK3sce4Json6Object8iteratoreqERKS2_(const SceJson2::ObjectIterator* self, const SceJson2::ObjectIterator* other); +bool APS5_VABI _ZNK3sce4Json6Object8iteratorneERKS2_(const SceJson2::ObjectIterator* self, const SceJson2::ObjectIterator* other); +void APS5_VABI _ZN3sce4Json6Object8iteratorC1ERKS2_(SceJson2::ObjectIterator* self, const SceJson2::ObjectIterator* other); +SceJson2::ObjectIterator* APS5_VABI _ZN3sce4Json6Object8iterator7advanceEm(SceJson2::ObjectIterator* self, std::size_t count); +bool APS5_VABI _ZNK3sce4Json6Object5emptyEv(const SceJson2::Object* self); +std::size_t APS5_VABI _ZNK3sce4Json6Object4sizeEv(const SceJson2::Object* self); +void APS5_VABI _ZN3sce4Json6Object5eraseERKNS0_6StringE(SceJson2::Object* self, const SceJson2::String* key); +void APS5_VABI _ZN3sce4Json5ValueC1Ev(SceJson2::Value* self); +void APS5_VABI _ZN3sce4Json5ValueC1Eb(SceJson2::Value* self, bool value); +void APS5_VABI _ZN3sce4Json5ValueC1El(SceJson2::Value* self, std::int64_t value); +void APS5_VABI _ZN3sce4Json5ValueC1Em(SceJson2::Value* self, std::uint64_t value); +void APS5_VABI _ZN3sce4Json5ValueC1Ed(SceJson2::Value* self, double value); +void APS5_VABI _ZN3sce4Json5ValueC1EPKc(SceJson2::Value* self, const char* text); +void APS5_VABI _ZN3sce4Json5ValueC1ERKNS0_6StringE(SceJson2::Value* self, const SceJson2::String* text); +void APS5_VABI _ZN3sce4Json5ValueC1ERKNS0_5ArrayE(SceJson2::Value* self, const SceJson2::Array* array); +void APS5_VABI _ZN3sce4Json5ValueC1ERKNS0_6ObjectE(SceJson2::Value* self, const SceJson2::Object* object); +void APS5_VABI _ZN3sce4Json5ValueC1ERKS1_(SceJson2::Value* self, const SceJson2::Value* other); +void APS5_VABI _ZN3sce4Json5ValueD1Ev(SceJson2::Value* self); +SceJson2::Value* APS5_VABI _ZN3sce4Json5ValueaSERKS1_(SceJson2::Value* self, const SceJson2::Value* other); +void APS5_VABI _ZN3sce4Json5Value4swapERS1_(SceJson2::Value* self, SceJson2::Value* other); +int APS5_VABI _ZN3sce4Json5Value3setENS0_9ValueTypeE(SceJson2::Value* self, SceJson2::ValueType type); +int APS5_VABI _ZN3sce4Json5Value3setEb(SceJson2::Value* self, bool value); +int APS5_VABI _ZN3sce4Json5Value3setEl(SceJson2::Value* self, std::int64_t value); +int APS5_VABI _ZN3sce4Json5Value3setEm(SceJson2::Value* self, std::uint64_t value); +int APS5_VABI _ZN3sce4Json5Value3setEd(SceJson2::Value* self, double value); +int APS5_VABI _ZN3sce4Json5Value3setEPKc(SceJson2::Value* self, const char* text); +int APS5_VABI _ZN3sce4Json5Value3setERKNS0_6StringE(SceJson2::Value* self, const SceJson2::String* text); +int APS5_VABI _ZN3sce4Json5Value3setERKNS0_5ArrayE(SceJson2::Value* self, const SceJson2::Array* array); +int APS5_VABI _ZN3sce4Json5Value3setERKNS0_6ObjectE(SceJson2::Value* self, const SceJson2::Object* object); +int APS5_VABI _ZN3sce4Json5Value3setERKS1_(SceJson2::Value* self, const SceJson2::Value* other); +SceJson2::ValueType APS5_VABI _ZNK3sce4Json5Value7getTypeEv(const SceJson2::Value* self); +const bool* APS5_VABI _ZNK3sce4Json5Value10getBooleanEv(const SceJson2::Value* self); +const std::int64_t* APS5_VABI _ZNK3sce4Json5Value10getIntegerEv(const SceJson2::Value* self); +const std::uint64_t* APS5_VABI _ZNK3sce4Json5Value11getUIntegerEv(const SceJson2::Value* self); +const double* APS5_VABI _ZNK3sce4Json5Value7getRealEv(const SceJson2::Value* self); +const SceJson2::String* APS5_VABI _ZNK3sce4Json5Value9getStringEv(const SceJson2::Value* self); +const SceJson2::Array* APS5_VABI _ZNK3sce4Json5Value8getArrayEv(const SceJson2::Value* self); +const SceJson2::Object* APS5_VABI _ZNK3sce4Json5Value9getObjectEv(const SceJson2::Value* self); +std::size_t APS5_VABI _ZNK3sce4Json5Value5countEv(const SceJson2::Value* self); +const SceJson2::Value* APS5_VABI _ZNK3sce4Json5ValueixEPKc(const SceJson2::Value* self, const char* key); +const SceJson2::Value* APS5_VABI _ZNK3sce4Json5ValueixEm(const SceJson2::Value* self, std::size_t index); +void APS5_VABI _ZN3sce4Json5ValueC1ENS0_9ValueTypeE(SceJson2::Value* self, SceJson2::ValueType type); +const SceJson2::Value* APS5_VABI _ZNK3sce4Json5Value8getValueEm(const SceJson2::Value* self, std::size_t index); +const SceJson2::Value* APS5_VABI _ZNK3sce4Json5Value8getValueERKNS0_6StringE(const SceJson2::Value* self, const SceJson2::String* key); +SceJson2::Value* APS5_VABI _ZN3sce4Json5Value10referValueEm(SceJson2::Value* self, std::size_t index); +SceJson2::Value* APS5_VABI _ZN3sce4Json5Value10referValueERKNS0_6StringE(SceJson2::Value* self, const SceJson2::String* key); +SceJson2::Array* APS5_VABI _ZN3sce4Json5Value10referArrayEv(SceJson2::Value* self); +SceJson2::Object* APS5_VABI _ZN3sce4Json5Value11referObjectEv(SceJson2::Value* self); +int APS5_VABI _ZN3sce4Json5Value9serializeERNS0_6StringE(SceJson2::Value* self, SceJson2::String* out); +int APS5_VABI _ZNK3sce4Json5Value8toStringERNS0_6StringE(const SceJson2::Value* self, SceJson2::String* out); +int APS5_VABI _ZN3sce4Json6Parser5parseERNS0_5ValueEPFiRcPvES5_(SceJson2::Value* out, SceJson2::ParserReadCallback read, void* context); +int APS5_VABI _ZN3sce4Json6Parser5parseERNS0_5ValueEPKcm(SceJson2::Value* out, const char* text, std::size_t size); +void APS5_VABI _ZN3sce4Json17InitParameterRttiC1EPNS0_14AllocParamRttiEPvm(SceJson2::InitParameterRtti* self, void* allocParam, void* userData, std::size_t fileBufferSize); +void APS5_VABI _ZN3sce4Json14InitParameter2C1Ev(SceJson2::InitParameter2* self); +void APS5_VABI _ZN3sce4Json14InitParameter2C2Ev(SceJson2::InitParameter2* self); +void APS5_VABI _ZN3sce4Json14InitParameter212setAllocatorEPNS0_12MemAllocatorEPv(SceJson2::InitParameter2* self, void* allocator, void* userData); +void APS5_VABI _ZN3sce4Json18InitParameterRtti216setAllocatorRttiEPNS0_14AllocParamRttiEPv(SceJson2::InitParameter2* self, void* allocParam, void* userData); +void APS5_VABI _ZN3sce4Json14InitParameter217setFileBufferSizeEm(SceJson2::InitParameter2* self, std::size_t size); +void APS5_VABI _ZN3sce4Json14InitParameter225setSpecialFloatFormatTypeENS0_22SpecialFloatFormatTypeE(SceJson2::InitParameter2* self, std::int32_t type); +int APS5_VABI _ZN3sce4Json11Initializer10initializeEPKNS0_14InitParameter2E(void* self, const SceJson2::InitParameter2* parameter); +void APS5_VABI _ZN3sce4Json5Value5clearEv(SceJson2::Value* self); +void APS5_VABI _ZN3sce4Json12MemAllocator11notifyErrorEimPv(void* self, int error, std::size_t size, void* userData); +void APS5_VABI _ZN3sce4Json5Value21setNullAccessCallBackEPFRKS1_NS0_9ValueTypeEPS2_PvES6_(SceJson2::NullAccessCallback callback, void* context); +int APS5_VABI _ZN3sce4Json5Value30setElementAccessFailureHandlerEPFviPKNS0_6StringEPKmPKS1_S8_PvES9_(SceJson2::Value* self, SceJson2::ElementAccessFailureHandler handler, void* context); +int APS5_VABI _ZN3sce4Json5Value22setSpecialFloatHandlerEPFKS1_NS0_12FunctionTypeEdPS2_PvPbES5_(SceJson2::Value* self, SceJson2::SpecialFloatHandler handler, void* context); +int APS5_VABI _ZN3sce4Json5Value22setTypeMismatchHandlerEPFRKS1_NS0_9ValueTypeEPS2_S5_PvES6_(SceJson2::Value* self, SceJson2::TypeMismatchHandler handler, void* context); +bool APS5_VABI _ZNK3sce4Json5ValuecvbEv(const SceJson2::Value* self); +void APS5_VABI _ZN3sce4Json6Object4PairC1ERKNS0_6StringERKNS0_5ValueE(SceJson2::Pair* self, const SceJson2::String* key, const SceJson2::Value* value); +void APS5_VABI _ZN3sce4Json6Object4PairD1Ev(SceJson2::Pair* self); +SceJson2::ObjectIterator* APS5_VABI _ZN3sce4Json6Object6insertERKNS1_4PairE(SceJson2::ObjectIterator* result, SceJson2::Object* self, const SceJson2::Pair* pair); +SceJson2::ArrayIterator* APS5_VABI _ZN3sce4Json5Array8iteratorppEi(SceJson2::ArrayIterator* result, SceJson2::ArrayIterator* self, int); +SceJson2::ArrayIterator* APS5_VABI _ZN3sce4Json5Array8iteratoraSERKS2_(SceJson2::ArrayIterator* self, const SceJson2::ArrayIterator* other); +void APS5_VABI _ZN3sce4Json5Array8iteratorC1Ev(SceJson2::ArrayIterator* self); +SceJson2::ObjectIterator* APS5_VABI _ZN3sce4Json6Object8iteratorppEi(SceJson2::ObjectIterator* result, SceJson2::ObjectIterator* self, int); +SceJson2::ObjectIterator* APS5_VABI _ZN3sce4Json6Object8iteratoraSERKS2_(SceJson2::ObjectIterator* self, const SceJson2::ObjectIterator* other); +void APS5_VABI _ZN3sce4Json6Object8iteratorC1Ev(SceJson2::ObjectIterator* self); +void APS5_VABI _ZN3sce4Json6Object4PairC1Ev(SceJson2::Pair* self); + +} diff --git a/core/libs/prx/libSceJson2/libSceJson2.hpp b/core/libs/prx/libSceJson2/libSceJson2.hpp new file mode 100644 index 0000000000..1ff338c252 --- /dev/null +++ b/core/libs/prx/libSceJson2/libSceJson2.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceJson2/include/Api.hpp" diff --git a/core/libs/prx/libSceJxr/Export.cpp b/core/libs/prx/libSceJxr/Export.cpp index de2c55aa4e..bd2404ed30 100644 --- a/core/libs/prx/libSceJxr/Export.cpp +++ b/core/libs/prx/libSceJxr/Export.cpp @@ -1,3 +1,5 @@ +#include "prx/libc/include/Api.hpp" +#include "prx/libSceJxr/include/Api.hpp" #include #include #include "SceTypes.hpp" @@ -9,12 +11,11 @@ constexpr std::int64_t WmpErrSuccess = 0; extern "C" { -void APS5_VABI free_nid_postfix(void* memory); - APS5_DUMMY_FUN std::int64_t APS5_VABI PKFree_nid_postfix(void** memory) { if (memory != nullptr) { free_nid_postfix(*memory); + *memory = nullptr; } return WmpErrSuccess; diff --git a/core/libs/prx/libSceJxr/include/Api.hpp b/core/libs/prx/libSceJxr/include/Api.hpp new file mode 100644 index 0000000000..b29df513d6 --- /dev/null +++ b/core/libs/prx/libSceJxr/include/Api.hpp @@ -0,0 +1,12 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +std::int64_t APS5_VABI PKFree_nid_postfix(void** memory); +int APS5_VABI PixelFormatLookup_nid_postfix(void); +int APS5_VABI readIS_nid_postfix(void); +int APS5_VABI writeIS_nid_postfix(void); + +} diff --git a/core/libs/prx/libSceJxr/libSceJxr.hpp b/core/libs/prx/libSceJxr/libSceJxr.hpp new file mode 100644 index 0000000000..e92de5c284 --- /dev/null +++ b/core/libs/prx/libSceJxr/libSceJxr.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceJxr/include/Api.hpp" diff --git a/core/libs/prx/libSceJxrParser/libSceJxrParser.hpp b/core/libs/prx/libSceJxrParser/libSceJxrParser.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceJxrParser/libSceJxrParser.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceKbEmulate/libSceKbEmulate.hpp b/core/libs/prx/libSceKbEmulate/libSceKbEmulate.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceKbEmulate/libSceKbEmulate.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceKeyboard/Export.cpp b/core/libs/prx/libSceKeyboard/Export.cpp index 9cbc7cd436..fce1492046 100644 --- a/core/libs/prx/libSceKeyboard/Export.cpp +++ b/core/libs/prx/libSceKeyboard/Export.cpp @@ -1,9 +1,7 @@ +#include "prx/libSceKeyboard/include/Api.hpp" #include "prx/libc/include/General.hpp" #include "prx/libSceKeyboard/include/KeyboardState.hpp" -struct KeyboardDeviceInfo; -struct KeyboardProcessFocus; - extern "C" { int APS5_VABI sceKeyboardInit(void) { diff --git a/core/libs/prx/libSceKeyboard/include/Api.hpp b/core/libs/prx/libSceKeyboard/include/Api.hpp new file mode 100644 index 0000000000..a44cb9ca83 --- /dev/null +++ b/core/libs/prx/libSceKeyboard/include/Api.hpp @@ -0,0 +1,38 @@ +#pragma once + +#include "SceTypes.hpp" + +struct KeyboardDeviceInfo; + +struct KeyboardProcessFocus; + +extern "C" { + +int APS5_VABI sceKeyboardInit(void); +int APS5_VABI sceKeyboardOpen(int userId, int32_t type, int32_t index, const void* param); +int APS5_VABI sceKeyboardClose(int32_t handle); +int APS5_VABI sceKeyboardRead(int32_t handle, KeyboardData* data, int32_t num); +int APS5_VABI sceKeyboardReadState(int32_t handle, KeyboardData* data); +int APS5_VABI sceKeyboardGetConnection(std::int32_t handle, bool* connected); +int APS5_VABI sceKeyboardGetKey2Char(std::int32_t handle, std::int32_t arrange, std::uint8_t led, std::uint8_t modifierKey, std::uint16_t keyCode, KeyboardCharData* charData); +int APS5_VABI sceKeyboardConnectPort(std::int32_t first, std::int32_t second); +int APS5_VABI sceKeyboardDebugGetDeviceId(std::int32_t handle, std::int32_t* deviceId); +int APS5_VABI sceKeyboardDeviceOpen(std::uint64_t deviceId, std::int32_t index, std::uint32_t options); +int APS5_VABI sceKeyboardDisconnectAll(void); +int APS5_VABI sceKeyboardDisconnectDevice(std::int32_t deviceId); +int APS5_VABI sceKeyboardDisconnectPort(std::int32_t first, std::int32_t second); +int APS5_VABI sceKeyboardGetDeviceInfo(std::int32_t deviceId, KeyboardDeviceInfo* info); +int APS5_VABI sceKeyboardGetHandle(std::int32_t userId, std::int32_t type, std::int32_t index); +int APS5_VABI sceKeyboardMbusInit(void); +int APS5_VABI sceKeyboardPadEmulateClose(void); +int APS5_VABI sceKeyboardPadEmulateOpen(void); +int APS5_VABI sceKeyboardSetProcessFocus(const KeyboardProcessFocus* focus); +int APS5_VABI sceKeyboardSetProcessPrivilege(std::uint8_t privilege); +int APS5_VABI sceDbgKeyboardClose(); +int APS5_VABI sceDbgKeyboardGetKey2Char(); +int APS5_VABI sceDbgKeyboardInit(); +int APS5_VABI sceDbgKeyboardOpen(); +int APS5_VABI sceDbgKeyboardRead(); +int APS5_VABI sceDbgKeyboardReadState(); + +} diff --git a/core/libs/prx/libSceKeyboard/libSceKeyboard.hpp b/core/libs/prx/libSceKeyboard/libSceKeyboard.hpp new file mode 100644 index 0000000000..8ab2bf1b0d --- /dev/null +++ b/core/libs/prx/libSceKeyboard/libSceKeyboard.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceKeyboard/include/Api.hpp" diff --git a/core/libs/prx/libSceKeyboard/tests/Keyboard.cpp b/core/libs/prx/libSceKeyboard/tests/Keyboard.cpp index 0307b994df..56b97a8d39 100644 --- a/core/libs/prx/libSceKeyboard/tests/Keyboard.cpp +++ b/core/libs/prx/libSceKeyboard/tests/Keyboard.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceKeyboard/include/Api.hpp" #include "prx/libSceKeyboard/include/keyboard_structs.h" #include "prx/libSceKeyboard/include/KeyboardState.hpp" #include "prx/libSceVideoOut/include/KeyboardInput.hpp" @@ -7,18 +8,6 @@ #include #include -extern "C" { -int APS5_VABI sceKeyboardInit(void); -int APS5_VABI sceKeyboardOpen(int, std::int32_t, std::int32_t, const void*); -int APS5_VABI sceKeyboardClose(std::int32_t); -int APS5_VABI sceKeyboardRead(std::int32_t, KeyboardData*, std::int32_t); -int APS5_VABI sceKeyboardReadState(std::int32_t, KeyboardData*); -int APS5_VABI sceKeyboardGetConnection(std::int32_t, bool*); -int APS5_VABI sceKeyboardGetKey2Char(std::int32_t, std::int32_t, std::uint8_t, std::uint8_t, std::uint16_t, KeyboardCharData*); -int APS5_VABI sceKeyboardConnectPort(void); -int APS5_VABI sceKeyboardDisconnectAll(void); -} - static void Require(bool value) { if (!value) std::abort(); } static SDL_Event KeyEvent(Uint32 type, SDL_Scancode scancode, Uint16 mod = 0, Uint8 repeat = 0) { @@ -181,7 +170,8 @@ int main() { bool threwConnect = false; try { - sceKeyboardConnectPort(); + sceKeyboardConnectPort(0, 0); + } catch (const std::runtime_error&) { threwConnect = true; } diff --git a/core/libs/prx/libSceLibcInternal/Directory.cpp b/core/libs/prx/libSceLibcInternal/Directory.cpp index 48a1614e85..ffb52e8614 100644 --- a/core/libs/prx/libSceLibcInternal/Directory.cpp +++ b/core/libs/prx/libSceLibcInternal/Directory.cpp @@ -1,12 +1,11 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" +#include "prx/libSceLibcInternal/include/Api.hpp" #include "prx/libc/include/GuestDirectory.hpp" #include "prx/libkernel/File/include/DirectoryDescriptor.hpp" #include #include -extern "C" int APS5_VABI close_nid_postfix(int d); -extern "C" int APS5_VABI fcntl_nid_postfix(int descriptor, int command, ...); -extern "C" int* APS5_VABI __error_nid_postfix(); - extern "C" void* APS5_VABI fdopendir_nid_postfix(int fd) { constexpr int SetDescriptorFlags = 2; constexpr int CloseOnExec = 1; diff --git a/core/libs/prx/libSceLibcInternal/Err.cpp b/core/libs/prx/libSceLibcInternal/Err.cpp index 08f9ae7622..3e67760ef9 100644 --- a/core/libs/prx/libSceLibcInternal/Err.cpp +++ b/core/libs/prx/libSceLibcInternal/Err.cpp @@ -1,18 +1,14 @@ +#include "prx/libc/include/Api.hpp" +#include "prx/libSceLibcInternal/include/Api.hpp" #include "prx/libc/include/FileStream.hpp" #include "prx/libc/include/Shutdown.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "SceTypes.hpp" #include -using ErrExit = void (APS5_VABI*)(int); - extern "C" { extern const char* __progname_nid_postfix; -int APS5_VABI vfprintf_nid_postfix(FileStream* stream, const char* format, VaList* args); -int APS5_VABI fprintf_nid_postfix(FileStream* stream, const char* format, ...); -int APS5_VABI fputs_nid_postfix(const char* str, FileStream* stream); -char* APS5_VABI strerror_nid_postfix(int error); -int* APS5_VABI __error_nid_postfix(); + } namespace { @@ -32,8 +28,10 @@ const char* ProgramName() { void Report(const char* format, VaList* args, const int* code) { FileStream* const stream = ErrFile(); fprintf_nid_postfix(stream, "%s: ", ProgramName()); + if (format != nullptr) { vfprintf_nid_postfix(stream, format, args); + if (code != nullptr) fputs_nid_postfix(": ", stream); } if (code != nullptr) fprintf_nid_postfix(stream, "%s\n", strerror_nid_postfix(*code)); @@ -73,6 +71,7 @@ void APS5_VABI vwarnc_nid_postfix(int code, const char* format, VaList* args) { void APS5_VABI vwarn_nid_postfix(const char* format, VaList* args) { vwarnc_nid_postfix(*__error_nid_postfix(), format, args); + } void APS5_VABI vwarnx_nid_postfix(const char* format, VaList* args) { @@ -86,6 +85,7 @@ void APS5_VABI vwarnx_nid_postfix(const char* format, VaList* args) { [[noreturn]] void APS5_VABI verr_nid_postfix(int status, const char* format, VaList* args) { verrc_nid_postfix(status, *__error_nid_postfix(), format, args); + } [[noreturn]] void APS5_VABI verrx_nid_postfix(int status, const char* format, VaList* args) { @@ -97,6 +97,7 @@ void APS5_VABI warnc_nid_postfix(int code, const char* format, ...) { APS5_ERR_VA_LIST args; APS5_ERR_VA_START(args, format); vwarnc_nid_postfix(code, format, reinterpret_cast(args)); + APS5_ERR_VA_END(args); } @@ -105,6 +106,7 @@ void APS5_VABI warn_nid_postfix(const char* format, ...) { APS5_ERR_VA_LIST args; APS5_ERR_VA_START(args, format); vwarnc_nid_postfix(code, format, reinterpret_cast(args)); + APS5_ERR_VA_END(args); } @@ -112,6 +114,7 @@ void APS5_VABI _warn_nid_postfix(const char* format, ...) { APS5_ERR_VA_LIST args; APS5_ERR_VA_START(args, format); vwarn_nid_postfix(format, reinterpret_cast(args)); + APS5_ERR_VA_END(args); } @@ -119,6 +122,7 @@ void APS5_VABI warnx_nid_postfix(const char* format, ...) { APS5_ERR_VA_LIST args; APS5_ERR_VA_START(args, format); vwarnx_nid_postfix(format, reinterpret_cast(args)); + APS5_ERR_VA_END(args); } @@ -126,6 +130,7 @@ void APS5_VABI warnx_nid_postfix(const char* format, ...) { APS5_ERR_VA_LIST args; APS5_ERR_VA_START(args, format); verrc_nid_postfix(status, code, format, reinterpret_cast(args)); + } [[noreturn]] void APS5_VABI err_nid_postfix(int status, const char* format, ...) { @@ -133,18 +138,21 @@ void APS5_VABI warnx_nid_postfix(const char* format, ...) { APS5_ERR_VA_LIST args; APS5_ERR_VA_START(args, format); verrc_nid_postfix(status, code, format, reinterpret_cast(args)); + } [[noreturn]] void APS5_VABI _err_nid_postfix(int status, const char* format, ...) { APS5_ERR_VA_LIST args; APS5_ERR_VA_START(args, format); verr_nid_postfix(status, format, reinterpret_cast(args)); + } [[noreturn]] void APS5_VABI errx_nid_postfix(int status, const char* format, ...) { APS5_ERR_VA_LIST args; APS5_ERR_VA_START(args, format); verrx_nid_postfix(status, format, reinterpret_cast(args)); + } } diff --git a/core/libs/prx/libSceLibcInternal/Export.cpp b/core/libs/prx/libSceLibcInternal/Export.cpp index d7c86c15f1..d018c80566 100644 --- a/core/libs/prx/libSceLibcInternal/Export.cpp +++ b/core/libs/prx/libSceLibcInternal/Export.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libSceLibcInternal/include/Api.hpp" #include "SceTypes.hpp" #include "prx/libc/include/General.hpp" #include "prx/libc/include/HeapDiagnostics.hpp" @@ -13,14 +15,10 @@ #include #endif -extern "C" void APS5_VABI sceKernelSetThreadDtors(thread_dtors_func_t dtors); -extern "C" int APS5_VABI sceKernelGetModuleInfoFromAddr(std::uint64_t address, int flags, ModuleInfoEx* info); extern "C" const char* __progname_nid_postfix; namespace { -using ThreadDestructorFunction = void (APS5_VABI*)(void*); - struct ThreadDestructor { ThreadDestructorFunction function; void* object; @@ -95,6 +93,7 @@ bool ForceThreadDestructorPass(KernelModule handle) { void RegisterThreadExitHook() { [[maybe_unused]] static const bool registered = [] { sceKernelSetThreadDtors(RunThreadDestructors_nid_no_patch); + return true; }(); } diff --git a/core/libs/prx/libSceLibcInternal/FileTime.cpp b/core/libs/prx/libSceLibcInternal/FileTime.cpp index a3bbfe8edc..5b98207e49 100644 --- a/core/libs/prx/libSceLibcInternal/FileTime.cpp +++ b/core/libs/prx/libSceLibcInternal/FileTime.cpp @@ -1,16 +1,12 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" +#include "prx/libSceLibcInternal/include/Api.hpp" #include "SceTypes.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include -struct LibcUtimbuf { - std::int64_t actime; - std::int64_t modtime; -}; static_assert(sizeof(LibcUtimbuf) == 16); -extern "C" int APS5_VABI utimes_nid_postfix(const char*, const KernelTimeval*); -extern "C" int* APS5_VABI __error_nid_postfix(); - extern "C" int APS5_VABI utime_nid_postfix(const char* path, const LibcUtimbuf* times) { int* const error = __error_nid_postfix(); const int saved = *error; diff --git a/core/libs/prx/libSceLibcInternal/Filesystem.cpp b/core/libs/prx/libSceLibcInternal/Filesystem.cpp index 55347ce843..36341ff483 100644 --- a/core/libs/prx/libSceLibcInternal/Filesystem.cpp +++ b/core/libs/prx/libSceLibcInternal/Filesystem.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/GuestDirectory.hpp" #include "prx/libc/include/General.hpp" #include "SceTypes.hpp" @@ -5,19 +7,6 @@ #include #include -extern "C" { -int APS5_VABI stat_nid_postfix(const char* path, FileStat* sb); -int APS5_VABI mkdir_nid_postfix(const char* path, std::uint16_t mode); -int APS5_VABI rmdir_nid_postfix(const char* path); -int APS5_VABI unlink_nid_postfix(const char* path); -int APS5_VABI chmod_nid_postfix(const char* path, int mode); -char* APS5_VABI getcwd_nid_postfix(char* buffer, std::size_t size); -void* APS5_VABI opendir_nid_postfix(const char* path); -int APS5_VABI readdir_r_nid_postfix(void* handle, GuestDirectoryEntry* entry, GuestDirectoryEntry** result); -int APS5_VABI closedir_nid_postfix(void* handle); -int* APS5_VABI __error_nid_postfix(); -} - namespace { constexpr std::size_t NameCapacity = 260; diff --git a/core/libs/prx/libSceLibcInternal/FilesystemStatistics.cpp b/core/libs/prx/libSceLibcInternal/FilesystemStatistics.cpp index 8cb50f1eca..998c338235 100644 --- a/core/libs/prx/libSceLibcInternal/FilesystemStatistics.cpp +++ b/core/libs/prx/libSceLibcInternal/FilesystemStatistics.cpp @@ -1,10 +1,10 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" +#include "prx/libSceLibcInternal/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libSceLibcInternal/include/Statvfs.hpp" #include -extern "C" int APS5_VABI _fstatfs_nid_postfix(int, KernelStatfs*); -extern "C" int* APS5_VABI __error_nid_postfix(); - extern "C" int APS5_VABI fstatvfs_nid_postfix(int descriptor, LibcStatvfs* output) { int* const error = __error_nid_postfix(); const int saved = *error; diff --git a/core/libs/prx/libSceLibcInternal/Getopt.cpp b/core/libs/prx/libSceLibcInternal/Getopt.cpp index 80645072b4..43248491d9 100644 --- a/core/libs/prx/libSceLibcInternal/Getopt.cpp +++ b/core/libs/prx/libSceLibcInternal/Getopt.cpp @@ -1,3 +1,5 @@ +#include "prx/libc/include/Api.hpp" +#include "prx/libSceLibcInternal/include/Api.hpp" #include "prx/libc/include/FileStream.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -7,12 +9,6 @@ #include #include -struct GuestOption { - const char* name; - int hasArgument; - int* flag; - int value; -}; static_assert(sizeof(GuestOption) == 32); static_assert(offsetof(GuestOption, hasArgument) == 8); static_assert(offsetof(GuestOption, flag) == 16); @@ -21,7 +17,6 @@ static_assert(offsetof(GuestOption, value) == 24); extern "C" { extern const char* __progname_nid_postfix; extern FileStream* __stderrp_nid_postfix; -char* APS5_VABI getenv_nid_postfix(const char* name); int opterr_nid_postfix = 1; int optind_nid_postfix = 1; diff --git a/core/libs/prx/libSceLibcInternal/Inet.cpp b/core/libs/prx/libSceLibcInternal/Inet.cpp index c11c6201ac..1dd8ad853d 100644 --- a/core/libs/prx/libSceLibcInternal/Inet.cpp +++ b/core/libs/prx/libSceLibcInternal/Inet.cpp @@ -1,12 +1,10 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libSceLibcInternal/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include #include -extern "C" { -const char* APS5_VABI __inet_ntop_nid_postfix(int family, const void* source, char* destination, std::uint32_t capacity); -} - namespace { constexpr int AddressFamilyInet = 2; @@ -94,6 +92,7 @@ std::uint32_t APS5_VABI inet_addr_nid_postfix(const char* text) { char* APS5_VABI inet_ntoa_r_nid_postfix(std::uint32_t address, char* buffer, std::uint32_t size) { __inet_ntop_nid_postfix(AddressFamilyInet, &address, buffer, size); + return buffer; } @@ -104,6 +103,7 @@ char* APS5_VABI __inet_ntoa_r_nid_postfix(std::uint32_t address, char* buffer, s char* APS5_VABI inet_ntoa_nid_postfix(std::uint32_t address) { std::memcpy(g_ntoaBuffer, "[inet_ntoa error]", sizeof(g_ntoaBuffer)); __inet_ntop_nid_postfix(AddressFamilyInet, &address, g_ntoaBuffer, sizeof(g_ntoaBuffer)); + return g_ntoaBuffer; } diff --git a/core/libs/prx/libSceLibcInternal/InitOnce.cpp b/core/libs/prx/libSceLibcInternal/InitOnce.cpp index 56f54923a0..94d59b1ce7 100644 --- a/core/libs/prx/libSceLibcInternal/InitOnce.cpp +++ b/core/libs/prx/libSceLibcInternal/InitOnce.cpp @@ -1,3 +1,4 @@ +#include "prx/libkernel/include/Api.hpp" #include "SceTypes.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -5,9 +6,6 @@ #include #include -extern "C" int APS5_VABI sceKernelSyncOnAddressWait(std::uint32_t* address, std::uint32_t expected, const KernelUseconds* timeout, const char* name); -extern "C" int APS5_VABI sceKernelSyncOnAddressWake(void* address, std::int32_t count); - namespace { constexpr std::uintptr_t OnceIdle = 0; diff --git a/core/libs/prx/libSceLibcInternal/PathStatistics.cpp b/core/libs/prx/libSceLibcInternal/PathStatistics.cpp index c66f3dcc3b..bca817dd44 100644 --- a/core/libs/prx/libSceLibcInternal/PathStatistics.cpp +++ b/core/libs/prx/libSceLibcInternal/PathStatistics.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceLibcInternal/include/Api.hpp" #include "prx/libc/include/FilesystemError.hpp" #include #include @@ -18,7 +19,6 @@ #endif struct LibcStatvfs; -extern "C" int APS5_VABI fstatvfs_nid_postfix(int, LibcStatvfs*); namespace { int Fail(int error) { diff --git a/core/libs/prx/libSceLibcInternal/SignalList.cpp b/core/libs/prx/libSceLibcInternal/SignalList.cpp index d27a5531c4..e33acb01fe 100644 --- a/core/libs/prx/libSceLibcInternal/SignalList.cpp +++ b/core/libs/prx/libSceLibcInternal/SignalList.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libSceLibcInternal/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -77,16 +79,16 @@ extern const char* const sys_signame_nid_postfix[32] = { "USR2", }; -std::int64_t APS5_VABI _write_nid_postfix(int descriptor, const void* buffer, std::size_t count); - void APS5_VABI psignal_nid_postfix(unsigned int signal, const char* prefix) { const char* const message = signal < 32 ? sys_siglist_nid_postfix[signal] : "Unknown signal"; if (prefix != nullptr && prefix[0] != 0) { _write_nid_postfix(2, prefix, std::strlen(prefix)); _write_nid_postfix(2, ": ", 2); + } _write_nid_postfix(2, message, std::strlen(message)); _write_nid_postfix(2, "\n", 1); + } } diff --git a/core/libs/prx/libSceLibcInternal/Spawn.cpp b/core/libs/prx/libSceLibcInternal/Spawn.cpp index b40cbc9d10..72e1bfcaae 100644 --- a/core/libs/prx/libSceLibcInternal/Spawn.cpp +++ b/core/libs/prx/libSceLibcInternal/Spawn.cpp @@ -1,3 +1,5 @@ +#include "prx/libc/include/Api.hpp" +#include "prx/libSceLibcInternal/include/Api.hpp" #include "prx/libSceLibcInternal/include/Spawn.hpp" #include "prx/libc/include/FilesystemError.hpp" #include "prx/libc/include/General.hpp" @@ -10,8 +12,6 @@ #include #include -extern "C" char* APS5_VABI getenv_nid_postfix(const char* name); - namespace { constexpr int NoSuchFile = 2; diff --git a/core/libs/prx/libSceLibcInternal/UserContext.cpp b/core/libs/prx/libSceLibcInternal/UserContext.cpp index 3f743af8f4..9ef01bd612 100644 --- a/core/libs/prx/libSceLibcInternal/UserContext.cpp +++ b/core/libs/prx/libSceLibcInternal/UserContext.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libSceLibcInternal/include/Api.hpp" #include "prx/libc/include/GuestStacks.hpp" #include "prx/libc/include/Shutdown.hpp" #include "prx/libc/include/general/VabiMacros.hpp" @@ -7,8 +9,6 @@ #include #include -extern "C" int APS5_VABI setcontext_nid_postfix(const UserUcontext* context); - namespace { using ContextFunction = void (APS5_VABI*)(std::uint64_t, std::uint64_t, std::uint64_t, std::uint64_t, std::uint64_t, std::uint64_t); @@ -26,6 +26,7 @@ extern "C" { [[noreturn]] void APS5_VABI Aps5MakecontextFinish_nid_no_patch(UserUcontext* context) { if (context->link == nullptr) LibcExit_nid_no_patch(0); setcontext_nid_postfix(context->link); + std::abort(); } @@ -62,6 +63,7 @@ Aps5MakecontextStart_nid_no_patch: function(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4], arguments[5]); if (context->link == nullptr) LibcExit_nid_no_patch(0); setcontext_nid_postfix(context->link); + std::abort(); } #endif diff --git a/core/libs/prx/libSceLibcInternal/include/Api.hpp b/core/libs/prx/libSceLibcInternal/include/Api.hpp new file mode 100644 index 0000000000..d10e3f958b --- /dev/null +++ b/core/libs/prx/libSceLibcInternal/include/Api.hpp @@ -0,0 +1,106 @@ +#pragma once + +#include "prx/libSceLibcInternal/include/Statvfs.hpp" +#include "prx/libSceLibcInternal/include/Spawn.hpp" +#include "prx/libkernel/System/include/UserContext.hpp" +#include "prx/libc/include/FileStream.hpp" +#include "SceTypes.hpp" + +using ErrExit = void (APS5_VABI*)(int); + +struct GuestOption { + const char* name; + int hasArgument; + int* flag; + int value; +}; + +struct LibcUtimbuf { + std::int64_t actime; + std::int64_t modtime; +}; + +using ThreadDestructorFunction = void (APS5_VABI*)(void*); + +extern "C" { + +void* APS5_VABI fdopendir_nid_postfix(int fd); +void APS5_VABI err_set_file_nid_postfix(FileStream* stream); +void APS5_VABI err_set_exit_nid_postfix(ErrExit function); +void APS5_VABI vwarnc_nid_postfix(int code, const char* format, VaList* args); +void APS5_VABI vwarn_nid_postfix(const char* format, VaList* args); +void APS5_VABI vwarnx_nid_postfix(const char* format, VaList* args); +void APS5_VABI warnc_nid_postfix(int code, const char* format, ...); +void APS5_VABI warn_nid_postfix(const char* format, ...); +void APS5_VABI _warn_nid_postfix(const char* format, ...); +void APS5_VABI warnx_nid_postfix(const char* format, ...); +const char* APS5_VABI getprogname_nid_postfix(); +const char* APS5_VABI _getprogname_nid_postfix(); +void APS5_VABI __cxa_finalize_nid_postfix(void* dsoHandle); +void APS5_VABI sceLibcHeapGetTraceInfo_nid_postfix(Info* info); +int APS5_VABI _sceLibcInternalThreadAtexit_nid_postfix(ThreadDestructorFunction destructor, void* object, void* dsoSymbol); +void APS5_VABI _sceLibcInternalThreadDtors_nid_postfix(); +int APS5_VABI _sceLibcInternalForceTlsDestructor_nid_postfix(KernelModule handle); +unsigned int APS5_VABI alarm_nid_postfix(unsigned int seconds); +int APS5_VABI fstatvfs_nid_postfix(int descriptor, LibcStatvfs* output); +int APS5_VABI utime_nid_postfix(const char* path, const LibcUtimbuf* times); +int APS5_VABI getopt_nid_postfix(int count, char* const* arguments, const char* options); +int APS5_VABI getopt_long_nid_postfix(int count, char* const* arguments, const char* options, const GuestOption* longOptions, int* index); +int APS5_VABI getopt_long_only_nid_postfix(int count, char* const* arguments, const char* options, const GuestOption* longOptions, int* index); +int APS5_VABI inet_aton_nid_postfix(const char* text, std::uint32_t* address); +std::uint32_t APS5_VABI inet_addr_nid_postfix(const char* text); +char* APS5_VABI inet_ntoa_r_nid_postfix(std::uint32_t address, char* buffer, std::uint32_t size); +char* APS5_VABI __inet_ntoa_r_nid_postfix(std::uint32_t address, char* buffer, std::uint32_t size); +char* APS5_VABI inet_ntoa_nid_postfix(std::uint32_t address); +int APS5_VABI statvfs_nid_postfix(const char* path, LibcStatvfs* output); +void APS5_VABI psignal_nid_postfix(unsigned int signal, const char* prefix); +int APS5_VABI posix_spawnattr_init_nid_postfix(PosixSpawnAttributes** attributes); +int APS5_VABI posix_spawnattr_destroy_nid_postfix(PosixSpawnAttributes** attributes); +int APS5_VABI posix_spawnattr_setflags_nid_postfix(PosixSpawnAttributes** attributes, std::int16_t flags); +int APS5_VABI posix_spawnattr_setsigdefault_nid_postfix(PosixSpawnAttributes** attributes, const GuestSignalSet* signalDefault); +int APS5_VABI posix_spawnattr_getflags_nid_postfix(PosixSpawnAttributes* const* attributes, std::int16_t* flags); +int APS5_VABI posix_spawnattr_getpgroup_nid_postfix(PosixSpawnAttributes* const* attributes, std::int32_t* processGroup); +int APS5_VABI posix_spawnattr_getschedparam_nid_postfix(PosixSpawnAttributes* const* attributes, std::int32_t* schedulingParameter); +int APS5_VABI posix_spawnattr_getschedpolicy_nid_postfix(PosixSpawnAttributes* const* attributes, std::int32_t* schedulingPolicy); +int APS5_VABI posix_spawnattr_getsigdefault_nid_postfix(PosixSpawnAttributes* const* attributes, GuestSignalSet* signalDefault); +int APS5_VABI posix_spawnattr_getsigmask_nid_postfix(PosixSpawnAttributes* const* attributes, GuestSignalSet* signalMask); +int APS5_VABI posix_spawnattr_setpgroup_nid_postfix(PosixSpawnAttributes** attributes, std::int32_t processGroup); +int APS5_VABI posix_spawnattr_setschedparam_nid_postfix(PosixSpawnAttributes** attributes, const std::int32_t* schedulingParameter); +int APS5_VABI posix_spawnattr_setschedpolicy_nid_postfix(PosixSpawnAttributes** attributes, std::int32_t schedulingPolicy); +int APS5_VABI posix_spawnattr_setsigmask_nid_postfix(PosixSpawnAttributes** attributes, const GuestSignalSet* signalMask); +int APS5_VABI posix_spawn_file_actions_init_nid_postfix(PosixSpawnFileActions** actions); +int APS5_VABI posix_spawn_file_actions_destroy_nid_postfix(PosixSpawnFileActions** actions); +int APS5_VABI posix_spawn_file_actions_addopen_nid_postfix(PosixSpawnFileActions** actions, int descriptor, const char* path, int openFlags, std::uint16_t mode); +int APS5_VABI posix_spawn_file_actions_adddup2_nid_postfix(PosixSpawnFileActions** actions, int descriptor, int newDescriptor); +int APS5_VABI posix_spawn_file_actions_addclose_nid_postfix(PosixSpawnFileActions** actions, int descriptor); +int APS5_VABI posix_spawn_nid_postfix(std::int32_t* processId, const char* path, PosixSpawnFileActions* const* actions, PosixSpawnAttributes* const* attributes, char* const* arguments, char* const* environment); +int APS5_VABI posix_spawnp_nid_postfix(std::int32_t* processId, const char* file, PosixSpawnFileActions* const* actions, PosixSpawnAttributes* const* attributes, char* const* arguments, char* const* environment); +void APS5_VABI makecontext_nid_postfix(UserUcontext* context, void (APS5_VABI* start)(), int count, ...); + +[[noreturn]] void APS5_VABI verrc_nid_postfix(int status, int code, const char* format, VaList* args); +[[noreturn]] void APS5_VABI verr_nid_postfix(int status, const char* format, VaList* args); +[[noreturn]] void APS5_VABI verrx_nid_postfix(int status, const char* format, VaList* args); +[[noreturn]] void APS5_VABI errc_nid_postfix(int status, int code, const char* format, ...); +[[noreturn]] void APS5_VABI err_nid_postfix(int status, const char* format, ...); +[[noreturn]] void APS5_VABI _err_nid_postfix(int status, const char* format, ...); +[[noreturn]] void APS5_VABI errx_nid_postfix(int status, const char* format, ...); + +int APS5_VABI _ZNSt10filesystem5_StatEPKcPNS_5permsEPi_nid_postfix(const char* path, int* perms, int* error); +int APS5_VABI _ZNSt10filesystem6_LstatEPKcPNS_5permsEPi_nid_postfix(const char* path, int* perms, int* error); +std::uint64_t APS5_VABI _ZNSt10filesystem10_File_sizeEPKcPi_nid_postfix(const char* path, int* error); +int APS5_VABI _ZNSt10filesystem16_Last_write_timeEPKcPlS2__nid_postfix(const char* path, std::int64_t* seconds, std::int64_t* nanoseconds); +int APS5_VABI _ZNSt10filesystem9_Make_dirEPKcS1__nid_postfix(const char* path, const char* existing); +bool APS5_VABI _ZNSt10filesystem11_Remove_dirEPKc_nid_postfix(const char* path); +int APS5_VABI _ZNSt10filesystem7_UnlinkEPKc_nid_postfix(const char* path); +int APS5_VABI _ZNSt10filesystem6_ChmodEPKcNS_5permsE_nid_postfix(const char* path, int perms); +bool APS5_VABI _ZNSt10filesystem12_Current_getERA260_c_nid_postfix(char* target); +char* APS5_VABI _ZNSt10filesystem9_Read_dirERA260_cPvRNS_9file_typeE_nid_postfix(char* target, void* handle, int* type); +void* APS5_VABI _ZNSt10filesystem9_Open_dirERA260_cPKcRiRNS_9file_typeE_nid_postfix(char* target, const char* path, int* error, int* type); +int APS5_VABI _ZNSt10filesystem10_Close_dirEPv_nid_postfix(void* handle); +void APS5_VABI _ZNSt10filesystem18_Xfilesystem_errorEPKcSt10error_code_nid_postfix(); +void APS5_VABI _ZNSt10filesystem18_Xfilesystem_errorEPKcRKNS_4pathESt10error_code_nid_postfix(); +int APS5_VABI __std_init_once_begin_initialize_clr_nid_postfix(void** once, unsigned long flags, int* pending, void** context); +int APS5_VABI __std_init_once_complete_clr_nid_postfix(void** once, unsigned long flags, void* context); +[[noreturn]] void APS5_VABI __std_init_once_link_alternate_names_and_abort_nid_postfix(); + +} diff --git a/core/libs/prx/libSceLibcInternal/libSceLibcInternal.hpp b/core/libs/prx/libSceLibcInternal/libSceLibcInternal.hpp new file mode 100644 index 0000000000..7da0381b01 --- /dev/null +++ b/core/libs/prx/libSceLibcInternal/libSceLibcInternal.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceLibcInternal/include/Api.hpp" diff --git a/core/libs/prx/libSceLibreSsl/CMakeLists.txt b/core/libs/prx/libSceLibreSsl/CMakeLists.txt index ea084db6e0..20e7b85ba9 100644 --- a/core/libs/prx/libSceLibreSsl/CMakeLists.txt +++ b/core/libs/prx/libSceLibreSsl/CMakeLists.txt @@ -1,7 +1,8 @@ -add_library(libSceLibreSsl SHARED EXCLUDE_FROM_ALL ${CMAKE_CURRENT_SOURCE_DIR}/Export.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Digest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Runtime.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Aes.cpp) +add_library(libSceLibreSsl SHARED EXCLUDE_FROM_ALL ${CMAKE_CURRENT_SOURCE_DIR}/Export.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) target_include_directories(libSceLibreSsl PRIVATE ${LIBS_INCLUDE_DIR}) target_link_libraries(libSceLibreSsl PRIVATE mbedcrypto) configure_windows_unwind(libSceLibreSsl) +target_sources(libSceLibreSsl PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src/Asn1.cpp) if(BUILD_TESTING) add_test_executable(guest_libressl_x509_errors_tests ${LIBS_INCLUDE_DIR}/tests/GuestLibreSslX509Errors.cpp) @@ -21,8 +22,15 @@ if(BUILD_TESTING) configure_windows_unwind(guest_libressl_digest_tests) add_test(NAME guest_libressl_digest COMMAND guest_libressl_digest_tests) set_tests_properties(guest_libressl_digest PROPERTIES TIMEOUT 30) + add_test_executable(guest_libressl_asn1_tests ${CMAKE_CURRENT_SOURCE_DIR}/tests/Asn1.cpp) + target_include_directories(guest_libressl_asn1_tests PRIVATE ${LIBS_INCLUDE_DIR}) + target_link_libraries(guest_libressl_asn1_tests PRIVATE libSceLibreSsl libc) + configure_windows_unwind(guest_libressl_asn1_tests) + add_test(NAME guest_libressl_asn1 COMMAND guest_libressl_asn1_tests) + add_test(NAME guest_libressl_asn1_allocator COMMAND guest_libressl_asn1_tests allocator) + set_tests_properties(guest_libressl_asn1 guest_libressl_asn1_allocator PROPERTIES TIMEOUT 30) if(WIN32) - set_tests_properties(guest_libressl_digest PROPERTIES ENVIRONMENT_MODIFICATION + set_tests_properties(guest_libressl_digest guest_libressl_asn1 guest_libressl_asn1_allocator PROPERTIES ENVIRONMENT_MODIFICATION "PATH=path_list_prepend:$") endif() @@ -58,4 +66,30 @@ if(BUILD_TESTING) set_tests_properties(guest_libressl_aes PROPERTIES ENVIRONMENT_MODIFICATION "PATH=path_list_prepend:$") endif() + + add_test_executable(guest_libressl_error_tests ${LIBS_INCLUDE_DIR}/tests/GuestLibreSslError.cpp) + target_include_directories(guest_libressl_error_tests PRIVATE ${LIBS_INCLUDE_DIR}) + target_link_libraries(guest_libressl_error_tests PRIVATE libSceLibreSsl libc) + configure_windows_unwind(guest_libressl_error_tests) + add_test(NAME guest_libressl_error COMMAND guest_libressl_error_tests) + set_tests_properties(guest_libressl_error PROPERTIES TIMEOUT 30) + if(WIN32) + set_tests_properties(guest_libressl_error PROPERTIES ENVIRONMENT_MODIFICATION + "PATH=path_list_prepend:$") + endif() +endif() + +target_sources(libSceLibreSsl PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src/Cipher.cpp) + +if(BUILD_TESTING) + add_test_executable(guest_libressl_cipher_tests ${LIBS_INCLUDE_DIR}/tests/GuestLibreSslCipher.cpp) + target_include_directories(guest_libressl_cipher_tests PRIVATE ${LIBS_INCLUDE_DIR}) + target_link_libraries(guest_libressl_cipher_tests PRIVATE libSceLibreSsl libc) + configure_windows_unwind(guest_libressl_cipher_tests) + add_test(NAME guest_libressl_cipher COMMAND guest_libressl_cipher_tests) + set_tests_properties(guest_libressl_cipher PROPERTIES TIMEOUT 30) + if(WIN32) + set_tests_properties(guest_libressl_cipher PROPERTIES ENVIRONMENT_MODIFICATION + "PATH=path_list_prepend:$") + endif() endif() diff --git a/core/libs/prx/libSceLibreSsl/Export.cpp b/core/libs/prx/libSceLibreSsl/Export.cpp index 0de9afd97e..dfbd9c146d 100644 --- a/core/libs/prx/libSceLibreSsl/Export.cpp +++ b/core/libs/prx/libSceLibreSsl/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceLibreSsl/include/Api.hpp" #include #include #include @@ -18,36 +19,11 @@ constexpr std::size_t DesScheduleBytes = 128; extern "C" { APS5_DUMMY_FUN -int APS5_VABI ASN1_INTEGER_get_nid_postfix(void) { - NotImplemented_nid_no_patch(__func__); - return 0; -} - -int APS5_VABI ASN1_STRING_data_nid_postfix(void) { - NotImplemented_nid_no_patch(__func__); - return 0; -} - -int APS5_VABI ASN1_STRING_length_nid_postfix(void) { - NotImplemented_nid_no_patch(__func__); - return 0; -} - int APS5_VABI ASN1_STRING_print_nid_postfix(void) { NotImplemented_nid_no_patch(__func__); return 0; } -int APS5_VABI ASN1_STRING_to_UTF8_nid_postfix(void) { - NotImplemented_nid_no_patch(__func__); - return 0; -} - -int APS5_VABI ASN1_STRING_type_nid_postfix(void) { - NotImplemented_nid_no_patch(__func__); - return 0; -} - int APS5_VABI ASN1_TIME_print_nid_postfix(void) { NotImplemented_nid_no_patch(__func__); return 0; @@ -472,11 +448,6 @@ int APS5_VABI ENGINE_set_default_nid_postfix(void) { return 0; } -int APS5_VABI ERR_clear_error_nid_postfix(void) { - NotImplemented_nid_no_patch(__func__); - return 0; -} - int APS5_VABI ERR_error_string_nid_postfix(void) { NotImplemented_nid_no_patch(__func__); return 0; @@ -492,21 +463,6 @@ int APS5_VABI ERR_free_strings_nid_postfix(void) { return 0; } -int APS5_VABI ERR_get_error_nid_postfix(void) { - NotImplemented_nid_no_patch(__func__); - return 0; -} - -int APS5_VABI ERR_peek_error_nid_postfix(void) { - NotImplemented_nid_no_patch(__func__); - return 0; -} - -int APS5_VABI ERR_remove_thread_state_nid_postfix(void) { - NotImplemented_nid_no_patch(__func__); - return 0; -} - int APS5_VABI EVP_CIPHER_CTX_cleanup_nid_postfix(void) { NotImplemented_nid_no_patch(__func__); return 0; @@ -1027,21 +983,6 @@ int APS5_VABI RSA_verify_PKCS1_PSS_nid_postfix(void) { return 0; } -int APS5_VABI SSL_CIPHER_get_bits_nid_postfix(void) { - NotImplemented_nid_no_patch(__func__); - return 0; -} - -int APS5_VABI SSL_CIPHER_get_name_nid_postfix(void) { - NotImplemented_nid_no_patch(__func__); - return 0; -} - -int APS5_VABI SSL_CIPHER_get_version_nid_postfix(void) { - NotImplemented_nid_no_patch(__func__); - return 0; -} - int APS5_VABI SSL_CTX_add_client_CA_nid_postfix(void) { NotImplemented_nid_no_patch(__func__); return 0; diff --git a/core/libs/prx/libSceLibreSsl/include/Api.hpp b/core/libs/prx/libSceLibreSsl/include/Api.hpp new file mode 100644 index 0000000000..a9bfae70a0 --- /dev/null +++ b/core/libs/prx/libSceLibreSsl/include/Api.hpp @@ -0,0 +1,456 @@ +#pragma once + +#include "SceTypes.hpp" + +struct Asn1String { + std::int32_t length; + std::int32_t type; + unsigned char* data; + std::int64_t flags; +}; + +inline constexpr int MaxRounds = 14; + +struct AesKey { + std::uint32_t roundKeys[4 * (MaxRounds + 1)]; + std::int32_t rounds; +}; + +struct Md4Context { + std::uint32_t A, B, C, D; + std::uint32_t Nl, Nh; + std::uint32_t data[16]; + std::uint32_t num; +}; + +struct Md5Context { + std::uint32_t A, B, C, D; + std::uint32_t Nl, Nh; + std::uint32_t data[16]; + std::uint32_t num; +}; + +struct Sha1Context { + std::uint32_t h[5]; + std::uint32_t Nl, Nh; + std::uint32_t data[16]; + std::uint32_t num; +}; + +struct Sha256Context { + std::uint32_t h[8]; + std::uint32_t Nl, Nh; + std::uint32_t data[16]; + std::uint32_t num, mdLength; +}; + +struct Sha512Context { + std::uint64_t h[8]; + std::uint64_t Nl, Nh; + std::uint64_t data[16]; + std::uint32_t num, mdLength; +}; + +extern "C" { + +std::int64_t APS5_VABI ASN1_INTEGER_get_nid_postfix(const Asn1String* value); +unsigned char* APS5_VABI ASN1_STRING_data_nid_postfix(Asn1String* value); +int APS5_VABI ASN1_STRING_length_nid_postfix(const Asn1String* value); +int APS5_VABI ASN1_STRING_print_nid_postfix(void); +int APS5_VABI ASN1_STRING_to_UTF8_nid_postfix(unsigned char** output, Asn1String* value); +int APS5_VABI ASN1_STRING_type_nid_postfix(Asn1String* value); +int APS5_VABI ASN1_TIME_print_nid_postfix(void); +int APS5_VABI BIO_ctrl_nid_postfix(void); +int APS5_VABI BIO_f_ssl_nid_postfix(void); +int APS5_VABI BIO_free_nid_postfix(void); +int APS5_VABI BIO_new_nid_postfix(void); +int APS5_VABI BIO_new_fp_nid_postfix(void); +int APS5_VABI BIO_new_mem_buf_nid_postfix(void); +int APS5_VABI BIO_new_socket_nid_postfix(void); +int APS5_VABI BIO_printf_nid_postfix(void); +int APS5_VABI BIO_puts_nid_postfix(void); +int APS5_VABI BIO_s_file_nid_postfix(void); +int APS5_VABI BIO_s_mem_nid_postfix(void); +int APS5_VABI BIO_write_nid_postfix(void); +int APS5_VABI BN_CTX_end_nid_postfix(void); +int APS5_VABI BN_CTX_free_nid_postfix(void); +int APS5_VABI BN_CTX_new_nid_postfix(void); +int APS5_VABI BN_CTX_start_nid_postfix(void); +int APS5_VABI BN_add_word_nid_postfix(void); +int APS5_VABI BN_bin2bn_nid_postfix(void); +int APS5_VABI BN_bn2bin_nid_postfix(void); +int APS5_VABI BN_free_nid_postfix(void); +int APS5_VABI BN_hex2bn_nid_postfix(void); +int APS5_VABI BN_mod_inverse_nid_postfix(void); +int APS5_VABI BN_mul_nid_postfix(void); +int APS5_VABI BN_new_nid_postfix(void); +int APS5_VABI BN_num_bits_nid_postfix(void); +int APS5_VABI BN_print_nid_postfix(void); +int APS5_VABI BN_set_word_nid_postfix(void); +int APS5_VABI BN_sub_word_nid_postfix(void); +int APS5_VABI CMAC_CTX_free_nid_postfix(void); +int APS5_VABI CMAC_CTX_new_nid_postfix(void); +int APS5_VABI CMAC_Final_nid_postfix(void); +int APS5_VABI CMAC_Init_nid_postfix(void); +int APS5_VABI CMAC_Update_nid_postfix(void); +int APS5_VABI CONF_modules_free_nid_postfix(void); +int APS5_VABI CONF_modules_load_file_nid_postfix(void); +int APS5_VABI CRYPTO_THREADID_set_callback_nid_postfix(void); +int APS5_VABI CRYPTO_THREADID_set_numeric_nid_postfix(void); +int APS5_VABI CRYPTO_cleanup_all_ex_data_nid_postfix(void); +int APS5_VABI CRYPTO_num_locks_nid_postfix(void); +int APS5_VABI CRYPTO_set_add_lock_callback_nid_postfix(void); +int APS5_VABI CRYPTO_set_locking_callback_nid_postfix(void); +void APS5_VABI DES_ecb_encrypt_nid_postfix(const unsigned char* input, unsigned char* output, const unsigned char* schedule, int enc); +int APS5_VABI DES_set_key_nid_postfix(const unsigned char* key, unsigned char* schedule); +void APS5_VABI DES_set_odd_parity_nid_postfix(unsigned char* key); +int APS5_VABI DTLSv1_client_method_nid_postfix(void); +int APS5_VABI DTLSv1_server_method_nid_postfix(void); +int APS5_VABI ECDH_compute_key_nid_postfix(void); +int APS5_VABI ECDSA_sign_nid_postfix(void); +int APS5_VABI ECDSA_size_nid_postfix(void); +int APS5_VABI ECDSA_verify_nid_postfix(void); +int APS5_VABI EC_GROUP_free_nid_postfix(void); +int APS5_VABI EC_GROUP_get_degree_nid_postfix(void); +int APS5_VABI EC_GROUP_new_by_curve_name_nid_postfix(void); +int APS5_VABI EC_KEY_check_key_nid_postfix(void); +int APS5_VABI EC_KEY_free_nid_postfix(void); +int APS5_VABI EC_KEY_generate_key_nid_postfix(void); +int APS5_VABI EC_KEY_get0_group_nid_postfix(void); +int APS5_VABI EC_KEY_get0_private_key_nid_postfix(void); +int APS5_VABI EC_KEY_get0_public_key_nid_postfix(void); +int APS5_VABI EC_KEY_new_nid_postfix(void); +int APS5_VABI EC_KEY_new_by_curve_name_nid_postfix(void); +int APS5_VABI EC_KEY_set_group_nid_postfix(void); +int APS5_VABI EC_KEY_set_private_key_nid_postfix(void); +int APS5_VABI EC_KEY_set_public_key_nid_postfix(void); +int APS5_VABI EC_POINT_free_nid_postfix(void); +int APS5_VABI EC_POINT_mul_nid_postfix(void); +int APS5_VABI EC_POINT_new_nid_postfix(void); +int APS5_VABI EC_POINT_oct2point_nid_postfix(void); +int APS5_VABI EC_POINT_point2oct_nid_postfix(void); +int APS5_VABI ENGINE_by_id_nid_postfix(void); +int APS5_VABI ENGINE_cleanup_nid_postfix(void); +int APS5_VABI ENGINE_ctrl_nid_postfix(void); +int APS5_VABI ENGINE_ctrl_cmd_nid_postfix(void); +int APS5_VABI ENGINE_finish_nid_postfix(void); +int APS5_VABI ENGINE_free_nid_postfix(void); +int APS5_VABI ENGINE_get_first_nid_postfix(void); +int APS5_VABI ENGINE_get_id_nid_postfix(void); +int APS5_VABI ENGINE_get_next_nid_postfix(void); +int APS5_VABI ENGINE_init_nid_postfix(void); +int APS5_VABI ENGINE_load_builtin_engines_nid_postfix(void); +int APS5_VABI ENGINE_load_private_key_nid_postfix(void); +int APS5_VABI ENGINE_set_default_nid_postfix(void); +void APS5_VABI ERR_clear_error_nid_postfix(void); +int APS5_VABI ERR_error_string_nid_postfix(void); +int APS5_VABI ERR_error_string_n_nid_postfix(void); +int APS5_VABI ERR_free_strings_nid_postfix(void); +std::uint64_t APS5_VABI ERR_get_error_nid_postfix(void); +std::uint64_t APS5_VABI ERR_peek_error_nid_postfix(void); +void APS5_VABI ERR_remove_thread_state_nid_postfix(const void* threadId); +int APS5_VABI EVP_CIPHER_CTX_cleanup_nid_postfix(void); +int APS5_VABI EVP_CIPHER_CTX_ctrl_nid_postfix(void); +int APS5_VABI EVP_CIPHER_CTX_free_nid_postfix(void); +int APS5_VABI EVP_CIPHER_CTX_init_nid_postfix(void); +int APS5_VABI EVP_CIPHER_CTX_new_nid_postfix(void); +int APS5_VABI EVP_CIPHER_CTX_set_padding_nid_postfix(void); +int APS5_VABI EVP_CIPHER_block_size_nid_postfix(void); +int APS5_VABI EVP_CipherFinal_ex_nid_postfix(void); +int APS5_VABI EVP_CipherInit_ex_nid_postfix(void); +int APS5_VABI EVP_CipherUpdate_nid_postfix(void); +int APS5_VABI EVP_DecryptFinal_ex_nid_postfix(void); +int APS5_VABI EVP_DecryptInit_ex_nid_postfix(void); +int APS5_VABI EVP_DecryptUpdate_nid_postfix(void); +int APS5_VABI EVP_Digest_nid_postfix(void); +int APS5_VABI EVP_DigestFinal_ex_nid_postfix(void); +int APS5_VABI EVP_DigestInit_ex_nid_postfix(void); +int APS5_VABI EVP_DigestUpdate_nid_postfix(void); +int APS5_VABI EVP_DigestVerifyFinal_nid_postfix(void); +int APS5_VABI EVP_DigestVerifyInit_nid_postfix(void); +int APS5_VABI EVP_EncryptFinal_ex_nid_postfix(void); +int APS5_VABI EVP_EncryptInit_ex_nid_postfix(void); +int APS5_VABI EVP_EncryptUpdate_nid_postfix(void); +int APS5_VABI EVP_MD_CTX_cleanup_nid_postfix(void); +int APS5_VABI EVP_MD_CTX_create_nid_postfix(void); +int APS5_VABI EVP_MD_CTX_destroy_nid_postfix(void); +int APS5_VABI EVP_MD_CTX_init_nid_postfix(void); +int APS5_VABI EVP_MD_size_nid_postfix(void); +int APS5_VABI EVP_PKEY_copy_parameters_nid_postfix(void); +int APS5_VABI EVP_PKEY_free_nid_postfix(void); +int APS5_VABI EVP_PKEY_get1_EC_KEY_nid_postfix(void); +int APS5_VABI EVP_PKEY_get1_RSA_nid_postfix(void); +int APS5_VABI EVP_PKEY_id_nid_postfix(void); +int APS5_VABI EVP_PKEY_new_nid_postfix(void); +int APS5_VABI EVP_PKEY_set1_RSA_nid_postfix(void); +int APS5_VABI EVP_PKEY_type_nid_postfix(void); +int APS5_VABI EVP_aes_128_cbc_nid_postfix(void); +int APS5_VABI EVP_aes_128_cfb8_nid_postfix(void); +int APS5_VABI EVP_aes_128_ctr_nid_postfix(void); +int APS5_VABI EVP_aes_128_gcm_nid_postfix(void); +int APS5_VABI EVP_aes_192_cbc_nid_postfix(void); +int APS5_VABI EVP_aes_192_cfb8_nid_postfix(void); +int APS5_VABI EVP_aes_192_ctr_nid_postfix(void); +int APS5_VABI EVP_aes_192_gcm_nid_postfix(void); +int APS5_VABI EVP_aes_256_cbc_nid_postfix(void); +int APS5_VABI EVP_aes_256_cfb8_nid_postfix(void); +int APS5_VABI EVP_aes_256_ctr_nid_postfix(void); +int APS5_VABI EVP_aes_256_gcm_nid_postfix(void); +int APS5_VABI EVP_cleanup_nid_postfix(void); +int APS5_VABI EVP_md5_nid_postfix(void); +int APS5_VABI EVP_sha256_nid_postfix(void); +int APS5_VABI EVP_sha384_nid_postfix(void); +int APS5_VABI EVP_sha512_nid_postfix(void); +int APS5_VABI GENERAL_NAMES_free_nid_postfix(void); +int APS5_VABI GENERAL_NAME_free_nid_postfix(void); +int APS5_VABI HMAC_nid_postfix(void); +int APS5_VABI HMAC_CTX_cleanup_nid_postfix(void); +int APS5_VABI HMAC_CTX_init_nid_postfix(void); +int APS5_VABI HMAC_Final_nid_postfix(void); +int APS5_VABI HMAC_Init_nid_postfix(void); +int APS5_VABI HMAC_Init_ex_nid_postfix(void); +int APS5_VABI HMAC_Update_nid_postfix(void); +int APS5_VABI OBJ_cleanup_nid_postfix(void); +int APS5_VABI OBJ_create_nid_postfix(void); +int APS5_VABI OBJ_nid2sn_nid_postfix(void); +int APS5_VABI OBJ_obj2nid_nid_postfix(void); +int APS5_VABI OBJ_sn2nid_nid_postfix(void); +int APS5_VABI OCSP_BASICRESP_free_nid_postfix(void); +int APS5_VABI OCSP_RESPONSE_free_nid_postfix(void); +int APS5_VABI OCSP_basic_add1_cert_nid_postfix(void); +int APS5_VABI OCSP_basic_verify_nid_postfix(void); +int APS5_VABI OCSP_cert_status_str_nid_postfix(void); +int APS5_VABI OCSP_check_validity_nid_postfix(void); +int APS5_VABI OCSP_crl_reason_str_nid_postfix(void); +int APS5_VABI OCSP_resp_count_nid_postfix(void); +int APS5_VABI OCSP_resp_get0_nid_postfix(void); +int APS5_VABI OCSP_response_get1_basic_nid_postfix(void); +int APS5_VABI OCSP_response_status_nid_postfix(void); +int APS5_VABI OCSP_response_status_str_nid_postfix(void); +int APS5_VABI OCSP_single_get0_status_nid_postfix(void); +int APS5_VABI OPENSSL_add_all_algorithms_noconf_nid_postfix(void); +int APS5_VABI OPENSSL_load_builtin_modules_nid_postfix(void); +int APS5_VABI PEM_X509_INFO_read_bio_nid_postfix(void); +int APS5_VABI PEM_read_RSAPrivateKey_nid_postfix(void); +int APS5_VABI PEM_read_X509_nid_postfix(void); +int APS5_VABI PEM_read_bio_PrivateKey_nid_postfix(void); +int APS5_VABI PEM_read_bio_X509_nid_postfix(void); +int APS5_VABI PEM_read_bio_X509_AUX_nid_postfix(void); +int APS5_VABI PEM_write_bio_X509_nid_postfix(void); +int APS5_VABI PKCS12_PBE_add_nid_postfix(void); +int APS5_VABI PKCS12_free_nid_postfix(void); +int APS5_VABI PKCS12_parse_nid_postfix(void); +int APS5_VABI RSA_flags_nid_postfix(void); +int APS5_VABI RSA_free_nid_postfix(void); +int APS5_VABI RSA_generate_key_ex_nid_postfix(void); +int APS5_VABI RSA_new_nid_postfix(void); +int APS5_VABI RSA_padding_add_PKCS1_PSS_nid_postfix(void); +int APS5_VABI RSA_private_decrypt_nid_postfix(void); +int APS5_VABI RSA_private_encrypt_nid_postfix(void); +int APS5_VABI RSA_public_decrypt_nid_postfix(void); +int APS5_VABI RSA_public_encrypt_nid_postfix(void); +int APS5_VABI RSA_sign_nid_postfix(void); +int APS5_VABI RSA_size_nid_postfix(void); +int APS5_VABI RSA_verify_nid_postfix(void); +int APS5_VABI RSA_verify_PKCS1_PSS_nid_postfix(void); +int APS5_VABI SSL_CIPHER_get_bits_nid_postfix(const void* cipher, std::int32_t* algorithmBits); +const char* APS5_VABI SSL_CIPHER_get_name_nid_postfix(const void* cipher); +char* APS5_VABI SSL_CIPHER_get_version_nid_postfix(const void* cipher); +int APS5_VABI SSL_CTX_add_client_CA_nid_postfix(void); +int APS5_VABI SSL_CTX_callback_ctrl_nid_postfix(void); +int APS5_VABI SSL_CTX_check_private_key_nid_postfix(void); +int APS5_VABI SSL_CTX_ctrl_nid_postfix(void); +int APS5_VABI SSL_CTX_free_nid_postfix(void); +int APS5_VABI SSL_CTX_get_cert_store_nid_postfix(void); +int APS5_VABI SSL_CTX_get_ex_data_nid_postfix(void); +int APS5_VABI SSL_CTX_get_ex_new_index_nid_postfix(void); +int APS5_VABI SSL_CTX_get_verify_mode_nid_postfix(void); +int APS5_VABI SSL_CTX_load_verify_locations_nid_postfix(void); +int APS5_VABI SSL_CTX_load_verify_mem_nid_postfix(void); +int APS5_VABI SSL_CTX_new_nid_postfix(void); +int APS5_VABI SSL_CTX_sess_set_new_cb_nid_postfix(void); +int APS5_VABI SSL_CTX_set1_groups_list_nid_postfix(void); +int APS5_VABI SSL_CTX_set_alpn_protos_nid_postfix(void); +int APS5_VABI SSL_CTX_set_alpn_select_cb_nid_postfix(void); +int APS5_VABI SSL_CTX_set_cert_store_nid_postfix(void); +int APS5_VABI SSL_CTX_set_cert_verify_callback_nid_postfix(void); +int APS5_VABI SSL_CTX_set_cipher_list_nid_postfix(void); +int APS5_VABI SSL_CTX_set_client_cert_cb_nid_postfix(void); +int APS5_VABI SSL_CTX_set_default_passwd_cb_nid_postfix(void); +int APS5_VABI SSL_CTX_set_default_passwd_cb_userdata_nid_postfix(void); +int APS5_VABI SSL_CTX_set_ex_data_nid_postfix(void); +int APS5_VABI SSL_CTX_set_info_callback_nid_postfix(void); +int APS5_VABI SSL_CTX_set_msg_callback_nid_postfix(void); +int APS5_VABI SSL_CTX_set_next_proto_select_cb_nid_postfix(void); +int APS5_VABI SSL_CTX_set_quiet_shutdown_nid_postfix(void); +int APS5_VABI SSL_CTX_set_session_id_context_nid_postfix(void); +int APS5_VABI SSL_CTX_set_verify_nid_postfix(void); +int APS5_VABI SSL_CTX_use_PrivateKey_nid_postfix(void); +int APS5_VABI SSL_CTX_use_PrivateKey_ASN1_nid_postfix(void); +int APS5_VABI SSL_CTX_use_PrivateKey_file_nid_postfix(void); +int APS5_VABI SSL_CTX_use_certificate_nid_postfix(void); +int APS5_VABI SSL_CTX_use_certificate_ASN1_nid_postfix(void); +int APS5_VABI SSL_CTX_use_certificate_chain_file_nid_postfix(void); +int APS5_VABI SSL_CTX_use_certificate_file_nid_postfix(void); +int APS5_VABI SSL_SESSION_free_nid_postfix(void); +int APS5_VABI SSL_accept_nid_postfix(void); +int APS5_VABI SSL_alert_desc_string_long_nid_postfix(void); +int APS5_VABI SSL_check_private_key_nid_postfix(void); +int APS5_VABI SSL_connect_nid_postfix(void); +int APS5_VABI SSL_ctrl_nid_postfix(void); +int APS5_VABI SSL_free_nid_postfix(void); +int APS5_VABI SSL_get0_alpn_selected_nid_postfix(void); +int APS5_VABI SSL_get0_param_nid_postfix(void); +int APS5_VABI SSL_get1_session_nid_postfix(void); +int APS5_VABI SSL_get_SSL_CTX_nid_postfix(void); +int APS5_VABI SSL_get_certificate_nid_postfix(void); +int APS5_VABI SSL_get_current_cipher_nid_postfix(void); +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); +int APS5_VABI SSL_get_ex_new_index_nid_postfix(void); +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); +int APS5_VABI SSL_get_rbio_nid_postfix(void); +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(void); +int APS5_VABI SSL_get_verify_result_nid_postfix(void); +int APS5_VABI SSL_get_wbio_nid_postfix(void); +int APS5_VABI SSL_library_init_nid_postfix(void); +int APS5_VABI SSL_load_error_strings_nid_postfix(void); +int APS5_VABI SSL_new_nid_postfix(void); +int APS5_VABI SSL_peek_nid_postfix(void); +int APS5_VABI SSL_pending_nid_postfix(void); +int APS5_VABI SSL_read_nid_postfix(void); +int APS5_VABI SSL_select_next_proto_nid_postfix(void); +int APS5_VABI SSL_set_SSL_CTX_nid_postfix(void); +int APS5_VABI SSL_set_bio_nid_postfix(void); +int APS5_VABI SSL_set_connect_state_nid_postfix(void); +int APS5_VABI SSL_set_ex_data_nid_postfix(void); +int APS5_VABI SSL_set_fd_nid_postfix(void); +int APS5_VABI SSL_set_session_nid_postfix(void); +int APS5_VABI SSL_set_verify_nid_postfix(void); +int APS5_VABI SSL_shutdown_nid_postfix(void); +int APS5_VABI SSL_use_PrivateKey_ASN1_nid_postfix(void); +int APS5_VABI SSL_use_certificate_ASN1_nid_postfix(void); +int APS5_VABI SSL_version_nid_postfix(void); +int APS5_VABI SSL_want_nid_postfix(void); +int APS5_VABI SSL_write_nid_postfix(void); +int APS5_VABI SSLeay_nid_postfix(void); +int APS5_VABI SSLv23_client_method_nid_postfix(void); +int APS5_VABI SSLv23_server_method_nid_postfix(void); +int APS5_VABI TLS_client_method_nid_postfix(void); +int APS5_VABI UI_OpenSSL_nid_postfix(void); +int APS5_VABI UI_create_method_nid_postfix(void); +int APS5_VABI UI_destroy_method_nid_postfix(void); +int APS5_VABI UI_get0_user_data_nid_postfix(void); +int APS5_VABI UI_get_input_flags_nid_postfix(void); +int APS5_VABI UI_get_string_type_nid_postfix(void); +int APS5_VABI UI_method_get_closer_nid_postfix(void); +int APS5_VABI UI_method_get_opener_nid_postfix(void); +int APS5_VABI UI_method_get_reader_nid_postfix(void); +int APS5_VABI UI_method_get_writer_nid_postfix(void); +int APS5_VABI UI_method_set_closer_nid_postfix(void); +int APS5_VABI UI_method_set_opener_nid_postfix(void); +int APS5_VABI UI_method_set_reader_nid_postfix(void); +int APS5_VABI UI_method_set_writer_nid_postfix(void); +int APS5_VABI UI_set_result_nid_postfix(void); +int APS5_VABI X509V3_EXT_print_nid_postfix(void); +int APS5_VABI X509_EXTENSION_get_critical_nid_postfix(void); +int APS5_VABI X509_EXTENSION_get_data_nid_postfix(void); +int APS5_VABI X509_EXTENSION_get_object_nid_postfix(void); +int APS5_VABI X509_INFO_free_nid_postfix(void); +int APS5_VABI X509_LOOKUP_file_nid_postfix(void); +int APS5_VABI X509_NAME_ENTRY_get_data_nid_postfix(void); +int APS5_VABI X509_NAME_get_entry_nid_postfix(void); +int APS5_VABI X509_NAME_get_index_by_NID_nid_postfix(void); +int APS5_VABI X509_NAME_get_text_by_NID_nid_postfix(void); +int APS5_VABI X509_NAME_oneline_nid_postfix(void); +int APS5_VABI X509_NAME_print_ex_nid_postfix(void); +int APS5_VABI X509_STORE_CTX_get1_chain_nid_postfix(void); +int APS5_VABI X509_STORE_CTX_get_chain_nid_postfix(void); +int APS5_VABI X509_STORE_CTX_get_current_cert_nid_postfix(void); +int APS5_VABI X509_STORE_CTX_get_error_nid_postfix(void); +int APS5_VABI X509_STORE_CTX_get_error_depth_nid_postfix(void); +int APS5_VABI X509_STORE_CTX_get_ex_data_nid_postfix(void); +int APS5_VABI X509_STORE_CTX_set_error_nid_postfix(void); +int APS5_VABI X509_STORE_add_cert_nid_postfix(void); +int APS5_VABI X509_STORE_add_crl_nid_postfix(void); +int APS5_VABI X509_STORE_add_lookup_nid_postfix(void); +int APS5_VABI X509_STORE_free_nid_postfix(void); +int APS5_VABI X509_STORE_new_nid_postfix(void); +int APS5_VABI X509_STORE_set_flags_nid_postfix(void); +int APS5_VABI X509_VERIFY_PARAM_set1_host_nid_postfix(void); +int APS5_VABI X509_VERIFY_PARAM_set1_ip_asc_nid_postfix(void); +int APS5_VABI X509_VERIFY_PARAM_set_hostflags_nid_postfix(void); +int APS5_VABI X509_check_issued_nid_postfix(void); +int APS5_VABI X509_free_nid_postfix(void); +int APS5_VABI X509_get_ext_d2i_nid_postfix(void); +int APS5_VABI X509_get_issuer_name_nid_postfix(void); +int APS5_VABI X509_get_pubkey_nid_postfix(void); +int APS5_VABI X509_get_serialNumber_nid_postfix(void); +int APS5_VABI X509_get_subject_name_nid_postfix(void); +int APS5_VABI X509_load_crl_file_nid_postfix(void); +int APS5_VABI X509_print_ex_nid_postfix(void); +int APS5_VABI X509_verify_cert_nid_postfix(void); +const char* APS5_VABI X509_verify_cert_error_string_nid_postfix(std::int64_t error); +int APS5_VABI d2i_OCSP_RESPONSE_nid_postfix(void); +int APS5_VABI d2i_PKCS12_bio_nid_postfix(void); +int APS5_VABI d2i_PKCS12_fp_nid_postfix(void); +int APS5_VABI d2i_RSA_PUBKEY_nid_postfix(void); +int APS5_VABI d2i_X509_nid_postfix(void); +int APS5_VABI i2a_ASN1_OBJECT_nid_postfix(void); +int APS5_VABI i2d_X509_PUBKEY_nid_postfix(void); +int APS5_VABI i2t_ASN1_OBJECT_nid_postfix(void); +int APS5_VABI sceLibreSslGetMemoryPoolStats(void); +int APS5_VABI sceLibreSslInit(void); +int APS5_VABI sceLibreSslInitEx(void); +int APS5_VABI sceLibreSslInitEx2(void); +int APS5_VABI sceLibreSslTerm(void); +int APS5_VABI sk_num_nid_postfix(void); +int APS5_VABI sk_pop_nid_postfix(void); +int APS5_VABI sk_pop_free_nid_postfix(void); +int APS5_VABI sk_value_nid_postfix(void); +int APS5_VABI AES_set_encrypt_key_nid_postfix(const unsigned char* userKey, int bits, AesKey* key); +int APS5_VABI AES_set_decrypt_key_nid_postfix(const unsigned char* userKey, int bits, AesKey* key); +void APS5_VABI AES_encrypt_nid_postfix(const unsigned char* in, unsigned char* out, const AesKey* key); +void APS5_VABI AES_decrypt_nid_postfix(const unsigned char* in, unsigned char* out, const AesKey* key); +void APS5_VABI AES_ecb_encrypt_nid_postfix(const unsigned char* in, unsigned char* out, const AesKey* key, int encrypt); +void APS5_VABI AES_cbc_encrypt_nid_postfix(const unsigned char* in, unsigned char* out, std::size_t length, const AesKey* key, unsigned char* ivec, int encrypt); +void APS5_VABI AES_cfb128_encrypt_nid_postfix(const unsigned char* in, unsigned char* out, std::size_t length, const AesKey* key, unsigned char* ivec, int* num, int encrypt); +void APS5_VABI AES_ctr128_encrypt_nid_postfix(const unsigned char* in, unsigned char* out, std::size_t length, const AesKey* key, unsigned char* ivec, unsigned char* ecountBuffer, unsigned* num); +int APS5_VABI MD4_Init_nid_postfix(Md4Context* context); +int APS5_VABI MD4_Update_nid_postfix(Md4Context* context, const void* data, std::size_t length); +int APS5_VABI MD4_Final_nid_postfix(unsigned char* digest, Md4Context* context); +int APS5_VABI MD5_Init_nid_postfix(Md5Context* context); +int APS5_VABI MD5_Update_nid_postfix(Md5Context* context, const void* data, std::size_t length); +int APS5_VABI MD5_Final_nid_postfix(unsigned char* digest, Md5Context* context); +int APS5_VABI SHA1_Init_nid_postfix(Sha1Context* context); +int APS5_VABI SHA1_Update_nid_postfix(Sha1Context* context, const void* data, std::size_t length); +int APS5_VABI SHA1_Final_nid_postfix(unsigned char* digest, Sha1Context* context); +int APS5_VABI SHA224_Init_nid_postfix(Sha256Context* context); +int APS5_VABI SHA256_Init_nid_postfix(Sha256Context* context); +int APS5_VABI SHA256_Update_nid_postfix(Sha256Context* context, const void* data, std::size_t length); +int APS5_VABI SHA224_Update_nid_postfix(Sha256Context* context, const void* data, std::size_t length); +int APS5_VABI SHA256_Final_nid_postfix(unsigned char* digest, Sha256Context* context); +int APS5_VABI SHA224_Final_nid_postfix(unsigned char* digest, Sha256Context* context); +unsigned char* APS5_VABI SHA256_nid_postfix(const unsigned char* data, std::size_t length, unsigned char* digest); +int APS5_VABI SHA384_Init_nid_postfix(Sha512Context* context); +int APS5_VABI SHA512_Init_nid_postfix(Sha512Context* context); +int APS5_VABI SHA512_Update_nid_postfix(Sha512Context* context, const void* data, std::size_t length); +int APS5_VABI SHA384_Update_nid_postfix(Sha512Context* context, const void* data, std::size_t length); +int APS5_VABI SHA512_Final_nid_postfix(unsigned char* digest, Sha512Context* context); +int APS5_VABI SHA384_Final_nid_postfix(unsigned char* digest, Sha512Context* context); +void APS5_VABI RAND_add_nid_postfix(const void*, int, double); +int APS5_VABI RAND_status_nid_postfix(void); +int APS5_VABI RAND_bytes_nid_postfix(unsigned char* buffer, int count); +int APS5_VABI RAND_load_file_nid_postfix(const char*, std::int64_t bytes); +const char* APS5_VABI RAND_file_name_nid_postfix(char* buffer, std::size_t size); +void* APS5_VABI CRYPTO_malloc_nid_postfix(int count, const char*, int); +void APS5_VABI CRYPTO_free_nid_postfix(void* pointer); +int APS5_VABI CRYPTO_set_mem_functions_nid_postfix(void*, void*, void*); + +} diff --git a/core/libs/prx/libSceLibreSsl/include/Error.hpp b/core/libs/prx/libSceLibreSsl/include/Error.hpp new file mode 100644 index 0000000000..0c7a23712f --- /dev/null +++ b/core/libs/prx/libSceLibreSsl/include/Error.hpp @@ -0,0 +1,10 @@ +#ifndef CORE_LIBS_PRX_LIBSCELIBRESSL_INCLUDE_ERROR_HPP +#define CORE_LIBS_PRX_LIBSCELIBRESSL_INCLUDE_ERROR_HPP + +extern "C" { + +void LibreSslPutError_nid_no_patch(int library, int function, int reason); + +} + +#endif diff --git a/core/libs/prx/libSceLibreSsl/libSceLibreSsl.hpp b/core/libs/prx/libSceLibreSsl/libSceLibreSsl.hpp new file mode 100644 index 0000000000..7b25337c40 --- /dev/null +++ b/core/libs/prx/libSceLibreSsl/libSceLibreSsl.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceLibreSsl/include/Api.hpp" diff --git a/core/libs/prx/libSceLibreSsl/src/Aes.cpp b/core/libs/prx/libSceLibreSsl/src/Aes.cpp index 3009da6ec1..ddbdbe61db 100644 --- a/core/libs/prx/libSceLibreSsl/src/Aes.cpp +++ b/core/libs/prx/libSceLibreSsl/src/Aes.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceLibreSsl/include/Api.hpp" #include #include #include @@ -8,13 +9,8 @@ #include "prx/libc/include/General.hpp" namespace { -constexpr int MaxRounds = 14; -constexpr std::size_t BlockSize = 16; -struct AesKey { - std::uint32_t roundKeys[4 * (MaxRounds + 1)]; - std::int32_t rounds; -}; +constexpr std::size_t BlockSize = 16; static_assert(sizeof(AesKey) == 244); @@ -31,9 +27,10 @@ constexpr std::uint8_t Multiply(std::uint8_t a, std::uint8_t b) { constexpr std::array MakeSubstitution() { std::array box {}; for (int value = 0; value < 256; ++value) { - std::uint8_t inverse = 0; - for (int candidate = 1; candidate < 256 && value; ++candidate) - if (Multiply(static_cast(value), static_cast(candidate)) == 1) inverse = static_cast(candidate); + const auto element = static_cast(value); + std::uint8_t inverse = element; + for (int step = 0; step < 6; ++step) inverse = Multiply(Multiply(inverse, inverse), element); + inverse = Multiply(inverse, inverse); std::uint8_t result = 0x63; for (int shift = 0; shift < 5; ++shift) result ^= static_cast((inverse << shift) | (inverse >> ((8 - shift) & 7))); diff --git a/core/libs/prx/libSceLibreSsl/src/Asn1.cpp b/core/libs/prx/libSceLibreSsl/src/Asn1.cpp new file mode 100644 index 0000000000..304ad8ad93 --- /dev/null +++ b/core/libs/prx/libSceLibreSsl/src/Asn1.cpp @@ -0,0 +1,128 @@ +#include "prx/libSceLibreSsl/libSceLibreSsl.hpp" +#include "prx/libc/include/Api.hpp" +#include "prx/libc/include/General.hpp" +#include +#include +#include +#include +#include +#include + +namespace { + +static_assert(sizeof(Asn1String) == 24); +static_assert(offsetof(Asn1String, data) == 8); +static_assert(offsetof(Asn1String, flags) == 16); + +int CharacterWidth(int type) { + switch (type) { + case 12: return 0; + case 19: + case 20: + case 22: + case 23: + case 24: + case 26: return 1; + case 28: return 4; + case 30: return 2; + default: return -1; + } +} + +bool ReadCharacter(std::span& input, int width, std::uint32_t& value) { + value = 0; + if (width != 0) { + if (input.size() < static_cast(width)) return false; + for (int index = 0; index < width; ++index) value = (value << 8) | input[index]; + input = input.subspan(width); + } else { + const unsigned char lead = input.front(); + const int bytes = lead < 0x80 ? 1 : lead >= 0xc2 && lead <= 0xdf ? 2 + : lead >= 0xe0 && lead <= 0xef ? 3 : lead >= 0xf0 && lead <= 0xf4 ? 4 : 0; + if (bytes == 0 || input.size() < static_cast(bytes)) return false; + value = lead & (0x7f >> (bytes == 1 ? 0 : bytes)); + for (int index = 1; index < bytes; ++index) { + if ((input[index] & 0xc0) != 0x80) return false; + value = (value << 6) | (input[index] & 0x3f); + } + constexpr std::uint32_t minimum[] = {0, 0, 0x80, 0x800, 0x10000}; + if (value < minimum[bytes]) return false; + input = input.subspan(bytes); + } + return value <= 0x10ffff && (value < 0xd800 || value > 0xdfff); +} + +void AppendCharacter(std::vector& output, std::uint32_t value) { + const int bytes = value < 0x80 ? 1 : value < 0x800 ? 2 : value < 0x10000 ? 3 : 4; + if (output.size() >= static_cast(std::numeric_limits::max() - bytes)) + NotImplemented_nid_no_patch("ASN1_STRING_to_UTF8: output length overflow"); + if (bytes == 1) { + output.push_back(static_cast(value)); + return; + } + constexpr unsigned char prefix[] = {0, 0, 0xc0, 0xe0, 0xf0}; + output.push_back(static_cast(prefix[bytes] | (value >> (6 * (bytes - 1))))); + for (int index = bytes - 2; index >= 0; --index) + output.push_back(static_cast(0x80 | ((value >> (6 * index)) & 0x3f))); +} + +} // namespace + +extern "C" { + +std::int64_t APS5_VABI ASN1_INTEGER_get_nid_postfix(const Asn1String* value) { + if (!value) return 0; + const auto& integer = *value; + if (integer.type != 2 && integer.type != 0x102) return -1; + if (integer.length > 8) return -1; + if (integer.length <= 0 || !integer.data) return 0; + std::uint64_t magnitude = 0; + for (int index = 0; index < integer.length; ++index) magnitude = (magnitude << 8) | integer.data[index]; + const bool negative = integer.type == 0x102; + const auto limit = static_cast(std::numeric_limits::max()) + negative; + if (magnitude > limit) + NotImplemented_nid_no_patch(__func__); + if (negative && magnitude != 0) return -static_cast(magnitude - 1) - 1; + return static_cast(magnitude); +} + +unsigned char* APS5_VABI ASN1_STRING_data_nid_postfix(Asn1String* value) { + if (!value) NotImplemented_nid_no_patch(__func__); + return value->data; +} + +int APS5_VABI ASN1_STRING_length_nid_postfix(const Asn1String* value) { + if (!value) NotImplemented_nid_no_patch(__func__); + return value->length; +} + +int APS5_VABI ASN1_STRING_type_nid_postfix(Asn1String* value) { + if (!value) NotImplemented_nid_no_patch(__func__); + return value->type; +} + +int APS5_VABI ASN1_STRING_to_UTF8_nid_postfix(unsigned char** output, Asn1String* value) { + if (!value) return -1; + const auto& string = *value; + const int width = CharacterWidth(string.type); + if (width < 0) return -1; + if (!output || (!string.data && string.length != 0)) NotImplemented_nid_no_patch(__func__); + std::size_t length = string.length < 0 ? std::strlen(reinterpret_cast(string.data)) + : static_cast(string.length); + if (length > static_cast(std::numeric_limits::max())) NotImplemented_nid_no_patch(__func__); + std::span input(string.data, length); + std::vector converted; + while (!input.empty()) { + std::uint32_t character; + if (!ReadCharacter(input, width, character)) NotImplemented_nid_no_patch(__func__); + AppendCharacter(converted, character); + } + auto* result = static_cast(malloc_nid_postfix(converted.size() + 1)); + if (!result) NotImplemented_nid_no_patch(__func__); + if (!converted.empty()) std::memcpy(result, converted.data(), converted.size()); + result[converted.size()] = 0; + *output = result; + return static_cast(converted.size()); +} + +} diff --git a/core/libs/prx/libSceLibreSsl/src/Cipher.cpp b/core/libs/prx/libSceLibreSsl/src/Cipher.cpp new file mode 100644 index 0000000000..bf213e3cbd --- /dev/null +++ b/core/libs/prx/libSceLibreSsl/src/Cipher.cpp @@ -0,0 +1,60 @@ +#include +#include +#include +#include "prx/libSceLibreSsl/libSceLibreSsl.hpp" + +namespace { + +struct Cipher { + std::int32_t valid; + const char* name; + std::uint64_t id; + std::uint64_t keyExchange; + std::uint64_t authentication; + std::uint64_t encryption; + std::uint64_t mac; + std::uint64_t protocol; + std::uint64_t strengthFlags; + std::uint64_t extraFlags; + std::int32_t strengthBits; + std::int32_t algorithmBits; +}; + +static_assert(sizeof(Cipher) == 88); +static_assert(offsetof(Cipher, name) == 8); +static_assert(offsetof(Cipher, id) == 16); +static_assert(offsetof(Cipher, strengthBits) == 80); +static_assert(offsetof(Cipher, algorithmBits) == 84); + +} // namespace + +extern "C" { + +int APS5_VABI SSL_CIPHER_get_bits_nid_postfix(const void* cipher, std::int32_t* algorithmBits) { + if (!cipher) return 0; + const auto* bytes = static_cast(cipher); + if (algorithmBits) { + std::int32_t bits; + std::memcpy(&bits, bytes + offsetof(Cipher, algorithmBits), sizeof(bits)); + *algorithmBits = bits; + } + std::int32_t strength; + std::memcpy(&strength, bytes + offsetof(Cipher, strengthBits), sizeof(strength)); + return strength; +} + +const char* APS5_VABI SSL_CIPHER_get_name_nid_postfix(const void* cipher) { + if (!cipher) return "(NONE)"; + const char* name; + std::memcpy(&name, static_cast(cipher) + offsetof(Cipher, name), sizeof(name)); + return name; +} + +char* APS5_VABI SSL_CIPHER_get_version_nid_postfix(const void* cipher) { + if (!cipher) return const_cast("(NONE)"); + std::uint64_t id; + std::memcpy(&id, static_cast(cipher) + offsetof(Cipher, id), sizeof(id)); + return const_cast((id >> 24) == 3 ? "TLSv1/SSLv3" : "unknown"); +} + +} diff --git a/core/libs/prx/libSceLibreSsl/src/Digest.cpp b/core/libs/prx/libSceLibreSsl/src/Digest.cpp index e58974597e..b15e61d7a0 100644 --- a/core/libs/prx/libSceLibreSsl/src/Digest.cpp +++ b/core/libs/prx/libSceLibreSsl/src/Digest.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceLibreSsl/include/Api.hpp" #include #include #include @@ -7,40 +8,6 @@ #include "prx/libc/include/General.hpp" namespace { -struct Md4Context { - std::uint32_t A, B, C, D; - std::uint32_t Nl, Nh; - std::uint32_t data[16]; - std::uint32_t num; -}; - -struct Md5Context { - std::uint32_t A, B, C, D; - std::uint32_t Nl, Nh; - std::uint32_t data[16]; - std::uint32_t num; -}; - -struct Sha1Context { - std::uint32_t h[5]; - std::uint32_t Nl, Nh; - std::uint32_t data[16]; - std::uint32_t num; -}; - -struct Sha256Context { - std::uint32_t h[8]; - std::uint32_t Nl, Nh; - std::uint32_t data[16]; - std::uint32_t num, mdLength; -}; - -struct Sha512Context { - std::uint64_t h[8]; - std::uint64_t Nl, Nh; - std::uint64_t data[16]; - std::uint32_t num, mdLength; -}; static_assert(sizeof(Md4Context) == 92); static_assert(sizeof(Md5Context) == 92); @@ -494,6 +461,7 @@ unsigned char* APS5_VABI SHA256_nid_postfix(const unsigned char* data, std::size if (!digest) NotImplemented_nid_no_patch("SHA256: null digest buffer"); Sha256Context c; SHA256_Init_nid_postfix(&c); + if (length) Update32(c, data, length, Sha256Block); Sha256Final(digest, c, __func__); return digest; diff --git a/core/libs/prx/libSceLibreSsl/src/Error.cpp b/core/libs/prx/libSceLibreSsl/src/Error.cpp new file mode 100644 index 0000000000..bad0374dbb --- /dev/null +++ b/core/libs/prx/libSceLibreSsl/src/Error.cpp @@ -0,0 +1,64 @@ +#include "prx/libSceLibreSsl/include/Api.hpp" +#include +#include +#include +#include "prx/libSceLibreSsl/include/Error.hpp" +#include "prx/libc/include/General.hpp" + +namespace { +constexpr int QueueSize = 16; + +struct ErrorQueue { + std::array codes; + int top; + int bottom; +}; + +static_assert(std::is_trivially_destructible_v); + +thread_local ErrorQueue queue{}; + +std::uint64_t Oldest(bool remove) { + if (queue.bottom == queue.top) return 0; + const int index = (queue.bottom + 1) % QueueSize; + const std::uint64_t code = queue.codes[index]; + if (remove) { + queue.bottom = index; + queue.codes[index] = 0; + } + return code; +} + +void Clear() { + queue = {}; +} +} + +extern "C" { + +void LibreSslPutError_nid_no_patch(int library, int function, int reason) { + queue.top = (queue.top + 1) % QueueSize; + if (queue.top == queue.bottom) queue.bottom = (queue.bottom + 1) % QueueSize; + queue.codes[queue.top] = (static_cast(library) & 0xff) << 24 | + (static_cast(function) & 0xfff) << 12 | + (static_cast(reason) & 0xfff); +} + +std::uint64_t APS5_VABI ERR_get_error_nid_postfix() { + return Oldest(true); +} + +std::uint64_t APS5_VABI ERR_peek_error_nid_postfix() { + return Oldest(false); +} + +void APS5_VABI ERR_clear_error_nid_postfix() { + Clear(); +} + +void APS5_VABI ERR_remove_thread_state_nid_postfix(const void* threadId) { + if (threadId != nullptr) NotImplemented_nid_no_patch("ERR_remove_thread_state of a CRYPTO_THREADID"); + Clear(); +} + +} diff --git a/core/libs/prx/libSceLibreSsl/src/Runtime.cpp b/core/libs/prx/libSceLibreSsl/src/Runtime.cpp index 14f1cb5572..b3ea2389a0 100644 --- a/core/libs/prx/libSceLibreSsl/src/Runtime.cpp +++ b/core/libs/prx/libSceLibreSsl/src/Runtime.cpp @@ -1,3 +1,5 @@ +#include "prx/libc/include/Api.hpp" +#include "prx/libSceLibreSsl/include/Api.hpp" #include #include #include @@ -7,8 +9,6 @@ #include "prx/libc/include/HostEntropy.hpp" extern "C" { -void* APS5_VABI malloc_nid_postfix(std::size_t size); -void APS5_VABI free_nid_postfix(void* pointer); void APS5_VABI RAND_add_nid_postfix(const void*, int, double) { } @@ -47,6 +47,7 @@ void* APS5_VABI CRYPTO_malloc_nid_postfix(int count, const char*, int) { void APS5_VABI CRYPTO_free_nid_postfix(void* pointer) { free_nid_postfix(pointer); + } int APS5_VABI CRYPTO_set_mem_functions_nid_postfix(void*, void*, void*) { diff --git a/core/libs/prx/libSceLibreSsl/tests/Asn1.cpp b/core/libs/prx/libSceLibreSsl/tests/Asn1.cpp new file mode 100644 index 0000000000..354f36a0c9 --- /dev/null +++ b/core/libs/prx/libSceLibreSsl/tests/Asn1.cpp @@ -0,0 +1,221 @@ +#include "prx/libSceLibreSsl/libSceLibreSsl.hpp" +#include "prx/libc/include/Api.hpp" +#include "prx/libc/include/ApplicationHeap.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace { + +static_assert(sizeof(Asn1String) == 24); +static_assert(offsetof(Asn1String, data) == 8); +static_assert(offsetof(Asn1String, flags) == 16); + +void Require(bool condition, const char* message) { + if (condition) return; + std::fprintf(stderr, "failed: %s\n", message); + std::abort(); +} + +template +void RequireThrows(TAction action, const char* message) { + try { + action(); + } catch (const std::exception&) { + return; + } + Require(false, message); +} + +void CheckConversion(int type, std::span input, std::span expected, int length = -2) { + std::vector storage(input.begin(), input.end()); + storage.push_back(0); + Asn1String value{length == -2 ? static_cast(input.size()) : length, type, storage.data(), 0x123456789abcdef}; + const Asn1String original = value; + unsigned char sentinel = 0xab; + unsigned char* result = &sentinel; + Require(ASN1_STRING_to_UTF8_nid_postfix(&result, &value) == static_cast(expected.size()), "UTF-8 byte length"); + Require(result && result != &sentinel && result != storage.data(), "conversion owns a new buffer"); + Require(expected.empty() || std::memcmp(result, expected.data(), expected.size()) == 0, "converted UTF-8 bytes"); + Require(result[expected.size()] == 0, "conversion terminator"); + Require(value.length == original.length && value.type == original.type && value.data == original.data + && value.flags == original.flags, "conversion preserves the input object"); + Require(std::equal(input.begin(), input.end(), storage.begin()), "conversion preserves the input bytes"); + free_nid_postfix(result); +} + +void Accessors() { + unsigned char data[] = {'a', 0, 'b'}; + Asn1String value{3, 12, data, std::numeric_limits::max()}; + Require(ASN1_STRING_data_nid_postfix(&value) == data, "data accessor preserves pointer identity"); + ASN1_STRING_data_nid_postfix(&value)[2] = 'c'; + Require(data[2] == 'c', "data accessor permits writes"); + Require(ASN1_STRING_length_nid_postfix(&value) == 3, "length includes embedded NUL"); + Require(ASN1_STRING_type_nid_postfix(&value) == 12, "type accessor"); + value = {-9, 0x7fffffff, nullptr, -1}; + Require(ASN1_STRING_data_nid_postfix(&value) == nullptr, "null data is preserved"); + Require(ASN1_STRING_length_nid_postfix(&value) == -9, "length is returned without normalization"); + Require(ASN1_STRING_type_nid_postfix(&value) == 0x7fffffff, "type is returned without normalization"); + RequireThrows([] { ASN1_STRING_data_nid_postfix(nullptr); }, "null data accessor input"); + RequireThrows([] { ASN1_STRING_length_nid_postfix(nullptr); }, "null length accessor input"); + RequireThrows([] { ASN1_STRING_type_nid_postfix(nullptr); }, "null type accessor input"); +} + +void Integers() { + Require(ASN1_INTEGER_get_nid_postfix(nullptr) == 0, "null integer"); + unsigned char data[] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0}; + constexpr std::array expected{ + 0, 0x01, 0x0123, 0x012345, 0x01234567, 0x0123456789, 0x0123456789ab, + 0x0123456789abcd, 0x0123456789abcdef}; + for (int length = 0; length <= 8; ++length) { + Asn1String value{length, 2, data, -1}; + Require(ASN1_INTEGER_get_nid_postfix(&value) == expected[length], "positive integer and 64-bit guest long"); + value.type = 0x102; + Require(ASN1_INTEGER_get_nid_postfix(&value) == -expected[length], "negative integer magnitude"); + } + Asn1String value{9, 2, nullptr, 0}; + Require(ASN1_INTEGER_get_nid_postfix(&value) == -1, "overlength is rejected before null data"); + value.length = 8; + Require(ASN1_INTEGER_get_nid_postfix(&value) == 0, "integer with null data"); + for (int length : {std::numeric_limits::min(), -8, -1, 0}) { + for (int type : {2, 0x102}) { + for (auto* bytes : {data, static_cast(nullptr), reinterpret_cast(1)}) { + value = {length, type, bytes, -1}; + const Asn1String original = value; + Require(ASN1_INTEGER_get_nid_postfix(&value) == 0, "LibreSSL 2.5.4 nonpositive integer length"); + Require(value.length == original.length && value.type == original.type && value.data == original.data + && value.flags == original.flags, "nonpositive integer length preserves input"); + } + } + } + value = {-1, 2, data, 0}; + for (int type : {-1, 0, 1, 3, 12, 0x100, 0x202, 0x302}) { + value.type = type; + Require(ASN1_INTEGER_get_nid_postfix(&value) == -1, "only integer types are accepted"); + } + std::array maximum{0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + value = {8, 2, maximum.data(), 0}; + Require(ASN1_INTEGER_get_nid_postfix(&value) == std::numeric_limits::max(), "maximum signed integer"); + value.type = 0x102; + Require(ASN1_INTEGER_get_nid_postfix(&value) == -std::numeric_limits::max(), "negative maximum magnitude"); + std::array minimum{0x80, 0, 0, 0, 0, 0, 0, 0}; + value = {8, 0x102, minimum.data(), -1}; + const Asn1String original = value; + Require(ASN1_INTEGER_get_nid_postfix(&value) == std::numeric_limits::min(), "minimum signed integer"); + Require(value.length == original.length && value.type == original.type && value.data == original.data + && value.flags == original.flags && minimum == std::array{0x80, 0, 0, 0, 0, 0, 0, 0}, "minimum integer preserves input"); + value.type = 2; + RequireThrows([&] { ASN1_INTEGER_get_nid_postfix(&value); }, "positive magnitude above signed maximum"); + value.type = 0x102; + minimum.back() = 1; + RequireThrows([&] { ASN1_INTEGER_get_nid_postfix(&value); }, "negative magnitude below signed minimum"); + value.data = maximum.data(); + maximum[0] = 0x80; + for (int type : {2, 0x102}) { + value.type = type; + RequireThrows([&] { ASN1_INTEGER_get_nid_postfix(&value); }, "source signed-overflow path throws"); + } + std::array zero{}; + value = {9, 2, zero.data(), 0}; + Require(ASN1_INTEGER_get_nid_postfix(&value) == -1, "overlength leading zeros are not trimmed"); +} + +void Strings() { + constexpr unsigned char latin[] = {0, 0x41, 0x7f, 0x80, 0xa3, 0xff}; + constexpr unsigned char latinUtf8[] = {0, 0x41, 0x7f, 0xc2, 0x80, 0xc2, 0xa3, 0xc3, 0xbf}; + constexpr unsigned char bmp[] = {0, 0, 0, 0x7f, 0, 0x80, 7, 0xff, 8, 0, 0x20, 0xac, 0xd7, 0xff, 0xe0, 0, 0xff, 0xff}; + constexpr unsigned char bmpUtf8[] = {0, 0x7f, 0xc2, 0x80, 0xdf, 0xbf, 0xe0, 0xa0, 0x80, 0xe2, 0x82, 0xac, + 0xed, 0x9f, 0xbf, 0xee, 0x80, 0x80, 0xef, 0xbf, 0xbf}; + constexpr unsigned char universal[] = {0, 0, 0, 0x41, 0, 1, 0, 0, 0, 1, 0xf6, 0, 0, 0x10, 0xff, 0xff}; + constexpr unsigned char universalUtf8[] = {0x41, 0xf0, 0x90, 0x80, 0x80, 0xf0, 0x9f, 0x98, 0x80, 0xf4, 0x8f, 0xbf, 0xbf}; + for (int type : {19, 20, 22, 23, 24, 26}) CheckConversion(type, latin, latinUtf8); + CheckConversion(30, bmp, bmpUtf8); + CheckConversion(28, universal, universalUtf8); + CheckConversion(12, bmpUtf8, bmpUtf8); + CheckConversion(12, universalUtf8, universalUtf8); + for (int type : {12, 19, 20, 22, 23, 24, 26, 28, 30}) { + CheckConversion(type, {}, {}); + Asn1String empty{0, type, nullptr, 0}; + unsigned char* result = nullptr; + Require(ASN1_STRING_to_UTF8_nid_postfix(&result, &empty) == 0 && result && *result == 0, "empty null-data string"); + free_nid_postfix(result); + } + constexpr unsigned char terminated[] = {'A', 0xc2, 0xa3, 0, 'X'}; + CheckConversion(12, terminated, std::span(terminated).first(3), -1); + CheckConversion(12, terminated, std::span(terminated).first(3), -7); + constexpr unsigned char ascii[] = {'A', 'B', 'C'}; + CheckConversion(19, ascii, ascii, -1); + + unsigned char sentinel = 0xab; + unsigned char* result = &sentinel; + Require(ASN1_STRING_to_UTF8_nid_postfix(&result, nullptr) == -1 && result == &sentinel, "null conversion input"); + Require(ASN1_STRING_to_UTF8_nid_postfix(nullptr, nullptr) == -1, "null input checked before output"); + for (int type = -1; type <= 32; ++type) { + if (type == 12 || type == 19 || type == 20 || type == 22 || type == 23 || type == 24 || type == 26 || type == 28 || type == 30) continue; + Asn1String value{0, type, nullptr, 0}; + Require(ASN1_STRING_to_UTF8_nid_postfix(&result, &value) == -1 && result == &sentinel, "unsupported string tag"); + Require(ASN1_STRING_to_UTF8_nid_postfix(nullptr, &value) == -1, "tag checked before output"); + } + Asn1String value{0, 12, nullptr, 0}; + RequireThrows([&] { ASN1_STRING_to_UTF8_nid_postfix(nullptr, &value); }, "null conversion output"); + value.length = 1; + RequireThrows([&] { ASN1_STRING_to_UTF8_nid_postfix(&result, &value); }, "null nonempty string data"); + value.length = -1; + RequireThrows([&] { ASN1_STRING_to_UTF8_nid_postfix(&result, &value); }, "null terminated-string data"); +} + +std::size_t lastAllocationSize = 0; +int allocationCount = 0; +int freeCount = 0; + +void* APS5_VABI Allocate_nid_no_patch(std::size_t size) { + lastAllocationSize = size; + ++allocationCount; + return std::malloc(size); +} + +void APS5_VABI Free_nid_no_patch(void* pointer) { + ++freeCount; + std::free(pointer); +} + +void* APS5_VABI Calloc_nid_no_patch(std::size_t, std::size_t) { throw std::runtime_error("unexpected calloc"); } +void* APS5_VABI Reallocate_nid_no_patch(void*, std::size_t) { throw std::runtime_error("unexpected realloc"); } +void* APS5_VABI Align_nid_no_patch(std::size_t, std::size_t) { throw std::runtime_error("unexpected aligned allocation"); } +void* APS5_VABI Realign_nid_no_patch(void*, std::size_t, std::size_t) { throw std::runtime_error("unexpected aligned reallocation"); } +int APS5_VABI PosixAlign_nid_no_patch(void**, std::size_t, std::size_t) { throw std::runtime_error("unexpected posix_memalign"); } + +void Allocator() { + std::array api{ + reinterpret_cast(Allocate_nid_no_patch), reinterpret_cast(Free_nid_no_patch), reinterpret_cast(Calloc_nid_no_patch), + reinterpret_cast(Reallocate_nid_no_patch), reinterpret_cast(Align_nid_no_patch), reinterpret_cast(Realign_nid_no_patch), + reinterpret_cast(PosixAlign_nid_no_patch)}; + ApplicationHeapRegister_nid_no_patch(api.data()); + constexpr unsigned char input[] = {0xff}; + constexpr unsigned char expected[] = {0xc3, 0xbf}; + CheckConversion(20, input, expected); + Require(allocationCount == 1 && lastAllocationSize == 3 && freeCount == 1, "conversion uses the application allocator"); +} + +} // namespace + +int main(int argc, char**) { + if (argc > 1) { + Allocator(); + return 0; + } + std::array api{}; + ApplicationHeapRegister_nid_no_patch(api.data()); + Accessors(); + Integers(); + Strings(); +} diff --git a/core/libs/prx/libSceLibreSsl3/Export.cpp b/core/libs/prx/libSceLibreSsl3/Export.cpp index 623b05d144..dfd0b1b483 100644 --- a/core/libs/prx/libSceLibreSsl3/Export.cpp +++ b/core/libs/prx/libSceLibreSsl3/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceLibreSsl3/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceLibreSsl3/include/Api.hpp b/core/libs/prx/libSceLibreSsl3/include/Api.hpp new file mode 100644 index 0000000000..ff2a535fd7 --- /dev/null +++ b/core/libs/prx/libSceLibreSsl3/include/Api.hpp @@ -0,0 +1,95 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI ASN1_INTEGER_free_nid_postfix(void); +int APS5_VABI ASN1_OBJECT_free_nid_postfix(void); +int APS5_VABI ASN1_STRING_get0_data_nid_postfix(void); +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); +int APS5_VABI DH_get0_key_nid_postfix(void); +int APS5_VABI DH_get0_pqg_nid_postfix(void); +int APS5_VABI DSA_get0_key_nid_postfix(void); +int APS5_VABI DSA_get0_pqg_nid_postfix(void); +int APS5_VABI EC_KEY_up_ref_nid_postfix(void); +int APS5_VABI ERR_load_crypto_strings_nid_postfix(void); +int APS5_VABI ERR_peek_last_error_nid_postfix(void); +int APS5_VABI ERR_print_errors_cb_nid_postfix(void); +int APS5_VABI EVP_CIPHER_CTX_set_flags_nid_postfix(void); +int APS5_VABI EVP_DigestInit_nid_postfix(void); +int APS5_VABI EVP_DigestSignFinal_nid_postfix(void); +int APS5_VABI EVP_DigestSignInit_nid_postfix(void); +int APS5_VABI EVP_EncryptInit_nid_postfix(void); +int APS5_VABI EVP_MD_CTX_free_nid_postfix(void); +int APS5_VABI EVP_MD_CTX_new_nid_postfix(void); +int APS5_VABI EVP_PKCS82PKEY_nid_postfix(void); +int APS5_VABI EVP_PKEY_CTX_ctrl_nid_postfix(void); +int APS5_VABI EVP_PKEY_CTX_new_nid_postfix(void); +int APS5_VABI EVP_PKEY_decrypt_nid_postfix(void); +int APS5_VABI EVP_PKEY_decrypt_init_nid_postfix(void); +int APS5_VABI EVP_PKEY_encrypt_nid_postfix(void); +int APS5_VABI EVP_PKEY_encrypt_init_nid_postfix(void); +int APS5_VABI EVP_PKEY_get0_DH_nid_postfix(void); +int APS5_VABI EVP_PKEY_get0_DSA_nid_postfix(void); +int APS5_VABI EVP_PKEY_get0_RSA_nid_postfix(void); +int APS5_VABI EVP_PKEY_new_mac_key_nid_postfix(void); +int APS5_VABI EVP_PKEY_set1_EC_KEY_nid_postfix(void); +int APS5_VABI EVP_PKEY_size_nid_postfix(void); +int APS5_VABI EVP_PKEY_up_ref_nid_postfix(void); +int APS5_VABI EVP_SignFinal_nid_postfix(void); +int APS5_VABI EVP_VerifyFinal_nid_postfix(void); +int APS5_VABI EVP_aes_128_wrap_nid_postfix(void); +int APS5_VABI EVP_aes_192_wrap_nid_postfix(void); +int APS5_VABI EVP_aes_256_wrap_nid_postfix(void); +int APS5_VABI EVP_sha1_nid_postfix(void); +int APS5_VABI EVP_sha224_nid_postfix(void); +int APS5_VABI OBJ_cmp_nid_postfix(void); +int APS5_VABI OBJ_txt2obj_nid_postfix(void); +int APS5_VABI OCSP_CERTID_free_nid_postfix(void); +int APS5_VABI OCSP_cert_to_id_nid_postfix(void); +int APS5_VABI OCSP_resp_find_status_nid_postfix(void); +int APS5_VABI OpenSSL_version_nid_postfix(void); +int APS5_VABI PKCS7_free_nid_postfix(void); +int APS5_VABI PKCS8_PRIV_KEY_INFO_free_nid_postfix(void); +int APS5_VABI RSA_check_key_nid_postfix(void); +int APS5_VABI RSA_get0_key_nid_postfix(void); +int APS5_VABI RSA_padding_add_PKCS1_PSS_mgf1_nid_postfix(void); +int APS5_VABI RSA_up_ref_nid_postfix(void); +int APS5_VABI SSL_CTX_add0_chain_cert_nid_postfix(void); +int APS5_VABI SSL_CTX_clear_chain_certs_nid_postfix(void); +int APS5_VABI SSL_CTX_set_max_proto_version_nid_postfix(void); +int APS5_VABI SSL_CTX_set_min_proto_version_nid_postfix(void); +int APS5_VABI SSL_CTX_up_ref_nid_postfix(void); +int APS5_VABI SSL_SESSION_up_ref_nid_postfix(void); +int APS5_VABI SSL_get_client_random_nid_postfix(void); +int APS5_VABI SSL_up_ref_nid_postfix(void); +int APS5_VABI X509_PUBKEY_get0_param_nid_postfix(void); +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); +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); +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); +int APS5_VABI X509_up_ref_nid_postfix(void); +int APS5_VABI d2i_ASN1_INTEGER_nid_postfix(void); +int APS5_VABI d2i_ECParameters_nid_postfix(void); +int APS5_VABI d2i_PKCS7_nid_postfix(void); +int APS5_VABI d2i_PKCS8_PRIV_KEY_INFO_bio_nid_postfix(void); +int APS5_VABI d2i_PrivateKey_bio_nid_postfix(void); +int APS5_VABI d2i_RSAPublicKey_bio_nid_postfix(void); +int APS5_VABI d2i_X509_bio_nid_postfix(void); +int APS5_VABI o2i_ECPublicKey_nid_postfix(void); +unsigned char* APS5_VABI MD5_nid_postfix(const unsigned char* data, std::size_t length, unsigned char* digest); +unsigned char* APS5_VABI SHA1_nid_postfix(const unsigned char* data, std::size_t length, unsigned char* digest); + +} diff --git a/core/libs/prx/libSceLibreSsl3/libSceLibreSsl3.hpp b/core/libs/prx/libSceLibreSsl3/libSceLibreSsl3.hpp new file mode 100644 index 0000000000..e9b09745c0 --- /dev/null +++ b/core/libs/prx/libSceLibreSsl3/libSceLibreSsl3.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceLibreSsl3/include/Api.hpp" diff --git a/core/libs/prx/libSceLibreSsl3/src/Digest.cpp b/core/libs/prx/libSceLibreSsl3/src/Digest.cpp index 373654f3d5..ae6a5b5e19 100644 --- a/core/libs/prx/libSceLibreSsl3/src/Digest.cpp +++ b/core/libs/prx/libSceLibreSsl3/src/Digest.cpp @@ -1,29 +1,27 @@ +#include "prx/libSceLibreSsl3/include/Api.hpp" +#include "prx/libSceLibreSsl/include/Api.hpp" #include #include "prx/libc/include/General.hpp" extern "C" { -int APS5_VABI MD5_Init_nid_postfix(void* context); -int APS5_VABI MD5_Update_nid_postfix(void* context, const void* data, std::size_t length); -int APS5_VABI MD5_Final_nid_postfix(unsigned char* digest, void* context); -int APS5_VABI SHA1_Init_nid_postfix(void* context); -int APS5_VABI SHA1_Update_nid_postfix(void* context, const void* data, std::size_t length); -int APS5_VABI SHA1_Final_nid_postfix(unsigned char* digest, void* context); unsigned char* APS5_VABI MD5_nid_postfix(const unsigned char* data, std::size_t length, unsigned char* digest) { if (!digest) NotImplemented_nid_no_patch("MD5: null digest buffer"); - alignas(8) unsigned char context[92]; - MD5_Init_nid_postfix(context); - MD5_Update_nid_postfix(context, data, length); - MD5_Final_nid_postfix(digest, context); + Md5Context context; + MD5_Init_nid_postfix(&context); + MD5_Update_nid_postfix(&context, data, length); + MD5_Final_nid_postfix(digest, &context); + return digest; } unsigned char* APS5_VABI SHA1_nid_postfix(const unsigned char* data, std::size_t length, unsigned char* digest) { if (!digest) NotImplemented_nid_no_patch("SHA1: null digest buffer"); - alignas(8) unsigned char context[96]; - SHA1_Init_nid_postfix(context); - SHA1_Update_nid_postfix(context, data, length); - SHA1_Final_nid_postfix(digest, context); + Sha1Context context; + SHA1_Init_nid_postfix(&context); + SHA1_Update_nid_postfix(&context, data, length); + SHA1_Final_nid_postfix(digest, &context); + return digest; } diff --git a/core/libs/prx/libSceLoginDialog/Export.cpp b/core/libs/prx/libSceLoginDialog/Export.cpp index 8fcd0f4daf..1f652d35fb 100644 --- a/core/libs/prx/libSceLoginDialog/Export.cpp +++ b/core/libs/prx/libSceLoginDialog/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceLoginDialog/include/Api.hpp" #include #include #include diff --git a/core/libs/prx/libSceLoginDialog/include/Api.hpp b/core/libs/prx/libSceLoginDialog/include/Api.hpp new file mode 100644 index 0000000000..51bca2f699 --- /dev/null +++ b/core/libs/prx/libSceLoginDialog/include/Api.hpp @@ -0,0 +1,16 @@ +#pragma once + +#include "prx/libSceCommonDialog/CommonDialog.hpp" +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceLoginDialogInitialize(void); +int APS5_VABI sceLoginDialogOpen(const LoginDialogParam* param); +int APS5_VABI sceLoginDialogUpdateStatus(void); +int APS5_VABI sceLoginDialogGetStatus(void); +int APS5_VABI sceLoginDialogGetResult(LoginDialogResult* result); +int APS5_VABI sceLoginDialogClose(void); +int APS5_VABI sceLoginDialogTerminate(void); + +} diff --git a/core/libs/prx/libSceLoginDialog/libSceLoginDialog.hpp b/core/libs/prx/libSceLoginDialog/libSceLoginDialog.hpp new file mode 100644 index 0000000000..eed4b0aa93 --- /dev/null +++ b/core/libs/prx/libSceLoginDialog/libSceLoginDialog.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceLoginDialog/include/Api.hpp" diff --git a/core/libs/prx/libSceLoginMgrServer/Export.cpp b/core/libs/prx/libSceLoginMgrServer/Export.cpp index c0497cf3de..8c56379312 100644 --- a/core/libs/prx/libSceLoginMgrServer/Export.cpp +++ b/core/libs/prx/libSceLoginMgrServer/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceLoginMgrServer/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceLoginMgrServer/include/Api.hpp b/core/libs/prx/libSceLoginMgrServer/include/Api.hpp new file mode 100644 index 0000000000..de64daf5d9 --- /dev/null +++ b/core/libs/prx/libSceLoginMgrServer/include/Api.hpp @@ -0,0 +1,38 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceLoginMgrServerCheckSafetyNoticeShown(); +int APS5_VABI sceLoginMgrServerClearMorpheusRequiredUserId(); +int APS5_VABI sceLoginMgrServerConvertToUserId(); +int APS5_VABI sceLoginMgrServerCreateUser(); +int APS5_VABI sceLoginMgrServerDestroyUser(); +int APS5_VABI sceLoginMgrServerDialogGetAppId(); +int APS5_VABI sceLoginMgrServerDialogGetOpenParam(); +int APS5_VABI sceLoginMgrServerDialogNotifyCloseFinished(); +int APS5_VABI sceLoginMgrServerDialogNotifyOpenFinished(); +int APS5_VABI sceLoginMgrServerDialogSetResult(); +int APS5_VABI sceLoginMgrServerGetLogoutInfo(); +int APS5_VABI sceLoginMgrServerGetMorpheusRequiredUserId(); +int APS5_VABI sceLoginMgrServerGetSharePlayAllowPadOperation(); +int APS5_VABI sceLoginMgrServerInitialize(); +int APS5_VABI sceLoginMgrServerInitializeSharePlayAllowPadOperation(); +int APS5_VABI sceLoginMgrServerIsRequestedCdlgClose(); +int APS5_VABI sceLoginMgrServerLoginServiceGetRequestParam(); +int APS5_VABI sceLoginMgrServerLoginServiceNotifyRequestFinished(); +int APS5_VABI sceLoginMgrServerNotifyEasySignInFinished(); +int APS5_VABI sceLoginMgrServerNotifyEasySignInUserCode(); +int APS5_VABI sceLoginMgrServerNotifyHmdConnectInfo(); +int APS5_VABI sceLoginMgrServerNotifySafetyNoticeShown(); +int APS5_VABI sceLoginMgrServerNotifyShellUIState(); +int APS5_VABI sceLoginMgrServerSetLoginFlag(); +int APS5_VABI sceLoginMgrServerSetMorpheusAssignEnabledFlag(); +int APS5_VABI sceLoginMgrServerSetMorpheusRequiredUserId(); +int APS5_VABI sceLoginMgrServerSetSharePlayMode(); +int APS5_VABI sceLoginMgrServerSetUserStatus(); +int APS5_VABI sceLoginMgrServerTerminate(); +int APS5_VABI sceLoginMgrServerUpdateUserIdRalatedToPadUniqueId(); + +} diff --git a/core/libs/prx/libSceLoginMgrServer/libSceLoginMgrServer.hpp b/core/libs/prx/libSceLoginMgrServer/libSceLoginMgrServer.hpp new file mode 100644 index 0000000000..244b5b6a16 --- /dev/null +++ b/core/libs/prx/libSceLoginMgrServer/libSceLoginMgrServer.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceLoginMgrServer/include/Api.hpp" diff --git a/core/libs/prx/libSceLoginService/Export.cpp b/core/libs/prx/libSceLoginService/Export.cpp index 71262ec59b..e3a24fd796 100644 --- a/core/libs/prx/libSceLoginService/Export.cpp +++ b/core/libs/prx/libSceLoginService/Export.cpp @@ -1,9 +1,8 @@ +#include "prx/libSceLoginService/include/Api.hpp" #include #include "SceTypes.hpp" #include "prx/libc/include/General.hpp" -struct LoginServiceDeviceRequest; - extern "C" { int APS5_VABI sceLoginServiceInitialize(void) { diff --git a/core/libs/prx/libSceLoginService/include/Api.hpp b/core/libs/prx/libSceLoginService/include/Api.hpp new file mode 100644 index 0000000000..853ce09844 --- /dev/null +++ b/core/libs/prx/libSceLoginService/include/Api.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include "SceTypes.hpp" + +struct LoginServiceDeviceRequest; + +extern "C" { + +int APS5_VABI sceLoginServiceInitialize(void); +int APS5_VABI sceLoginServiceTerminate(void); +int APS5_VABI sceLoginServiceRequestDevices(const LoginServiceDeviceRequest* param); + +} diff --git a/core/libs/prx/libSceLoginService/libSceLoginService.hpp b/core/libs/prx/libSceLoginService/libSceLoginService.hpp new file mode 100644 index 0000000000..7de7ce0c1e --- /dev/null +++ b/core/libs/prx/libSceLoginService/libSceLoginService.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceLoginService/include/Api.hpp" diff --git a/core/libs/prx/libSceM4aacEnc/Export.cpp b/core/libs/prx/libSceM4aacEnc/Export.cpp index e71f829cca..64de066d07 100644 --- a/core/libs/prx/libSceM4aacEnc/Export.cpp +++ b/core/libs/prx/libSceM4aacEnc/Export.cpp @@ -1,9 +1,9 @@ +#include "prx/libSceM4aacEnc/include/Api.hpp" #include #include #include "SceTypes.hpp" #include "prx/libc/include/General.hpp" - extern "C" { int32_t APS5_VABI sceM4aacEncClearContext(int32_t m4aacEncHandle) { diff --git a/core/libs/prx/libSceM4aacEnc/include/Api.hpp b/core/libs/prx/libSceM4aacEnc/include/Api.hpp new file mode 100644 index 0000000000..a981414104 --- /dev/null +++ b/core/libs/prx/libSceM4aacEnc/include/Api.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int32_t APS5_VABI sceM4aacEncClearContext(int32_t m4aacEncHandle); +int APS5_VABI sceM4aacEncClearContextEx(); +int32_t APS5_VABI sceM4aacEncCreateEncoder(int32_t channels, int32_t samplingRate, int32_t bitRate, int32_t inputFormat, int32_t outputFormat, int32_t *pInternalError); +int APS5_VABI sceM4aacEncCreateEncoderEx(); +int32_t APS5_VABI sceM4aacEncDeleteEncoder(int32_t m4aacEncHandle, int32_t *pInternalError); +int APS5_VABI sceM4aacEncDeleteEncoderEx(); +int32_t APS5_VABI sceM4aacEncEncode(int32_t m4aacEncHandle, void *pInput, uint32_t inputByte, void *pOutput, uint32_t *pOutputByte, int32_t *pInternalError); +int APS5_VABI sceM4aacEncEncodeEx(); +int APS5_VABI sceM4aacEncEncodeWithPriority(); +int APS5_VABI sceM4aacEncEncodeWithPriorityEx(); +int32_t APS5_VABI sceM4aacEncFlush(int32_t m4aacEncHandle, void *pOutput, uint32_t *pOutputByte, int32_t *pInternalError); +int APS5_VABI sceM4aacEncFlushEx(); +int APS5_VABI sceM4aacEncFlushWithPriority(); +int APS5_VABI sceM4aacEncFlushWithPriorityEx(); +int APS5_VABI sceM4aacEncGetContext(); +int APS5_VABI sceM4aacEncInitialize(); +int APS5_VABI sceM4aacEncTerminate(); + +} diff --git a/core/libs/prx/libSceM4aacEnc/libSceM4aacEnc.hpp b/core/libs/prx/libSceM4aacEnc/libSceM4aacEnc.hpp new file mode 100644 index 0000000000..23842cc39b --- /dev/null +++ b/core/libs/prx/libSceM4aacEnc/libSceM4aacEnc.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceM4aacEnc/include/Api.hpp" diff --git a/core/libs/prx/libSceMarlin/libSceMarlin.hpp b/core/libs/prx/libSceMarlin/libSceMarlin.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceMarlin/libSceMarlin.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceMat/libSceMat.hpp b/core/libs/prx/libSceMat/libSceMat.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceMat/libSceMat.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceMbus/Export.cpp b/core/libs/prx/libSceMbus/Export.cpp index ca49b545be..5212afd405 100644 --- a/core/libs/prx/libSceMbus/Export.cpp +++ b/core/libs/prx/libSceMbus/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceMbus/include/Api.hpp" #include #include #include "SceTypes.hpp" @@ -5,24 +6,6 @@ #include -struct DeviceServiceThreadParam { - std::uint64_t affinityMask; - std::int32_t priority; - std::uint32_t reserved; -}; - -struct DeviceServiceInitParam { - std::uint32_t size; - std::uint32_t reserved; - const DeviceServiceThreadParam* threadParam; -}; - -struct DeviceServiceUsageFilter { - std::uint16_t usagePage; - std::uint16_t minimumUsage; - std::uint16_t maximumUsage; -}; - static_assert(sizeof(DeviceServiceThreadParam) == 16); static_assert(offsetof(DeviceServiceThreadParam, priority) == 8); static_assert(sizeof(DeviceServiceInitParam) == 16); diff --git a/core/libs/prx/libSceMbus/PendingExports.cpp b/core/libs/prx/libSceMbus/PendingExports.cpp index 76313b1a67..d5f6a7f050 100644 --- a/core/libs/prx/libSceMbus/PendingExports.cpp +++ b/core/libs/prx/libSceMbus/PendingExports.cpp @@ -1,38 +1,13 @@ +#include "prx/libSceMbus/include/Api.hpp" #include "prx/libc/include/General.hpp" #include -struct MbusDeviceFunctionState { - std::byte data[180]; -}; - static_assert(sizeof(MbusDeviceFunctionState) == 180); -struct MbusDeviceDescription; -struct MbusDeviceInfo; -struct MbusSimulatedHandleStatus; -struct MbusSparkState; -struct MbusDriverCallbacks; -struct MbusUsbPowerEntry; -struct MbusEvent; -struct alignas(8) MbusDeviceCondition { - std::byte data[256]; -}; static_assert(sizeof(MbusDeviceCondition) == 256); -struct MbusDeviceServiceInfo; -struct MbusEventCallbacks { - void (APS5_VABI *onOverflow)(std::int32_t eventHandle, void* userData); - void (APS5_VABI *onEvent)(std::int32_t eventHandle, void* userData, const MbusEvent* event); -}; static_assert(sizeof(MbusEventCallbacks) == 16); -struct MbusProcessInfo; -struct MbusStartupInfo; -struct MbusStartupParam; -struct MbusControlStatus; -struct MbusDebugDeviceInfo; -struct MbusInternalInfo; -struct MbusPriorityInfo; extern "C" { diff --git a/core/libs/prx/libSceMbus/include/Api.hpp b/core/libs/prx/libSceMbus/include/Api.hpp new file mode 100644 index 0000000000..d31c99a8aa --- /dev/null +++ b/core/libs/prx/libSceMbus/include/Api.hpp @@ -0,0 +1,192 @@ +#pragma once + +#include "SceTypes.hpp" +#include +#include +#include + +struct DeviceServiceThreadParam { + std::uint64_t affinityMask; + std::int32_t priority; + std::uint32_t reserved; +}; + +struct DeviceServiceInitParam { + std::uint32_t size; + std::uint32_t reserved; + const DeviceServiceThreadParam* threadParam; +}; + +struct DeviceServiceUsageFilter { + std::uint16_t usagePage; + std::uint16_t minimumUsage; + std::uint16_t maximumUsage; +}; + +struct MbusDeviceFunctionState { + std::byte data[180]; +}; + +struct MbusDeviceDescription; + +struct MbusDeviceInfo; + +struct MbusSimulatedHandleStatus; + +struct MbusSparkState; + +struct MbusDriverCallbacks; + +struct MbusUsbPowerEntry; + +struct MbusEvent; + +struct alignas(8) MbusDeviceCondition { + std::byte data[256]; +}; + +struct MbusDeviceServiceInfo; + +struct MbusEventCallbacks { + void (APS5_VABI *onOverflow)(std::int32_t eventHandle, void* userData); + void (APS5_VABI *onEvent)(std::int32_t eventHandle, void* userData, const MbusEvent* event); +}; + +struct MbusProcessInfo; + +struct MbusStartupInfo; + +struct MbusStartupParam; + +struct MbusControlStatus; + +struct MbusDebugDeviceInfo; + +struct MbusInternalInfo; + +struct MbusPriorityInfo; + +extern "C" { + +std::int32_t APS5_VABI sceDeviceServiceInitialize(std::int32_t mode, const DeviceServiceInitParam* param); +std::int32_t APS5_VABI sceDeviceServiceTerminate(); +std::int32_t APS5_VABI sceDeviceServiceGetEventState(std::int32_t clear); +std::int32_t APS5_VABI sceDeviceServiceQueryDeviceInfo_(std::int32_t deviceClass, const DeviceServiceUsageFilter* filter, std::int32_t arg2, void* infos, std::int32_t maxInfos, std::int32_t* count, std::int32_t* reserved, std::uint32_t infoSize); +std::int32_t APS5_VABI sceDeviceServiceGetGeneration(void); +int APS5_VABI sceMbusAcquireControl(std::uint64_t control, std::int32_t first, std::int32_t second); +int APS5_VABI sceMbusAcquireControlList(); +int APS5_VABI sceMbusAcquireControlWithState(std::uint32_t deviceClass, std::int32_t state); +int APS5_VABI sceMbusAcquireControlWithState2(std::uint32_t deviceClass, std::int32_t moduleId, std::int32_t state); +int APS5_VABI sceMbusAcquireControlWithStateFlag(std::uint32_t deviceClass, std::uint32_t moduleId, std::uint32_t state, std::uint32_t flags); +int APS5_VABI sceMbusAddHandle(std::uint32_t deviceClass, std::int32_t handle, std::uint32_t flags); +int APS5_VABI sceMbusAddHandleByDeviceId(std::uint32_t deviceClass, std::int32_t handle, std::uint64_t deviceId, std::uint32_t first, std::uint32_t second, std::uint32_t third); +int APS5_VABI sceMbusAddHandleByUserId(std::uint32_t deviceClass, std::int32_t handle, std::int32_t userId, std::int32_t first, std::int32_t second, std::int32_t third); +int APS5_VABI sceMbusAddHandleByVidPid(std::uint32_t deviceClass, std::int32_t handle, std::int32_t first, std::uint16_t vendorId, std::uint16_t productId, std::int32_t second, std::int32_t third); +int APS5_VABI sceMbusAddHandleWithModuleId(std::uint32_t deviceClass, std::int32_t handle, std::uint32_t flags, std::uint32_t moduleId); +int APS5_VABI sceMbusAttachToApplicationByPid(std::int32_t processId, std::int32_t deviceClass, std::int32_t flags); +int APS5_VABI sceMbusBindDeviceWithUserId(std::uint64_t deviceId, std::int32_t userId); +int APS5_VABI sceMbusChangeAppModuleState(std::uint32_t deviceClass, std::int32_t moduleId, std::uint32_t state); +int APS5_VABI sceMbusCheckDriverCallback(); +int APS5_VABI sceMbusConvertToLocalDeviceId(std::uint64_t deviceId, std::uint32_t* localId, std::uint32_t* deviceClass); +int APS5_VABI sceMbusConvertToLocalDeviceId2(std::uint64_t deviceId, std::uint32_t deviceClass, std::uint64_t* localId); +int APS5_VABI sceMbusConvertToMbusDeviceId(std::uint64_t localId, std::uint32_t deviceClass, std::uint64_t* deviceId); +int APS5_VABI sceMbusDebugAcquireControl(std::uint64_t control, std::int32_t first, std::int32_t second, std::int32_t processId); +int APS5_VABI sceMbusDebugAcquireControlWithState(std::uint32_t deviceClass, std::int32_t state, std::int32_t processId); +int APS5_VABI sceMbusDebugAcquireControlWithState2(std::uint32_t deviceClass, std::int32_t moduleId, std::int32_t state, std::int32_t processId); +int APS5_VABI sceMbusDebugAcquireControlWithStateFlag(std::uint32_t deviceClass, std::uint32_t moduleId, std::uint32_t state, std::uint32_t flags, std::int32_t processId); +int APS5_VABI sceMbusDebugAddProcess(std::int32_t processId, std::int32_t flags, const MbusProcessInfo* info); +int APS5_VABI sceMbusDebugCheckProcessResume(MbusProcessInfo* info, std::uint32_t flags); +int APS5_VABI sceMbusDebugDisableBgmForShellUi(std::int32_t processId); +int APS5_VABI sceMbusDebugGetApplicationStartupInfo(std::uint32_t appId, const MbusProcessInfo* info, MbusStartupInfo* startupInfo); +int APS5_VABI sceMbusDebugGetControlStatus(std::int32_t deviceClass, std::int32_t processId, MbusControlStatus* status); +int APS5_VABI sceMbusDebugGetDeviceInfo(std::uint64_t deviceClass, MbusDebugDeviceInfo* info); +int APS5_VABI sceMbusDebugGetInternalInfo(MbusInternalInfo* info); +int APS5_VABI sceMbusDebugGetPriorityInfo(std::uint32_t deviceClass, MbusPriorityInfo* info); +int APS5_VABI sceMbusDebugReenableBgmForShellUi(std::int32_t processId); +int APS5_VABI sceMbusDebugReleaseControl(std::uint64_t control, std::int32_t processId); +int APS5_VABI sceMbusDebugRemoveCameraAppModuleFocus(std::int32_t processId); +int APS5_VABI sceMbusDebugResumeApplication(std::int32_t appId, std::uint8_t firstFlag, std::uint8_t secondFlag, MbusProcessInfo* info); +int APS5_VABI sceMbusDebugSetApplicationFocusByAppId(std::uint32_t appId); +int APS5_VABI sceMbusDebugSetCameraAppModuleFocus(std::int32_t processId, std::int32_t moduleId); +int APS5_VABI sceMbusDebugSetControllerFocusByAppId(std::uint32_t appId); +int APS5_VABI sceMbusDebugSetOtherProcessExcludedAction(std::uint64_t control, std::uint32_t action, std::int32_t processId); +int APS5_VABI sceMbusDebugSetPriority(std::uint64_t control, std::uint32_t priority, std::int32_t processId); +int APS5_VABI sceMbusDebugStartApplication(std::int32_t appId, std::int32_t first, std::int32_t second, std::uint8_t firstFlag, std::uint8_t secondFlag, const MbusStartupParam* param); +int APS5_VABI sceMbusDebugStartApplication2(std::int32_t appId, std::int32_t first, std::int32_t second, std::uint8_t firstFlag, std::uint8_t secondFlag, const MbusStartupParam* param); +int APS5_VABI sceMbusDebugStartApplicationNull(std::int32_t appId, std::int32_t first, std::int32_t second, std::uint8_t firstFlag, std::uint8_t secondFlag); +int APS5_VABI sceMbusDebugSuspendApplication(std::uint32_t appId); +int APS5_VABI sceMbusDebugTerminateApplication(std::uint32_t appId); +int APS5_VABI sceMbusDebugTerminateProcess(std::int32_t processId); +int APS5_VABI sceMbusDetachFromApplicationByPid(std::int32_t processId, std::int32_t deviceClass); +int APS5_VABI sceMbusDisableBgmForShellUi(); +int APS5_VABI sceMbusDisableChat(std::uint32_t deviceClass); +int APS5_VABI sceMbusDisconnectDevice(std::uint64_t deviceId); +int APS5_VABI sceMbusDumpAppInfo(); +int APS5_VABI sceMbusDumpDeviceInfo(); +int APS5_VABI sceMbusDumpHandleStatusInfo(std::uint64_t control, std::int32_t processId); +int APS5_VABI sceMbusDumpHandleStatusInfoAll(std::uint32_t flags); +int APS5_VABI sceMbusDumpModuleStateInfo(std::uint64_t control); +int APS5_VABI sceMbusDumpModuleStateInfoAll(); +int APS5_VABI sceMbusDumpPlayerInfo(); +int APS5_VABI sceMbusDumpPortHandleInfo(); +int APS5_VABI sceMbusDumpProcMediaInfo(std::uint64_t control); +int APS5_VABI sceMbusDumpProcMediaInfoAll(); +int APS5_VABI sceMbusDumpUserMediaInfo(); +int APS5_VABI sceMbusEnableChat(std::uint32_t deviceClass); +int APS5_VABI sceMbusEnterAudioOutAutoAttenuation(std::int32_t first, std::int32_t second); +int APS5_VABI sceMbusEventBusStatusChangeSubscribe(std::int32_t eventHandle, std::uint32_t first, std::uint32_t second, std::uint64_t firstValue, std::uint64_t secondValue); +int APS5_VABI sceMbusEventBusStatusChangeUnsubscribe(std::uint64_t unusedSlot, std::int32_t subscription); +int APS5_VABI sceMbusEventCallbackFuncsInit_(MbusEventCallbacks* callbacks, std::uint32_t size); +int APS5_VABI sceMbusEventCreate_(std::uint32_t flags, MbusEvent* buffer, std::uint32_t capacity, const MbusEventCallbacks* callbacks, void* userData); +int APS5_VABI sceMbusEventDestroy(std::int32_t eventHandle); +int APS5_VABI sceMbusEventReceive(std::int32_t eventHandle, MbusEvent* events, std::int32_t capacity, std::int32_t wait); +int APS5_VABI sceMbusGetControlStatus(std::uint64_t control, MbusControlStatus* status); +int APS5_VABI sceMbusGetDeviceDescription(std::uint64_t deviceId, std::uint32_t selector, MbusDeviceDescription* description); +int APS5_VABI sceMbusGetDeviceInfoByBusId_(std::int32_t busId, MbusDeviceInfo* info, std::uint32_t size); +int APS5_VABI sceMbusGetDeviceInfoByConditionForDeviceService(std::int32_t flags, MbusDeviceServiceInfo* infos, std::int32_t capacity, std::int32_t* first, std::int32_t* second, MbusDeviceCondition condition); +int APS5_VABI sceMbusGetDeviceInfoByCondition_(const MbusDeviceCondition* condition, std::int32_t flags, MbusDeviceInfo* infos, std::int32_t capacity, std::int32_t* first, std::int32_t* second, std::uint32_t infoSize); +int APS5_VABI sceMbusGetDeviceInfo_(std::uint64_t deviceId, MbusDeviceInfo* info, std::uint32_t size); +int APS5_VABI sceMbusGetSimulatedBusUsableStatusByBusType(std::uint32_t busType, std::int32_t first, std::uint64_t deviceId, std::uint32_t second, std::uint32_t third); +int APS5_VABI sceMbusGetSimulatedHandleStatusInfo(std::int32_t deviceClass, std::int32_t first, std::int32_t second, MbusSimulatedHandleStatus* status); +int APS5_VABI sceMbusGetSimulatedHandleStatusInfo2(std::uint32_t deviceClass, std::uint32_t first, std::uint32_t second, std::uint32_t third, MbusSimulatedHandleStatus* status); +int APS5_VABI sceMbusGetSparkState(std::uint64_t deviceId, MbusSparkState* state); +int APS5_VABI sceMbusInit(); +int APS5_VABI sceMbusIsBgmProhibited(); +int APS5_VABI sceMbusIsUsingDevice(std::int32_t deviceClass, std::int32_t handle); +int APS5_VABI sceMbusLeaveAudioOutAutoAttenuation(std::int32_t first, std::int32_t second); +int APS5_VABI sceMbusNotifyBtDisconnection(std::uint64_t deviceId); +int APS5_VABI sceMbusNotifyDriverEvent(std::int32_t driverId, std::int32_t eventId, std::uint64_t firstValue, std::int32_t flags, std::uint64_t secondValue); +int APS5_VABI sceMbusReenableBgmForShellUi(); +int APS5_VABI sceMbusRegisterDriver(std::int32_t driverId, const MbusDriverCallbacks* callbacks, void* userData); +int APS5_VABI sceMbusReleaseControl(std::uint64_t control); +int APS5_VABI sceMbusRemoveCameraAppModuleFocus(); +int APS5_VABI sceMbusRemoveHandle(std::int32_t deviceClass, std::int32_t handle); +int APS5_VABI sceMbusRemoveProxy(std::int32_t processId, std::uint32_t deviceClass, std::uint64_t deviceId); +int APS5_VABI sceMbusResolveByDeviceId(std::int32_t deviceClass, std::uint64_t deviceId, std::uint32_t first, std::uint32_t second); +int APS5_VABI sceMbusResolveByHandle(std::int32_t deviceClass, std::int32_t handle, std::int32_t flags); +int APS5_VABI sceMbusResolveByPlayerId(std::uint32_t deviceClass, std::uint32_t playerId, std::uint32_t first, std::uint32_t second); +int APS5_VABI sceMbusResolveByUserId(std::uint32_t deviceClass, std::int32_t userId, std::uint32_t first, std::uint32_t second); +int APS5_VABI sceMbusSetAutoLoginMode(std::uint32_t mode); +int APS5_VABI sceMbusSetCameraAppModuleFocus(std::int32_t moduleId); +int APS5_VABI sceMbusSetDeviceFunctionState(std::uint64_t deviceId, MbusDeviceFunctionState state); +int APS5_VABI sceMbusSetDuckingSetting(std::int32_t setting); +int APS5_VABI sceMbusSetProxy(std::int32_t processId, std::int32_t first, std::int32_t second, std::int32_t third, std::uint64_t deviceId); +int APS5_VABI sceMbusSetRoutingMode(std::int32_t mode); +int APS5_VABI sceMbusSetScratchData(std::uint64_t deviceId, std::int32_t first, std::int32_t second); +int APS5_VABI sceMbusSetScratchDataUpdatedEventMask(std::uint32_t mask); +int APS5_VABI sceMbusSetSocialScreenAudioMode(std::int32_t first, std::int32_t second); +int APS5_VABI sceMbusSetTestFlag(std::uint32_t flags); +int APS5_VABI sceMbusSetThreadParam(std::int32_t priority, std::uint64_t affinityMask, std::uint64_t reserved); +int APS5_VABI sceMbusSetUsbPowerBlackList(std::int32_t first, std::uint8_t count, const MbusUsbPowerEntry* entries); +int APS5_VABI sceMbusSetUserMuteStatus(std::int32_t userId, std::int32_t status); +int APS5_VABI sceMbusSetVolumeDown(std::uint32_t deviceClass, std::uint8_t volume); +int APS5_VABI sceMbusStartAudioOutAuxBroadcast(); +int APS5_VABI sceMbusStartAudioOutSharePlay(std::int32_t mode); +int APS5_VABI sceMbusStopAudioOutAuxBroadcast(); +int APS5_VABI sceMbusStopAudioOutSharePlay(); +int APS5_VABI sceMbusTerm(); +int APS5_VABI sceMbusUnregisterDriver(std::int32_t driverId); +int APS5_VABI sceMbusUserLogin(std::int32_t userId); +int APS5_VABI sceMbusUserLogout(std::int32_t userId); + +} diff --git a/core/libs/prx/libSceMbus/libSceMbus.hpp b/core/libs/prx/libSceMbus/libSceMbus.hpp new file mode 100644 index 0000000000..e6b42950e3 --- /dev/null +++ b/core/libs/prx/libSceMbus/libSceMbus.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceMbus/include/Api.hpp" diff --git a/core/libs/prx/libSceMediaAppSharedStorage/libSceMediaAppSharedStorage.hpp b/core/libs/prx/libSceMediaAppSharedStorage/libSceMediaAppSharedStorage.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceMediaAppSharedStorage/libSceMediaAppSharedStorage.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceMediaFrameworkInterface/libSceMediaFrameworkInterface.hpp b/core/libs/prx/libSceMediaFrameworkInterface/libSceMediaFrameworkInterface.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceMediaFrameworkInterface/libSceMediaFrameworkInterface.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceMediaFrameworkUtil/libSceMediaFrameworkUtil.hpp b/core/libs/prx/libSceMediaFrameworkUtil/libSceMediaFrameworkUtil.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceMediaFrameworkUtil/libSceMediaFrameworkUtil.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceMetadataReaderWriter/libSceMetadataReaderWriter.hpp b/core/libs/prx/libSceMetadataReaderWriter/libSceMetadataReaderWriter.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceMetadataReaderWriter/libSceMetadataReaderWriter.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceMouse/Export.cpp b/core/libs/prx/libSceMouse/Export.cpp index 121b9d2e6a..1b1cd0f317 100644 --- a/core/libs/prx/libSceMouse/Export.cpp +++ b/core/libs/prx/libSceMouse/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceMouse/include/Api.hpp" #include "prx/libSceMouse/include/MouseState.hpp" #include "prx/libc/include/General.hpp" diff --git a/core/libs/prx/libSceMouse/include/Api.hpp b/core/libs/prx/libSceMouse/include/Api.hpp new file mode 100644 index 0000000000..e37913bd10 --- /dev/null +++ b/core/libs/prx/libSceMouse/include/Api.hpp @@ -0,0 +1,23 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceMouseInit(); +int APS5_VABI sceMouseOpen(int userId, std::int32_t type, std::int32_t index, const void* param); +int APS5_VABI sceMouseClose(std::int32_t handle); +int APS5_VABI sceMouseRead(std::int32_t handle, MouseData* data, std::int32_t num); +int APS5_VABI sceMouseResetAbsolutePosition(std::int32_t handle, std::uint16_t x, std::uint16_t y); +int APS5_VABI sceMouseConnectPort(); +int APS5_VABI sceMouseDebugGetDeviceId(); +int APS5_VABI sceMouseDeviceOpen(); +int APS5_VABI sceMouseDisconnectDevice(); +int APS5_VABI sceMouseDisconnectPort(); +int APS5_VABI sceMouseGetDeviceInfo(); +int APS5_VABI sceMouseMbusInit(); +int APS5_VABI sceMouseSetHandType(); +int APS5_VABI sceMouseSetPointerSpeed(); +int APS5_VABI sceMouseSetProcessPrivilege(); + +} diff --git a/core/libs/prx/libSceMouse/libSceMouse.hpp b/core/libs/prx/libSceMouse/libSceMouse.hpp new file mode 100644 index 0000000000..512051b814 --- /dev/null +++ b/core/libs/prx/libSceMouse/libSceMouse.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceMouse/include/Api.hpp" diff --git a/core/libs/prx/libSceMouse/tests/Mouse.cpp b/core/libs/prx/libSceMouse/tests/Mouse.cpp index 7e7b1fcf13..27c99cc622 100644 --- a/core/libs/prx/libSceMouse/tests/Mouse.cpp +++ b/core/libs/prx/libSceMouse/tests/Mouse.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceMouse/include/Api.hpp" #include "prx/libSceMouse/include/mouse_structs.h" #include "prx/libSceMouse/include/MouseState.hpp" #include "prx/libSceVideoOut/include/MouseInput.hpp" @@ -8,11 +9,7 @@ extern "C" { bool MouseIsOpen_nid_no_patch(); -int APS5_VABI sceMouseInit(); -int APS5_VABI sceMouseOpen(int, std::int32_t, std::int32_t, const void*); -int APS5_VABI sceMouseClose(std::int32_t); -int APS5_VABI sceMouseRead(std::int32_t, MouseData*, std::int32_t); -int APS5_VABI sceMouseResetAbsolutePosition(std::int32_t, std::uint16_t, std::uint16_t); + } static void Require(bool value) { if (!value) std::abort(); } diff --git a/core/libs/prx/libSceMove/Export.cpp b/core/libs/prx/libSceMove/Export.cpp index effeda1e5c..b69438284d 100644 --- a/core/libs/prx/libSceMove/Export.cpp +++ b/core/libs/prx/libSceMove/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceMove/include/Api.hpp" #include #include #include diff --git a/core/libs/prx/libSceMove/include/Api.hpp b/core/libs/prx/libSceMove/include/Api.hpp new file mode 100644 index 0000000000..5461d6d775 --- /dev/null +++ b/core/libs/prx/libSceMove/include/Api.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceMoveInit(void); +int APS5_VABI sceMoveTerm(void); +int APS5_VABI sceMoveOpen(int32_t userId, int32_t type, int32_t index); +int APS5_VABI sceMoveClose(int32_t handle); +int APS5_VABI sceMoveGetDeviceInfo(int32_t handle, void* info); +int APS5_VABI sceMoveGetExtensionPortInfo(int32_t handle, void* data); +int APS5_VABI sceMoveReadStateLatest(int32_t handle, void* data); +int APS5_VABI sceMoveReadStateRecent(int32_t handle, int64_t timestamp, void* data, int32_t* outCount); +int APS5_VABI sceMoveSetVibration(int32_t handle, uint8_t motor); +int APS5_VABI sceMoveSetLightSphere(int32_t handle, uint8_t red, uint8_t green, uint8_t blue); +int APS5_VABI sceMoveResetLightSphere(int32_t handle); +int APS5_VABI sceMoveGetBluetoothAddress(void); +int APS5_VABI sceMoveGetCalibrationInfo(void); +int APS5_VABI sceMoveGetDeviceId(void); +int APS5_VABI sceMoveIsReproductionModel(void); +int APS5_VABI sceMoveIsValidHandle(void); +int APS5_VABI sceMoveReadStateRecentForTracker(void); +int APS5_VABI sceMoveSetCalibrationMode(void); +int APS5_VABI sceMoveSetExtensionPortOutput(void); +int APS5_VABI sceMoveSetLightSphereForTracker(void); +int APS5_VABI sceMoveWriteCalibrationInfo(void); + +} diff --git a/core/libs/prx/libSceMove/libSceMove.hpp b/core/libs/prx/libSceMove/libSceMove.hpp new file mode 100644 index 0000000000..522d39cc61 --- /dev/null +++ b/core/libs/prx/libSceMove/libSceMove.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceMove/include/Api.hpp" diff --git a/core/libs/prx/libSceMoveTracker/Export.cpp b/core/libs/prx/libSceMoveTracker/Export.cpp index ef780c7000..e1c32fd781 100644 --- a/core/libs/prx/libSceMoveTracker/Export.cpp +++ b/core/libs/prx/libSceMoveTracker/Export.cpp @@ -1,13 +1,9 @@ +#include "prx/libSceMoveTracker/include/Api.hpp" #include #include #include "SceTypes.hpp" #include "prx/libc/include/General.hpp" -struct MoveTrackerCameraFrame; -struct MoveTrackerControllerInput; -struct MoveTrackerState; -struct MoveTrackerPlaybackInfo; - extern "C" { int APS5_VABI sceMoveTrackerCalibrateReset() { diff --git a/core/libs/prx/libSceMoveTracker/include/Api.hpp b/core/libs/prx/libSceMoveTracker/include/Api.hpp new file mode 100644 index 0000000000..bfe72f92fd --- /dev/null +++ b/core/libs/prx/libSceMoveTracker/include/Api.hpp @@ -0,0 +1,34 @@ +#pragma once + +#include "SceTypes.hpp" + +struct MoveTrackerCameraFrame; + +struct MoveTrackerControllerInput; + +struct MoveTrackerPlaybackInfo; + +struct MoveTrackerState; + +extern "C" { + +int APS5_VABI sceMoveTrackerCalibrateReset(); +int APS5_VABI sceMoveTrackerCalibrateYaw(std::int32_t handle, const float* direction); +int APS5_VABI sceMoveTrackerCameraUpdate(const MoveTrackerCameraFrame* frames); +int APS5_VABI sceMoveTrackerCaptureInit(void* imageMemory, std::int32_t capacity, std::int32_t interval, const char* path, std::int32_t mode); +int APS5_VABI sceMoveTrackerCaptureTerm(); +int APS5_VABI sceMoveTrackerControllersUpdate(const MoveTrackerControllerInput* controllers); +int APS5_VABI sceMoveTrackerGetState(std::int32_t handle, std::uint64_t timestamp, MoveTrackerState* state); +int APS5_VABI sceMoveTrackerGetVersion(); +int APS5_VABI sceMoveTrackerGetWorkingMemorySize(std::uint32_t* totalSize, std::uint32_t* processingSize); +int APS5_VABI sceMoveTrackerInit(void* workMemory, std::uint64_t requiredArgument, std::uint32_t pipeId, std::uint32_t queueId); +int APS5_VABI sceMoveTrackerPlayGetImages(MoveTrackerCameraFrame* frames); +int APS5_VABI sceMoveTrackerPlayGetStates(MoveTrackerPlaybackInfo* info, MoveTrackerState* states); +int APS5_VABI sceMoveTrackerPlayStart(); +int APS5_VABI sceMoveTrackerPlayStep(); +int APS5_VABI sceMoveTrackerRecordSave(); +int APS5_VABI sceMoveTrackerRecordStart(); +int APS5_VABI sceMoveTrackerRecordStop(); +int APS5_VABI sceMoveTrackerTerm(); + +} diff --git a/core/libs/prx/libSceMoveTracker/libSceMoveTracker.hpp b/core/libs/prx/libSceMoveTracker/libSceMoveTracker.hpp new file mode 100644 index 0000000000..02c0750675 --- /dev/null +++ b/core/libs/prx/libSceMoveTracker/libSceMoveTracker.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceMoveTracker/include/Api.hpp" diff --git a/core/libs/prx/libSceMsgDialog.native/Export.cpp b/core/libs/prx/libSceMsgDialog.native/Export.cpp index 339bf0049a..52d1a12279 100644 --- a/core/libs/prx/libSceMsgDialog.native/Export.cpp +++ b/core/libs/prx/libSceMsgDialog.native/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceMsgDialog.native/libSceMsgDialog.native.hpp" #include #include #include diff --git a/core/libs/prx/libSceMsgDialog.native/libSceMsgDialog.native.hpp b/core/libs/prx/libSceMsgDialog.native/libSceMsgDialog.native.hpp new file mode 100644 index 0000000000..ec8e5c89ab --- /dev/null +++ b/core/libs/prx/libSceMsgDialog.native/libSceMsgDialog.native.hpp @@ -0,0 +1,5 @@ +#pragma once + +#include "prx/libSceMsgDialog/include/Api.hpp" + +extern "C" int APS5_VABI sceMsgDialogGetResult(MsgDialogResult* result); diff --git a/core/libs/prx/libSceMsgDialog/Export.cpp b/core/libs/prx/libSceMsgDialog/Export.cpp index 1e02b26eab..a94de137f5 100644 --- a/core/libs/prx/libSceMsgDialog/Export.cpp +++ b/core/libs/prx/libSceMsgDialog/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceMsgDialog/include/Api.hpp" // libSceMsgDialog: message dialog state machine (NONE -> INITIALIZED -> RUNNING -> FINISHED) without a visible dialog. // The dialog "closes" with the affirmative button after a couple of status polls, so a title waiting for the user // never blocks. The message text is logged for the first calls. @@ -25,7 +26,6 @@ constexpr int kStatusFinished = 3; constexpr int kErrOk = 0; constexpr int kErrNotInitialized = static_cast(0x80B80003u); -constexpr int kErrNotFinished = static_cast(0x80B80005u); constexpr int kErrBusy = static_cast(0x80B80007u); constexpr int kErrNotRunning = static_cast(0x80B8000Bu); constexpr int kErrArgNull = static_cast(0x80B8000Du); @@ -42,7 +42,6 @@ constexpr int kButtonTypeYesNoFocusNo = 4; constexpr int kButtonIdOk = 1; // OK / YES / BUTTON1 constexpr int kButtonIdNo = 2; // NO / BUTTON2 -constexpr int kResultOk = 0; std::mutex g_lock; int g_status = kStatusNone; @@ -137,15 +136,6 @@ int APS5_VABI sceMsgDialogGetStatus(void) { int APS5_VABI sceMsgDialogUpdateStatus(void) { return Poll(); } -// SceMsgDialogResult: { int32 mode; int32 result; int32 buttonId; uint8 reserved[32] }. -int APS5_VABI sceMsgDialogGetResult(void* result) { - if (result == nullptr) return kErrArgNull; - std::lock_guard g(g_lock); - if (g_status != kStatusFinished) return kErrNotFinished; - std::int32_t out[3] = {g_mode, kResultOk, g_buttonId}; - std::memcpy(result, out, sizeof(out)); - return kErrOk; -} int APS5_VABI sceMsgDialogClose(void) { std::lock_guard g(g_lock); if (g_status != kStatusRunning) return kErrNotRunning; diff --git a/core/libs/prx/libSceMsgDialog/include/Api.hpp b/core/libs/prx/libSceMsgDialog/include/Api.hpp new file mode 100644 index 0000000000..44ceec5270 --- /dev/null +++ b/core/libs/prx/libSceMsgDialog/include/Api.hpp @@ -0,0 +1,17 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceMsgDialogInitialize(void); +int APS5_VABI sceMsgDialogTerminate(void); +int APS5_VABI sceMsgDialogOpen(const void* param); +int APS5_VABI sceMsgDialogGetStatus(void); +int APS5_VABI sceMsgDialogUpdateStatus(void); +int APS5_VABI sceMsgDialogClose(void); +int APS5_VABI sceMsgDialogProgressBarInc(int target, std::uint32_t delta); +int APS5_VABI sceMsgDialogProgressBarSetMsg(int target, const char* msg); +int APS5_VABI sceMsgDialogProgressBarSetValue(int target, std::uint32_t rate); + +} diff --git a/core/libs/prx/libSceMsgDialog/libSceMsgDialog.hpp b/core/libs/prx/libSceMsgDialog/libSceMsgDialog.hpp new file mode 100644 index 0000000000..f25195526f --- /dev/null +++ b/core/libs/prx/libSceMsgDialog/libSceMsgDialog.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceMsgDialog/include/Api.hpp" diff --git a/core/libs/prx/libSceMusicCoreInterface/libSceMusicCoreInterface.hpp b/core/libs/prx/libSceMusicCoreInterface/libSceMusicCoreInterface.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceMusicCoreInterface/libSceMusicCoreInterface.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceMusicFrameworkInterface/Export.cpp b/core/libs/prx/libSceMusicFrameworkInterface/Export.cpp index dc0e9adc97..9053d6ba40 100644 --- a/core/libs/prx/libSceMusicFrameworkInterface/Export.cpp +++ b/core/libs/prx/libSceMusicFrameworkInterface/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceMusicFrameworkInterface/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceMusicFrameworkInterface/include/Api.hpp b/core/libs/prx/libSceMusicFrameworkInterface/include/Api.hpp new file mode 100644 index 0000000000..8164b75a7d --- /dev/null +++ b/core/libs/prx/libSceMusicFrameworkInterface/include/Api.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceMusicFwGetCurrentTime(); +int APS5_VABI sceMusicFwGetLoop(); +int APS5_VABI sceMusicFwGetMuted(); +int APS5_VABI sceMusicFwGetNetworkState(); +int APS5_VABI sceMusicFwGetVolume(); +int APS5_VABI sceMusicFwIsEnded(); +int APS5_VABI sceMusicFwIsPlaying(); +int APS5_VABI sceMusicFwIsStopped(); +int APS5_VABI sceMusicFwRemoveSrc(); +int APS5_VABI sceMusicFwSendMessageAsynchronously(); +int APS5_VABI sceMusicFwSendMessageSynchronously(); +int APS5_VABI sceMusicFwSetCurrentTime(); +int APS5_VABI sceMusicFwSetLoop(); +int APS5_VABI sceMusicFwSetShuffle(); +int APS5_VABI sceMusicFwSetVolume(); +int APS5_VABI sceMusicFwSkipNext(); +int APS5_VABI sceMusicFwSkipPrevious(); + +} diff --git a/core/libs/prx/libSceMusicFrameworkInterface/libSceMusicFrameworkInterface.hpp b/core/libs/prx/libSceMusicFrameworkInterface/libSceMusicFrameworkInterface.hpp new file mode 100644 index 0000000000..83fbfaf531 --- /dev/null +++ b/core/libs/prx/libSceMusicFrameworkInterface/libSceMusicFrameworkInterface.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceMusicFrameworkInterface/include/Api.hpp" diff --git a/core/libs/prx/libSceNKWeb/Export.cpp b/core/libs/prx/libSceNKWeb/Export.cpp index 81401ab485..fdef9184da 100644 --- a/core/libs/prx/libSceNKWeb/Export.cpp +++ b/core/libs/prx/libSceNKWeb/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNKWeb/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceNKWeb/include/Api.hpp b/core/libs/prx/libSceNKWeb/include/Api.hpp new file mode 100644 index 0000000000..57b480c9e7 --- /dev/null +++ b/core/libs/prx/libSceNKWeb/include/Api.hpp @@ -0,0 +1,10 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceNKWebInitialize(); +int APS5_VABI sceNKWebTerminate(); + +} diff --git a/core/libs/prx/libSceNKWeb/libSceNKWeb.hpp b/core/libs/prx/libSceNKWeb/libSceNKWeb.hpp new file mode 100644 index 0000000000..d65e494889 --- /dev/null +++ b/core/libs/prx/libSceNKWeb/libSceNKWeb.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceNKWeb/include/Api.hpp" diff --git a/core/libs/prx/libSceNKWebCdlgInjectedBundle/libSceNKWebCdlgInjectedBundle.hpp b/core/libs/prx/libSceNKWebCdlgInjectedBundle/libSceNKWebCdlgInjectedBundle.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceNKWebCdlgInjectedBundle/libSceNKWebCdlgInjectedBundle.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceNKWebKit/Export.cpp b/core/libs/prx/libSceNKWebKit/Export.cpp index a6caa403e8..43ccd2eeb3 100644 --- a/core/libs/prx/libSceNKWebKit/Export.cpp +++ b/core/libs/prx/libSceNKWebKit/Export.cpp @@ -1,3 +1,153 @@ +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" +#include "prx/libSceNKWebKit/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceNKWebKit/include/Api.hpp b/core/libs/prx/libSceNKWebKit/include/Api.hpp new file mode 100644 index 0000000000..9312101ad1 --- /dev/null +++ b/core/libs/prx/libSceNKWebKit/include/Api.hpp @@ -0,0 +1,158 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceNKWebKitUnknown____URPJNZ18_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown___67uYkhqBU_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown___8RYr2gjrw_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown___BntMcao1o_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown___R8IXi10PI_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown___j2h_QO22w_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown____7XwmYLnI_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown___wmVyLhgm0_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__0QEt8ZQWgg_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__0YNxcA_duk_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__0ZZzGYxx_I_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__0rdnkSicqk_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__1Ex5GCP8Xs_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__1FfZ_0sxvQ_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__1ObAtzCrYE_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__1n_h4FUu9E_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__26aZpK535w_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__2XuBaAXb_4_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__2rTX2KM7Ms_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__31dbB3S_6Y_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__3p6wRzzzlQ_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__4_GNOUIBt0_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__45BiDnCTxw_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__4lVmXsIwqM_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__5E2YZZIstM_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__5V_UOk8zS4_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__63IB3UdMOY_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__6boXsT6XFA_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__79w68212vg_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__7HpqmfJz48_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__8T1y8Y_lgQ_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__8VuTEFp13s_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__9TKACifR2g_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__9ZBRWNf4og_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__9us0nrDaCU_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__AIEKk6K05M_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__Abk7CfTivU_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__AnsPWo12m8_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__BDqCDede1o_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__BSUP6XSeAw_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__BZCJi3OIiQ_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__ByVxWl1pW8_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__CgSI_4D534_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__CpPA9_CKUA_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__DcUw5YwkSY_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__DpDBrSZWUc_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__E3D_W4kpl8_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__EN6MgNmVv4_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__ErgockOJwc_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__FKudG3uS8A_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__FWUl_T8yG8_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__Fca5Eyr4BU_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__FcvpbbdrZM_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__FvUhrQaiJQ_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__GOwQvxqztE_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__Gp0M0sPj9I_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__H_bnpXdWtk_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__H5PTMieXNE_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__HuPyGuX_jY_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__IMGO_dXHis_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__ImJ026_DAw_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__IoqHgIw0PM_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__JnngM7WyHI_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__Kb7j57jDzs_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__Kx_IV_21hk_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__LUabdo811U_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__LiOmqon2ZI_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__LoAenYdWlM_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__LrmM3KN3N8_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__MzGFuNN348_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__N_GwpCV4yk_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__N6UhRaLrJE_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__NGrXdCa0q8_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__NiLTGGKF_E_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__Nqfy8HVG84_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__NuhuZH75ak_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__OCxbaKiBUo_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__OOjOkuWL6g_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__OkTn3_PBxM_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__PDx3sfB_l4_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__POsWAWjXo8_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__PeIrQMgYpw_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__Q7xLvpc0PA_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__QL3zQ6ZNy4_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__QqzEnc5c80_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__R0GXLrsPM0_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__R2eXISeSvw_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__RkwSDm5kGU_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__RtBREW92M0_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__S72K_fa2_8_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__S7ftAAWhoQ_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__SHzgUiuQDE_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__Sgy63JgEgQ_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__Sozphy1Wa8_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__TPntL1OK80_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__TT_AplhQWA_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__TjNmuhxdBQ_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__U_nxwdrnDY_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__UKI_MUuiCU_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__VvktcfIouQ_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__WS2yRv5aBI_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__XZfnHByVO0_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__YBfWz5udq4_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__YPwmEWTZwE_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__YYEOsi3IMk_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__YyqQTUIQJQ_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__ZgGbFykhls_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__ZwjLJ74Y38_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__b1xwU7aUwU_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__b5TfVQ3_4s_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__bDb7iby5NI_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__baqz7ahOng_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__bvtn3pCtek_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__byORTSkWQo_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__dAwquupevQ_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__dTlroLZao8_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__eVN0UdRT8c_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__fTKZiGqo8E_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__feeFP8Y2_c_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__iLBOBrdx5A_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__iLdIVuhDhY_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__jG4wqqA8yg_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__jLvgfDA97c_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__ji7IBGwnCM_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__k3JGU_UUXo_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__kX_CdbguB0_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__keSg8ay8cE_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__lI9zCCS_HQ_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__lwLqZJLo3g_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__mS029ncrbo_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__mYy22Ucg7Y_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__nHWcLWOmb4_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__nSg5kHtXkg_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__nc3IouJMEA_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__ndmq8LhAjA_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__nrEMsyYHiw_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__oJHrfcyJJM_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__ovAafdG0O8_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__pWGccNXto8_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__q0GELad_mY_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__qXuNlEFSRQ_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__qsTbJFS86A_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__r_TJDA2yIM_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__r0UH41I1dI_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__r8OGkuL4dc_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__rFA8ZR_qaI_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__rPvFDsPbXM_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__sUvE9LF80k_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__suuwfNT5Oc_nid_no_patch(); +int APS5_VABI sceNKWebKitUnknown__t_MaTLADe4_nid_no_patch(); + +} diff --git a/core/libs/prx/libSceNKWebKit/libSceNKWebKit.hpp b/core/libs/prx/libSceNKWebKit/libSceNKWebKit.hpp new file mode 100644 index 0000000000..f291edcd57 --- /dev/null +++ b/core/libs/prx/libSceNKWebKit/libSceNKWebKit.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceNKWebKit/include/Api.hpp" diff --git a/core/libs/prx/libSceNKWebKitRequirements/libSceNKWebKitRequirements.hpp b/core/libs/prx/libSceNKWebKitRequirements/libSceNKWebKitRequirements.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceNKWebKitRequirements/libSceNKWebKitRequirements.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceNet/CMakeLists.txt b/core/libs/prx/libSceNet/CMakeLists.txt index dbf0992fae..eee438654e 100644 --- a/core/libs/prx/libSceNet/CMakeLists.txt +++ b/core/libs/prx/libSceNet/CMakeLists.txt @@ -4,6 +4,16 @@ target_link_libraries(libSceNet PRIVATE libSceNetCtl) configure_windows_unwind(libSceNet) if(BUILD_TESTING) + add_test_executable(guest_net_protocol_tests ${LIBS_INCLUDE_DIR}/tests/GuestNetProtocol.cpp) + target_include_directories(guest_net_protocol_tests PRIVATE ${LIBS_INCLUDE_DIR}) + target_link_libraries(guest_net_protocol_tests PRIVATE libSceNet libkernel libc) + configure_windows_unwind(guest_net_protocol_tests) + add_test(NAME guest_net_protocol COMMAND guest_net_protocol_tests) + set_tests_properties(guest_net_protocol PROPERTIES TIMEOUT 20) + if(WIN32) + set_tests_properties(guest_net_protocol PROPERTIES ENVIRONMENT_MODIFICATION + "PATH=path_list_prepend:$") + endif() add_test_executable(net_dontwait_tests ${LIBS_INCLUDE_DIR}/tests/NetDontWait.cpp) target_include_directories(net_dontwait_tests PRIVATE ${LIBS_INCLUDE_DIR}) target_link_libraries(net_dontwait_tests PRIVATE libSceNet libkernel libc) @@ -107,6 +117,17 @@ if(BUILD_TESTING) set_tests_properties(guest_sce_net guest_net_thread PROPERTIES ENVIRONMENT_MODIFICATION "PATH=path_list_prepend:$") endif() + add_test_executable(guest_net_nodelay_readback_tests ${LIBS_INCLUDE_DIR}/tests/GuestNetNodelayReadback.cpp) + target_include_directories(guest_net_nodelay_readback_tests PRIVATE ${LIBS_INCLUDE_DIR}) + target_link_libraries(guest_net_nodelay_readback_tests PRIVATE libSceNet libkernel libc) + configure_windows_unwind(guest_net_nodelay_readback_tests) + add_test(NAME guest_net_nodelay_readback COMMAND guest_net_nodelay_readback_tests) + set_tests_properties(guest_net_nodelay_readback PROPERTIES TIMEOUT 20) + if(WIN32) + target_link_libraries(guest_net_nodelay_readback_tests PRIVATE ws2_32) + set_tests_properties(guest_net_nodelay_readback PROPERTIES ENVIRONMENT_MODIFICATION + "PATH=path_list_prepend:$") + endif() add_test_executable(net_epoll_lifetime_tests ${LIBS_INCLUDE_DIR}/tests/NetEpollLifetime.cpp) target_include_directories(net_epoll_lifetime_tests PRIVATE ${LIBS_INCLUDE_DIR}) target_link_libraries(net_epoll_lifetime_tests PRIVATE libkernel libc libSceNetCtl) diff --git a/core/libs/prx/libSceNet/Export.cpp b/core/libs/prx/libSceNet/Export.cpp index 99b804e54e..e93be026dc 100644 --- a/core/libs/prx/libSceNet/Export.cpp +++ b/core/libs/prx/libSceNet/Export.cpp @@ -1,3 +1,6 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" +#include "prx/libSceNet/include/Net.hpp" #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN #include @@ -49,108 +52,11 @@ // Guest socket descriptors retain PS5 semantics while their transport is backed by host sockets. -struct NetWlanInformationElement; -struct NetWlanWakeParameter; -struct NetWlanScanParameter; -struct NetWlanScanResult; -struct NetWlanAdhocScanParameter; -struct NetWlanInfraScanParameter; -struct NetWlanJoinResult; -struct NetDumpFilterParameter; - -struct NetWlanAdhocParameter; -struct NetWlanWakeInfo; -struct NetWlanPspWakeInfo; -struct NetWlanPspWakeParameter; -struct NetWlanApParameter; -struct NetWlanDeviceInfo; -struct NetWlanAntennaParameter; -struct NetWlanRateParameter; -struct NetWlanDeviceConfiguration; -struct NetWlanRssiInfo; -struct NetDhcpInfo; -struct NetAutoIpInfo; -struct NetAddress6Info; - -struct NetDhcpOptionInfo { - std::uint32_t option; - std::uint32_t capacity; - void* data; - std::uint32_t size; - std::uint32_t reserved; -}; - static_assert(sizeof(NetDhcpOptionInfo) == 24); static_assert(offsetof(NetDhcpOptionInfo, capacity) == 4); static_assert(offsetof(NetDhcpOptionInfo, data) == 8); static_assert(offsetof(NetDhcpOptionInfo, size) == 16); -struct NetSockInfo6; -struct NetStatisticsInfo; -struct NetInterfaceStats; -struct NetRouteInfo; -struct NetDebugParameter; -struct NetArpInfo; -struct NetAppMemoryInfo; -struct NetSystemMemoryInfo; -struct NetBandwidthParameter; -struct NetDataTraffic; -struct NetEmulationParameter; - -struct NetResolverConnection; -struct NetThreadParameter { - void (APS5_VABI *entry)(void*); - void* arg; - std::uint64_t reserved; - std::uint32_t flags; -}; -struct NetIpv4InterfaceAddress; -struct NetStatisticsInfoInternal; -struct NetInitializeParameter; -struct NetDhcpStartParameter; -struct NetAddress6StartParameter; - -using NetAddressCallback = void (APS5_VABI *)(void* userArg, std::int32_t event, std::int32_t error); - -struct NetDhcpdStartParameter { - std::uint32_t addresses[5]; - std::uint32_t maxClients; -}; - -struct NetPppoeStartParameter { - std::uint32_t dnsAddresses[2]; - char userName[128]; - char password[128]; - std::int32_t mtu; - std::uint32_t flags; -}; - -struct NetRoutingAddressParameter { - std::uint32_t address; - std::uint32_t mask; -}; - -struct NetRoutingServerParameter { - std::int32_t count; - std::uint32_t localAddresses[2]; - std::uint32_t remoteAddresses[2]; -}; - -struct NetRoutingRule { - std::int32_t protocol; - std::uint32_t firstAddress; - std::uint16_t firstPort; - std::uint16_t reserved; - std::uint32_t secondAddress; - std::uint16_t secondPort; - std::uint16_t flags; -}; - -struct NetRoutingRuleParameter { - std::int32_t count; - const NetRoutingRule* rules; -}; - static_assert(sizeof(NetRoutingAddressParameter) == 8); static_assert(sizeof(NetRoutingServerParameter) == 20); static_assert(offsetof(NetRoutingServerParameter, remoteAddresses) == 12); @@ -169,66 +75,21 @@ static_assert(offsetof(NetPppoeStartParameter, password) == 136); static_assert(offsetof(NetPppoeStartParameter, mtu) == 264); static_assert(offsetof(NetPppoeStartParameter, flags) == 268); -struct NetInfoDumpParameter { - std::uint32_t flags; - std::uint32_t intervalSeconds; - char path[64]; -}; - static_assert(sizeof(NetInfoDumpParameter) == 72); static_assert(offsetof(NetInfoDumpParameter, path) == 8); -struct NetInterfaceInfo; -struct NetInterfaceStatistics; - -struct NetResolverConnectOption { - std::int32_t connectionTimeout; - std::int32_t resolverTimeout; - std::int32_t resolverRetryCount; - std::uint32_t reserved; -}; - static_assert(sizeof(NetResolverConnectOption) == 16); static_assert(offsetof(NetResolverConnectOption, resolverTimeout) == 4); static_assert(offsetof(NetResolverConnectOption, resolverRetryCount) == 8); static_assert(offsetof(NetResolverConnectOption, reserved) == 12); -struct NetSyncObject { - void* mutex; - void* condition; - std::uint32_t signals; - std::uint32_t reserved; -}; - static_assert(sizeof(NetSyncObject) == 24); -using NetEventCallback = std::uint64_t (APS5_VABI*)(std::uint32_t interfaceId, std::uint64_t events, void* userData, void* waitData); - -struct NetIpv6Address { - std::uint8_t bytes[16]; -}; - static_assert(sizeof(NetIpv6Address) == 16); -struct NetDnsInfo { - std::uint32_t primaryAddress; - std::uint32_t secondaryAddress; -}; - -struct NetDns6Info { - NetIpv6Address primaryAddress; - NetIpv6Address secondaryAddress; -}; - static_assert(sizeof(NetDnsInfo) == 8); static_assert(sizeof(NetDns6Info) == 32); -struct NetIpv6InterfaceAddress { - NetIpv6Address address; - std::uint8_t prefixLength; - std::uint8_t reserved[3]; -}; - static_assert(sizeof(NetIpv6InterfaceAddress) == 20); namespace { @@ -282,6 +143,7 @@ constexpr int NET_TF_NODELAY = 4; constexpr int NET_SO_SNDTIMEO = 0x1005; constexpr int NET_SO_RCVTIMEO = 0x1006; constexpr int NET_SO_ERROR = 0x1007; +constexpr int NET_SO_PROTOCOL = 0x1016; constexpr int NET_SO_NBIO = 0x1200; constexpr int NET_SO_REUSEADDR = 0x4; constexpr int NET_SO_BROADCAST = 0x20; @@ -399,6 +261,7 @@ bool native_to_guest_address(const sockaddr_storage& native, void* address, std: struct Sock { int family = 0; int type = 0; + int protocol = 0; std::shared_ptr native; bool bound = false; bool listening = false; @@ -470,11 +333,6 @@ std::map g_epoll_socks; std::set g_epoll_aborted; std::map g_pools; -struct NetMemoryPoolStats { - std::size_t pool_size; - std::size_t max_inuse_size; - std::size_t current_inuse_size; -}; struct Resolver { int error = 0; int running = 0; @@ -495,7 +353,6 @@ int* errno_slot() { return &e; } -extern "C" int* APS5_VABI __error_nid_postfix(); extern "C" std::size_t NetCtlHostDnsServers_nid_no_patch(std::uint32_t* servers, std::size_t capacity); void set_errno(int err) { @@ -508,9 +365,6 @@ int fail(int err) { return NET_ERROR_BASE | err; } -extern "C" int APS5_VABI scePthreadCreate(Pthread* thread, const PthreadAttr* attr, PthreadEntry entry, void* arg, const char* name); -extern "C" int APS5_VABI scePthreadJoin(Pthread thread, void** retval); - void* APS5_VABI RunNetThread(void* param) { const auto* thread = static_cast(param); thread->entry(thread->arg); @@ -600,20 +454,6 @@ std::uint64_t swap64(std::uint64_t v) { ((v >> 8) & 0xFF000000u) | ((v >> 24) & 0xFF0000u) | ((v >> 40) & 0xFF00u) | (v >> 56); } -struct NetIovec { - void* base; - std::uint64_t length; -}; - -struct NetMsghdr { - void* name; - std::uint32_t name_length; - NetIovec* iov; - int iov_length; - void* control; - std::uint32_t control_length; - int flags; -}; static_assert(sizeof(NetMsghdr) == 48 && offsetof(NetMsghdr, iov) == 16 && offsetof(NetMsghdr, control) == 32 && offsetof(NetMsghdr, flags) == 44); @@ -912,8 +752,6 @@ int PollSockets(KernelSocketPoll::Entry* entries, int count, int timeoutMillisec const bool g_socketPollerRegistered = (KernelSetSocketPoller_nid_no_patch(&PollSockets), true); -extern "C" int APS5_VABI sceNetSocketClose(int s); - bool CloseSocketForKernel(int descriptor, int* error) { { std::lock_guard lk(g_mutex); @@ -925,8 +763,6 @@ bool CloseSocketForKernel(int descriptor, int* error) { const bool g_socketCloserRegistered = (KernelSetSocketCloser_nid_no_patch(&CloseSocketForKernel), true); -extern "C" int APS5_VABI sceNetSetsockopt(int s, int level, int optname, const void* optval, uint32_t optlen); - bool SetSocketOptionForKernel(int descriptor, int level, int option, const void* value, std::uint32_t length, int* error) { { std::lock_guard lk(g_mutex); @@ -1057,13 +893,14 @@ int APS5_VABI sceNetSocket(const char* name, int family, int type, int protocol) Sock s; s.family = family; s.type = type; + s.protocol = protocol; + if (protocol == 0 && type == NET_SOCK_STREAM) s.protocol = IPPROTO_TCP; + if (protocol == 0 && type == NET_SOCK_DGRAM) s.protocol = IPPROTO_UDP; s.native = std::move(handle); g_socks[fd] = s; return fd; } -extern "C" int APS5_VABI close_nid_postfix(int d); - int APS5_VABI sceNetSocketClose(int s) { std::shared_ptr native; bool found = false; @@ -1181,6 +1018,7 @@ int APS5_VABI sceNetAccept(int s, void* addr, uint32_t* addrlen) { Sock connection; connection.family = listener.family; connection.type = NET_SOCK_STREAM; + connection.protocol = listener.protocol; connection.connectAttempted = true; connection.native = std::move(handle); #ifdef _WIN32 @@ -1321,6 +1159,10 @@ int64_t APS5_VABI sceNetRecv(int s, void* buf, size_t len, int flags) { return result >= 0 ? result : fail(native_error()); } +int64_t APS5_VABI GuestNetRecv_nid_no_patch(int s, void* buf, size_t len, int flags) { + return sceNetRecv(s, buf, len, flags); +} + int64_t APS5_VABI sceNetRecvfrom(int s, void* buf, size_t len, int flags, void* from, uint32_t* fromlen) { if (!message_flags_supported(flags, NET_MSG_PEEK | NET_MSG_DONTWAIT)) return fail(NET_EOPNOTSUPP); if (!buf && len) return fail(NET_EINVAL); @@ -1381,6 +1223,10 @@ int64_t APS5_VABI sceNetSend(int s, const void* buf, size_t len, int flags) { return result >= 0 ? result : fail(native_error()); } +int64_t APS5_VABI GuestNetSend_nid_no_patch(int s, const void* buf, size_t len, int flags) { + return sceNetSend(s, buf, len, flags); +} + int64_t APS5_VABI sceNetSendto(int s, const void* buf, size_t len, int flags, const void* to, uint32_t tolen) { if (!message_flags_supported(flags, NET_MSG_DONTWAIT)) return fail(NET_EOPNOTSUPP); if (!buf && len) return fail(NET_EINVAL); @@ -1518,8 +1364,6 @@ int APS5_VABI sceNetShutdown(int s, int how) { return error == 0 ? 0 : fail(error); } -extern "C" int APS5_VABI setsockopt_nid_postfix(int descriptor, int level, int option, const void* value, std::uint32_t length); - int APS5_VABI sceNetSetsockopt(int s, int level, int optname, const void* optval, uint32_t optlen) { Sock socket; bool found = false; @@ -1595,6 +1439,12 @@ int APS5_VABI sceNetGetsockopt(int s, int level, int optname, void* optval, uint socket = it->second; } if (optval == nullptr || optlen == nullptr) return fail(NET_EINVAL); + if (level == NET_SOL_SOCKET && optname == NET_SO_PROTOCOL) { + if (socket.type == NET_SOCK_RAW) NotImplemented_nid_no_patch(__func__); + *optlen = std::min(*optlen, static_cast(sizeof(socket.protocol))); + std::memcpy(optval, &socket.protocol, *optlen); + return 0; + } if (level == NET_SOL_SOCKET && (optname == NET_SO_RCVTIMEO || optname == NET_SO_SNDTIMEO)) { const int microseconds = optname == NET_SO_RCVTIMEO ? socket.native->receiveTimeout.load() : socket.native->sendTimeout.load(); const KernelTimeval timeout{microseconds / 1000000, microseconds % 1000000}; @@ -1602,7 +1452,6 @@ int APS5_VABI sceNetGetsockopt(int s, int level, int optname, void* optval, uint std::memcpy(optval, &timeout, *optlen); return 0; } - if (*optlen < sizeof(int)) return fail(NET_EINVAL); if (level == NET_IPPROTO_TCP && socket.type != NET_SOCK_STREAM) return fail(NET_EINVAL); if (level == NET_IPPROTO_TCP && optname == NET_TCP_NODELAY) { int enabled = 0; @@ -1610,10 +1459,11 @@ int APS5_VABI sceNetGetsockopt(int s, int level, int optname, void* optval, uint if (::getsockopt(socket.native->value, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast(&enabled), &size) != 0) return fail(native_error()); const int value = enabled != 0 ? NET_TF_NODELAY : 0; - std::memcpy(optval, &value, sizeof(value)); - *optlen = sizeof(value); + *optlen = std::min(*optlen, static_cast(sizeof(value))); + std::memcpy(optval, &value, *optlen); return 0; } + if (*optlen < sizeof(int)) return fail(NET_EINVAL); if (level == NET_IPPROTO_TCP) return fail(NET_ENOPROTOOPT); if (level != NET_SOL_SOCKET) return fail(NET_EOPNOTSUPP); int value = 0; @@ -1734,39 +1584,6 @@ struct NetSockInfo { static_assert(sizeof(NetSockInfo) == 0xA0 && offsetof(NetSockInfo, s) == 0x24 && offsetof(NetSockInfo, local_adr) == 0x34 && offsetof(NetSockInfo, local_port) == 0x3C && offsetof(NetSockInfo, recv_buffer_size) == 0x64); -struct NetSockInfo6 { - char name[32]; - std::int32_t pid; - std::int32_t s; - std::int8_t socket_type; - std::int8_t policy; - std::int8_t priority; - std::int8_t reserved8; - std::int32_t recv_queue_length; - std::int32_t send_queue_length; - std::uint32_t local_adr; - std::uint32_t remote_adr; - std::uint16_t local_port; - std::uint16_t remote_port; - std::uint16_t local_vport; - std::uint16_t remote_vport; - std::int32_t state; - std::int32_t flags; - std::int32_t tx_bps; - std::int32_t rx_bps; - std::int32_t max_tx_bps; - std::int32_t max_rx_bps; - std::int32_t tx_vbps; - std::int32_t rx_vbps; - std::int32_t recv_buffer_size; - std::int32_t send_buffer_size; - std::uint8_t local_adr6[16]; - std::uint8_t remote_adr6[16]; - std::int32_t tx_drops; - std::int32_t rx_drops; - std::int32_t tx_wait; - std::int32_t reserved[2]; -}; static_assert(sizeof(NetSockInfo6) == sizeof(NetSockInfo) && offsetof(NetSockInfo6, s) == offsetof(NetSockInfo, s) && offsetof(NetSockInfo6, local_port) == offsetof(NetSockInfo, local_port) && offsetof(NetSockInfo6, flags) == offsetof(NetSockInfo, flags) && offsetof(NetSockInfo6, recv_buffer_size) == offsetof(NetSockInfo, recv_buffer_size) && offsetof(NetSockInfo6, local_adr6) == 0x6C && @@ -2306,19 +2123,6 @@ int APS5_VABI sceNetResolverStartNtoa6(int rid, const char* hostname, void* addr return 0; } -struct NetResolverRecord { - std::uint32_t address; - std::uint8_t address6[12]; - std::int32_t family; - std::int32_t reserved[3]; -}; - -struct NetResolverInfo { - NetResolverRecord records[10]; - std::int32_t count; - std::int32_t count4; - std::int32_t reserved[14]; -}; static_assert(sizeof(NetResolverRecord) == 32 && offsetof(NetResolverRecord, family) == 16); static_assert(sizeof(NetResolverInfo) == 384 && offsetof(NetResolverInfo, count) == 320 && offsetof(NetResolverInfo, count4) == 324); @@ -2656,8 +2460,6 @@ int APS5_VABI sceNetInetPtonEx(int af, const char* src, void* dst, int) { return 1; } -extern "C" int APS5_VABI ioctl_nid_postfix(int descriptor, std::uint64_t request, void* argument); - int APS5_VABI sceNetIoctl(int socketId, std::uint32_t command, void* argument) { constexpr std::uint32_t nonblockingRequest = 0x8004667e; constexpr std::uint32_t readableRequest = 0x4004667f; @@ -2772,7 +2574,11 @@ int APS5_VABI sceNetThreadJoin(void* thread) { int APS5_VABI sceNetUsleep(int microseconds) { if (!g_net_inited) return fail(NET_ENOTINIT); - if (microseconds < 0) return fail(NET_EINVAL); + if (microseconds < 0) { + std::fprintf(stdout, "[LIBNET] usleep %d\n", microseconds); + std::fflush(stdout); + return fail(NET_EINVAL); + } const int result = sceKernelUsleep_nid_postfix(static_cast(microseconds)); if (result < 0) set_errno((result & 0xFF00) == 0x100 ? result & 0xFF : 205); return result; diff --git a/core/libs/prx/libSceNet/include/Net.hpp b/core/libs/prx/libSceNet/include/Net.hpp new file mode 100644 index 0000000000..deffa39409 --- /dev/null +++ b/core/libs/prx/libSceNet/include/Net.hpp @@ -0,0 +1,438 @@ +#pragma once + +#include "SceTypes.hpp" + +struct NetRoutingRule { + std::int32_t protocol; + std::uint32_t firstAddress; + std::uint16_t firstPort; + std::uint16_t reserved; + std::uint32_t secondAddress; + std::uint16_t secondPort; + std::uint16_t flags; +}; + +struct NetIovec { + void* base; + std::uint64_t length; +}; + +struct NetResolverRecord { + std::uint32_t address; + std::uint8_t address6[12]; + std::int32_t family; + std::int32_t reserved[3]; +}; + +struct NetWlanInformationElement; +struct NetWlanWakeParameter; +struct NetWlanScanParameter; +struct NetWlanScanResult; +struct NetWlanAdhocScanParameter; +struct NetWlanInfraScanParameter; +struct NetWlanJoinResult; +struct NetDumpFilterParameter; +struct NetWlanAdhocParameter; +struct NetWlanWakeInfo; +struct NetWlanPspWakeInfo; +struct NetWlanPspWakeParameter; +struct NetWlanApParameter; +struct NetWlanDeviceInfo; +struct NetWlanAntennaParameter; +struct NetWlanRateParameter; +struct NetWlanDeviceConfiguration; +struct NetWlanRssiInfo; +struct NetDhcpInfo; +struct NetAutoIpInfo; +struct NetAddress6Info; + +struct NetDhcpOptionInfo { + std::uint32_t option; + std::uint32_t capacity; + void* data; + std::uint32_t size; + std::uint32_t reserved; +}; + +struct NetSockInfo6 { + char name[32]; + std::int32_t pid; + std::int32_t s; + std::int8_t socket_type; + std::int8_t policy; + std::int8_t priority; + std::int8_t reserved8; + std::int32_t recv_queue_length; + std::int32_t send_queue_length; + std::uint32_t local_adr; + std::uint32_t remote_adr; + std::uint16_t local_port; + std::uint16_t remote_port; + std::uint16_t local_vport; + std::uint16_t remote_vport; + std::int32_t state; + std::int32_t flags; + std::int32_t tx_bps; + std::int32_t rx_bps; + std::int32_t max_tx_bps; + std::int32_t max_rx_bps; + std::int32_t tx_vbps; + std::int32_t rx_vbps; + std::int32_t recv_buffer_size; + std::int32_t send_buffer_size; + std::uint8_t local_adr6[16]; + std::uint8_t remote_adr6[16]; + std::int32_t tx_drops; + std::int32_t rx_drops; + std::int32_t tx_wait; + std::int32_t reserved[2]; +}; +struct NetStatisticsInfo; +struct NetInterfaceStats; +struct NetRouteInfo; +struct NetDebugParameter; +struct NetArpInfo; +struct NetAppMemoryInfo; +struct NetSystemMemoryInfo; +struct NetBandwidthParameter; +struct NetDataTraffic; +struct NetEmulationParameter; +struct NetResolverConnection; +struct NetThreadParameter { + void (APS5_VABI *entry)(void*); + void* arg; + std::uint64_t reserved; + std::uint32_t flags; +}; +struct NetIpv4InterfaceAddress; +struct NetStatisticsInfoInternal; +struct NetInitializeParameter; +struct NetDhcpStartParameter; +struct NetAddress6StartParameter; + +struct NetDhcpdStartParameter { + std::uint32_t addresses[5]; + std::uint32_t maxClients; +}; + +struct NetPppoeStartParameter { + std::uint32_t dnsAddresses[2]; + char userName[128]; + char password[128]; + std::int32_t mtu; + std::uint32_t flags; +}; + +struct NetRoutingAddressParameter { + std::uint32_t address; + std::uint32_t mask; +}; + +struct NetRoutingServerParameter { + std::int32_t count; + std::uint32_t localAddresses[2]; + std::uint32_t remoteAddresses[2]; +}; + +struct NetRoutingRuleParameter { + std::int32_t count; + const NetRoutingRule* rules; +}; + +struct NetInfoDumpParameter { + std::uint32_t flags; + std::uint32_t intervalSeconds; + char path[64]; +}; + +struct NetInterfaceInfo; +struct NetInterfaceStatistics; + +struct NetResolverConnectOption { + std::int32_t connectionTimeout; + std::int32_t resolverTimeout; + std::int32_t resolverRetryCount; + std::uint32_t reserved; +}; + +struct NetSyncObject { + void* mutex; + void* condition; + std::uint32_t signals; + std::uint32_t reserved; +}; + +struct NetIpv6Address { + std::uint8_t bytes[16]; +}; + +struct NetDnsInfo { + std::uint32_t primaryAddress; + std::uint32_t secondaryAddress; +}; + +struct NetDns6Info { + NetIpv6Address primaryAddress; + NetIpv6Address secondaryAddress; +}; + +struct NetIpv6InterfaceAddress { + NetIpv6Address address; + std::uint8_t prefixLength; + std::uint8_t reserved[3]; +}; + +struct NetMemoryPoolStats { + std::size_t pool_size; + std::size_t max_inuse_size; + std::size_t current_inuse_size; +}; + +struct NetMsghdr { + void* name; + std::uint32_t name_length; + NetIovec* iov; + int iov_length; + void* control; + std::uint32_t control_length; + int flags; +}; + +struct NetResolverInfo { + NetResolverRecord records[10]; + std::int32_t count; + std::int32_t count4; + std::int32_t reserved[14]; +}; + +using NetAddressCallback = void (APS5_VABI *)(void* userArg, std::int32_t event, std::int32_t error); + +using NetEventCallback = std::uint64_t (APS5_VABI*)(std::uint32_t interfaceId, std::uint64_t events, void* userData, void* waitData); + +extern "C" { + +int* APS5_VABI sceNetErrnoLoc(void); +int APS5_VABI sceNetShowNetstat(void); +int APS5_VABI sceNetInit_nid_postfix(void); +int APS5_VABI sceNetTerm(void); +int APS5_VABI sceNetPoolCreate(const char* name, int size, int flags); +int APS5_VABI sceNetPoolDestroy(int memid); +int APS5_VABI sceNetSocket(const char* name, int family, int type, int protocol); +int APS5_VABI sceNetSocketClose(int s); +int APS5_VABI sceNetSocketAbort(int s, int flags); +int APS5_VABI sceNetBind_nid_postfix(int s, const void* addr, uint32_t addrlen); +int APS5_VABI sceNetListen(int s, int backlog); +int APS5_VABI sceNetAccept(int s, void* addr, uint32_t* addrlen); +int APS5_VABI sceNetConnect(int s, const void* addr, uint32_t addrlen); +int64_t APS5_VABI sceNetRecv(int s, void* buf, size_t len, int flags); +int64_t APS5_VABI sceNetRecvfrom(int s, void* buf, size_t len, int flags, void* from, uint32_t* fromlen); +int64_t APS5_VABI sceNetSend(int s, const void* buf, size_t len, int flags); +int64_t APS5_VABI sceNetSendto(int s, const void* buf, size_t len, int flags, const void* to, uint32_t tolen); +int64_t APS5_VABI sceNetSendmsg(int s, const NetMsghdr* msg, int flags); +int64_t APS5_VABI sceNetRecvmsg(int s, NetMsghdr* msg, int flags); +int APS5_VABI sceNetShutdown(int s, int how); +int APS5_VABI sceNetSetsockopt(int s, int level, int optname, const void* optval, uint32_t optlen); +int APS5_VABI sceNetGetsockopt(int s, int level, int optname, void* optval, uint32_t* optlen); +int APS5_VABI sceNetGetsockname(int s, void* addr, uint32_t* addrlen); +int APS5_VABI sceNetGetpeername(int s, void* addr, uint32_t* addrlen); +int APS5_VABI sceNetGetSockInfo(int s, void* info, int n, int flags); +int APS5_VABI sceNetEpollCreate(const char* name, int flags); +int APS5_VABI sceNetShowNetstatWithMemory(int memid); +int APS5_VABI sceNetGetMemoryPoolStats(int memid, NetMemoryPoolStats* stats); +int APS5_VABI sceNetEpollDestroy(int eid); +int APS5_VABI sceNetEpollAbort(int eid, int flags); +int APS5_VABI sceNetEpollControl(int eid, int op, int id, const NetEpollEvent* event); +int APS5_VABI sceNetEpollWait(int eid, NetEpollEvent* events, int maxevents, int timeout); +uint32_t APS5_VABI sceNetHtonl_nid_postfix(uint32_t host32); +uint16_t APS5_VABI sceNetHtons_nid_postfix(uint16_t host16); +uint64_t APS5_VABI sceNetHtonll(std::uint64_t host64); +uint64_t APS5_VABI sceNetNtohll(std::uint64_t net64); +uint32_t APS5_VABI sceNetNtohl_nid_postfix(uint32_t net32); +uint16_t APS5_VABI sceNetNtohs_nid_postfix(uint16_t net16); +int APS5_VABI sceNetInetPton(int af, const char* src, void* dst); +const char* APS5_VABI sceNetInetNtop(int af, const void* src, char* dst, uint32_t size); +int APS5_VABI sceNetEtherNtostr(const NetEtherAddr* n, char* str, size_t len); +int APS5_VABI sceNetEtherStrton(const char* text, NetEtherAddr* address); +int APS5_VABI sceNetGetMacAddress(NetEtherAddr* addr, int flags); +int APS5_VABI sceNetResolverCreate(const char* name, int memid, int flags); +int APS5_VABI sceNetResolverDestroy(int rid); +int APS5_VABI sceNetResolverStartNtoa(int rid, const char* hostname, void* addr, int timeout, int retry, int flags); +int APS5_VABI sceNetResolverStartNtoa6(int rid, const char* hostname, void* addr, int timeout, int retry, int flags); +int APS5_VABI sceNetResolverStartNtoaMultipleRecords(int rid, const char* hostname, NetResolverInfo* info, int timeout, int retry, int flags); +int APS5_VABI sceNetResolverStartNtoaMultipleRecordsEx(int rid, const char* hostname, NetResolverInfo* info, int timeout, int retry, int flags); +int APS5_VABI sceNetResolverStartAton(int rid, const void* addr, char* hostname, int len, int timeout, int retry, int flags); +int APS5_VABI sceNetResolverStartAton6(int rid, const void* addr, char* hostname, int len, int timeout, int retry, int flags); +int APS5_VABI sceNetResolverGetError(int rid, int* status); +int APS5_VABI sceNetResolverAbort(int rid, int flags); +int APS5_VABI sceNetShowIfconfig(); +int APS5_VABI sceNetClearDnsCache(int flags); +int APS5_VABI sceNetGetStatisticsInfo(NetStatisticsInfo* info, std::uint32_t flags); +int APS5_VABI sceNetGetInterfaceStats(NetInterfaceStats* stats, std::uint32_t flags); +int APS5_VABI sceNetSetDnsInfo(const NetDnsInfo* info, std::uint32_t flags); +int APS5_VABI sceNetShowIfconfigWithMemory(std::int32_t poolId); +int APS5_VABI sceNetShowPolicy(void); +int APS5_VABI sceNetShowPolicyWithMemory(std::int32_t poolId); +int APS5_VABI sceNetShowRoute(void); +int APS5_VABI sceNetShowRouteWithMemory(std::int32_t poolId); +int APS5_VABI sceNetResolverConnectAbort(NetResolverConnection* connection, std::uint32_t flags); +int APS5_VABI sceNetResolverConnectCreate(const char* name, std::int32_t socketType, NetResolverConnection* connection, std::uint32_t flags); +int APS5_VABI sceNetResolverConnect(NetResolverConnection* connection, const char* hostname, std::uint16_t port, const NetResolverConnectOption* option); +int APS5_VABI sceNetResolverConnectDestroy(NetResolverConnection* connection); +int APS5_VABI sceNetGetSockInfo6(std::int32_t socket, NetSockInfo6* info, std::uint32_t capacity, std::uint32_t flags); +int APS5_VABI sceNetSetDns6Info(const NetDns6Info* info, std::uint32_t flags); +int APS5_VABI sceNetShowRoute6(void); +int APS5_VABI sceNetShowRoute6WithMemory(std::int32_t poolId); +NetRouteInfo* APS5_VABI sceNetAllocateAllRouteInfo(std::int32_t interfaceId, std::int32_t* count); +NetRouteInfo* APS5_VABI sceNetAllocateAllRouteInfo6(std::int32_t interfaceId, std::int32_t* count); +int APS5_VABI sceNetControl(std::uint32_t interfaceId, std::int32_t interfaceIndex, std::uint32_t command, void* data, std::uint32_t dataSize); +int APS5_VABI sceNetDbgInit(NetDebugParameter* parameter, std::uint32_t flags); +int APS5_VABI sceNetEventCallbackCreate(std::uint32_t interfaceId, NetEventCallback callback, void* userData, std::uint32_t flags); +int APS5_VABI sceNetEventCallbackDestroy(std::uint32_t interfaceId, std::uint32_t flags); +int APS5_VABI sceNetEventCallbackGetError(std::uint32_t interfaceId, std::int32_t* error, std::uint32_t flags); +int APS5_VABI sceNetEventCallbackWaitCB(std::int32_t timeout, void* waitData, std::uint32_t flags); +int APS5_VABI sceNetFreeAllRouteInfo(void* routes); +int APS5_VABI sceNetGetArpInfo(NetArpInfo* info, std::uint32_t flags); +int APS5_VABI sceNetGetAppMemInfo(NetAppMemoryInfo* info, std::uint32_t flags); +int APS5_VABI sceNetGetDnsInfo(NetDnsInfo* info, std::uint32_t flags); +int APS5_VABI sceNetGetIfList(std::int32_t interfaceId, NetInterfaceInfo* interfaces, std::uint32_t capacity); +int APS5_VABI sceNetGetIfListEx(std::int32_t interfaceId, NetInterfaceInfo* interfaces, std::uint32_t capacity, std::uint32_t flags); +int APS5_VABI sceNetGetIfListOnce(std::int32_t interfaceId, NetInterfaceStatistics* statistics, std::uint32_t count); +const char* APS5_VABI sceNetGetIfName(std::uint32_t index); +int APS5_VABI sceNetGetIfnameNumList(std::uint32_t* interfaceIds, std::int32_t capacity, std::uint32_t flags); +int APS5_VABI sceNetGetNameToIndex(std::uint32_t interfaceId); +int APS5_VABI sceNetGetRandom(std::uint32_t* output); +int APS5_VABI sceNetGetRouteInfo(std::int32_t family, NetRouteInfo* routes, std::int32_t capacity, std::uint8_t flags); +int APS5_VABI sceNetGetsockoptEx(int socketId, int level, int option, void* value, std::uint32_t* valueSize); +void APS5_VABI sceNetGetSystemTime(std::uint64_t* output); +int APS5_VABI sceNetGetSystemMemInfo(NetSystemMemoryInfo* info, std::uint32_t flags); +int APS5_VABI sceNetInitParam(const NetInitializeParameter* parameter); +int APS5_VABI sceNetInetPtonEx(int af, const char* src, void* dst, int); +int APS5_VABI sceNetIoctl(int socketId, std::uint32_t command, void* argument); +void* APS5_VABI sceNetMemoryAllocate(std::int32_t size, int flags); +void APS5_VABI sceNetMemoryFree(void* memory); +int APS5_VABI sceNetSetDnsInfoToKernel(const NetDnsInfo* info, std::uint32_t flags); +int APS5_VABI sceNetSetsockoptEx(int socketId, int level, int option, const void* value, std::uint32_t valueSize); +int APS5_VABI sceNetSocketInternal(const char* name, int domain, int type, int protocol); +int APS5_VABI sceNetSyncCreate(NetSyncObject* sync, std::uint32_t signals, const char* name); +int APS5_VABI sceNetSyncDestroy(NetSyncObject* sync); +NetSyncObject* APS5_VABI sceNetSyncGet(std::uint32_t index); +int APS5_VABI sceNetSyncSignal(NetSyncObject* sync, std::uint32_t signals); +int APS5_VABI sceNetSyncWait(NetSyncObject* sync, std::uint32_t* timeout); +int APS5_VABI sceNetSysctl(const int* name, std::uint32_t nameLength, void* oldValue, std::size_t* oldSize, const void* newValue, std::size_t newSize); +int APS5_VABI sceNetThreadCreate(Pthread* thread, const NetThreadParameter* parameter, const char* name); +void APS5_VABI sceNetThreadExit(); +int APS5_VABI sceNetThreadJoin(void* thread); +int APS5_VABI sceNetUsleep(int microseconds); +int APS5_VABI sceNetShowIfconfigForBuffer(char* buffer, std::int32_t bufferSize, std::int32_t poolId); +int APS5_VABI sceNetShowRouteForBuffer(char* buffer, std::int32_t bufferSize, std::int32_t poolId); +int APS5_VABI sceNetShowNetstatForBuffer(char* buffer, std::int32_t bufferSize, std::int32_t poolId); +int APS5_VABI sceNetShowNetstatEx(std::uint32_t flags); +int APS5_VABI sceNetShowNetstatExForBuffer(char* buffer, std::int32_t bufferSize, std::int32_t poolId, std::uint32_t flags); +const char* APS5_VABI sceNetInetNtopWithScopeId(std::int32_t family, const void* address, char* text, std::uint32_t size, std::uint32_t scopeId); +int APS5_VABI sceNetInetPtonWithScopeId(std::int32_t family, const char* text, void* address, std::uint32_t* scopeId); +int APS5_VABI sceNetGetDns6Info(NetDns6Info* info, std::uint32_t flags); +int APS5_VABI sceNetSetDns6InfoToKernel(const NetDns6Info* info, std::uint32_t flags); +int APS5_VABI sceNetShowRoute6ForBuffer(char* buffer, std::int32_t bufferSize, std::int32_t poolId); +int APS5_VABI sceNetConfigGetIfFlags(std::uint32_t interfaceId, std::uint32_t* flags); +int APS5_VABI sceNetConfigSetIfFlags(std::uint32_t interfaceId, std::uint32_t flags); +int APS5_VABI sceNetConfigUnsetIfFlags(std::uint32_t interfaceId, std::uint32_t flags); +int APS5_VABI sceNetConfigDelIfaddr(int interfaceId); +int APS5_VABI sceNetConfigDownInterface(int interfaceId); +int APS5_VABI sceNetConfigSetDefaultRoute(const std::uint32_t* gateway); +int APS5_VABI sceNetConfigSetDefaultRouteDev(const std::uint32_t* gateway); +int APS5_VABI sceNetConfigSetIfaddr(int interfaceId, const std::uint32_t* address, const std::uint32_t* broadcastAddress, const std::uint32_t* netmask); +int APS5_VABI sceNetConfigSetIfLinkLocalAddr6(std::uint32_t interfaceId); +int APS5_VABI sceNetConfigUpInterface(int interfaceId); +int APS5_VABI sceNetConfigUpInterfaceWithFlags(std::uint32_t interfaceId, std::uint32_t flags); +int APS5_VABI sceNetConfigCleanUpAllInterfaces(void); +int APS5_VABI sceNetConfigFlushRoute(std::uint32_t interfaceId); +int APS5_VABI sceNetConfigFlushRoute6(std::uint32_t interfaceId); +int APS5_VABI sceNetConfigAddIfaddr(int interfaceId, const std::uint32_t* address, const std::uint32_t* broadcastAddress, const std::uint32_t* netmask); +int APS5_VABI sceNetConfigGetIfaddr(std::int32_t interfaceId, NetIpv4InterfaceAddress* addresses, std::int32_t capacity); +int APS5_VABI sceNetConfigSetIfmtu(std::uint32_t interfaceId, int mtu); +int APS5_VABI sceNetConfigAddArp(const NetEtherAddr* etherAddress, const std::uint32_t* address); +int APS5_VABI sceNetConfigAddArpWithInterface(int interfaceId, const NetEtherAddr* etherAddress, const std::uint32_t* address); +int APS5_VABI sceNetConfigAddMRoute(const std::uint32_t* address); +int APS5_VABI sceNetConfigAddRoute(const std::uint32_t* destination, const std::uint32_t* gateway, const std::uint32_t* netmask, int hostRoute); +int APS5_VABI sceNetConfigAddRouteWithInterface(int interfaceId, const std::uint32_t* destination, const std::uint32_t* gateway, const std::uint32_t* netmask, int hostRoute); +int APS5_VABI sceNetConfigDelArp(const NetEtherAddr* etherAddress, const std::uint32_t* address); +int APS5_VABI sceNetConfigDelArpWithInterface(int interfaceId, const NetEtherAddr* etherAddress, const std::uint32_t* address); +int APS5_VABI sceNetConfigDelDefaultRoute(void); +int APS5_VABI sceNetConfigDelDefaultRouteDev(void); +int APS5_VABI sceNetConfigDelMRoute(const std::uint32_t* address); +int APS5_VABI sceNetConfigDelRoute(const std::uint32_t* destination, const std::uint32_t* gateway, const std::uint32_t* netmask); +int APS5_VABI sceNetConfigGetDefaultRoute(std::uint32_t* gateway); +int APS5_VABI sceNetDhcpGetAutoipInfo(std::int32_t interfaceId, NetAutoIpInfo* parameter); +int APS5_VABI sceNetDhcpGetInfo(std::int32_t interfaceId, NetDhcpInfo* parameter); +int APS5_VABI sceNetDhcpGetInfoEx(std::int32_t interfaceId, std::int32_t type, NetDhcpOptionInfo* info, std::uint32_t size); +int APS5_VABI sceNetDhcpStart(std::uint32_t interfaceId, NetAddressCallback callback, void* userArg, std::int32_t threadParameter1, std::int32_t threadParameter2, NetDhcpStartParameter* parameter); +int APS5_VABI sceNetDhcpStop(int interfaceId); +int APS5_VABI sceNetConfigAddIfaddr6(int interfaceId, const NetIpv6Address* address, std::uint8_t prefixLength); +int APS5_VABI sceNetConfigDelIfaddr6(int interfaceId, const NetIpv6Address* address); +int APS5_VABI sceNetConfigDelDefaultRoute6(void); +int APS5_VABI sceNetConfigSetIfaddr6(int interfaceId, const NetIpv6Address* address, std::uint8_t prefixLength); +int APS5_VABI sceNetConfigSetIfaddr6WithFlags(int interfaceId, const NetIpv6Address* address, std::uint8_t prefixLength, std::uint32_t flags); +int APS5_VABI sceNetConfigSetDefaultRoute6(int interfaceId, const NetIpv6Address* gateway); +int APS5_VABI sceNetConfigGetIfaddr6(int interfaceId, NetIpv6InterfaceAddress* addresses, std::uint32_t count); +int APS5_VABI sceNetConfigGetDefaultRoute6(NetIpv6Address* gateway); +int APS5_VABI sceNetConfigDelRoute6(const NetIpv6Address* destination, std::uint8_t prefixLength); +int APS5_VABI sceNetConfigAddRoute6(const NetIpv6Address* destination, const NetIpv6Address* gateway, std::uint8_t prefixLength); +int APS5_VABI sceNetAddrConfig6Start(std::uint32_t interfaceId, NetAddressCallback callback, void* userArg, std::int32_t threadParameter1, std::int32_t threadParameter2, const NetAddress6StartParameter* parameter); +int APS5_VABI sceNetAddrConfig6Stop(int interfaceId); +int APS5_VABI sceNetAddrConfig6GetInfo(std::int32_t interfaceId, NetAddress6Info* parameter); +int APS5_VABI sceNetInfoDumpStart(std::int32_t threadParameter1, std::int32_t threadParameter2, const NetInfoDumpParameter* parameter); +int APS5_VABI sceNetInfoDumpStop(void); +int APS5_VABI sceNetDhcpdStart(std::uint32_t interfaceId, NetAddressCallback callback, void* userArg, std::int32_t threadParameter1, std::int32_t threadParameter2, const NetDhcpdStartParameter* parameter); +int APS5_VABI sceNetDhcpdStop(int interfaceId); +int APS5_VABI sceNetDuplicateIpStart(std::int32_t interfaceId, NetAddressCallback callback, void* userArg, std::int32_t threadParameter1, std::int32_t threadParameter2); +int APS5_VABI sceNetDuplicateIpStop(int interfaceId); +int APS5_VABI sceNetConfigWlanAdhocClearWakeOnWlan(std::uint32_t interfaceId); +int APS5_VABI sceNetConfigWlanAdhocCreate(std::int32_t interfaceId, NetWlanAdhocParameter* parameter); +int APS5_VABI sceNetConfigWlanAdhocGetWakeOnWlanInfo(std::int32_t interfaceId, NetWlanWakeInfo* parameter); +int APS5_VABI sceNetConfigWlanAdhocJoin(std::int32_t interfaceId, NetWlanAdhocParameter* parameter); +int APS5_VABI sceNetConfigWlanAdhocLeave(int interfaceId); +int APS5_VABI sceNetConfigWlanAdhocPspEmuClearWakeOnWlan(std::uint32_t interfaceId); +int APS5_VABI sceNetConfigWlanAdhocPspEmuGetWakeOnWlanInfo(std::int32_t interfaceId, NetWlanPspWakeInfo* parameter); +int APS5_VABI sceNetConfigWlanAdhocPspEmuSetWakeOnWlan(std::int32_t interfaceId, NetWlanPspWakeParameter* parameter); +int APS5_VABI sceNetConfigWlanAdhocScanJoin(std::int32_t interfaceId, const NetWlanAdhocScanParameter* parameter, void* buffer, std::size_t bufferSize, NetWlanJoinResult** result); +int APS5_VABI sceNetConfigWlanAdhocSetExtInfoElement(std::int32_t interfaceId, NetWlanInformationElement* parameter, std::int32_t size); +int APS5_VABI sceNetConfigWlanAdhocSetWakeOnWlan(std::int32_t interfaceId, NetWlanWakeParameter* parameter, std::size_t size); +int APS5_VABI sceNetConfigWlanApStart(std::int32_t interfaceId, NetWlanApParameter* parameter); +int APS5_VABI sceNetConfigWlanApStop(int interfaceId); +int APS5_VABI sceNetConfigWlanBackgroundScanQuery(std::int32_t interfaceId, void* buffer, std::int32_t size, NetWlanScanResult** results, std::size_t* count); +int APS5_VABI sceNetConfigWlanBackgroundScanStart(std::int32_t interfaceId, NetWlanScanParameter* parameter, std::uint32_t size); +int APS5_VABI sceNetConfigWlanBackgroundScanStop(int interfaceId); +int APS5_VABI sceNetConfigWlanDiagGetDeviceInfo(std::int32_t interfaceId, NetWlanDeviceInfo* parameter); +int APS5_VABI sceNetConfigWlanDiagSetAntenna(std::int32_t interfaceId, NetWlanAntennaParameter* parameter); +int APS5_VABI sceNetConfigWlanDiagSetTxFixedRate(std::int32_t interfaceId, NetWlanRateParameter* parameter); +int APS5_VABI sceNetConfigWlanGetDeviceConfig(std::int32_t interfaceId, NetWlanDeviceConfiguration* parameter); +int APS5_VABI sceNetConfigWlanInfraGetRssiInfo(std::int32_t interfaceId, NetWlanRssiInfo* parameter); +int APS5_VABI sceNetConfigWlanInfraLeave(int interfaceId); +int APS5_VABI sceNetConfigWlanInfraScanJoin(std::int32_t interfaceId, const NetWlanInfraScanParameter* parameter, void* buffer, std::size_t bufferSize, NetWlanJoinResult** result); +int APS5_VABI sceNetConfigWlanScan(std::int32_t interfaceId, const NetWlanScanParameter* parameter, std::size_t parameterSize, void* buffer, std::size_t bufferSize, NetWlanScanResult** results, std::size_t* count); +int APS5_VABI sceNetConfigWlanSetDeviceConfig(std::int32_t interfaceId, NetWlanDeviceConfiguration* parameter); +int APS5_VABI sceNetConfigEtherGetLinkMode(std::uint32_t interfaceId, int* mode); +int APS5_VABI sceNetConfigEtherPostPlugInOutEvent(std::uint32_t interfaceId); +int APS5_VABI sceNetConfigEtherSetLinkMode(std::uint32_t interfaceId, int mode); +int APS5_VABI sceNetPppoeStart(std::uint32_t interfaceId, std::int32_t pppoeInterfaceId, NetAddressCallback callback, void* userArg, std::int32_t threadParameter1, std::int32_t threadParameter2, const NetPppoeStartParameter* parameter); +int APS5_VABI sceNetPppoeStop(void); +int APS5_VABI sceNetBandwidthControlSetDefaultParam(const NetBandwidthParameter* parameter, std::uint32_t flags); +int APS5_VABI sceNetBandwidthControlGetDefaultParam(NetBandwidthParameter* parameter, std::uint32_t flags); +int APS5_VABI sceNetBandwidthControlGetDataTraffic(std::int32_t interfaceId, NetDataTraffic* traffic, std::uint32_t flags); +int APS5_VABI sceNetConfigSetDefaultScope(std::uint32_t interfaceId, const char* interfaceName, std::int32_t scopeId); +int APS5_VABI sceNetConfigRoutingStart(std::uint32_t firstInterfaceId, std::uint32_t secondInterfaceId, const NetRoutingAddressParameter* addressParameter, NetRoutingServerParameter* serverParameter, const NetRoutingRuleParameter* ruleParameter); +int APS5_VABI sceNetConfigRoutingStop(void); +int APS5_VABI sceNetConfigRoutingShowRoutingConfig(void); +int APS5_VABI sceNetConfigRoutingShowtCtlVar(const char* name); +int APS5_VABI sceNetGetStatisticsInfoInternal(NetStatisticsInfoInternal* info); +int APS5_VABI sceNetDumpAbort(std::int32_t dumpId, std::uint32_t flags); +int APS5_VABI sceNetDumpCreate(const char* name, std::int32_t bufferSize, std::uint32_t flags); +int APS5_VABI sceNetDumpSetFilterParam(std::int32_t socket, const NetDumpFilterParameter* parameter); +int APS5_VABI sceNetDumpDestroy(std::int32_t dumpId); +int APS5_VABI sceNetDumpRead(std::int32_t dumpId, void* buffer, std::int32_t bufferSize, std::uint32_t* flags); +int APS5_VABI sceNetEmulationDebugSettingsSet(const NetEmulationParameter* parameter, std::uint32_t flags); +int APS5_VABI sceNetEmulationDebugSettingsGet(NetEmulationParameter* parameter, std::uint32_t flags); +int APS5_VABI sceNetEmulationSet(const NetEmulationParameter* parameter, std::uint32_t flags); +int APS5_VABI sceNetEmulationGet(NetEmulationParameter* parameter, std::uint32_t flags); + +} diff --git a/core/libs/prx/libSceNet/libSceNet.hpp b/core/libs/prx/libSceNet/libSceNet.hpp new file mode 100644 index 0000000000..9f4c162ed2 --- /dev/null +++ b/core/libs/prx/libSceNet/libSceNet.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceNet/include/Net.hpp" diff --git a/core/libs/prx/libSceNetCtl/Export.cpp b/core/libs/prx/libSceNetCtl/Export.cpp index c8b0e482f3..d3e153e34a 100644 --- a/core/libs/prx/libSceNetCtl/Export.cpp +++ b/core/libs/prx/libSceNetCtl/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNetCtl/include/NetCtl.hpp" #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN #include @@ -35,16 +36,6 @@ #include // Network-control state reflects host interface addressing, not PSN sign-in status. -union NetCtlInfoV6; -struct NetCtlConnectionConfiguration; -struct NetCtlScanOptions; -struct NetCtlScanBssidList; -struct NetCtlScanInfo; -struct NetCtlNatInfoInternal; -struct NetCtlBandwidthInfo; -struct NetCtlNetEvConfiguration; -struct NetBweInfo; -struct NetCtlWifiInfo; static constexpr int SCE_NET_CTL_ERROR_NOT_INITIALIZED = static_cast(0x80412101); static constexpr int SCE_NET_CTL_ERROR_ID_NOT_FOUND = static_cast(0x80412104); diff --git a/core/libs/prx/libSceNetCtl/include/NetCtl.hpp b/core/libs/prx/libSceNetCtl/include/NetCtl.hpp new file mode 100644 index 0000000000..f2fa735b00 --- /dev/null +++ b/core/libs/prx/libSceNetCtl/include/NetCtl.hpp @@ -0,0 +1,104 @@ +#pragma once + +#include "SceTypes.hpp" + +union NetCtlInfoV6; +struct NetCtlConnectionConfiguration; +struct NetCtlScanOptions; +struct NetCtlScanBssidList; +struct NetCtlScanInfo; +struct NetCtlNatInfoInternal; +struct NetCtlBandwidthInfo; +struct NetCtlNetEvConfiguration; +struct NetBweInfo; +struct NetCtlWifiInfo; + +extern "C" { + +int APS5_VABI sceNetCtlCheckCallback(void); +int APS5_VABI sceNetCtlGetIfStat(NetCtlIfStat* stat); +int APS5_VABI sceNetCtlGetInfo(int code, NetCtlInfo* info); +int APS5_VABI sceNetCtlGetNatInfo(NetCtlNatInfo* info); +int APS5_VABI sceNetCtlGetResult(int event, int* result); +int APS5_VABI sceNetCtlGetState(int* state); +int APS5_VABI sceNetCtlGetStateV6(int* state); +int APS5_VABI sceNetCtlInit(void); +int APS5_VABI sceNetCtlRegisterCallback(NetCtlCallback func, void* arg, int* cid); +int APS5_VABI sceNetCtlRegisterCallbackV6(NetCtlCallback func, void* arg, int* cid); +int APS5_VABI sceNetCtlGetInfoV6(std::uint32_t code, NetCtlInfoV6* info); +void APS5_VABI sceNetCtlTerm(void); +int APS5_VABI sceNetCtlUnregisterCallback(int cid); +int APS5_VABI sceNetCtlUnregisterCallbackV6(int cid); +int APS5_VABI sceNetCtlRegisterCallbackForNpToolkit(NetCtlCallback callback, void* argument, int* callbackId); +int APS5_VABI sceNetCtlRegisterCallbackIpcInt(NetCtlCallback callback, void* argument, int* callbackId); +int APS5_VABI sceNetCtlRegisterCallbackForLibIpcInt(NetCtlCallback callback, void* argument, int* callbackId); +int APS5_VABI sceNetCtlUnregisterCallbackForNpToolkit(int callbackId); +int APS5_VABI sceNetCtlUnregisterCallbackIpcInt(int callbackId); +int APS5_VABI sceNetCtlUnregisterCallbackForLibIpcInt(int callbackId); +int APS5_VABI sceNetCtlCheckCallbackForNpToolkit(void); +int APS5_VABI sceNetCtlCheckCallbackForLibIpcInt(void); +int APS5_VABI sceNetCtlClearEventIpcInt(int event); +int APS5_VABI sceNetCtlClearEventForNpToolkit(int event); +int APS5_VABI sceNetCtlClearEventForLibIpcInt(int event); +int APS5_VABI sceNetCtlGetResultIpcInt(int event, int* result); +int APS5_VABI sceNetCtlGetStateIpcInt(int* state); +int APS5_VABI sceNetCtlGetState2IpcInt(int* state); +int APS5_VABI sceNetCtlGetInfoIpcInt(std::uint32_t code, NetCtlInfo* info); +int APS5_VABI sceNetCtlGetEtherLinkMode(int* mode); +int APS5_VABI sceNetCtlGetWifiType(int* type); +int APS5_VABI sceNetCtlConnectIpcInt(void); +int APS5_VABI sceNetCtlConnectWithRetryIpcInt(void); +int APS5_VABI sceNetCtlConnectConfIpcInt(const NetCtlConnectionConfiguration* configuration); +int APS5_VABI sceNetCtlDisconnectIpcInt(void); +int APS5_VABI sceNetCtlScanIpcInt(const char* const* ssids, std::uint32_t count, const NetCtlScanOptions* options); +int APS5_VABI sceNetCtlGetScanInfoBssidIpcInt(NetCtlScanBssidList* bssids, std::uint32_t capacity); +int APS5_VABI sceNetCtlGetScanInfoByBssidIpcInt(const std::uint8_t* bssid, NetCtlScanInfo* info, void* buffer, std::size_t* size); +int APS5_VABI sceNetCtlGetScanInfoForSsidScanIpcInt(NetCtlScanInfo* info, void* buffer, std::size_t* size); +int APS5_VABI sceNetCtlGetScanInfoBssidForSsidListScanIpcInt(NetCtlScanBssidList* bssids, std::uint32_t capacity); +int APS5_VABI sceNetCtlGetScanInfoForSsidListScanIpcInt(const std::uint8_t* bssid, NetCtlScanInfo* info, void* buffer, std::size_t* size); +int APS5_VABI sceNetCtlSetErrorNotificationEnabledIpcInt(int enabled); +int APS5_VABI sceNetCtlRegisterCallbackV6IpcInt(NetCtlCallback callback, void* argument, int* callbackId); +int APS5_VABI sceNetCtlUnregisterCallbackV6IpcInt(int callbackId); +int APS5_VABI sceNetCtlGetResultV6(int eventType, int* errorCode); +int APS5_VABI sceNetCtlGetResultV6IpcInt(int event, int* result); +int APS5_VABI sceNetCtlGetStateV6IpcInt(int* state); +int APS5_VABI sceNetCtlGetInfoV6IpcInt(std::uint32_t code, NetCtlInfoV6* info); +int APS5_VABI sceNetCtlGetNatInfoIpcInt(NetCtlNatInfoInternal* info); +int APS5_VABI sceNetCtlSetStunWithPaddingFlagIpcInt(void); +int APS5_VABI sceNetCtlUnsetStunWithPaddingFlagIpcInt(void); +int APS5_VABI sceNetCtlIsBandwidthManagementEnabledIpcInt(void); +int APS5_VABI sceNetCtlDisableBandwidthManagementIpcInt(void); +int APS5_VABI sceNetCtlEnableBandwidthManagementIpcInt(void); +int APS5_VABI sceNetCtlGetBandwidthInfoIpcInt(NetCtlBandwidthInfo* info); +int APS5_VABI sceNetCtlGetNetEvConfigInfoIpcInt(NetCtlNetEvConfiguration* configuration); +int APS5_VABI sceNetCtlGetConnectionElapsedTimeIpcInt(std::uint64_t* elapsedTime); +int APS5_VABI sceNetCtlApRpCheckCallback(void); +int APS5_VABI sceNetCtlApRpClearEvent(void); +int APS5_VABI sceNetCtlApRpRegisterCallback(void); +int APS5_VABI sceNetCtlApRpUnregisterCallback(void); +int APS5_VABI sceNetCtlApRpGetResult(void); +int APS5_VABI sceNetCtlApRpGetState(void); +int APS5_VABI sceNetCtlApRpGetInfo(void); +int APS5_VABI sceNetCtlApRpStart(void); +int APS5_VABI sceNetCtlApCpStart(void); +int APS5_VABI sceNetCtlApAppStartWithRetryPid(std::int32_t processId, const char* passcode); +int APS5_VABI sceNetCtlApAppStartWithRetry(const char* passcode); +int APS5_VABI sceNetCtlApRpStartWithRetry(void); +int APS5_VABI sceNetCtlApRpStartConf(void); +int APS5_VABI sceNetCtlApRpStop(void); +int APS5_VABI sceNetCtlApCpStop(void); +int APS5_VABI sceNetCtlApAppInitWpaKey(void); +int APS5_VABI sceNetCtlApAppInitWpaKeyForQa(std::uint8_t mode); +int APS5_VABI sceNetCtlApRestart(void); +int APS5_VABI sceNetBweCheckCallbackIpcInt(void); +int APS5_VABI sceNetBweClearEventIpcInt(int event); +int APS5_VABI sceNetBweRegisterCallbackIpcInt(NetCtlCallback callback, void* argument, int* callbackId); +int APS5_VABI sceNetBweUnregisterCallbackIpcInt(int callbackId); +int APS5_VABI sceNetBweGetInfoIpcInt(NetBweInfo* info); +int APS5_VABI sceNetBweStartInternetConnectionTestIpcInt(void); +int APS5_VABI sceNetBweFinishInternetConnectionTestIpcInt(void); +int APS5_VABI sceNetBweStartInternetConnectionTestBandwidthTestIpcInt(void); +int APS5_VABI sceNetBweSetInternetConnectionTestResultIpcInt(std::int32_t firstResult, std::int32_t secondResult); +int APS5_VABI sceNetCtlGetWifiInfoIpcInt(NetCtlWifiInfo* info); + +} diff --git a/core/libs/prx/libSceNetCtl/libSceNetCtl.hpp b/core/libs/prx/libSceNetCtl/libSceNetCtl.hpp new file mode 100644 index 0000000000..d60a79d958 --- /dev/null +++ b/core/libs/prx/libSceNetCtl/libSceNetCtl.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceNetCtl/include/NetCtl.hpp" diff --git a/core/libs/prx/libSceNetCtlAp/Export.cpp b/core/libs/prx/libSceNetCtlAp/Export.cpp index cc3d9a2492..8eafcd5e4f 100644 --- a/core/libs/prx/libSceNetCtlAp/Export.cpp +++ b/core/libs/prx/libSceNetCtlAp/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNetCtlAp/include/Api.hpp" #include #include #include @@ -23,8 +24,6 @@ constexpr std::size_t NET_CTL_AP_INFO_SIZE = 152; constexpr std::size_t NET_CTL_AP_CONNECT_INFO_SIZE = 184; constexpr int MAX_CALLBACKS = 8; -using NetCtlApCallback = void(APS5_VABI*)(int, void*); - struct CallbackSlot { NetCtlApCallback func = nullptr; void* arg = nullptr; diff --git a/core/libs/prx/libSceNetCtlAp/include/Api.hpp b/core/libs/prx/libSceNetCtlAp/include/Api.hpp new file mode 100644 index 0000000000..31649a048f --- /dev/null +++ b/core/libs/prx/libSceNetCtlAp/include/Api.hpp @@ -0,0 +1,21 @@ +#pragma once + +#include "SceTypes.hpp" + +using NetCtlApCallback = void(APS5_VABI*)(int, void*); + +extern "C" { + +int APS5_VABI sceNetCtlApInit(); +void APS5_VABI sceNetCtlApTerm(); +int APS5_VABI sceNetCtlApCheckCallback(); +int APS5_VABI sceNetCtlApClearEvent(int eventType); +int APS5_VABI sceNetCtlApRegisterCallback(NetCtlApCallback func, void* arg, int* cid); +int APS5_VABI sceNetCtlApUnregisterCallback(int cid); +int APS5_VABI sceNetCtlApGetResult(int eventType, int* errorCode); +int APS5_VABI sceNetCtlApGetInfo(void* info); +int APS5_VABI sceNetCtlApGetState(int* state); +int APS5_VABI sceNetCtlApStop(); +int APS5_VABI sceNetCtlApGetConnectInfo(const char* optStr, void* connectInfo); + +} diff --git a/core/libs/prx/libSceNetCtlAp/libSceNetCtlAp.hpp b/core/libs/prx/libSceNetCtlAp/libSceNetCtlAp.hpp new file mode 100644 index 0000000000..1f1138e728 --- /dev/null +++ b/core/libs/prx/libSceNetCtlAp/libSceNetCtlAp.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceNetCtlAp/include/Api.hpp" diff --git a/core/libs/prx/libSceNetCtlApDialog/Export.cpp b/core/libs/prx/libSceNetCtlApDialog/Export.cpp index 64a0d3086e..d6c67ca827 100644 --- a/core/libs/prx/libSceNetCtlApDialog/Export.cpp +++ b/core/libs/prx/libSceNetCtlApDialog/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNetCtlApDialog/include/Api.hpp" #include #include #include diff --git a/core/libs/prx/libSceNetCtlApDialog/include/Api.hpp b/core/libs/prx/libSceNetCtlApDialog/include/Api.hpp new file mode 100644 index 0000000000..ec8df01ad0 --- /dev/null +++ b/core/libs/prx/libSceNetCtlApDialog/include/Api.hpp @@ -0,0 +1,16 @@ +#pragma once + +#include "prx/libSceCommonDialog/CommonDialog.hpp" +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceNetCtlApDialogInitialize(void); +int APS5_VABI sceNetCtlApDialogTerminate(void); +int APS5_VABI sceNetCtlApDialogOpen(const NetCtlApDialogParam* param); +int APS5_VABI sceNetCtlApDialogClose(void); +int APS5_VABI sceNetCtlApDialogUpdateStatus(void); +int APS5_VABI sceNetCtlApDialogGetStatus(void); +int APS5_VABI sceNetCtlApDialogGetResult(NetCtlApDialogResult* result); + +} diff --git a/core/libs/prx/libSceNetCtlApDialog/libSceNetCtlApDialog.hpp b/core/libs/prx/libSceNetCtlApDialog/libSceNetCtlApDialog.hpp new file mode 100644 index 0000000000..b62243d95c --- /dev/null +++ b/core/libs/prx/libSceNetCtlApDialog/libSceNetCtlApDialog.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceNetCtlApDialog/include/Api.hpp" diff --git a/core/libs/prx/libSceNgs2.native/CMakeLists.txt b/core/libs/prx/libSceNgs2.native/CMakeLists.txt index 93bb6c445e..fddd6277ab 100644 --- a/core/libs/prx/libSceNgs2.native/CMakeLists.txt +++ b/core/libs/prx/libSceNgs2.native/CMakeLists.txt @@ -2,7 +2,7 @@ include(${CMAKE_CURRENT_SOURCE_DIR}/Ngs2Library.cmake) add_sce_ngs2_library(libSceNgs2.native) if(BUILD_TESTING) - foreach(ngs2Test IN ITEMS Render Atrac9 Filter Custom Parse Stream UserFx Report Geom VoiceIndex HandleErrors VoiceHandles) + foreach(ngs2Test IN ITEMS Render Atrac9 Filter Custom Parse Stream UserFx Report Geom VoiceIndex HandleErrors VoiceHandles VoiceEvents) string(TOLOWER ${ngs2Test} testName) add_test_executable(ngs2_${testName}_tests ${CMAKE_CURRENT_SOURCE_DIR}/tests/Ngs2${ngs2Test}.cpp) target_include_directories(ngs2_${testName}_tests PRIVATE ${LIBS_INCLUDE_DIR} ${CMAKE_SOURCE_DIR}/3rdparty/LibAtrac9/C/src) diff --git a/core/libs/prx/libSceNgs2.native/Export.cpp b/core/libs/prx/libSceNgs2.native/Export.cpp index 984f3782fe..6f5160436e 100644 --- a/core/libs/prx/libSceNgs2.native/Export.cpp +++ b/core/libs/prx/libSceNgs2.native/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNgs2.native/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceNgs2.native/include/Api.hpp b/core/libs/prx/libSceNgs2.native/include/Api.hpp new file mode 100644 index 0000000000..7bc7c26ad3 --- /dev/null +++ b/core/libs/prx/libSceNgs2.native/include/Api.hpp @@ -0,0 +1,23 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceNgs2JobSchedulerResetOption(void); +int APS5_VABI sceNgs2ModuleArrayEnumItems(void); +int APS5_VABI sceNgs2ModuleEnumConfigs(void); +int APS5_VABI sceNgs2ModuleQueueEnumItems(void); +int APS5_VABI sceNgs2RackQueryInfo(void); +int APS5_VABI sceNgs2RackRunCommands(void); +int APS5_VABI sceNgs2StreamCreate(void); +int APS5_VABI sceNgs2StreamCreateWithAllocator(void); +int APS5_VABI sceNgs2StreamDestroy(void); +int APS5_VABI sceNgs2StreamQueryBufferSize(void); +int APS5_VABI sceNgs2StreamQueryInfo(void); +int APS5_VABI sceNgs2StreamResetOption(void); +int APS5_VABI sceNgs2StreamRunCommands(void); +int APS5_VABI sceNgs2SystemQueryInfo(void); +int APS5_VABI sceNgs2SystemRunCommands(void); + +} diff --git a/core/libs/prx/libSceNgs2.native/include/Ngs2Types.hpp b/core/libs/prx/libSceNgs2.native/include/Ngs2Types.hpp index eda5e07ef3..04b86aa717 100644 --- a/core/libs/prx/libSceNgs2.native/include/Ngs2Types.hpp +++ b/core/libs/prx/libSceNgs2.native/include/Ngs2Types.hpp @@ -26,6 +26,7 @@ static constexpr int SCE_NGS2_ERROR_UNKNOWN_WAVEFORM_FORMAT = static_cast(0 static constexpr int SCE_NGS2_ERROR_INVALID_PAN_UNIT_ANGLE = static_cast(0x804A8450); static constexpr int SCE_NGS2_ERROR_INVALID_PAN_SPEAKER = static_cast(0x804A8451); static constexpr int SCE_NGS2_ERROR_INVALID_VOICE_HANDLE = static_cast(0x804A8203); +static constexpr int SCE_NGS2_ERROR_INVALID_VOICE_ACCESS = static_cast(0x804A8351); static constexpr int SCE_NGS2_ERROR_NULL_PARAM_LIST = static_cast(0x804A8360); static constexpr int SCE_NGS2_ERROR_INVALID_GEOM_LISTENER_ADDRESS = static_cast(0x804A8461); static constexpr int SCE_NGS2_ERROR_INVALID_GEOM_FLAG = static_cast(0x804A8463); diff --git a/core/libs/prx/libSceNgs2.native/libSceNgs2.native.hpp b/core/libs/prx/libSceNgs2.native/libSceNgs2.native.hpp new file mode 100644 index 0000000000..1ca6a1c884 --- /dev/null +++ b/core/libs/prx/libSceNgs2.native/libSceNgs2.native.hpp @@ -0,0 +1,4 @@ +#pragma once + +#include "prx/libSceNgs2.native/include/Api.hpp" +#include "prx/libSceNgs2.native/tests/Ngs2Test.hpp" diff --git a/core/libs/prx/libSceNgs2.native/src/Atrac9.cpp b/core/libs/prx/libSceNgs2.native/src/Atrac9.cpp index 3a85bb761c..ecebdfed40 100644 --- a/core/libs/prx/libSceNgs2.native/src/Atrac9.cpp +++ b/core/libs/prx/libSceNgs2.native/src/Atrac9.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNgs2.native/tests/Ngs2Test.hpp" #include #include #include diff --git a/core/libs/prx/libSceNgs2.native/src/Rack.cpp b/core/libs/prx/libSceNgs2.native/src/Rack.cpp index fd8f22db33..13277128e3 100644 --- a/core/libs/prx/libSceNgs2.native/src/Rack.cpp +++ b/core/libs/prx/libSceNgs2.native/src/Rack.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNgs2.native/tests/Ngs2Test.hpp" #include #include #include diff --git a/core/libs/prx/libSceNgs2.native/src/System.cpp b/core/libs/prx/libSceNgs2.native/src/System.cpp index 1f6dd14d90..28a7828f36 100644 --- a/core/libs/prx/libSceNgs2.native/src/System.cpp +++ b/core/libs/prx/libSceNgs2.native/src/System.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNgs2.native/tests/Ngs2Test.hpp" #include #include #include @@ -18,7 +19,6 @@ #include "prx/libc/include/General.hpp" #include "Ngs2Internal.hpp" - static std::vector& Systems() { static auto* const systems = new std::vector(); return *systems; diff --git a/core/libs/prx/libSceNgs2.native/src/Voice.cpp b/core/libs/prx/libSceNgs2.native/src/Voice.cpp index 5ff13687d9..add38b4d3f 100644 --- a/core/libs/prx/libSceNgs2.native/src/Voice.cpp +++ b/core/libs/prx/libSceNgs2.native/src/Voice.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNgs2.native/tests/Ngs2Test.hpp" #include #include #include @@ -20,6 +21,15 @@ static constexpr std::uint8_t COMMAND_TYPE_UINT = 4; static constexpr std::uint8_t COMMAND_TYPE_FLOAT_ARRAY = 0x11; static constexpr float MAX_MATRIX_LEVEL = 4.0f; +struct Ngs2ReturnCode { + int code; +}; + +static void SendEvent(Ngs2Voice& voice, std::uint32_t eventId) { + if (eventId == SCE_NGS2_VOICE_EVENT_PLAY && voice.channels == 0) throw Ngs2ReturnCode{SCE_NGS2_ERROR_INVALID_VOICE_ACCESS}; + voice.SetEvent(eventId); +} + void Ngs2Voice::SetEvent(std::uint32_t eventId) { switch (eventId) { case SCE_NGS2_VOICE_EVENT_PLAY: @@ -159,7 +169,7 @@ static void ApplyCommonParam(Ngs2Voice& voice, const Ngs2VoiceParamHeader& param break; } case SCE_NGS2_VOICE_PARAM_PATCH: Patch(voice, ParamAs(param)); break; - case SCE_NGS2_VOICE_PARAM_EVENT: voice.SetEvent(ParamAs(param).event_id); break; + case SCE_NGS2_VOICE_PARAM_EVENT: SendEvent(voice, ParamAs(param).event_id); break; case SCE_NGS2_VOICE_PARAM_CALLBACK: { const auto& callback = ParamAs(param); voice.callback = callback.callback; @@ -172,8 +182,11 @@ static void ApplyCommonParam(Ngs2Voice& voice, const Ngs2VoiceParamHeader& param } static void SetupSampler(Ngs2Voice& voice, const Ngs2WaveformFormat& format) { + if (format.waveform_type == 0 && format.num_channels == 0 && format.sample_rate == 0) { + if (voice.channels == 0) voice.ResetSetup(); + return; + } voice.ResetSetup(); - if (format.waveform_type == 0 && format.num_channels == 0 && format.sample_rate == 0) return; if (format.waveform_type != SCE_NGS2_WAVEFORM_TYPE_PCM_I16L && format.waveform_type != SCE_NGS2_WAVEFORM_TYPE_ATRAC9) { throw std::runtime_error("NGS2: waveform type " + Ngs2Hex(format.waveform_type) + " is not implemented"); } @@ -404,9 +417,13 @@ int APS5_VABI sceNgs2VoiceControl(uintptr_t voice_handle, const Ngs2VoiceParamHe auto* found = Ngs2FindVoice(voice_handle); if (found == nullptr) return SCE_NGS2_ERROR_INVALID_VOICE_HANDLE; auto& voice = *found; - for (const auto* param = param_list;; param = reinterpret_cast(reinterpret_cast(param) + param->next)) { - ApplyParam(voice, *param); - if (param->next == 0) break; + try { + for (const auto* param = param_list;; param = reinterpret_cast(reinterpret_cast(param) + param->next)) { + ApplyParam(voice, *param); + if (param->next == 0) break; + } + } catch (const Ngs2ReturnCode& result) { + return result.code; } return SCE_NGS2_OK; } @@ -417,20 +434,24 @@ int APS5_VABI sceNgs2VoiceRunCommands(uintptr_t voice_handle, const Ngs2VoiceCom if (found == nullptr) return SCE_NGS2_ERROR_INVALID_VOICE_HANDLE; auto& voice = *found; if (commands == nullptr && num_commands != 0) APS5_INVALID_ARG_EX; - for (std::size_t i = 0; i < num_commands; i++) { - const auto& command = commands[i]; - const std::uint32_t index = command.id >> 24; - const std::uint32_t id = command.id & 0xffffff; - const std::uint8_t expectedType = id == COMMAND_EVENT ? COMMAND_TYPE_UINT - : id == COMMAND_MATRIX_LEVELS ? COMMAND_TYPE_FLOAT_ARRAY - : id == COMMAND_PORT_VOLUME ? COMMAND_TYPE_FLOAT - : id == COMMAND_PORT_MATRIX ? COMMAND_TYPE_INT : 0; - if (expectedType == 0) throw std::runtime_error("NGS2: voice command " + Ngs2Hex(command.id) + " is not implemented"); - if (command.type != expectedType) throw std::invalid_argument("NGS2: voice command " + Ngs2Hex(command.id) + " has value type " + Ngs2Hex(command.type)); - if (id == COMMAND_EVENT) voice.SetEvent(command.value.u); - else if (id == COMMAND_MATRIX_LEVELS) SetMatrixLevels(voice, index, command.value.levels, command.count); - else if (id == COMMAND_PORT_VOLUME) PortAt(voice, index).volume = command.value.f; - else SetPortMatrix(voice, index, command.value.i); + try { + for (std::size_t i = 0; i < num_commands; i++) { + const auto& command = commands[i]; + const std::uint32_t index = command.id >> 24; + const std::uint32_t id = command.id & 0xffffff; + const std::uint8_t expectedType = id == COMMAND_EVENT ? COMMAND_TYPE_UINT + : id == COMMAND_MATRIX_LEVELS ? COMMAND_TYPE_FLOAT_ARRAY + : id == COMMAND_PORT_VOLUME ? COMMAND_TYPE_FLOAT + : id == COMMAND_PORT_MATRIX ? COMMAND_TYPE_INT : 0; + if (expectedType == 0) throw std::runtime_error("NGS2: voice command " + Ngs2Hex(command.id) + " is not implemented"); + if (command.type != expectedType) throw std::invalid_argument("NGS2: voice command " + Ngs2Hex(command.id) + " has value type " + Ngs2Hex(command.type)); + if (id == COMMAND_EVENT) SendEvent(voice, command.value.u); + else if (id == COMMAND_MATRIX_LEVELS) SetMatrixLevels(voice, index, command.value.levels, command.count); + else if (id == COMMAND_PORT_VOLUME) PortAt(voice, index).volume = command.value.f; + else SetPortMatrix(voice, index, command.value.i); + } + } catch (const Ngs2ReturnCode& result) { + return result.code; } return SCE_NGS2_OK; } diff --git a/core/libs/prx/libSceNgs2.native/tests/Ngs2Atrac9.cpp b/core/libs/prx/libSceNgs2.native/tests/Ngs2Atrac9.cpp index c8260d8bb2..1c72ffa8d4 100644 --- a/core/libs/prx/libSceNgs2.native/tests/Ngs2Atrac9.cpp +++ b/core/libs/prx/libSceNgs2.native/tests/Ngs2Atrac9.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNgs2.native/tests/Ngs2Test.hpp" #include "Ngs2Test.hpp" #include "libatrac9.h" @@ -396,6 +397,7 @@ static bool ParseThrows(const std::vector& file) { Ngs2WaveformInfo info{}; try { sceNgs2ParseWaveformData(file.data(), file.size(), &info); + } catch (const std::runtime_error&) { return true; } diff --git a/core/libs/prx/libSceNgs2.native/tests/Ngs2Custom.cpp b/core/libs/prx/libSceNgs2.native/tests/Ngs2Custom.cpp index 80d9d2cb34..47a189ed42 100644 --- a/core/libs/prx/libSceNgs2.native/tests/Ngs2Custom.cpp +++ b/core/libs/prx/libSceNgs2.native/tests/Ngs2Custom.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNgs2.native/tests/Ngs2Test.hpp" #include "Ngs2Test.hpp" #include @@ -86,6 +87,7 @@ static bool CreateThrows(const Ngs2CustomSubmixerRackOption& option) { Ngs2ContextBufferInfo query{}; try { sceNgs2RackQueryBufferSize(SCE_NGS2_RACK_ID_CUSTOM_SUBMIXER, &option.custom_rack_option.rack_option, &query); + } catch (const TException&) { return true; } @@ -97,6 +99,7 @@ static bool CreateSamplerThrows(const Ngs2CustomSamplerRackOption& option) { Ngs2ContextBufferInfo query{}; try { sceNgs2RackQueryBufferSize(SCE_NGS2_RACK_ID_CUSTOM_SAMPLER, &option.custom_rack_option.rack_option, &query); + } catch (const TException&) { return true; } @@ -123,6 +126,7 @@ static bool ControlThrows(uintptr_t voice, std::uint32_t id, TParam param) { param.header = {static_cast(sizeof(TParam)), 0, id}; try { sceNgs2VoiceControl(voice, ¶m.header); + } catch (const TException&) { return true; } @@ -238,6 +242,7 @@ static void TestRackOptions() { bool failed = false; try { sceNgs2RackQueryBufferSize(SCE_NGS2_RACK_ID_CUSTOM_SUBMIXER, nullptr, &query); + } catch (const std::runtime_error&) { failed = true; } @@ -372,7 +377,6 @@ static void TestCustomFilter() { Require(sceNgs2SystemDestroy(system, nullptr) == SCE_NGS2_OK); } - struct ModuleOptionWords { std::uint32_t size; std::uint32_t words[15]; @@ -494,6 +498,7 @@ static void TestCustomRackChecks() { uintptr_t rack = 0; try { sceNgs2RackCreate(system, SCE_NGS2_RACK_ID_CUSTOM_SUBMIXER, &option.custom_rack_option.rack_option, nullptr, &rack); + } catch (const std::invalid_argument&) { rejected = true; } @@ -532,8 +537,10 @@ static void TestCustomRackChecks() { try { if (useAllocator) { sceNgs2RackCreateWithAllocator(system, SCE_NGS2_RACK_ID_CUSTOM_SAMPLER, &sampler.custom_rack_option.rack_option, &allocator, &rack); + } else { sceNgs2RackCreate(system, SCE_NGS2_RACK_ID_CUSTOM_SAMPLER, &sampler.custom_rack_option.rack_option, &info, &rack); + } } catch (const std::runtime_error&) { rejected = true; @@ -701,6 +708,7 @@ static void TestCustomDelay(std::uint32_t count, const DelayOption& delay) { bool rejected = false; try { sceNgs2VoiceControl(custom, ¶m.header); + } catch (const std::runtime_error& error) { const std::string message = error.what(); rejected = message.find("Delay") != std::string::npos && message.find("not implemented") != std::string::npos; @@ -791,6 +799,7 @@ static bool ModuleInfoThrows(uintptr_t rack, std::uint32_t moduleIndex, std::siz bool threw = false; try { sceNgs2CustomRackGetModuleInfo(rack, moduleIndex, &info, infoSize); + } catch (const TException&) { threw = true; } diff --git a/core/libs/prx/libSceNgs2.native/tests/Ngs2Filter.cpp b/core/libs/prx/libSceNgs2.native/tests/Ngs2Filter.cpp index cf47e314b2..f6dd4600d1 100644 --- a/core/libs/prx/libSceNgs2.native/tests/Ngs2Filter.cpp +++ b/core/libs/prx/libSceNgs2.native/tests/Ngs2Filter.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNgs2.native/tests/Ngs2Test.hpp" #include "Ngs2Test.hpp" #include @@ -151,6 +152,7 @@ static void RequireRejected(uintptr_t voice, const Ngs2SamplerVoiceFilterParam& bool rejected = false; try { sceNgs2VoiceControl(voice, ¶m.header); + } catch (const TError&) { rejected = true; } @@ -181,6 +183,7 @@ static void TestRateChangeUnderFilter() { bool rejected = false; try { sceNgs2SystemSetSampleRate(system, 96000); + } catch (const std::runtime_error&) { rejected = true; } diff --git a/core/libs/prx/libSceNgs2.native/tests/Ngs2Geom.cpp b/core/libs/prx/libSceNgs2.native/tests/Ngs2Geom.cpp index ae95253a90..b456ed0cd0 100644 --- a/core/libs/prx/libSceNgs2.native/tests/Ngs2Geom.cpp +++ b/core/libs/prx/libSceNgs2.native/tests/Ngs2Geom.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNgs2.native/tests/Ngs2Test.hpp" #include "Ngs2Test.hpp" #include @@ -105,6 +106,7 @@ static void RejectListener(const Ngs2GeomListenerParam* param, std::uint32_t fla bool rejected = false; try { sceNgs2GeomCalcListener(param, &work, flags); + } catch (const std::exception&) { rejected = true; } diff --git a/core/libs/prx/libSceNgs2.native/tests/Ngs2Render.cpp b/core/libs/prx/libSceNgs2.native/tests/Ngs2Render.cpp index 0e044309fa..b15456dae6 100644 --- a/core/libs/prx/libSceNgs2.native/tests/Ngs2Render.cpp +++ b/core/libs/prx/libSceNgs2.native/tests/Ngs2Render.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNgs2.native/tests/Ngs2Test.hpp" #include "Ngs2Test.hpp" #include @@ -836,6 +837,7 @@ static bool SystemOptionThrows(const Ngs2SystemOption& option) { Ngs2ContextBufferInfo query{}; try { sceNgs2SystemQueryBufferSize(&option, &query); + } catch (const std::runtime_error&) { return true; } @@ -878,6 +880,7 @@ static void TestUserData() { bool threw = false; try { sceNgs2SystemGetUserData(system, nullptr); + } catch (const std::invalid_argument&) { threw = true; } @@ -901,6 +904,7 @@ static void TestUserData() { threw = false; try { sceNgs2RackGetUserData(rack, nullptr); + } catch (const std::invalid_argument&) { threw = true; } @@ -1048,6 +1052,7 @@ static void TestStereoIntoSurround() { bool threw = false; try { sceNgs2SystemRender(system, info, 3); + } catch (const std::runtime_error&) { threw = true; } diff --git a/core/libs/prx/libSceNgs2.native/tests/Ngs2VoiceEvents.cpp b/core/libs/prx/libSceNgs2.native/tests/Ngs2VoiceEvents.cpp new file mode 100644 index 0000000000..da4b91132b --- /dev/null +++ b/core/libs/prx/libSceNgs2.native/tests/Ngs2VoiceEvents.cpp @@ -0,0 +1,103 @@ +#include "Ngs2Test.hpp" + +#include +#include + +static const Ngs2SamplerVoiceSetupParam SamplerSetup{{}, {SCE_NGS2_WAVEFORM_TYPE_PCM_I16L, 1, 48000, 0, 0, 0}}; + +static Ngs2VoiceEventParam PlayParam() { + return {{sizeof(Ngs2VoiceEventParam), 0, SCE_NGS2_VOICE_PARAM_EVENT}, SCE_NGS2_VOICE_EVENT_PLAY}; +} + +static uintptr_t Sampler(uintptr_t system) { + const auto master = Mastering(system, 1); + const auto voice = Voice(CreateRack(system, SCE_NGS2_RACK_ID_SAMPLER)); + Patch(voice, master); + return voice; +} + +static void TestPlayWithoutSetup() { + const auto system = CreateSystem(); + const auto voice = Sampler(system); + const auto play = PlayParam(); + const Ngs2VoiceCommand playCommand{2, 0, 4, 0, {.u = SCE_NGS2_VOICE_EVENT_PLAY}}; + Event(voice, SCE_NGS2_VOICE_EVENT_STOP_IMM); + Control(voice, SCE_NGS2_SAMPLER_VOICE_PARAM_ADD_WAVEFORM_BLOCKS, Ngs2SamplerVoiceWaveformBlocksParam{{}, nullptr, 0, 0, nullptr}); + Require(sceNgs2VoiceControl(voice, &play.header) == SCE_NGS2_ERROR_INVALID_VOICE_ACCESS); + Require(sceNgs2VoiceRunCommands(voice, &playCommand, 1) == SCE_NGS2_ERROR_INVALID_VOICE_ACCESS); + + std::vector out(Grain, -1.0f); + const Ngs2RenderBufferInfo info{out.data(), out.size() * sizeof(float), SCE_NGS2_WAVEFORM_TYPE_PCM_F32L, 1}; + for (int grain = 0; grain < 3; grain++) { + Require(Flags(voice) == 0); + Require(sceNgs2SystemRender(system, &info, 1) == SCE_NGS2_OK); + for (float sample : out) Require(sample == 0.0f); + } + Require(Flags(voice) == 0); + + Control(voice, SCE_NGS2_SAMPLER_VOICE_PARAM_SETUP, SamplerSetup); + Require(sceNgs2VoiceRunCommands(voice, &playCommand, 1) == SCE_NGS2_OK); + Require(Flags(voice) == SCE_NGS2_VOICE_STATE_FLAG_INUSE); + Require(sceNgs2SystemDestroy(system, nullptr) == SCE_NGS2_OK); +} + +static void TestEmptyFormatKeepsTheSetup() { + const auto system = CreateSystem(); + const auto voice = Sampler(system); + Control(voice, SCE_NGS2_SAMPLER_VOICE_PARAM_SETUP, SamplerSetup); + Control(voice, SCE_NGS2_SAMPLER_VOICE_PARAM_SETUP, Ngs2SamplerVoiceSetupParam{}); + Event(voice, SCE_NGS2_VOICE_EVENT_PLAY); + Require(Flags(voice) == SCE_NGS2_VOICE_STATE_FLAG_INUSE); + + const auto bare = Sampler(system); + Control(bare, SCE_NGS2_SAMPLER_VOICE_PARAM_SETUP, Ngs2SamplerVoiceSetupParam{}); + const auto play = PlayParam(); + Require(sceNgs2VoiceControl(bare, &play.header) == SCE_NGS2_ERROR_INVALID_VOICE_ACCESS); + Require(sceNgs2SystemDestroy(system, nullptr) == SCE_NGS2_OK); +} + +static void TestPlayAfterSetupInOneList() { + const auto system = CreateSystem(); + const auto voice = Sampler(system); + struct List { + Ngs2SamplerVoiceSetupParam setup; + Ngs2VoiceEventParam play; + }; + List list{SamplerSetup, PlayParam()}; + list.setup.header = {sizeof(list.setup), static_cast(sizeof(list.setup)), SCE_NGS2_SAMPLER_VOICE_PARAM_SETUP}; + Require(sceNgs2VoiceControl(voice, &list.setup.header) == SCE_NGS2_OK); + Require(Flags(voice) == SCE_NGS2_VOICE_STATE_FLAG_INUSE); + + const auto other = Sampler(system); + struct Reversed { + Ngs2VoiceEventParam play; + Ngs2SamplerVoiceSetupParam setup; + }; + Reversed reversed{PlayParam(), SamplerSetup}; + reversed.play.header = {sizeof(reversed.play), static_cast(sizeof(reversed.play)), SCE_NGS2_VOICE_PARAM_EVENT}; + reversed.setup.header = {sizeof(reversed.setup), 0, SCE_NGS2_SAMPLER_VOICE_PARAM_SETUP}; + Require(sceNgs2VoiceControl(other, &reversed.play.header) == SCE_NGS2_ERROR_INVALID_VOICE_ACCESS); + Require(Flags(other) == 0); + Require(sceNgs2SystemDestroy(system, nullptr) == SCE_NGS2_OK); +} + +static void TestNeverSetUpVoicesOfOtherRacks() { + const auto system = CreateSystem(); + const auto play = PlayParam(); + for (const auto rackId : {SCE_NGS2_RACK_ID_SUBMIXER, SCE_NGS2_RACK_ID_REVERB, SCE_NGS2_RACK_ID_MASTERING}) { + const auto voice = Voice(CreateRack(system, rackId)); + Require(sceNgs2VoiceControl(voice, &play.header) == SCE_NGS2_ERROR_INVALID_VOICE_ACCESS); + Require(Flags(voice) == 0); + } + const auto master = Mastering(system, 1); + Require(Flags(master) == SCE_NGS2_VOICE_STATE_FLAG_INUSE); + Require(sceNgs2SystemDestroy(system, nullptr) == SCE_NGS2_OK); +} + +int main() { + TestPlayWithoutSetup(); + TestEmptyFormatKeepsTheSetup(); + TestPlayAfterSetupInOneList(); + TestNeverSetUpVoicesOfOtherRacks(); + return 0; +} diff --git a/core/libs/prx/libSceNgs2.native/tests/Ngs2VoiceHandles.cpp b/core/libs/prx/libSceNgs2.native/tests/Ngs2VoiceHandles.cpp index 043e02c96d..7d525001c1 100644 --- a/core/libs/prx/libSceNgs2.native/tests/Ngs2VoiceHandles.cpp +++ b/core/libs/prx/libSceNgs2.native/tests/Ngs2VoiceHandles.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNgs2.native/tests/Ngs2Test.hpp" #include "Ngs2Test.hpp" #include @@ -42,6 +43,7 @@ static bool MatrixInfoThrows(uintptr_t voice, std::uint32_t matrixId) { bool threw = false; try { sceNgs2VoiceGetMatrixInfo(voice, matrixId, &info, sizeof(info)); + } catch (const TException&) { threw = true; } diff --git a/core/libs/prx/libSceNgs2/PendingExports.cpp b/core/libs/prx/libSceNgs2/PendingExports.cpp index ec4b3cad95..e1942c4923 100644 --- a/core/libs/prx/libSceNgs2/PendingExports.cpp +++ b/core/libs/prx/libSceNgs2/PendingExports.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNgs2/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceNgs2/include/Api.hpp b/core/libs/prx/libSceNgs2/include/Api.hpp new file mode 100644 index 0000000000..3398761ed6 --- /dev/null +++ b/core/libs/prx/libSceNgs2/include/Api.hpp @@ -0,0 +1,14 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceNgs2FftInit(); +int APS5_VABI sceNgs2FftProcess(); +int APS5_VABI sceNgs2FftQuerySize(); +int APS5_VABI sceNgs2ParseWaveformUser(std::uintptr_t handler, std::uintptr_t userData, void* outInfo); +int APS5_VABI sceNgs2SystemEnumHandles(std::uintptr_t* outHandles, std::uint32_t maxHandles); +int APS5_VABI sceNgs2SystemEnumRackHandles(std::uintptr_t systemHandle, std::uintptr_t* outHandles, std::uint32_t maxHandles); + +} diff --git a/core/libs/prx/libSceNgs2/libSceNgs2.hpp b/core/libs/prx/libSceNgs2/libSceNgs2.hpp new file mode 100644 index 0000000000..db4f270ed6 --- /dev/null +++ b/core/libs/prx/libSceNgs2/libSceNgs2.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceNgs2/include/Api.hpp" diff --git a/core/libs/prx/libSceNotification/Export.cpp b/core/libs/prx/libSceNotification/Export.cpp index 90362f2991..3431c8dbc3 100644 --- a/core/libs/prx/libSceNotification/Export.cpp +++ b/core/libs/prx/libSceNotification/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNotification/include/Api.hpp" #include #include "SceTypes.hpp" #include "prx/libc/include/General.hpp" diff --git a/core/libs/prx/libSceNotification/include/Api.hpp b/core/libs/prx/libSceNotification/include/Api.hpp new file mode 100644 index 0000000000..24cb956b82 --- /dev/null +++ b/core/libs/prx/libSceNotification/include/Api.hpp @@ -0,0 +1,12 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceNotificationSend(int type, std::uint8_t flag, std::uint8_t* message); +int APS5_VABI sceNotificationSendById(int type, std::uint8_t flag, std::uint8_t* id, std::uint8_t* jsonData); +int APS5_VABI sceNotificationShowPsButtonPersistentBanner(std::uint8_t* jsonParam); +void APS5_VABI sceNotificationHidePsButtonPersistentBanner(); + +} diff --git a/core/libs/prx/libSceNotification/libSceNotification.hpp b/core/libs/prx/libSceNotification/libSceNotification.hpp new file mode 100644 index 0000000000..780084c485 --- /dev/null +++ b/core/libs/prx/libSceNotification/libSceNotification.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceNotification/include/Api.hpp" diff --git a/core/libs/prx/libSceNotificationClient/libSceNotificationClient.hpp b/core/libs/prx/libSceNotificationClient/libSceNotificationClient.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceNotificationClient/libSceNotificationClient.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceNpAuth/Export.cpp b/core/libs/prx/libSceNpAuth/Export.cpp index 3289f920f0..2d2b89ec9d 100644 --- a/core/libs/prx/libSceNpAuth/Export.cpp +++ b/core/libs/prx/libSceNpAuth/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNpAuth/include/Api.hpp" #include #include #include diff --git a/core/libs/prx/libSceNpAuth/include/Api.hpp b/core/libs/prx/libSceNpAuth/include/Api.hpp new file mode 100644 index 0000000000..cb003d3a93 --- /dev/null +++ b/core/libs/prx/libSceNpAuth/include/Api.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceNpAuthAbortRequest(int reqId); +int APS5_VABI sceNpAuthCreateAsyncRequest(const void* param); +int APS5_VABI sceNpAuthCreateRequest(void); +int APS5_VABI sceNpAuthDeleteRequest(int reqId); +int APS5_VABI sceNpAuthGetAuthorizedAppCode(std::int32_t requestId, const NpAuthAuthorizedAppCodeParameter* parameter, char* code, std::int32_t* issuerId, bool* authorizationRequired); +int APS5_VABI sceNpAuthGetAuthorizationCodeV3(int reqId, const void* param, void* authCode, int* issuerId); +int APS5_VABI sceNpAuthGetIdTokenV3(int reqId, const void* param, void* idToken); +int APS5_VABI sceNpAuthGetAuthorizationCode(int reqId, const void* param, void* authCode); +int APS5_VABI sceNpAuthGetIdToken(int reqId, const void* param, void* idToken); +int APS5_VABI sceNpAuthPollAsync(int reqId, int* result); +int APS5_VABI sceNpAuthSetTimeout(std::int32_t requestId, std::int32_t resolveRetry, std::uint32_t resolveTimeout, std::uint32_t connectTimeout, std::uint32_t sendTimeout, std::uint32_t receiveTimeout); +int APS5_VABI sceNpAuthWaitAsync(int reqId, int* result); +int APS5_VABI sceNpAuthGetAuthorizationCodeA(int reqId, const void* param, void* authCode, int* issuerId); +int APS5_VABI sceNpAuthGetIdTokenA(int reqId, const void* param, void* token); + +} diff --git a/core/libs/prx/libSceNpAuth/libSceNpAuth.hpp b/core/libs/prx/libSceNpAuth/libSceNpAuth.hpp new file mode 100644 index 0000000000..1f4aaf4f77 --- /dev/null +++ b/core/libs/prx/libSceNpAuth/libSceNpAuth.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceNpAuth/include/Api.hpp" diff --git a/core/libs/prx/libSceNpAuthAuthorizedAppDialog/Export.cpp b/core/libs/prx/libSceNpAuthAuthorizedAppDialog/Export.cpp index 9244dedeea..e483fc0a9d 100644 --- a/core/libs/prx/libSceNpAuthAuthorizedAppDialog/Export.cpp +++ b/core/libs/prx/libSceNpAuthAuthorizedAppDialog/Export.cpp @@ -1,3 +1,5 @@ +#include "prx/libSceNpAuthAuthorizedAppDialog/include/Api.hpp" +#include "prx/libSceUserService/UserService.hpp" #include #include #include @@ -6,8 +8,6 @@ #include "prx/libSceCommonDialog/CommonDialog.hpp" #include "prx/libc/include/General.hpp" -extern "C" int APS5_VABI sceUserServiceGetLoginUserIdList(UserServiceLoginUserIdList* users); - namespace { constexpr int COMMON_DIALOG_STATUS_NONE = 0; diff --git a/core/libs/prx/libSceNpAuthAuthorizedAppDialog/include/Api.hpp b/core/libs/prx/libSceNpAuthAuthorizedAppDialog/include/Api.hpp new file mode 100644 index 0000000000..c2514b916f --- /dev/null +++ b/core/libs/prx/libSceNpAuthAuthorizedAppDialog/include/Api.hpp @@ -0,0 +1,16 @@ +#pragma once + +#include "prx/libSceCommonDialog/CommonDialog.hpp" +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceNpAuthAuthorizedAppDialogInitialize(void); +int APS5_VABI sceNpAuthAuthorizedAppDialogOpen(const NpAuthAuthorizedAppDialogParam* param); +int APS5_VABI sceNpAuthAuthorizedAppDialogUpdateStatus(void); +int APS5_VABI sceNpAuthAuthorizedAppDialogGetStatus(void); +int APS5_VABI sceNpAuthAuthorizedAppDialogGetResult(std::int32_t* result); +int APS5_VABI sceNpAuthAuthorizedAppDialogClose(void); +int APS5_VABI sceNpAuthAuthorizedAppDialogTerminate(void); + +} diff --git a/core/libs/prx/libSceNpAuthAuthorizedAppDialog/libSceNpAuthAuthorizedAppDialog.hpp b/core/libs/prx/libSceNpAuthAuthorizedAppDialog/libSceNpAuthAuthorizedAppDialog.hpp new file mode 100644 index 0000000000..c091f6db11 --- /dev/null +++ b/core/libs/prx/libSceNpAuthAuthorizedAppDialog/libSceNpAuthAuthorizedAppDialog.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceNpAuthAuthorizedAppDialog/include/Api.hpp" diff --git a/core/libs/prx/libSceNpCommerce/Export.cpp b/core/libs/prx/libSceNpCommerce/Export.cpp index 3a8ee95c0d..a94c5c9e82 100644 --- a/core/libs/prx/libSceNpCommerce/Export.cpp +++ b/core/libs/prx/libSceNpCommerce/Export.cpp @@ -1,3 +1,5 @@ +#include "prx/libSceNpCommerce/include/Api.hpp" +#include "prx/libSceUserService/UserService.hpp" #include #include #include @@ -7,8 +9,6 @@ #include "prx/libSceCommonDialog/CommonDialog.hpp" #include "prx/libc/include/General.hpp" -extern "C" int APS5_VABI sceUserServiceGetLoginUserIdList(UserServiceLoginUserIdList* users); - namespace { constexpr int COMMON_DIALOG_STATUS_NONE = 0; diff --git a/core/libs/prx/libSceNpCommerce/include/Api.hpp b/core/libs/prx/libSceNpCommerce/include/Api.hpp new file mode 100644 index 0000000000..ddb745fc4a --- /dev/null +++ b/core/libs/prx/libSceNpCommerce/include/Api.hpp @@ -0,0 +1,21 @@ +#pragma once + +#include "prx/libSceCommonDialog/CommonDialog.hpp" +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceNpCommerceDialogInitialize(); +int APS5_VABI sceNpCommerceDialogOpen(const NpCommerceDialogParam* param); +int APS5_VABI sceNpCommerceDialogUpdateStatus(void); +int APS5_VABI sceNpCommerceDialogGetStatus(void); +int APS5_VABI sceNpCommerceDialogGetResult(NpCommerceDialogResult* result); +int APS5_VABI sceNpCommerceDialogClose(void); +int APS5_VABI sceNpCommerceDialogTerminate(); +int APS5_VABI sceNpCommerceHidePsStoreIcon(void); +int APS5_VABI sceNpCommerceShowPsStoreIcon(int pos); +int APS5_VABI sceNpCommerceSetPsStoreIconLayout(int layout); +int APS5_VABI sceNpCommerceDialogOpen2(const NpCommerceDialogParam2* param); +int APS5_VABI sceNpCommerceDialogInitializeInternal(); + +} diff --git a/core/libs/prx/libSceNpCommerce/libSceNpCommerce.hpp b/core/libs/prx/libSceNpCommerce/libSceNpCommerce.hpp new file mode 100644 index 0000000000..240d2d12fe --- /dev/null +++ b/core/libs/prx/libSceNpCommerce/libSceNpCommerce.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceNpCommerce/include/Api.hpp" diff --git a/core/libs/prx/libSceNpCommon/Export.cpp b/core/libs/prx/libSceNpCommon/Export.cpp index f10b45437e..77a7b33fc9 100644 --- a/core/libs/prx/libSceNpCommon/Export.cpp +++ b/core/libs/prx/libSceNpCommon/Export.cpp @@ -1,3 +1,7 @@ +#include "prx/libkernel/Pthread/include/Mutex.hpp" +#include "prx/libkernel/Pthread/include/Cond.hpp" +#include "prx/libkernel/include/Api.hpp" +#include "prx/libSceNpCommon/include/Api.hpp" #include #include #include @@ -18,19 +22,9 @@ constexpr std::size_t ONLINE_ID_MAX_LENGTH = 16; constexpr int MUTEX_TYPE_RECURSIVE = 2; constexpr KernelClockid CLOCK_MONOTONIC_ID = 4; -struct NpIdFull { - NpOnlineId handle; - std::uint8_t opt[8]; - std::uint8_t reserved[8]; -}; static_assert(sizeof(NpIdFull) == 36); -struct SystemSwVersion { - std::uint64_t size; - char versionString[0x1C]; - std::uint32_t version; -}; -static_assert(sizeof(SystemSwVersion) == 0x28); +static_assert(sizeof(SceKernelSystemSwVersion) == 0x28); int compareBytes(const std::uint8_t* lhs, const std::uint8_t* rhs, std::size_t count) { for (std::size_t i = 0; i < count; ++i) { @@ -41,25 +35,6 @@ int compareBytes(const std::uint8_t* lhs, const std::uint8_t* rhs, std::size_t c } -extern "C" int APS5_VABI scePthreadMutexattrInit(PthreadMutexattr* attr); -extern "C" int APS5_VABI scePthreadMutexattrDestroy(PthreadMutexattr* attr); -extern "C" int APS5_VABI scePthreadMutexattrSettype(PthreadMutexattr* attr, int type); -extern "C" int APS5_VABI scePthreadMutexInit(PthreadMutex* mutex, const PthreadMutexattr* attr, const char* name); -extern "C" int APS5_VABI scePthreadMutexDestroy(PthreadMutex* mutex); -extern "C" int APS5_VABI scePthreadMutexLock(PthreadMutex* mutex); -extern "C" int APS5_VABI scePthreadMutexUnlock(PthreadMutex* mutex); -extern "C" int APS5_VABI scePthreadMutexTrylock(PthreadMutex* mutex); -extern "C" int APS5_VABI scePthreadCondattrInit(PthreadCondattr* attr); -extern "C" int APS5_VABI scePthreadCondattrDestroy(PthreadCondattr* attr); -extern "C" int APS5_VABI scePthreadCondInit(PthreadCond* cond, const PthreadCondattr* attr, const char* name); -extern "C" int APS5_VABI scePthreadCondDestroy(PthreadCond* cond); -extern "C" int APS5_VABI scePthreadCondSignal(PthreadCond* cond); -extern "C" int APS5_VABI scePthreadCondWait(PthreadCond* cond, PthreadMutex* mutex); -extern "C" int APS5_VABI scePthreadCondTimedwait(PthreadCond* cond, PthreadMutex* mutex, KernelUseconds usec); -extern "C" int APS5_VABI scePthreadJoin(Pthread thread, void** retval); -extern "C" int APS5_VABI sceKernelClockGettime(KernelClockid clockId, KernelTimespec* tp); -extern "C" int APS5_VABI sceKernelGetSystemSwVersion_nid_postfix(SystemSwVersion* version); - extern "C" { int APS5_VABI sceNpCmpOnlineId(const NpOnlineId* onlineId1, const NpOnlineId* onlineId2) { @@ -112,6 +87,7 @@ int APS5_VABI sceNpMutexInit(PthreadMutex* mutex, const char* name, std::uint64_ if (flags & 1) result = scePthreadMutexattrSettype(&attr, MUTEX_TYPE_RECURSIVE); if (result == 0) result = scePthreadMutexInit(mutex, &attr, name); scePthreadMutexattrDestroy(&attr); + return result; } @@ -158,6 +134,7 @@ int APS5_VABI sceNpCondInit(PthreadCond* cond, const char* name, std::uint64_t) if (result != 0) return result; result = scePthreadCondInit(cond, &attr, name); scePthreadCondattrDestroy(&attr); + return result; } @@ -187,9 +164,10 @@ int APS5_VABI sceNpGetSystemClockUsec(std::int64_t* usec) { } void APS5_VABI sceNpGetSdkVersion(char* version) { - SystemSwVersion swVersion{}; + SceKernelSystemSwVersion swVersion{}; swVersion.size = sizeof(swVersion); sceKernelGetSystemSwVersion_nid_postfix(&swVersion); + const std::uint32_t hex = swVersion.version; std::snprintf(version, 8, "%u.%02u", ((hex >> 24) & 0xF) + (hex >> 28) * 10, ((hex >> 16) & 0xF) + ((hex >> 20) & 0xF) * 10); } diff --git a/core/libs/prx/libSceNpCommon/PendingExports.cpp b/core/libs/prx/libSceNpCommon/PendingExports.cpp index 30a117b230..b6479f111b 100644 --- a/core/libs/prx/libSceNpCommon/PendingExports.cpp +++ b/core/libs/prx/libSceNpCommon/PendingExports.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNpCommon/include/Api.hpp" #include #include #include "SceTypes.hpp" @@ -5,11 +6,6 @@ extern "C" { -int APS5_VABI sceNpCloseEventFlag(void) { - NotImplemented_nid_no_patch(__func__); - return 0; -} - int APS5_VABI sceNpCloseSema(void) { NotImplemented_nid_no_patch(__func__); return 0; diff --git a/core/libs/prx/libSceNpCommon/Runtime.cpp b/core/libs/prx/libSceNpCommon/Runtime.cpp index 965506fa51..510328687f 100644 --- a/core/libs/prx/libSceNpCommon/Runtime.cpp +++ b/core/libs/prx/libSceNpCommon/Runtime.cpp @@ -1,3 +1,9 @@ +#include "prx/libSceSaveData/SaveDataCore.hpp" +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" +#include "prx/libSceNpCommon/include/Api.hpp" +#include "prx/libSceUserService/UserService.hpp" +#include "prx/libSceRtc/include/Rtc.hpp" #include #include #include @@ -14,112 +20,14 @@ #include "prx/libkernel/Pthread/include/Mutex.hpp" #include "prx/libkernel/Semaphore/include/Semaphore.hpp" -extern "C" { -int APS5_VABI sceNpMutexInit(PthreadMutex* mutex, const char* name, std::uint64_t flags); -int APS5_VABI sceNpMutexDestroy(PthreadMutex* mutex); -int APS5_VABI sceNpMutexLock(PthreadMutex* mutex); -int APS5_VABI sceNpMutexUnlock(PthreadMutex* mutex); -int APS5_VABI sceNpCondInit(PthreadCond* cond, const char* name, std::uint64_t flags); -int APS5_VABI sceNpCondDestroy(PthreadCond* cond); -int APS5_VABI sceNpCondSignal(PthreadCond* cond); -int APS5_VABI sceNpCondTimedwait(PthreadCond* cond, PthreadMutex* mutex, std::uint32_t usec); -int APS5_VABI sceNpJoinThread(Pthread thread, void** retval); -int APS5_VABI sceNpGetSystemClockUsec(std::int64_t* usec); -int APS5_VABI scePthreadCreate(Pthread* thread, const PthreadAttr* attr, PthreadEntry entry, void* arg, const char* name); -Pthread APS5_VABI scePthreadSelf(); -int APS5_VABI scePthreadJoin(Pthread thread, void** retval); -int APS5_VABI scePthreadAttrInit(PthreadAttr* attr); -int APS5_VABI scePthreadAttrDestroy(PthreadAttr* attr); -int APS5_VABI scePthreadAttrSetstacksize(PthreadAttr* attr, std::size_t stacksize); -int APS5_VABI scePthreadAttrSetinheritsched(PthreadAttr* attr, int inherit_sched); -int APS5_VABI scePthreadAttrSetschedpolicy(PthreadAttr* attr, int policy); -int APS5_VABI scePthreadAttrSetschedparam(PthreadAttr* attr, const KernelSchedParam* param); -int APS5_VABI scePthreadAttrSetaffinity(PthreadAttr* attr, KernelCpumask mask); -int APS5_VABI sceKernelCreateEventFlag(KernelEventFlag* ef, const char* name, uint32_t attr, uint64_t init_pattern, const void* param); -int APS5_VABI sceKernelDeleteEventFlag(KernelEventFlag ef); -int APS5_VABI sceKernelOpenEventFlag(KernelEventFlag* ef, const char* name); -int APS5_VABI sceKernelSetEventFlag(KernelEventFlag ef, uint64_t bit_pattern); -int APS5_VABI sceKernelClearEventFlag(KernelEventFlag ef, uint64_t bit_pattern); -int APS5_VABI sceKernelPollEventFlag(KernelEventFlag ef, uint64_t bit_pattern, uint32_t wait_mode, uint64_t* result_pat); -int APS5_VABI sceKernelCancelEventFlag(KernelEventFlag ef, uint64_t set_pattern, int* num_wait_threads); -int APS5_VABI getpid_nid_postfix(void); -int APS5_VABI sceRtcParseRFC3339(RtcTick* utc, const char* date_time); -int APS5_VABI sceRtcFormatRFC3339(char* date_time, const RtcTick* utc, int time_zone_minutes); -int APS5_VABI sceRtcSetTick(RtcDateTime* time, const RtcTick* tick); -int APS5_VABI sceRtcGetTime_t(const RtcDateTime* time, int64_t* seconds); -int APS5_VABI sceKernelGetSystemSwVersion_nid_postfix(void* version); -int APS5_VABI sceKernelClockGettime(KernelClockid clock_id, KernelTimespec* tp); -int APS5_VABI sceUserServiceGetRegisteredUserIdList(UserServiceRegisteredUserIdList* user_id_list); -int32_t APS5_VABI sceKernelMapNamedFlexibleMemory(void** addr_in_out, size_t len, int prot, int flags, const char* name); -int APS5_VABI sceKernelMunmap(uint64_t vaddr, size_t len); -void* APS5_VABI sceLibcMspaceCreate_nid_postfix(const char* name, void* base, std::size_t size, unsigned flags); -int APS5_VABI sceLibcMspaceDestroy_nid_postfix(void* handle); -void* APS5_VABI sceLibcMspaceMalloc_nid_postfix(void* handle, std::size_t size); -void APS5_VABI sceLibcMspaceFree_nid_postfix(void* handle, void* pointer); -void* APS5_VABI sceLibcMspaceRealloc_nid_postfix(void* handle, void* pointer, std::size_t size); -int APS5_VABI sceLibcMspaceMallocStats_nid_postfix(void* handle, MallocManagedSize* stats); -} - -struct NpTitleIdParts { - char id[9]; - char reserved; - std::uint8_t index; -}; - -struct NpCallout { - NpCallout* next; - void (APS5_VABI *handler)(void* arg); - std::uint64_t deadline; - void* arg; - std::uint64_t reserved; -}; static_assert(sizeof(NpCallout) == 0x28); -struct NpCalloutContext { - Pthread thread; - PthreadMutex mutex; - PthreadCond cond; - int initialized; - int stopping; - NpCallout* pending; -}; static_assert(sizeof(NpCalloutContext) == 0x28); -struct NpHeap { - void* mspace; -}; - -struct NpHeapStat { - std::uint64_t maxSystemSize; - std::uint64_t maxInuseSize; - std::uint64_t currentInuseSize; -}; - -struct NpKernelMemory { - std::uint64_t size; - std::uint64_t reserved; - void* address; -}; static_assert(sizeof(NpKernelMemory) == 0x18); -struct NpMemoryHeap { - NpKernelMemory memory; - NpHeap heap; -}; static_assert(sizeof(NpMemoryHeap) == 0x20); -struct NpAllocator { - void* (APS5_VABI *allocate)(std::size_t size, void* context); - void* (APS5_VABI *reallocate)(void* pointer, std::size_t size, void* context); - void (APS5_VABI *release)(void* pointer, void* context); - void* context; -}; - -struct NpAllocatorEx { - NpAllocator allocator; - int outOfMemoryError; -}; - namespace { constexpr int NP_ERROR_NULL_ARGUMENT = static_cast(0x80550003); @@ -193,17 +101,13 @@ constexpr std::size_t NP_USER_ID_LIST_SIZE = 20; constexpr int USER_ID_INVALID = -1; constexpr KernelClockid NP_SYSTEM_CLOCK = 4; -struct SystemSwVersion { - std::uint64_t size; - char versionString[0x1C]; - std::uint32_t version; -}; -static_assert(sizeof(SystemSwVersion) == 0x28); +static_assert(sizeof(SceKernelSystemSwVersion) == 0x28); std::uint32_t SystemVersion() { - SystemSwVersion version {}; + SceKernelSystemSwVersion version {}; version.size = sizeof(version); sceKernelGetSystemSwVersion_nid_postfix(&version); + return version.version; } @@ -211,7 +115,6 @@ int BcdPair(std::uint32_t value, int shift) { return static_cast((value >> (shift + 4)) & 0xF) * 10 + static_cast((value >> shift) & 0xF); } - constexpr int NP_ERROR_OUT_OF_MEMORY = static_cast(0x80550005); constexpr int NP_ERROR_NULL_OBJECT = static_cast(0x80558005); constexpr int NP_ERROR_HEAP_CREATE = static_cast(0x8055800A); @@ -273,6 +176,7 @@ int InitHeap(NpHeap* heap, void* base, std::size_t size, const char* name) { void DestroyHeap(NpHeap* heap) { if (heap->mspace == nullptr) return; sceLibcMspaceDestroy_nid_postfix(heap->mspace); + heap->mspace = nullptr; } @@ -343,6 +247,7 @@ int InitMutex(PthreadMutex* mutex, const char* name, std::uint32_t flags) { if ((flags & NP_MUTEX_FLAG_RECURSIVE) != 0) result = scePthreadMutexattrSettype(&attr, PTHREAD_MUTEX_TYPE_RECURSIVE); if (result >= 0) result = scePthreadMutexInit(mutex, &attr, name); scePthreadMutexattrDestroy(&attr); + return NpResult(result); } @@ -352,6 +257,7 @@ int InitCond(PthreadCond* cond, const char* name) { if (result < 0) return result; const int created = scePthreadCondInit(cond, &attr, name); scePthreadCondattrDestroy(&attr); + return created; } @@ -372,19 +278,6 @@ int APS5_VABI sceNpAtomicDec32(std::int32_t* value) { return std::atomic_ref(*value).fetch_sub(1); } - - - - - - - - - - - - - int APS5_VABI sceNpCondSignalAll(PthreadCond* cond) { return scePthreadCondBroadcast(cond); } @@ -397,7 +290,6 @@ int APS5_VABI sceNpCondWait(PthreadCond* cond, PthreadMutex* mutex) { return scePthreadCondWait(cond, mutex); } - int APS5_VABI sceNpLwCondInit(PthreadCond* cond, const char* name) { return InitCond(cond, name); } @@ -434,6 +326,10 @@ int APS5_VABI sceNpOpenEventFlag(KernelEventFlag* flag, const char* name) { return NpResult(sceKernelOpenEventFlag(flag, name)); } +int APS5_VABI sceNpCloseEventFlag(KernelEventFlag flag) { + return NpResult(sceKernelCloseEventFlag(flag)); +} + int APS5_VABI sceNpSetEventFlag(KernelEventFlag flag, std::uint64_t pattern) { return NpResult(sceKernelSetEventFlag(flag, pattern)); } @@ -474,6 +370,7 @@ int APS5_VABI sceNpCreateThread(Pthread* thread, PthreadEntry entry, void* arg, result = scePthreadAttrSetstacksize(&attr, stackSize); if (result < 0) { scePthreadAttrDestroy(&attr); + return result; } if (priority != 0) { @@ -488,10 +385,10 @@ int APS5_VABI sceNpCreateThread(Pthread* thread, PthreadEntry entry, void* arg, if (result >= 0 && affinity != 0) result = scePthreadAttrSetaffinity(&attr, affinity); if (result >= 0) result = scePthreadCreate(thread, &attr, entry, arg, name); scePthreadAttrDestroy(&attr); + return result; } - int APS5_VABI sceNpThreadGetId(Pthread* thread) { if (thread == nullptr) return NP_ERROR_INVALID_ARGUMENT; *thread = scePthreadSelf(); @@ -628,13 +525,11 @@ int APS5_VABI sceNpFreeKernelMemory(NpKernelMemory* memory) { return 0; } - void APS5_VABI sceNpGetSdkVersionUInt(std::uint32_t* version) { const std::uint32_t value = SystemVersion(); if (version != nullptr) *version = value; } - int APS5_VABI sceNpRtcConvertToPosixTime(const RtcTick* tick, std::int64_t* seconds) { if (tick->tick == 0) return NP_ERROR_INVALID_ARGUMENT; RtcDateTime time {}; @@ -672,28 +567,34 @@ int APS5_VABI sceNpRtcParseRFC3339(RtcTick* utc, const char* text) { static std::uint64_t ClockUsec() { std::int64_t usec = 0; sceNpGetSystemClockUsec(&usec); + return static_cast(usec); } static void* APS5_VABI CalloutThread(void* arg) { auto* context = static_cast(arg); sceNpMutexLock(&context->mutex); + for (;;) { const std::uint64_t now = ClockUsec(); NpCallout* head = context->pending; if (head != nullptr && head->deadline <= now) { context->pending = head->next; sceNpMutexUnlock(&context->mutex); + head->handler(head->arg); sceNpMutexLock(&context->mutex); + continue; } if (context->stopping > 0) break; const std::uint64_t wait = head != nullptr ? std::min(head->deadline - now, NP_CALLOUT_MAX_WAIT) : 0; sceNpCondTimedwait(&context->cond, &context->mutex, static_cast(wait)); + if (context->stopping > 0) break; } sceNpMutexUnlock(&context->mutex); + return nullptr; } @@ -712,20 +613,24 @@ int APS5_VABI sceNpCalloutInitCtx(NpCalloutContext* context, const char* name, s return 0; } sceNpCondDestroy(&context->cond); + } sceNpMutexDestroy(&context->mutex); + return result; } void APS5_VABI sceNpCalloutTermCtx(NpCalloutContext* context) { if (context->initialized == 0) return; sceNpMutexLock(&context->mutex); + context->stopping = 1; sceNpCondSignal(&context->cond); sceNpMutexUnlock(&context->mutex); sceNpJoinThread(context->thread, nullptr); sceNpCondDestroy(&context->cond); sceNpMutexDestroy(&context->mutex); + context->initialized = 0; } @@ -734,9 +639,11 @@ int APS5_VABI sceNpCalloutStartOnCtx64(NpCalloutContext* context, NpCallout* cal if (context->initialized == 0) return NP_ERROR_NOT_INITIALIZED; const std::uint64_t deadline = ClockUsec() + usec; sceNpMutexLock(&context->mutex); + for (NpCallout* entry = context->pending; entry != nullptr; entry = entry->next) { if (entry == callout) { sceNpMutexUnlock(&context->mutex); + return NP_ERROR_ALREADY_QUEUED; } } @@ -750,6 +657,7 @@ int APS5_VABI sceNpCalloutStartOnCtx64(NpCalloutContext* context, NpCallout* cal *link = callout; sceNpCondSignal(&context->cond); sceNpMutexUnlock(&context->mutex); + return 0; } @@ -761,6 +669,7 @@ int APS5_VABI sceNpCalloutStartOnCtx(NpCalloutContext* context, NpCallout* callo int APS5_VABI sceNpCalloutStopOnCtx(NpCalloutContext* context, NpCallout* callout, int* wasPending) { if (context->initialized == 0) return NP_ERROR_NOT_INITIALIZED; sceNpMutexLock(&context->mutex); + int removed = 0; for (NpCallout** link = &context->pending; *link != nullptr; link = &(*link)->next) { if (*link != callout) continue; @@ -770,6 +679,7 @@ int APS5_VABI sceNpCalloutStopOnCtx(NpCalloutContext* context, NpCallout* callou } if (wasPending != nullptr) *wasPending = removed; sceNpMutexUnlock(&context->mutex); + return 0; } @@ -778,7 +688,6 @@ std::uint32_t APS5_VABI sceNpGetRandom(void) { return static_cast(g_random()); } - int APS5_VABI sceNpUtilCmpAccountId(std::uint64_t left, std::uint64_t right) { return left != right ? 1 : 0; } @@ -799,7 +708,6 @@ bool APS5_VABI sceNpIntIsOnlineIdString(const char* text) { return text != nullptr && IsOnlineIdText(text); } - int APS5_VABI sceNpUtilGetNpLanguageCode(int language, char* code) { const NpLanguageCodes* codes = FindLanguageCodes(language); if (codes == nullptr || code == nullptr) return NP_ERROR_INVALID_ARGUMENT_UTIL; diff --git a/core/libs/prx/libSceNpCommon/Strings.cpp b/core/libs/prx/libSceNpCommon/Strings.cpp index ce17739d6f..08125a4c0f 100644 --- a/core/libs/prx/libSceNpCommon/Strings.cpp +++ b/core/libs/prx/libSceNpCommon/Strings.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNpCommon/include/Api.hpp" #include #include #include diff --git a/core/libs/prx/libSceNpCommon/include/Api.hpp b/core/libs/prx/libSceNpCommon/include/Api.hpp new file mode 100644 index 0000000000..d4c373e182 --- /dev/null +++ b/core/libs/prx/libSceNpCommon/include/Api.hpp @@ -0,0 +1,222 @@ +#pragma once + +#include "SceTypes.hpp" + +struct NpAllocator { + void* (APS5_VABI *allocate)(std::size_t size, void* context); + void* (APS5_VABI *reallocate)(void* pointer, std::size_t size, void* context); + void (APS5_VABI *release)(void* pointer, void* context); + void* context; +}; + +struct NpAllocatorEx { + NpAllocator allocator; + int outOfMemoryError; +}; + +struct NpCallout { + NpCallout* next; + void (APS5_VABI *handler)(void* arg); + std::uint64_t deadline; + void* arg; + std::uint64_t reserved; +}; + +struct NpCalloutContext { + Pthread thread; + PthreadMutex mutex; + PthreadCond cond; + int initialized; + int stopping; + NpCallout* pending; +}; + +struct NpHeap { + void* mspace; +}; + +struct NpHeapStat { + std::uint64_t maxSystemSize; + std::uint64_t maxInuseSize; + std::uint64_t currentInuseSize; +}; + +struct NpIdFull { + NpOnlineId handle; + std::uint8_t opt[8]; + std::uint8_t reserved[8]; +}; + +struct NpKernelMemory { + std::uint64_t size; + std::uint64_t reserved; + void* address; +}; + +struct NpMemoryHeap { + NpKernelMemory memory; + NpHeap heap; +}; + +struct NpTitleIdParts { + char id[9]; + char reserved; + std::uint8_t index; +}; + +extern "C" { + +int APS5_VABI sceNpCmpOnlineId(const NpOnlineId* onlineId1, const NpOnlineId* onlineId2); +int APS5_VABI sceNpCmpNpIdInOrder(const NpIdFull* npId1, const NpIdFull* npId2, std::int32_t* order); +int APS5_VABI sceNpGetPlatformType(const NpIdFull* npId); +int APS5_VABI sceNpIntIsValidOnlineId(const NpOnlineId* onlineId); +int APS5_VABI sceNpMutexInit(PthreadMutex* mutex, const char* name, std::uint64_t flags); +int APS5_VABI sceNpMutexDestroy(PthreadMutex* mutex); +int APS5_VABI sceNpMutexLock(PthreadMutex* mutex); +int APS5_VABI sceNpMutexTryLock(PthreadMutex* mutex); +int APS5_VABI sceNpMutexUnlock(PthreadMutex* mutex); +int APS5_VABI sceNpLwMutexInit(PthreadMutex* mutex, const char* name, std::uint64_t flags); +int APS5_VABI sceNpLwMutexDestroy(PthreadMutex* mutex); +int APS5_VABI sceNpLwMutexLock(PthreadMutex* mutex); +int APS5_VABI sceNpLwMutexTryLock(PthreadMutex* mutex); +int APS5_VABI sceNpLwMutexUnlock(PthreadMutex* mutex); +int APS5_VABI sceNpCondInit(PthreadCond* cond, const char* name, std::uint64_t); +int APS5_VABI sceNpCondDestroy(PthreadCond* cond); +int APS5_VABI sceNpCondSignal(PthreadCond* cond); +int APS5_VABI sceNpCondTimedwait(PthreadCond* cond, PthreadMutex* mutex, std::uint32_t usec); +int APS5_VABI sceNpJoinThread(Pthread thread, void** retval); +int APS5_VABI sceNpGetSystemClockUsec(std::int64_t* usec); +void APS5_VABI sceNpGetSdkVersion(char* version); +int APS5_VABI sceNpCloseSema(void); +int APS5_VABI sceNpGetNavSdkVersion(void); +int APS5_VABI sceNpIntGetPlatformType(void); +int APS5_VABI sceNpIntSetPlatformType(void); +int APS5_VABI sceNpJsonParse(void); +int APS5_VABI sceNpJsonParseBuf(void); +int APS5_VABI sceNpJsonParseBufInit(void); +int APS5_VABI sceNpJsonParseEx(void); +int APS5_VABI sceNpJsonParseExInit(void); +int APS5_VABI sceNpJsonParseInit(void); +int APS5_VABI sceNpOpenSema(void); +int APS5_VABI sceNpServerErrorJsonGetErrorCode(void); +int APS5_VABI sceNpServerErrorJsonMultiGetErrorCode(void); +int APS5_VABI sceNpServerErrorJsonParse(void); +int APS5_VABI sceNpServerErrorJsonParseInit(void); +int APS5_VABI sceNpServerErrorJsonParseMultiInit(void); +int APS5_VABI sceNpSetPlatformType(void); +int APS5_VABI sceNpUtilCanonicalizeNpIdForPs4(void); +int APS5_VABI sceNpUtilCanonicalizeNpIdForPsp2(void); +int APS5_VABI sceNpUtilGetDateSetAuto(void); +int APS5_VABI sceNpUtilGetDbgCommerce(void); +int APS5_VABI sceNpUtilGetEnv(void); +int APS5_VABI sceNpUtilGetFakeDisplayNameMode(void); +int APS5_VABI sceNpUtilGetFakeRateLimit(void); +int APS5_VABI sceNpUtilGetIgnoreNpTitleId(void); +int APS5_VABI sceNpUtilGetNpDebug(void); +int APS5_VABI sceNpUtilGetNpTestPatch(void); +int APS5_VABI sceNpUtilGetShareTitleCheck(void); +int APS5_VABI sceNpUtilGetSystemLanguage(void); +int APS5_VABI sceNpUtilGetTrcNotify(void); +int APS5_VABI sceNpUtilGetWebApi2FakeRateLimit(void); +int APS5_VABI sceNpUtilGetWebApi2FakeRateLimitTarget(void); +int APS5_VABI sceNpUtilGetWebTraceSetting(void); +int APS5_VABI sceNpUtilJidToNpId(void); +int APS5_VABI sceNpAtomicCas32(std::int32_t* value, std::int32_t expected, std::int32_t desired); +int APS5_VABI sceNpAtomicInc32(std::int32_t* value); +int APS5_VABI sceNpAtomicDec32(std::int32_t* value); +int APS5_VABI sceNpCondSignalAll(PthreadCond* cond); +int APS5_VABI sceNpCondSignalTo(PthreadCond* cond, Pthread thread); +int APS5_VABI sceNpCondWait(PthreadCond* cond, PthreadMutex* mutex); +int APS5_VABI sceNpLwCondInit(PthreadCond* cond, const char* name); +int APS5_VABI sceNpLwCondDestroy(PthreadCond* cond); +int APS5_VABI sceNpLwCondSignal(PthreadCond* cond); +int APS5_VABI sceNpLwCondSignalAll(PthreadCond* cond); +int APS5_VABI sceNpLwCondSignalTo(PthreadCond* cond, Pthread thread); +int APS5_VABI sceNpLwCondWait(PthreadCond* cond, PthreadMutex* mutex); +int APS5_VABI sceNpCreateEventFlag(KernelEventFlag* flag, const char* name, std::uint32_t attr, std::uint64_t pattern); +int APS5_VABI sceNpDeleteEventFlag(KernelEventFlag flag); +int APS5_VABI sceNpOpenEventFlag(KernelEventFlag* flag, const char* name); +int APS5_VABI sceNpCloseEventFlag(KernelEventFlag flag); +int APS5_VABI sceNpSetEventFlag(KernelEventFlag flag, std::uint64_t pattern); +int APS5_VABI sceNpClearEventFlag(KernelEventFlag flag, std::uint64_t pattern); +int APS5_VABI sceNpPollEventFlag(KernelEventFlag flag, std::uint64_t pattern, std::uint32_t mode, std::uint64_t* result); +int APS5_VABI sceNpCancelEventFlag(KernelEventFlag flag, std::uint64_t pattern, int* waiting); +int APS5_VABI sceNpCreateSema(KernelSema* sema, std::uint32_t flags, int initial, int maximum, const char* name); +int APS5_VABI sceNpDeleteSema(KernelSema sema); +int APS5_VABI sceNpPollSema(KernelSema sema); +int APS5_VABI sceNpSignalSema(KernelSema sema); +int APS5_VABI sceNpCreateThread(Pthread* thread, PthreadEntry entry, void* arg, int priority, std::size_t stackSize, KernelCpumask affinity, const char* name); +int APS5_VABI sceNpThreadGetId(Pthread* thread); +int APS5_VABI sceNpGetProcessId(void); +int APS5_VABI sceNpDbgDumpText(const char* text, int length); +int APS5_VABI sceNpIpc2ClientInit(void); +int APS5_VABI sceNpIpc2ClientTerm(void); +int APS5_VABI sceNpArchInit(void); +void APS5_VABI sceNpArchTerm(void); +int APS5_VABI sceNpHeapInit(NpHeap* heap, void* base, std::size_t size, const char* name); +void APS5_VABI sceNpHeapDestroy(NpHeap* heap); +void APS5_VABI sceNpHeapGetAllocator(NpHeap* heap, NpAllocator* allocator); +int APS5_VABI sceNpHeapGetStat(const NpHeap* heap, NpHeapStat* stat); +void APS5_VABI sceNpHeapShowStat(const NpHeap* heap); +int APS5_VABI sceNpMemoryHeapInit(NpMemoryHeap* heap, std::uint64_t size, const char* name); +void APS5_VABI sceNpMemoryHeapDestroy(NpMemoryHeap* heap); +void APS5_VABI sceNpMemoryHeapGetAllocator(NpMemoryHeap* heap, NpAllocator* allocator); +void APS5_VABI sceNpMemoryHeapGetAllocatorEx(NpMemoryHeap* heap, int outOfMemoryError, NpAllocatorEx* allocator); +void APS5_VABI sceNpGlobalHeapGetAllocator(NpAllocator* allocator); +void APS5_VABI sceNpGlobalHeapGetAllocatorEx(NpAllocatorEx* allocator); +NpAllocator* APS5_VABI sceNpGlobalHeapGetAllocatorPtr(void); +NpAllocatorEx* APS5_VABI sceNpGlobalHeapGetAllocatorExPtr(void); +int APS5_VABI sceNpAllocateKernelMemoryNoAlignment(std::uint64_t size, const char* name, void** address, NpKernelMemory* memory); +int APS5_VABI sceNpAllocateKernelMemoryWithAlignment(std::uint64_t size, const char* name, void** address, NpKernelMemory* memory); +int APS5_VABI sceNpFreeKernelMemory(NpKernelMemory* memory); +void APS5_VABI sceNpGetSdkVersionUInt(std::uint32_t* version); +int APS5_VABI sceNpRtcConvertToPosixTime(const RtcTick* tick, std::int64_t* seconds); +int APS5_VABI sceNpRtcFormatRFC3339(char* text, std::size_t size, const RtcTick* utc, int timeZoneMinutes); +int APS5_VABI sceNpUserGetUserIdList(int* users, std::size_t capacity, int* count); +int APS5_VABI sceNpRtcParseRFC3339(RtcTick* utc, const char* text); +int APS5_VABI sceNpCalloutInitCtx(NpCalloutContext* context, const char* name, std::size_t stackSize, int priority, KernelCpumask affinity); +void APS5_VABI sceNpCalloutTermCtx(NpCalloutContext* context); +int APS5_VABI sceNpCalloutStartOnCtx64(NpCalloutContext* context, NpCallout* callout, std::uint64_t usec, void (APS5_VABI *handler)(void* arg), void* arg); +int APS5_VABI sceNpCalloutStartOnCtx(NpCalloutContext* context, NpCallout* callout, std::uint32_t usec, void (APS5_VABI *handler)(void* arg), void* arg); +int APS5_VABI sceNpCalloutStopOnCtx(NpCalloutContext* context, NpCallout* callout, int* wasPending); +std::uint32_t APS5_VABI sceNpGetRandom(void); +int APS5_VABI sceNpUtilCmpAccountId(std::uint64_t left, std::uint64_t right); +int APS5_VABI sceNpCmpNpId(const void* npId1, const void* npId2); +bool APS5_VABI sceNpIntIsOnlineIdString(const char* text); +int APS5_VABI sceNpUtilGetNpLanguageCode(int language, char* code); +int APS5_VABI sceNpUtilGetNpLanguageCode2(int language, char* tag); +const char* APS5_VABI sceNpUtilGetNpLanguageCodeStr(int language); +const char* APS5_VABI sceNpUtilGetNpLanguageCode2Str(int language); +std::uint32_t APS5_VABI sceNpDbgAssignDebugId(void); +int APS5_VABI sceNpUtilBuildTitleId(const NpTitleIdParts* parts, char* titleId, std::size_t size); +void APS5_VABI sceNpDbgDumpBinary(const void* data, std::size_t size); +int APS5_VABI sceNpBase64GetDecodeSize(const char* src, std::size_t length); +int APS5_VABI sceNpBase64Decoder(const char* src, std::size_t length, void* dst, std::size_t capacity); +int APS5_VABI sceNpBase64Encoder(const void* src, char* dst, std::size_t length); +int APS5_VABI sceNpBase64UrlGetDecodeSize(const char* src, std::size_t length); +int APS5_VABI sceNpBase64UrlDecoder(const char* src, std::size_t length, void* dst, std::size_t capacity); +int APS5_VABI sceNpBase64UrlEncoder(const void* src, char* dst, std::size_t length); +int APS5_VABI sceNpHexToInt(int c); +int APS5_VABI sceNpIntToHex(std::uint32_t value, bool uppercase); +int APS5_VABI sceNpUInt32ToStr(char* buf, std::size_t size, std::uint32_t value, std::uint32_t radix, std::uint32_t flags, std::size_t* length); +int APS5_VABI sceNpUInt64ToStr(char* buf, std::size_t size, std::uint64_t value, std::uint32_t radix, std::uint32_t flags, std::size_t* length); +int APS5_VABI sceNpInt32ToStr(char* buf, std::size_t size, std::int32_t value, std::uint32_t radix, std::uint32_t flags, std::size_t* length); +int APS5_VABI sceNpInt64ToStr(char* buf, std::size_t size, std::int64_t value, std::uint32_t radix, std::uint32_t flags, std::size_t* length); +int APS5_VABI sceNpStrToInt32(const char* str, std::int32_t* value, int base, std::size_t* parsedLength); +int APS5_VABI sceNpStrToInt64(const char* str, std::int64_t* value, int base, std::size_t* parsedLength); +int APS5_VABI sceNpStrToUInt32(const char* str, std::uint32_t* value, int base, std::size_t* parsedLength); +int APS5_VABI sceNpStrToUInt64(const char* str, std::uint64_t* value, int base, std::size_t* parsedLength); +int APS5_VABI sceNpStrBuildHex(char* dst, std::size_t size, const void* src, std::size_t length, bool uppercase); +int APS5_VABI sceNpStrParseHex(const char* hex, void* out, std::size_t capacity); +int APS5_VABI sceNpStrnParseHex(const char* hex, std::size_t length, void* out, std::size_t capacity); +int APS5_VABI sceNpStrcpyToBuf(char* dst, std::size_t size, const char* src); +int APS5_VABI sceNpStrncpyToBuf(char* dst, std::size_t size, const char* src, std::size_t maxLength); +int APS5_VABI sceNpUtilJsonEscape(char* dst, std::size_t dstSize, const char* src, std::size_t srcLength); +int APS5_VABI sceNpUtilJsonUnescape(char* dst, std::size_t dstSize, const char* src, std::size_t srcLength, std::size_t* dstLength); +int APS5_VABI sceNpUtilJsonGetOneChar(char* dst, std::size_t dstSize, const char* src, std::size_t srcLength, std::size_t* dstLength, std::size_t* consumed); +int APS5_VABI sceNpUtilGetNthChar(std::size_t index, const char* text, const char** character); +int APS5_VABI sceNpUtilHttpUrlEncode(char* dst, std::size_t dstSize, const char* src, std::size_t srcLength, std::size_t* dstLength); + +[[noreturn]] void APS5_VABI sceNpPanic(void); + +} diff --git a/core/libs/prx/libSceNpCommon/libSceNpCommon.hpp b/core/libs/prx/libSceNpCommon/libSceNpCommon.hpp new file mode 100644 index 0000000000..baf8782fd4 --- /dev/null +++ b/core/libs/prx/libSceNpCommon/libSceNpCommon.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceNpCommon/include/Api.hpp" diff --git a/core/libs/prx/libSceNpCppWebApi/Export.cpp b/core/libs/prx/libSceNpCppWebApi/Export.cpp index 33bfb17ed2..6ab09331ae 100644 --- a/core/libs/prx/libSceNpCppWebApi/Export.cpp +++ b/core/libs/prx/libSceNpCppWebApi/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNpCppWebApi/include/Api.hpp" #include #include #include @@ -272,11 +273,6 @@ int APS5_VABI _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_12 return 0; } -struct IntrusivePtr { - void* object; - void (APS5_VABI* deleter)(void*); - void* libContext; -}; static_assert(sizeof(IntrusivePtr) == 0x18); static constexpr std::size_t ReferenceCountOffset = 0; @@ -463,12 +459,6 @@ int APS5_VABI _ZN3sce2Np9CppWebApi6Common21DownStreamTransactionINS2_12Intrusive return 0; } -struct CommonString { - std::int32_t referenceCount; - char* buffer; - std::uint64_t bufferSize; - void* libContext; -}; static_assert(sizeof(CommonString) == 0x20 && offsetof(CommonString, buffer) == 0x08); static_assert(offsetof(CommonString, bufferSize) == 0x10 && offsetof(CommonString, libContext) == 0x18); @@ -896,7 +886,6 @@ static int VectorPushBackString(IntrusivePtr* self, const CommonString* element) // libSceNpCppWebApi.prx. // -------------------------------------------------------------------------- - void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V115LocalizedStringEEC1ERS7_(IntrusivePtr* self, const IntrusivePtr* source) { CopyIntrusivePtr(self, source, 0x00); } diff --git a/core/libs/prx/libSceNpCppWebApi/include/Api.hpp b/core/libs/prx/libSceNpCppWebApi/include/Api.hpp new file mode 100644 index 0000000000..cdb32647a1 --- /dev/null +++ b/core/libs/prx/libSceNpCppWebApi/include/Api.hpp @@ -0,0 +1,684 @@ +#pragma once + +#include "SceTypes.hpp" + +struct CommonString { + std::int32_t referenceCount; + char* buffer; + std::uint64_t bufferSize; + void* libContext; +}; + +struct IntrusivePtr { + void* object; + void (APS5_VABI* deleter)(void*); + void* libContext; +}; + +extern "C" { + +int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V111UserFactory6createEPNS1_6Common10LibContextEPNS5_12IntrusivePtrINS3_4UserEEE(); +int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V121GetRankingRequestBody18setStartSerialRankERKi(); +int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V121GetRankingRequestBody8setGroupERKNS3_5GroupE(); +int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V121GetRankingRequestBody8setLimitERKi(); +int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V121GetRankingRequestBody8setUsersERKNS1_6Common6VectorINS5_12IntrusivePtrINS3_4UserEEEEE(); +int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V121GetRankingRequestBody9setOffsetERKi(); +void* APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V122GetRankingResponseBody10getEntriesEv(void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V122RecordScoreRequestBody10setCommentEPKc(); +int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V122RecordScoreRequestBody12setSmallDataEPKvm(); +int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V122RecordScoreRequestBody15setNeedsTmpRankERKb(); +int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V122RecordScoreRequestBody19setComparedDateTimeERK10SceRtcTick(); +int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V122RecordScoreRequestBody7setPcIdERKi(); +int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V128GetRankingRequestBodyFactory6createEPNS1_6Common10LibContextEPNS5_12IntrusivePtrINS3_21GetRankingRequestBodyEEE(); +int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V129RecordScoreRequestBodyFactory6createEPNS1_6Common10LibContextElPNS5_12IntrusivePtrINS3_22RecordScoreRequestBodyEEE(); +int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V14User12setAccountIdERKm(); +int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V14User7setPcIdERKi(); +int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V17ViewApi10getRankingEiRKNS4_21ParameterToGetRankingERNS1_6Common11TransactionINS8_12IntrusivePtrINS3_22GetRankingResponseBodyEEENSA_INS8_18ResponseHeaderBaseEEEEE(); +int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V17ViewApi21ParameterToGetRanking10initializeEPNS1_6Common10LibContextEi(); +int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V17ViewApi21ParameterToGetRanking24setgetRankingRequestBodyENS1_6Common12IntrusivePtrINS3_21GetRankingRequestBodyEEE(); +int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V17ViewApi21ParameterToGetRanking9terminateEv(); +int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V17ViewApi21ParameterToGetRankingC1Ev(void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V17ViewApi21ParameterToGetRankingD1Ev(void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V17ViewApi22getLargeDataByObjectIdEiRKNS4_33ParameterToGetLargeDataByObjectIdERNS1_6Common21DownStreamTransactionINS8_12IntrusivePtrINS4_37GetLargeDataByObjectIdResponseHeadersEEEEE(); +int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V17ViewApi33ParameterToGetLargeDataByObjectId10initializeEPNS1_6Common10LibContextEPKc(); +int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V17ViewApi33ParameterToGetLargeDataByObjectId9terminateEv(); +int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V17ViewApi33ParameterToGetLargeDataByObjectIdC1Ev(void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V17ViewApi33ParameterToGetLargeDataByObjectIdD1Ev(void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V19BoardsApi18getBoardDefinitionEiRKNS4_29ParameterToGetBoardDefinitionERNS1_6Common11TransactionINS8_12IntrusivePtrINS3_30GetBoardDefinitionResponseBodyEEENSA_INS8_18ResponseHeaderBaseEEEEE(); +int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V19BoardsApi29ParameterToGetBoardDefinition10initializeEPNS1_6Common10LibContextEi(); +int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V19BoardsApi29ParameterToGetBoardDefinition9terminateEv(); +int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V19BoardsApi29ParameterToGetBoardDefinitionC1Ev(void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V19BoardsApi29ParameterToGetBoardDefinitionD1Ev(void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V19RecordApi11recordScoreEiRKNS4_22ParameterToRecordScoreERNS1_6Common11TransactionINS8_12IntrusivePtrINS3_23RecordScoreResponseBodyEEENSA_INS4_26RecordScoreResponseHeadersEEEEE(); +int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V19RecordApi15recordLargeDataEiRKNS4_26ParameterToRecordLargeDataERNS1_6Common19UpStreamTransactionINS8_12IntrusivePtrINS3_27RecordLargeDataResponseBodyEEENSA_INS8_18ResponseHeaderBaseEEEEE(); +int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V19RecordApi22ParameterToRecordScore10initializeEPNS1_6Common10LibContextEiNS6_12IntrusivePtrINS3_22RecordScoreRequestBodyEEE(); +int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V19RecordApi22ParameterToRecordScore22setxPsnAtomicOperationENS5_19XPsnAtomicOperationE(); +int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V19RecordApi22ParameterToRecordScore9terminateEv(); +int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V19RecordApi22ParameterToRecordScoreC1Ev(void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V19RecordApi22ParameterToRecordScoreD1Ev(void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V19RecordApi26ParameterToRecordLargeData10initializeEPNS1_6Common10LibContextEiNS5_19XPsnAtomicOperationEPKc(); +int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V19RecordApi26ParameterToRecordLargeData9terminateEv(); +int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V19RecordApi26ParameterToRecordLargeDataC1Ev(void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V19RecordApi26ParameterToRecordLargeDataD1Ev(void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi17TitleCloudStorage2V17DataApi12downloadDataEiRKNS4_23ParameterToDownloadDataERNS1_6Common21DownStreamTransactionINS8_12IntrusivePtrINS4_27DownloadDataResponseHeadersEEEEE(); +int APS5_VABI _ZN3sce2Np9CppWebApi17TitleCloudStorage2V17DataApi23ParameterToDownloadData10initializeEPNS1_6Common10LibContextEPKci(); +int APS5_VABI _ZN3sce2Np9CppWebApi17TitleCloudStorage2V17DataApi23ParameterToDownloadData9terminateEv(); +int APS5_VABI _ZN3sce2Np9CppWebApi17TitleCloudStorage2V17DataApi23ParameterToDownloadDataC1Ev(void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi17TitleCloudStorage2V17DataApi23ParameterToDownloadDataD1Ev(void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common10InitParamsC1Ev(void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common10InitParamsD1Ev(void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common10LibContextC1Ev(uint64_t* self); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common10initializeERKNS2_10InitParamsERNS2_10LibContextE(const void* params, uint64_t* context); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_12Leaderboards2V122GetRankingResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEEC1Ev(void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_12Leaderboards2V122GetRankingResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEED1Ev(void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_12Leaderboards2V123RecordScoreResponseBodyEEENS4_INS6_9RecordApi26RecordScoreResponseHeadersEEEEC1Ev(void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_12Leaderboards2V123RecordScoreResponseBodyEEENS4_INS6_9RecordApi26RecordScoreResponseHeadersEEEED1Ev(void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_12Leaderboards2V130GetBoardDefinitionResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEEC1Ev(void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_12Leaderboards2V130GetBoardDefinitionResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEED1Ev(void* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V121GetRankingRequestBodyEEC1ERS7_(IntrusivePtr* self, const IntrusivePtr* source); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V121GetRankingRequestBodyEEC1Ev(IntrusivePtr* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V121GetRankingRequestBodyEED1Ev(IntrusivePtr* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V122GetRankingResponseBodyEEC1Ev(IntrusivePtr* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V122GetRankingResponseBodyEED1Ev(IntrusivePtr* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V122RecordScoreRequestBodyEEC1ERS7_(IntrusivePtr* self, const IntrusivePtr* source); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V122RecordScoreRequestBodyEEC1Ev(IntrusivePtr* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V122RecordScoreRequestBodyEED1Ev(IntrusivePtr* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V123RecordScoreResponseBodyEEC1Ev(IntrusivePtr* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V123RecordScoreResponseBodyEED1Ev(IntrusivePtr* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V130GetBoardDefinitionResponseBodyEEC1Ev(IntrusivePtr* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V130GetBoardDefinitionResponseBodyEED1Ev(IntrusivePtr* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V14UserEEC1Ev(IntrusivePtr* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V14UserEED1Ev(IntrusivePtr* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V19RecordApi26RecordScoreResponseHeadersEEC1Ev(IntrusivePtr* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V19RecordApi26RecordScoreResponseHeadersEED1Ev(IntrusivePtr* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS3_INS1_12Leaderboards2V15EntryEEEEEED1Ev(IntrusivePtr* self); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common13ConstIteratorINS2_12IntrusivePtrINS1_12Leaderboards2V15EntryEEEED2Ev(void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_12Leaderboards2V122GetRankingResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEE5startEPNS2_10LibContextE(); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_12Leaderboards2V122GetRankingResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEE6finishEv(); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_12Leaderboards2V123RecordScoreResponseBodyEEENS4_INS6_9RecordApi26RecordScoreResponseHeadersEEEE5startEPNS2_10LibContextE(); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_12Leaderboards2V123RecordScoreResponseBodyEEENS4_INS6_9RecordApi26RecordScoreResponseHeadersEEEE6finishEv(); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_12Leaderboards2V127RecordLargeDataResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEE6finishEv(); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_12Leaderboards2V130GetBoardDefinitionResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEE5startEPNS2_10LibContextE(); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_12Leaderboards2V130GetBoardDefinitionResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEE6finishEv(); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common19UpStreamTransactionINS2_12IntrusivePtrINS1_12Leaderboards2V127RecordLargeDataResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEE5startEPNS2_10LibContextEm(); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common19UpStreamTransactionINS2_12IntrusivePtrINS1_12Leaderboards2V127RecordLargeDataResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEE8sendDataEPKvm(); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common19UpStreamTransactionINS2_12IntrusivePtrINS1_12Leaderboards2V127RecordLargeDataResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEEC1Ev(void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common19UpStreamTransactionINS2_12IntrusivePtrINS1_12Leaderboards2V127RecordLargeDataResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEED1Ev(void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common21DownStreamTransactionINS2_12IntrusivePtrINS1_12Leaderboards2V17ViewApi37GetLargeDataByObjectIdResponseHeadersEEEE5startEPNS2_10LibContextE(); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common21DownStreamTransactionINS2_12IntrusivePtrINS1_12Leaderboards2V17ViewApi37GetLargeDataByObjectIdResponseHeadersEEEE6finishEv(); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common21DownStreamTransactionINS2_12IntrusivePtrINS1_12Leaderboards2V17ViewApi37GetLargeDataByObjectIdResponseHeadersEEEE8readDataEPcm(); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common21DownStreamTransactionINS2_12IntrusivePtrINS1_12Leaderboards2V17ViewApi37GetLargeDataByObjectIdResponseHeadersEEEEC1Ev(void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common21DownStreamTransactionINS2_12IntrusivePtrINS1_12Leaderboards2V17ViewApi37GetLargeDataByObjectIdResponseHeadersEEEED1Ev(void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common21DownStreamTransactionINS2_12IntrusivePtrINS1_17TitleCloudStorage2V17DataApi27DownloadDataResponseHeadersEEEE5startEPNS2_10LibContextE(); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common21DownStreamTransactionINS2_12IntrusivePtrINS1_17TitleCloudStorage2V17DataApi27DownloadDataResponseHeadersEEEE6finishEv(); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common21DownStreamTransactionINS2_12IntrusivePtrINS1_17TitleCloudStorage2V17DataApi27DownloadDataResponseHeadersEEEE8readDataEPcm(); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common21DownStreamTransactionINS2_12IntrusivePtrINS1_17TitleCloudStorage2V17DataApi27DownloadDataResponseHeadersEEEEC1Ev(void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common21DownStreamTransactionINS2_12IntrusivePtrINS1_17TitleCloudStorage2V17DataApi27DownloadDataResponseHeadersEEEED1Ev(void* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common6StringC1EPNS2_10LibContextE(CommonString* self, void* libContext); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common6StringD1Ev(CommonString* self); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_12Leaderboards2V14UserEEEE8pushBackERKS8_(); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_12Leaderboards2V14UserEEEEC1EPNS2_10LibContextE(void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_12Leaderboards2V14UserEEEED1Ev(void* self); +void* APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_12Leaderboards2V15EntryEEEE3endEv(void* self); +void* APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_12Leaderboards2V15EntryEEEE5beginEv(void* self); +void* APS5_VABI _ZN3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_12Leaderboards2V15EntryEEEEppEv(void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common9terminateERNS2_10LibContextE(uint64_t* context); +const void* APS5_VABI _ZNK3sce2Np9CppWebApi12Leaderboards2V122GetRankingResponseBody22getLastUpdatedDateTimeEv(const void* self); +int APS5_VABI _ZNK3sce2Np9CppWebApi12Leaderboards2V123RecordScoreResponseBody10getTmpRankEv(const void* self); +std::uint32_t APS5_VABI _ZNK3sce2Np9CppWebApi12Leaderboards2V123RecordScoreResponseBody16getTmpSerialRankEv(const void* self); +int APS5_VABI _ZNK3sce2Np9CppWebApi12Leaderboards2V130GetBoardDefinitionResponseBody11getSortModeEv(const void* self); +std::uint32_t APS5_VABI _ZNK3sce2Np9CppWebApi12Leaderboards2V130GetBoardDefinitionResponseBody13getEntryLimitEv(const void* self); +int APS5_VABI _ZNK3sce2Np9CppWebApi12Leaderboards2V130GetBoardDefinitionResponseBody13getUpdateModeEv(const void* self); +bool APS5_VABI _ZNK3sce2Np9CppWebApi12Leaderboards2V130GetBoardDefinitionResponseBody13sortModeIsSetEv(const void* self); +bool APS5_VABI _ZNK3sce2Np9CppWebApi12Leaderboards2V130GetBoardDefinitionResponseBody15entryLimitIsSetEv(const void* self); +bool APS5_VABI _ZNK3sce2Np9CppWebApi12Leaderboards2V130GetBoardDefinitionResponseBody15updateModeIsSetEv(const void* self); +std::int64_t APS5_VABI _ZNK3sce2Np9CppWebApi12Leaderboards2V130GetBoardDefinitionResponseBody16getMaxScoreLimitEv(const void* self); +std::int64_t APS5_VABI _ZNK3sce2Np9CppWebApi12Leaderboards2V130GetBoardDefinitionResponseBody16getMinScoreLimitEv(const void* self); +bool APS5_VABI _ZNK3sce2Np9CppWebApi12Leaderboards2V130GetBoardDefinitionResponseBody18maxScoreLimitIsSetEv(const void* self); +bool APS5_VABI _ZNK3sce2Np9CppWebApi12Leaderboards2V130GetBoardDefinitionResponseBody18minScoreLimitIsSetEv(const void* self); +std::uint32_t APS5_VABI _ZNK3sce2Np9CppWebApi12Leaderboards2V130GetBoardDefinitionResponseBody20getLargeDataNumLimitEv(const void* self); +std::size_t APS5_VABI _ZNK3sce2Np9CppWebApi12Leaderboards2V130GetBoardDefinitionResponseBody21getLargeDataSizeLimitEv(const void* self); +bool APS5_VABI _ZNK3sce2Np9CppWebApi12Leaderboards2V130GetBoardDefinitionResponseBody22largeDataNumLimitIsSetEv(const void* self); +bool APS5_VABI _ZNK3sce2Np9CppWebApi12Leaderboards2V130GetBoardDefinitionResponseBody23largeDataSizeLimitIsSetEv(const void* self); +const char* APS5_VABI _ZNK3sce2Np9CppWebApi12Leaderboards2V15Entry10getCommentEv(const void* self); +const char* APS5_VABI _ZNK3sce2Np9CppWebApi12Leaderboards2V15Entry11getObjectIdEv(const void* self); +const char* APS5_VABI _ZNK3sce2Np9CppWebApi12Leaderboards2V15Entry11getOnlineIdEv(const void* self); +bool APS5_VABI _ZNK3sce2Np9CppWebApi12Leaderboards2V15Entry12commentIsSetEv(const void* self); +std::uint64_t APS5_VABI _ZNK3sce2Np9CppWebApi12Leaderboards2V15Entry12getAccountIdEv(const void* self); +const void* APS5_VABI _ZNK3sce2Np9CppWebApi12Leaderboards2V15Entry12getSmallDataEv(const void* self); +std::uint32_t APS5_VABI _ZNK3sce2Np9CppWebApi12Leaderboards2V15Entry13getSerialRankEv(const void* self); +bool APS5_VABI _ZNK3sce2Np9CppWebApi12Leaderboards2V15Entry13objectIdIsSetEv(const void* self); +std::uint32_t APS5_VABI _ZNK3sce2Np9CppWebApi12Leaderboards2V15Entry14getHighestRankEv(const void* self); +bool APS5_VABI _ZNK3sce2Np9CppWebApi12Leaderboards2V15Entry14smallDataIsSetEv(const void* self); +std::uint32_t APS5_VABI _ZNK3sce2Np9CppWebApi12Leaderboards2V15Entry20getHighestSerialRankEv(const void* self); +int APS5_VABI _ZNK3sce2Np9CppWebApi12Leaderboards2V15Entry7getPcIdEv(const void* self); +std::uint32_t APS5_VABI _ZNK3sce2Np9CppWebApi12Leaderboards2V15Entry7getRankEv(const void* self); +std::int64_t APS5_VABI _ZNK3sce2Np9CppWebApi12Leaderboards2V15Entry8getScoreEv(const void* self); +const char* APS5_VABI _ZNK3sce2Np9CppWebApi12Leaderboards2V19RecordApi26RecordScoreResponseHeaders24getXPsnAtomicOperationIdEv(const void* self); +int APS5_VABI _ZNK3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_12Leaderboards2V122GetRankingResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEE11getResponseERS8_(); +int APS5_VABI _ZNK3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_12Leaderboards2V123RecordScoreResponseBodyEEENS4_INS6_9RecordApi26RecordScoreResponseHeadersEEEE11getResponseERS8_(); +int APS5_VABI _ZNK3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_12Leaderboards2V130GetBoardDefinitionResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEE11getResponseERS8_(); +void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V121GetRankingRequestBodyEEptEv(const IntrusivePtr* self); +void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V122GetRankingResponseBodyEEptEv(const IntrusivePtr* self); +void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V122RecordScoreRequestBodyEEptEv(const IntrusivePtr* self); +void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V123RecordScoreResponseBodyEEptEv(const IntrusivePtr* self); +void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V130GetBoardDefinitionResponseBodyEEptEv(const IntrusivePtr* self); +void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V14UserEEptEv(const IntrusivePtr* self); +void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V15EntryEEptEv(const IntrusivePtr* self); +void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V19RecordApi26RecordScoreResponseHeadersEEptEv(const IntrusivePtr* self); +void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6BinaryEEptEv(const IntrusivePtr* self); +void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS3_INS1_12Leaderboards2V15EntryEEEEEEdeEv(const IntrusivePtr* self); +int APS5_VABI _ZNK3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_12Leaderboards2V123RecordScoreResponseBodyEEENS4_INS6_9RecordApi26RecordScoreResponseHeadersEEEE18getResponseHeadersERSB_(); +std::size_t APS5_VABI _ZNK3sce2Np9CppWebApi6Common6Binary4sizeEv(const void* self); +const void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common6Binary9getBinaryEv(const void* self); +const char* APS5_VABI _ZNK3sce2Np9CppWebApi6Common6String5c_strEv(const CommonString* self); +void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_12Leaderboards2V15EntryEEEEdeEv(const void* self); +bool APS5_VABI _ZNK3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_12Leaderboards2V15EntryEEEEneERKS9_(const void* self, const void* other); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V115LocalizedStringEEC1ERS7_(IntrusivePtr* self, const IntrusivePtr* source); +void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V120RequestPlayerSessionEEptEv(const IntrusivePtr* self); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V120RequestPlayerSession16setMaxSpectatorsERKi(); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V139RequestPlayerSessionMemberPlayerFactory6createEPNS1_6Common10LibContextERKNS5_6VectorINS5_12IntrusivePtrINS3_32RequestCreatePlayerSessionPlayerEEEEEPNS9_INS3_32RequestPlayerSessionMemberPlayerEEE(); +void* APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_14SessionManager2V136UsersPlayerSessionsInvitationForReadEEEE3endEv(void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V117PlayerSessionsApi36ParameterToJoinPlayerSessionAsPlayerD1Ev(); +const char* APS5_VABI _ZNK3sce2Np9CppWebApi14SessionManager2V110FromMember11getOnlineIdEv(const void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V117PlayerSessionsApi38ParameterToGetPlayerSessionInvitations26setinvitationInvalidFilterEPKc(); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V120RequestPlayerSessionEEC1Ev(IntrusivePtr* self); +int APS5_VABI _ZNK3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_14SessionManager2V152PostPlayerSessionsSessionIdMemberPlayersResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEE11getResponseERS8_(); +void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V126RequestPlayerSessionPlayerEEptEv(const IntrusivePtr* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V151PostPlayerSessionsSessionIdMemberPlayersRequestBodyEEC1Ev(IntrusivePtr* self); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V117PlayerSessionsApi29ParameterToLeavePlayerSessionD1Ev(); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V122LocalizedStringFactory6createEPNS1_6Common10LibContextEPKcNS_4Json6ObjectEPNS5_12IntrusivePtrINS3_15LocalizedStringEEE(); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V151PostPlayerSessionsSessionIdMemberPlayersRequestBodyEED1Ev(IntrusivePtr* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_14SessionManager2V132RequestCreatePlayerSessionPlayerEEEED1Ev(IntrusivePtr* self); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common13ConstIteratorINS2_12IntrusivePtrINS1_14SessionManager2V136UsersPlayerSessionsInvitationForReadEEEED2Ev(void* self); +void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V113PlayerSessionEEptEv(const IntrusivePtr* self); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V120RequestPlayerSession20setInvitableUserTypeERKNS3_17InvitableUserTypeE(); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_14SessionManager2V132RequestCreatePlayerSessionPlayerEEEEC1EPNS2_10LibContextE(IntrusivePtr* self, void* libContext); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V132RequestCreatePlayerSessionPlayerEED1Ev(IntrusivePtr* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_6StringEEC1EPNS2_10LibContextE(IntrusivePtr* self, void* libContext); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_14SessionManager2V120RequestPlayerSessionEEEE8pushBackERKS8_(IntrusivePtr* self, const void* element); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V152PostPlayerSessionsSessionIdMemberPlayersResponseBodyEED1Ev(IntrusivePtr* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_6StringEED1Ev(IntrusivePtr* self); +void* APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_14SessionManager2V136UsersPlayerSessionsInvitationForReadEEEE5beginEv(void* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V129PostPlayerSessionsRequestBodyEEC1Ev(IntrusivePtr* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS3_INS1_14SessionManager2V136UsersPlayerSessionsInvitationForReadEEEEEED1Ev(IntrusivePtr* self); +void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS3_INS1_14SessionManager2V136UsersPlayerSessionsInvitationForReadEEEEEEdeEv(const IntrusivePtr* self); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common11TransactionINS2_15DefaultResponseENS2_12IntrusivePtrINS2_18ResponseHeaderBaseEEEEC1Ev(void* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V126RequestPlayerSessionPlayerEED1Ev(IntrusivePtr* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V115LocalizedStringEEC1Ev(IntrusivePtr* self); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_14SessionManager2V154GetUsersAccountIdPlayerSessionsInvitationsResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEEC1Ev(void* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V151PostPlayerSessionsSessionIdMemberPlayersRequestBodyEEC1ERS7_(IntrusivePtr* self, const IntrusivePtr* source); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V117PlayerSessionsApi25joinPlayerSessionAsPlayerEiRKNS4_36ParameterToJoinPlayerSessionAsPlayerERNS1_6Common11TransactionINS8_12IntrusivePtrINS3_52PostPlayerSessionsSessionIdMemberPlayersResponseBodyEEENSA_INS8_18ResponseHeaderBaseEEEEE(); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common6String6appendEPKc(CommonString* self, const char* text); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_14SessionManager2V132RequestCreatePlayerSessionPlayerEEEE8pushBackERKS8_(IntrusivePtr* self, const void* element); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common15DefaultResponseC1Ev(void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V117PlayerSessionsApi36ParameterToJoinPlayerSessionAsPlayer9terminateEv(); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V117PlayerSessionsApi31ParameterToCreatePlayerSessions10initializeEPNS1_6Common10LibContextENS6_12IntrusivePtrINS3_29PostPlayerSessionsRequestBodyEEE(); +void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V110FromMemberEEptEv(const IntrusivePtr* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V132RequestPlayerSessionMemberPlayerEED1Ev(IntrusivePtr* self); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_14SessionManager2V130PostPlayerSessionsResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEEC1Ev(void* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_14SessionManager2V126RequestPlayerSessionPlayerEEEED1Ev(IntrusivePtr* self); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V117PlayerSessionsApi29ParameterToLeavePlayerSessionC1Ev(); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V130PostPlayerSessionsResponseBodyEED1Ev(IntrusivePtr* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V126RequestPlayerSessionPlayerEEC1Ev(IntrusivePtr* self); +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); +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(); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V117PlayerSessionsApi31ParameterToCreatePlayerSessionsD1Ev(); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V117PlayerSessionsApi27getPlayerSessionInvitationsEiRKNS4_38ParameterToGetPlayerSessionInvitationsERNS1_6Common11TransactionINS8_12IntrusivePtrINS3_54GetUsersAccountIdPlayerSessionsInvitationsResponseBodyEEENSA_INS8_18ResponseHeaderBaseEEEEE(); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V132RequestPlayerSessionMemberPlayerEEC1Ev(IntrusivePtr* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V120RequestPlayerSessionEED1Ev(IntrusivePtr* self); +void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS3_INS1_14SessionManager2V113PlayerSessionEEEEEEdeEv(const IntrusivePtr* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V124PlayerSessionPushContextEEC1Ev(IntrusivePtr* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V130PostPlayerSessionsResponseBodyEEC1Ev(IntrusivePtr* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V110FromMemberEED1Ev(IntrusivePtr* self); +void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V154GetUsersAccountIdPlayerSessionsInvitationsResponseBodyEEptEv(const IntrusivePtr* self); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V117PlayerSessionsApi38ParameterToGetPlayerSessionInvitationsC1Ev(); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_14SessionManager2V126RequestPlayerSessionPlayerEEEE8pushBackERKS8_(IntrusivePtr* self, const void* element); +void* APS5_VABI _ZN3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_14SessionManager2V136UsersPlayerSessionsInvitationForReadEEEEppEv(void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_14SessionManager2V152PostPlayerSessionsSessionIdMemberPlayersResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEEC1Ev(void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V120RequestPlayerSession19setJoinableUserTypeERKNS3_16JoinableUserTypeE(); +int APS5_VABI _ZNK3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_14SessionManager2V154GetUsersAccountIdPlayerSessionsInvitationsResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEE11getResponseERS8_(); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V117PlayerSessionsApi38ParameterToGetPlayerSessionInvitationsD1Ev(); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS3_INS1_14SessionManager2V113PlayerSessionEEEEEED1Ev(IntrusivePtr* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V132RequestPlayerSessionMemberPlayerEEC1ERS7_(IntrusivePtr* self, const IntrusivePtr* source); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_14SessionManager2V130PostPlayerSessionsResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEE6finishEv(); +bool APS5_VABI _ZNK3sce2Np9CppWebApi14SessionManager2V136UsersPlayerSessionsInvitationForRead14sessionIdIsSetEv(const void* self); +bool APS5_VABI _ZNK3sce2Np9CppWebApi14SessionManager2V136UsersPlayerSessionsInvitationForRead17invitationIdIsSetEv(const void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_14SessionManager2V154GetUsersAccountIdPlayerSessionsInvitationsResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEE5startEPNS2_10LibContextE(); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V117PlayerSessionsApi31ParameterToCreatePlayerSessionsC1Ev(); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V117PlayerSessionsApi36ParameterToJoinPlayerSessionAsPlayer10initializeEPNS1_6Common10LibContextEPKcNS6_12IntrusivePtrINS3_51PostPlayerSessionsSessionIdMemberPlayersRequestBodyEEE(); +bool APS5_VABI _ZNK3sce2Np9CppWebApi14SessionManager2V154GetUsersAccountIdPlayerSessionsInvitationsResponseBody16invitationsIsSetEv(const void* self); +void* APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_14SessionManager2V113PlayerSessionEEEEixEm(void* self, std::uint64_t index); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V117PlayerSessionsApi29ParameterToLeavePlayerSession10initializeEPNS1_6Common10LibContextEPKcSA_(); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V115LocalizedStringEED1Ev(IntrusivePtr* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS2_6StringEEEEC1ERS7_(IntrusivePtr* self, const IntrusivePtr* source); +void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_14SessionManager2V136UsersPlayerSessionsInvitationForReadEEEEdeEv(const void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V117PlayerSessionsApi38ParameterToGetPlayerSessionInvitations9setfieldsENS1_6Common12IntrusivePtrINS6_6VectorINS6_6StringEEEEE(); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common15DefaultResponseD1Ev(void* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS2_6StringEEEEC1EPS6_PFvS8_EPNS2_10LibContextE(IntrusivePtr* self, void* body, void (APS5_VABI* deleter)(void*), void* libContext); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_14SessionManager2V120RequestPlayerSessionEEEEC1EPNS2_10LibContextE(IntrusivePtr* self, void* libContext); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V133RequestPlayerSessionPlayerFactory6createEPNS1_6Common10LibContextEPKcS9_PNS5_12IntrusivePtrINS3_26RequestPlayerSessionPlayerEEE(); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V117PlayerSessionsApi20createPlayerSessionsEiRKNS4_31ParameterToCreatePlayerSessionsERNS1_6Common11TransactionINS8_12IntrusivePtrINS3_30PostPlayerSessionsResponseBodyEEENSA_INS8_18ResponseHeaderBaseEEEEE(); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V117PlayerSessionsApi36ParameterToJoinPlayerSessionAsPlayerC1Ev(); +bool APS5_VABI _ZNK3sce2Np9CppWebApi14SessionManager2V136UsersPlayerSessionsInvitationForRead9fromIsSetEv(const void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V126RequestPlayerSessionPlayer15setPushContextsERKNS1_6Common6VectorINS5_12IntrusivePtrINS3_24PlayerSessionPushContextEEEEE(); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V127RequestPlayerSessionFactory6createEPNS1_6Common10LibContextEiNS5_12IntrusivePtrINS3_32RequestPlayerSessionMemberPlayerEEERKNS5_6VectorINS5_6StringEEENS8_INS3_15LocalizedStringEEEPNS8_INS3_20RequestPlayerSessionEEE(); +int APS5_VABI _ZNK3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_14SessionManager2V130PostPlayerSessionsResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEE11getResponseERS8_(); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_14SessionManager2V126RequestPlayerSessionPlayerEEEEC1EPNS2_10LibContextE(IntrusivePtr* self, void* libContext); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V124PlayerSessionPushContextEED1Ev(IntrusivePtr* self); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V131PlayerSessionPushContextFactory6createEPNS1_6Common10LibContextEPKcPNS5_12IntrusivePtrINS3_24PlayerSessionPushContextEEE(); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V129PostPlayerSessionsRequestBodyEED1Ev(IntrusivePtr* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V154GetUsersAccountIdPlayerSessionsInvitationsResponseBodyEEC1Ev(IntrusivePtr* self); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_6StringEE8pushBackERKS4_(IntrusivePtr* self, const void* element); +bool APS5_VABI _ZNK3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_14SessionManager2V136UsersPlayerSessionsInvitationForReadEEEEneERKS9_(const void* self, const void* other); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V117PlayerSessionsApi38ParameterToGetPlayerSessionInvitations10initializeEPNS1_6Common10LibContextEPKc(); +void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V130PostPlayerSessionsResponseBodyEEptEv(const IntrusivePtr* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V154GetUsersAccountIdPlayerSessionsInvitationsResponseBodyEED1Ev(IntrusivePtr* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS2_6StringEEEED1Ev(IntrusivePtr* self); +void* APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V154GetUsersAccountIdPlayerSessionsInvitationsResponseBody14getInvitationsEv(void* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V132RequestCreatePlayerSessionPlayerEEC1Ev(IntrusivePtr* self); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_14SessionManager2V152PostPlayerSessionsSessionIdMemberPlayersResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEE6finishEv(); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_15DefaultResponseENS2_12IntrusivePtrINS2_18ResponseHeaderBaseEEEE5startEPNS2_10LibContextE(); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_15DefaultResponseENS2_12IntrusivePtrINS2_18ResponseHeaderBaseEEEE6finishEv(); +bool APS5_VABI _ZNK3sce2Np9CppWebApi14SessionManager2V136UsersPlayerSessionsInvitationForRead22receivedTimestampIsSetEv(const void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_14SessionManager2V130PostPlayerSessionsResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEED1Ev(void* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_14SessionManager2V120RequestPlayerSessionEEEED1Ev(IntrusivePtr* self); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_14SessionManager2V154GetUsersAccountIdPlayerSessionsInvitationsResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEE6finishEv(); +int APS5_VABI _ZNK3sce2Np9CppWebApi6Common11TransactionINS2_15DefaultResponseENS2_12IntrusivePtrINS2_18ResponseHeaderBaseEEEE11getResponseERS4_(); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_14SessionManager2V154GetUsersAccountIdPlayerSessionsInvitationsResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEED1Ev(void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V139RequestCreatePlayerSessionPlayerFactory6createEPNS1_6Common10LibContextEPKcS9_RKNS5_6VectorINS5_12IntrusivePtrINS3_24PlayerSessionPushContextEEEEEPNSB_INS3_32RequestCreatePlayerSessionPlayerEEE(); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_14SessionManager2V152PostPlayerSessionsSessionIdMemberPlayersResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEED1Ev(void* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_14SessionManager2V124PlayerSessionPushContextEEEEC1EPNS2_10LibContextE(IntrusivePtr* self, void* libContext); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_14SessionManager2V124PlayerSessionPushContextEEEED1Ev(IntrusivePtr* self); +void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V136UsersPlayerSessionsInvitationForReadEEptEv(const IntrusivePtr* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V152PostPlayerSessionsSessionIdMemberPlayersResponseBodyEEC1Ev(IntrusivePtr* self); +const char* APS5_VABI _ZNK3sce2Np9CppWebApi14SessionManager2V113PlayerSession12getSessionIdEv(const void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V158PostPlayerSessionsSessionIdMemberPlayersRequestBodyFactory6createEPNS1_6Common10LibContextERKNS5_6VectorINS5_12IntrusivePtrINS3_26RequestPlayerSessionPlayerEEEEEPNS9_INS3_51PostPlayerSessionsSessionIdMemberPlayersRequestBodyEEE(); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V136PostPlayerSessionsRequestBodyFactory6createEPNS1_6Common10LibContextERKNS5_6VectorINS5_12IntrusivePtrINS3_20RequestPlayerSessionEEEEEPNS9_INS3_29PostPlayerSessionsRequestBodyEEE(); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_14SessionManager2V130PostPlayerSessionsResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEE5startEPNS2_10LibContextE(); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V120RequestPlayerSession28setExclusiveLeaderPrivilegesERKNS1_6Common6VectorINS5_6StringEEE(); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common11TransactionINS2_15DefaultResponseENS2_12IntrusivePtrINS2_18ResponseHeaderBaseEEEED1Ev(void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common13ConstIteratorINS2_12IntrusivePtrINS1_13InGameCatalog2V57ProductEEEED2Ev(void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common13ConstIteratorINS2_12IntrusivePtrINS1_17TitleCloudStorage2V110DataStatusEEEED2Ev(void* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS3_INS1_13InGameCatalog2V59ContainerEEEEEEC1Ev(IntrusivePtr* self); +void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS3_INS1_13InGameCatalog2V59ContainerEEEEEEdeEv(const IntrusivePtr* self); +void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS3_INS1_13InGameCatalog2V59ContainerEEEEEEptEv(const IntrusivePtr* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS3_INS1_13InGameCatalog2V59ContainerEEEEEED1Ev(IntrusivePtr* self); +void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS3_INS1_13InGameCatalog2V57ProductEEEEEEptEv(const IntrusivePtr* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS3_INS1_13InGameCatalog2V57ProductEEEEEED1Ev(IntrusivePtr* self); +void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS3_INS1_13InGameCatalog2V53SkuEEEEEEptEv(const IntrusivePtr* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS3_INS1_13InGameCatalog2V53SkuEEEEEED1Ev(IntrusivePtr* self); +void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS3_INS1_17TitleCloudStorage2V110DataStatusEEEEEEdeEv(const IntrusivePtr* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS3_INS1_17TitleCloudStorage2V110DataStatusEEEEEED1Ev(IntrusivePtr* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_13InGameCatalog2V59ContainerEEC1ERS7_(IntrusivePtr* self, const IntrusivePtr* source); +void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_13InGameCatalog2V59ContainerEEptEv(const IntrusivePtr* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_13InGameCatalog2V59ContainerEED1Ev(IntrusivePtr* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_13InGameCatalog2V57ProductEEC1ERS7_(IntrusivePtr* self, const IntrusivePtr* source); +void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_13InGameCatalog2V57ProductEEptEv(const IntrusivePtr* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_13InGameCatalog2V57ProductEED1Ev(IntrusivePtr* self); +void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_17TitleCloudStorage2V110DataStatusEEptEv(const IntrusivePtr* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_17TitleCloudStorage2V132GetMultiDataStatusesResponseBodyEEC1Ev(IntrusivePtr* self); +void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_17TitleCloudStorage2V132GetMultiDataStatusesResponseBodyEEptEv(const IntrusivePtr* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_17TitleCloudStorage2V132GetMultiDataStatusesResponseBodyEED1Ev(IntrusivePtr* self); +void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_17TitleCloudStorage2V15OwnerEEptEv(const IntrusivePtr* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_17TitleCloudStorage2V15OwnerEED1Ev(IntrusivePtr* self); +bool APS5_VABI _ZNK3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_13InGameCatalog2V57ProductEEEEneERKS9_(const void* self, const void* other); +void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_13InGameCatalog2V57ProductEEEEdeEv(const void* self); +void* APS5_VABI _ZN3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_13InGameCatalog2V57ProductEEEEppEv(void* self); +bool APS5_VABI _ZNK3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_17TitleCloudStorage2V110DataStatusEEEEneERKS9_(const void* self, const void* other); +void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_17TitleCloudStorage2V110DataStatusEEEEdeEv(const void* self); +void* APS5_VABI _ZN3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_17TitleCloudStorage2V110DataStatusEEEEppEv(void* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS2_6VectorINS4_INS1_13InGameCatalog2V59ContainerEEEEEEENS4_INS2_18ResponseHeaderBaseEEEEC1Ev(void* self); +int APS5_VABI _ZNK3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS2_6VectorINS4_INS1_13InGameCatalog2V59ContainerEEEEEEENS4_INS2_18ResponseHeaderBaseEEEE11getResponseERSB_(const void* self, void* response); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS2_6VectorINS4_INS1_13InGameCatalog2V59ContainerEEEEEEENS4_INS2_18ResponseHeaderBaseEEEED1Ev(void* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_17TitleCloudStorage2V132GetMultiDataStatusesResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEEC1Ev(void* self); +int APS5_VABI _ZNK3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_17TitleCloudStorage2V132GetMultiDataStatusesResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEE11getResponseERS8_(const void* self, void* response); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_17TitleCloudStorage2V132GetMultiDataStatusesResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEED1Ev(void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS2_6VectorINS4_INS1_13InGameCatalog2V59ContainerEEEEEEENS4_INS2_18ResponseHeaderBaseEEEE6finishEv(void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS2_6VectorINS4_INS1_13InGameCatalog2V59ContainerEEEEEEENS4_INS2_18ResponseHeaderBaseEEEE5startEPNS2_10LibContextE(void* self, void* context); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_17TitleCloudStorage2V132GetMultiDataStatusesResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEE6finishEv(void* self); +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); +std::size_t APS5_VABI _ZNK3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_13InGameCatalog2V53SkuEEEE4sizeEv(const void* self); +void* APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_17TitleCloudStorage2V110DataStatusEEEE5beginEv(void* self); +void* APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_17TitleCloudStorage2V110DataStatusEEEE3endEv(void* self); +void* APS5_VABI _ZN3sce2Np9CppWebApi13InGameCatalog2V59Container11getChildrenEv(void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi13InGameCatalog2V512ContainerApi23ParameterToGetContainerC1Ev(void); +int APS5_VABI _ZN3sce2Np9CppWebApi13InGameCatalog2V512ContainerApi23ParameterToGetContainer10initializeEPNS1_6Common10LibContextE(); +bool APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V512ContainerApi23ParameterToGetContainer13isInitializedEv(const void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi13InGameCatalog2V512ContainerApi23ParameterToGetContainer15setserviceLabelEi(void); +int APS5_VABI _ZN3sce2Np9CppWebApi13InGameCatalog2V512ContainerApi23ParameterToGetContainer9terminateEv(); +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); +bool APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V57Product9skusIsSetEv(const void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi17TitleCloudStorage2V17DataApi23ParameterToDownloadData11setobjectIdEPKc(void); +int APS5_VABI _ZN3sce2Np9CppWebApi17TitleCloudStorage2V17DataApi37ParameterToGetMultiDataStatusesByUserC1Ev(void); +int APS5_VABI _ZN3sce2Np9CppWebApi17TitleCloudStorage2V17DataApi37ParameterToGetMultiDataStatusesByUser10initializeEPNS1_6Common10LibContextEPKcSA_(void); +int APS5_VABI _ZN3sce2Np9CppWebApi17TitleCloudStorage2V17DataApi37ParameterToGetMultiDataStatusesByUser9setfieldsEPKc(void); +int APS5_VABI _ZN3sce2Np9CppWebApi17TitleCloudStorage2V17DataApi37ParameterToGetMultiDataStatusesByUser9terminateEv(void); +int APS5_VABI _ZN3sce2Np9CppWebApi17TitleCloudStorage2V17DataApi37ParameterToGetMultiDataStatusesByUserD1Ev(void); +int APS5_VABI _ZN3sce2Np9CppWebApi17TitleCloudStorage2V17DataApi26getMultiDataStatusesByUserEiRKNS4_37ParameterToGetMultiDataStatusesByUserERNS1_6Common11TransactionINS8_12IntrusivePtrINS3_32GetMultiDataStatusesResponseBodyEEENSA_INS8_18ResponseHeaderBaseEEEEE(void); +std::size_t APS5_VABI _ZNK3sce2Np9CppWebApi17TitleCloudStorage2V110DataStatus11getDataSizeEv(const void* self); +const char* APS5_VABI _ZNK3sce2Np9CppWebApi17TitleCloudStorage2V110DataStatus11getObjectIdEv(const void* self); +void* APS5_VABI _ZNK3sce2Np9CppWebApi17TitleCloudStorage2V110DataStatus8getOwnerEv(const void* self); +int APS5_VABI _ZNK3sce2Np9CppWebApi17TitleCloudStorage2V110DataStatus9getSlotIdEv(const void* self); +void* APS5_VABI _ZN3sce2Np9CppWebApi17TitleCloudStorage2V132GetMultiDataStatusesResponseBody17getDataStatusListEv(void* self); +std::uint32_t APS5_VABI _ZNK3sce2Np9CppWebApi17TitleCloudStorage2V132GetMultiDataStatusesResponseBody23getTotalDataStatusCountEv(const void* self); +std::uint64_t APS5_VABI _ZNK3sce2Np9CppWebApi17TitleCloudStorage2V15Owner12getAccountIdEv(const void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V110FriendsApi10getFriendsEiRKNS4_21ParameterToGetFriendsERNS1_6Common11TransactionINS8_12IntrusivePtrINS3_18GetFriendsResponseEEENSA_INS8_18ResponseHeaderBaseEEEEE(); +int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V110FriendsApi21ParameterToGetFriends10initializeEPNS1_6Common10LibContextEPKc(); +int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V110FriendsApi21ParameterToGetFriends9terminateEv(); +int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V110FriendsApi21ParameterToGetFriendsC1Ev(void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V110FriendsApi21ParameterToGetFriendsD1Ev(void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V111PresenceApi17getBasicPresencesEiRKNS4_28ParameterToGetBasicPresencesERNS1_6Common11TransactionINS8_12IntrusivePtrINS3_25GetBasicPresencesResponseEEENSA_INS8_18ResponseHeaderBaseEEEEE(); +int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V111PresenceApi28ParameterToGetBasicPresences10initializeEPNS1_6Common10LibContextEPKc(); +int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V111PresenceApi28ParameterToGetBasicPresences9terminateEv(); +int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V111PresenceApi28ParameterToGetBasicPresencesC1Ev(void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V111PresenceApi28ParameterToGetBasicPresencesD1Ev(void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V118GetFriendsResponse10getFriendsEv(); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V149PostPlayerSessionsSessionIdInvitationsRequestBody14setInvitationsERKNS1_6Common6VectorINS5_12IntrusivePtrINS3_30RequestPlayerSessionInvitationEEEEE(); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V117PlayerSessionsApi28sendPlayerSessionInvitationsEiRKNS4_39ParameterToSendPlayerSessionInvitationsERNS1_6Common11TransactionINS8_12IntrusivePtrINS3_50PostPlayerSessionsSessionIdInvitationsResponseBodyEEENSA_INS8_18ResponseHeaderBaseEEEEE(); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V117PlayerSessionsApi17getPlayerSessionsEiRKNS4_28ParameterToGetPlayerSessionsERNS1_6Common11TransactionINS8_12IntrusivePtrINS3_29GetPlayerSessionsResponseBodyEEENSA_INS8_18ResponseHeaderBaseEEEEE(); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V120RequestPlayerSession14setCustomData2EPKvm(); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V117PlayerSessionsApi49ParameterToAddPlayerSessionJoinableSpecifiedUsers10initializeEPNS1_6Common10LibContextEPKcNS6_12IntrusivePtrINS3_60PostPlayerSessionsSessionIdJoinableSpecifiedUsersRequestBodyEEE(); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V117PlayerSessionsApi37ParameterToSetPlayerSessionProperties10initializeEPNS1_6Common10LibContextEPKcNS6_12IntrusivePtrINS3_39PatchPlayerSessionsSessionIdRequestBodyEEE(); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V117PlayerSessionsApi36ParameterToChangePlayerSessionLeader9terminateEv(); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V117PlayerSessionsApi37ParameterToSetPlayerSessionPropertiesC1Ev(); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V117PlayerSessionsApi49ParameterToAddPlayerSessionJoinableSpecifiedUsers9terminateEv(); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V120RequestPlayerSession14setCustomData1EPKvm(); +int APS5_VABI _ZNK3sce2Np9CppWebApi14SessionManager2V120PlayerSessionForRead16customData2IsSetEv(); +int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V124GetBlockingUsersResponse9getBlocksEv(); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V117PlayerSessionsApi37ParameterToSetPlayerSessionPropertiesD1Ev(); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V117PlayerSessionsApi39ParameterToSendPlayerSessionInvitations10initializeEPNS1_6Common10LibContextEPKcNS6_12IntrusivePtrINS3_49PostPlayerSessionsSessionIdInvitationsRequestBodyEEE(); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V146PatchPlayerSessionsSessionIdRequestBodyFactory6createEPNS1_6Common10LibContextEPNS5_12IntrusivePtrINS3_39PatchPlayerSessionsSessionIdRequestBodyEEE(); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V137RequestPlayerSessionInvitationFactory6createEPNS1_6Common10LibContextENS5_12IntrusivePtrINS3_2ToEEEPNS8_INS3_30RequestPlayerSessionInvitationEEE(); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V139PatchPlayerSessionsSessionIdRequestBody19setJoinableUserTypeERKNS3_22CustomJoinableUserTypeE(); +int APS5_VABI _ZNK3sce2Np9CppWebApi14SessionManager2V127ResponsePlayerSessionPlayer11getPlatformEv(); +int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V125GetBasicPresencesResponse17getBasicPresencesEv(); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V117PlayerSessionsApi28ParameterToGetPlayerSessions9setfieldsENS1_6Common12IntrusivePtrINS6_6VectorINS6_6StringEEEEE(); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V117PlayerSessionsApi28ParameterToGetPlayerSessions9terminateEv(); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V117PlayerSessionsApi29ParameterToLeavePlayerSession9terminateEv(); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V117PlayerSessionsApi39ParameterToSendPlayerSessionInvitationsD1Ev(); +int APS5_VABI _ZNK3sce2Np9CppWebApi14SessionManager2V120PlayerSessionForRead14getCustomData1Ev(); +int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V19BlocksApi16getBlockingUsersEiRKNS4_27ParameterToGetBlockingUsersERNS1_6Common11TransactionINS8_12IntrusivePtrINS3_24GetBlockingUsersResponseEEENSA_INS8_18ResponseHeaderBaseEEEEE(); +int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V19BlocksApi27ParameterToGetBlockingUsers10initializeEPNS1_6Common10LibContextE(); +int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V19BlocksApi27ParameterToGetBlockingUsers9terminateEv(); +int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V19BlocksApi27ParameterToGetBlockingUsersC1Ev(void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V117PlayerSessionsApi31ParameterToCreatePlayerSessions9terminateEv(); +int APS5_VABI _ZNK3sce2Np9CppWebApi14SessionManager2V120PlayerSessionForRead16customData1IsSetEv(); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V117PlayerSessionsApi38addPlayerSessionJoinableSpecifiedUsersEiRKNS4_49ParameterToAddPlayerSessionJoinableSpecifiedUsersERNS1_6Common11TransactionINS8_12IntrusivePtrINS3_61PostPlayerSessionsSessionIdJoinableSpecifiedUsersResponseBodyEEENSA_INS8_18ResponseHeaderBaseEEEEE(); +int APS5_VABI _ZNK3sce2Np9CppWebApi14SessionManager2V120PlayerSessionForRead9getLeaderEv(); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V117PlayerSessionsApi39ParameterToSendPlayerSessionInvitationsC1Ev(); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V117PlayerSessionsApi28ParameterToGetPlayerSessionsD1Ev(); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V120PlayerSessionForRead28getExclusiveLeaderPrivilegesEv(); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V117PlayerSessionsApi26setPlayerSessionPropertiesEiRKNS4_37ParameterToSetPlayerSessionPropertiesERNS1_6Common11TransactionINS8_15DefaultResponseENS8_12IntrusivePtrINS8_18ResponseHeaderBaseEEEEE(); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V117PlayerSessionsApi25changePlayerSessionLeaderEiRKNS4_36ParameterToChangePlayerSessionLeaderERNS1_6Common11TransactionINS8_15DefaultResponseENS8_12IntrusivePtrINS8_18ResponseHeaderBaseEEEEE(); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V150PutPlayerSessionsSessionIdLeaderRequestBodyFactory6createEPNS1_6Common10LibContextERKNS_4Json5ValueEPNS5_12IntrusivePtrINS3_43PutPlayerSessionsSessionIdLeaderRequestBodyEEE(); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V119JoinableUserFactory6createEPNS1_6Common10LibContextERKmPNS5_12IntrusivePtrINS3_12JoinableUserEEE(); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V117PlayerSessionsApi36ParameterToChangePlayerSessionLeaderD1Ev(); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V156PostPlayerSessionsSessionIdInvitationsRequestBodyFactory6createEPNS1_6Common10LibContextEPNS5_12IntrusivePtrINS3_49PostPlayerSessionsSessionIdInvitationsRequestBodyEEE(); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V117PlayerSessionsApi39ParameterToSendPlayerSessionInvitations9terminateEv(); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V117PlayerSessionsApi28ParameterToGetPlayerSessions10initializeEPNS1_6Common10LibContextEPKc(); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V117PlayerSessionsApi28ParameterToGetPlayerSessionsC1Ev(); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V133ResponsePlayerSessionMemberPlayer10getPlayersEv(); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V139PatchPlayerSessionsSessionIdRequestBody28setExclusiveLeaderPrivilegesERKNS1_6Common6VectorINS5_6StringEEE(); +int APS5_VABI _ZNK3sce2Np9CppWebApi14SessionManager2V113PlayerSession9getMemberEv(); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V19ToFactory6createEPNS1_6Common10LibContextERKmPNS5_12IntrusivePtrINS3_2ToEEE(); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V117PlayerSessionsApi49ParameterToAddPlayerSessionJoinableSpecifiedUsersD1Ev(); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V117PlayerSessionsApi36ParameterToChangePlayerSessionLeader10initializeEPNS1_6Common10LibContextEPKcNS6_12IntrusivePtrINS3_43PutPlayerSessionsSessionIdLeaderRequestBodyEEE(); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V167PostPlayerSessionsSessionIdJoinableSpecifiedUsersRequestBodyFactory6createEPNS1_6Common10LibContextERKNS5_6VectorINS5_12IntrusivePtrINS3_12JoinableUserEEEEEPNS9_INS3_60PostPlayerSessionsSessionIdJoinableSpecifiedUsersRequestBodyEEE(); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V117PlayerSessionsApi36ParameterToChangePlayerSessionLeaderC1Ev(); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V117PlayerSessionsApi37ParameterToSetPlayerSessionProperties9terminateEv(); +int APS5_VABI _ZNK3sce2Np9CppWebApi14SessionManager2V118LeaderWithOnlineId12getAccountIdEv(); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V139PatchPlayerSessionsSessionIdRequestBody20setInvitableUserTypeERKNS3_23CustomInvitableUserTypeE(); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V129GetPlayerSessionsResponseBody17getPlayerSessionsEv(); +int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V117PlayerSessionsApi49ParameterToAddPlayerSessionJoinableSpecifiedUsersC1Ev(); +int APS5_VABI _ZNK3sce2Np9CppWebApi14SessionManager2V120PlayerSessionForRead14getCustomData2Ev(); +int APS5_VABI _ZNK3sce2Np9CppWebApi14SessionManager2V127ResponsePlayerSessionPlayer12getAccountIdEv(); +int APS5_VABI _ZNK3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_14SessionManager2V130PostPlayerSessionsResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEE11hasResponseEv(); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V112JoinableUserEED1Ev(IntrusivePtr* self); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_14SessionManager2V129GetPlayerSessionsResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEEC1Ev(void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V19BlocksApi27ParameterToGetBlockingUsersD1Ev(void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi15ProfanityFilter2V212ProfanityApi15filterProfanityEiRKNS4_26ParameterToFilterProfanityERNS1_6Common11TransactionINS8_12IntrusivePtrINS3_23FilterProfanityResponseEEENSA_INS8_18ResponseHeaderBaseEEEEE(); +int APS5_VABI _ZN3sce2Np9CppWebApi15ProfanityFilter2V212ProfanityApi26ParameterToFilterProfanity10initializeEPNS1_6Common10LibContextEPKcSA_NS6_12IntrusivePtrINS3_19WebApiFilterRequestEEE(); +int APS5_VABI _ZN3sce2Np9CppWebApi15ProfanityFilter2V212ProfanityApi26ParameterToFilterProfanity9terminateEv(); +int APS5_VABI _ZN3sce2Np9CppWebApi15ProfanityFilter2V212ProfanityApi26ParameterToFilterProfanityC1Ev(void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi15ProfanityFilter2V212ProfanityApi26ParameterToFilterProfanityD1Ev(void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi15ProfanityFilter2V226WebApiFilterRequestFactory6createEPNS1_6Common10LibContextEPKcPNS5_12IntrusivePtrINS3_19WebApiFilterRequestEEE(); +int APS5_VABI _ZN3sce2Np9CppWebApi30CommunicationRestrictionStatus2V333CommunicationRestrictionStatusApi33getCommunicationRestrictionStatusEiRKNS4_44ParameterToGetCommunicationRestrictionStatusERNS1_6Common11TransactionINS8_12IntrusivePtrINS3_38CommunicationRestrictionStatusResponseEEENSA_INS8_18ResponseHeaderBaseEEEEE(); +int APS5_VABI _ZN3sce2Np9CppWebApi30CommunicationRestrictionStatus2V333CommunicationRestrictionStatusApi44ParameterToGetCommunicationRestrictionStatus10initializeEPNS1_6Common10LibContextEm(); +int APS5_VABI _ZN3sce2Np9CppWebApi30CommunicationRestrictionStatus2V333CommunicationRestrictionStatusApi44ParameterToGetCommunicationRestrictionStatus9terminateEv(); +int APS5_VABI _ZN3sce2Np9CppWebApi30CommunicationRestrictionStatus2V333CommunicationRestrictionStatusApi44ParameterToGetCommunicationRestrictionStatusC1Ev(void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi30CommunicationRestrictionStatus2V333CommunicationRestrictionStatusApi44ParameterToGetCommunicationRestrictionStatusD1Ev(void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_11UserProfile2V118GetFriendsResponseEEENS4_INS2_18ResponseHeaderBaseEEEE21setOnFinishedCallbackEPFvliS8_PvEPFvliSC_ESC_(); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_11UserProfile2V118GetFriendsResponseEEENS4_INS2_18ResponseHeaderBaseEEEEC1Ev(void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_11UserProfile2V118GetFriendsResponseEEENS4_INS2_18ResponseHeaderBaseEEEED1Ev(void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_11UserProfile2V124GetBlockingUsersResponseEEENS4_INS2_18ResponseHeaderBaseEEEE21setOnFinishedCallbackEPFvliS8_PvEPFvliSC_ESC_(); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_11UserProfile2V124GetBlockingUsersResponseEEENS4_INS2_18ResponseHeaderBaseEEEEC1Ev(void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_11UserProfile2V124GetBlockingUsersResponseEEENS4_INS2_18ResponseHeaderBaseEEEED1Ev(void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_11UserProfile2V125GetBasicPresencesResponseEEENS4_INS2_18ResponseHeaderBaseEEEE21setOnFinishedCallbackEPFvliS8_PvEPFvliSC_ESC_(); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_11UserProfile2V125GetBasicPresencesResponseEEENS4_INS2_18ResponseHeaderBaseEEEEC1Ev(void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_11UserProfile2V125GetBasicPresencesResponseEEENS4_INS2_18ResponseHeaderBaseEEEED1Ev(void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_15ProfanityFilter2V223FilterProfanityResponseEEENS4_INS2_18ResponseHeaderBaseEEEE21setOnFinishedCallbackEPFvliS8_PvEPFvliSC_ESC_(); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_15ProfanityFilter2V223FilterProfanityResponseEEENS4_INS2_18ResponseHeaderBaseEEEEC1Ev(void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_15ProfanityFilter2V223FilterProfanityResponseEEENS4_INS2_18ResponseHeaderBaseEEEED1Ev(void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_30CommunicationRestrictionStatus2V338CommunicationRestrictionStatusResponseEEENS4_INS2_18ResponseHeaderBaseEEEE21setOnFinishedCallbackEPFvliS8_PvEPFvliSC_ESC_(); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_30CommunicationRestrictionStatus2V338CommunicationRestrictionStatusResponseEEENS4_INS2_18ResponseHeaderBaseEEEEC1Ev(void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_30CommunicationRestrictionStatus2V338CommunicationRestrictionStatusResponseEEENS4_INS2_18ResponseHeaderBaseEEEED1Ev(void* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_15ProfanityFilter2V219WebApiFilterRequestEEC1ERS7_(IntrusivePtr* self, const IntrusivePtr* source); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_15ProfanityFilter2V219WebApiFilterRequestEEC1Ev(IntrusivePtr* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_15ProfanityFilter2V219WebApiFilterRequestEED1Ev(IntrusivePtr* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS2_18ResponseHeaderBaseEEC1Ev(IntrusivePtr* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS2_18ResponseHeaderBaseEED1Ev(IntrusivePtr* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6StringEEC1Ev(IntrusivePtr* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6StringEED1Ev(IntrusivePtr* self); +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 _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V118LeaderWithOnlineIdEEptEv(const IntrusivePtr* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_14SessionManager2V112JoinableUserEEEED1Ev(IntrusivePtr* self); +int APS5_VABI _ZNK3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_14SessionManager2V129GetPlayerSessionsResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEE11hasResponseEv(); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V160PostPlayerSessionsSessionIdJoinableSpecifiedUsersRequestBodyEED1Ev(IntrusivePtr* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V143PutPlayerSessionsSessionIdLeaderRequestBodyEED1Ev(IntrusivePtr* self); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_14SessionManager2V129GetPlayerSessionsResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEED1Ev(void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common13ConstIteratorImED2Ev(void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_14SessionManager2V161PostPlayerSessionsSessionIdJoinableSpecifiedUsersResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEE6finishEv(); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS3_INS1_14SessionManager2V127ResponsePlayerSessionPlayerEEEEEED1Ev(IntrusivePtr* self); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_14SessionManager2V129GetPlayerSessionsResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEE5startEPNS2_10LibContextE(); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_14SessionManager2V129GetPlayerSessionsResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEE5abortEv(); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V149PostPlayerSessionsSessionIdInvitationsRequestBodyEEC1Ev(IntrusivePtr* self); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_14SessionManager2V129GetPlayerSessionsResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEE6finishEv(); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_14SessionManager2V112JoinableUserEEEE8pushBackERKS8_(IntrusivePtr* self, const void* element); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V149PostPlayerSessionsSessionIdInvitationsRequestBodyEEC1ERS7_(IntrusivePtr* self, const IntrusivePtr* source); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_14SessionManager2V150PostPlayerSessionsSessionIdInvitationsResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEE6finishEv(); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V113PlayerSessionEEaSERS7_(IntrusivePtr* self, const IntrusivePtr* source); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V12ToEEC1Ev(IntrusivePtr* self); +void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V129GetPlayerSessionsResponseBodyEEptEv(const IntrusivePtr* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V160PostPlayerSessionsSessionIdJoinableSpecifiedUsersRequestBodyEEC1ERS7_(IntrusivePtr* self, const IntrusivePtr* source); +void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS3_INS1_14SessionManager2V120PlayerSessionForReadEEEEEEptEv(const IntrusivePtr* self); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_14SessionManager2V161PostPlayerSessionsSessionIdJoinableSpecifiedUsersResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEEC1Ev(void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_11UserProfile2V118GetFriendsResponseEEENS4_INS2_18ResponseHeaderBaseEEEE28setResponseInformationOptionEP37SceNpWebApi2ResponseInformationOption(); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_11UserProfile2V118GetFriendsResponseEEENS4_INS2_18ResponseHeaderBaseEEEE5startEPNS2_10LibContextE(); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_11UserProfile2V118GetFriendsResponseEEENS4_INS2_18ResponseHeaderBaseEEEE6finishEv(); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_11UserProfile2V124GetBlockingUsersResponseEEENS4_INS2_18ResponseHeaderBaseEEEE28setResponseInformationOptionEP37SceNpWebApi2ResponseInformationOption(); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_11UserProfile2V124GetBlockingUsersResponseEEENS4_INS2_18ResponseHeaderBaseEEEE5startEPNS2_10LibContextE(); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_11UserProfile2V124GetBlockingUsersResponseEEENS4_INS2_18ResponseHeaderBaseEEEE6finishEv(); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_11UserProfile2V125GetBasicPresencesResponseEEENS4_INS2_18ResponseHeaderBaseEEEE28setResponseInformationOptionEP37SceNpWebApi2ResponseInformationOption(); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_11UserProfile2V125GetBasicPresencesResponseEEENS4_INS2_18ResponseHeaderBaseEEEE5startEPNS2_10LibContextE(); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_11UserProfile2V125GetBasicPresencesResponseEEENS4_INS2_18ResponseHeaderBaseEEEE6finishEv(); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_15ProfanityFilter2V223FilterProfanityResponseEEENS4_INS2_18ResponseHeaderBaseEEEE28setResponseInformationOptionEP37SceNpWebApi2ResponseInformationOption(); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_15ProfanityFilter2V223FilterProfanityResponseEEENS4_INS2_18ResponseHeaderBaseEEEE5startEPNS2_10LibContextE(); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_15ProfanityFilter2V223FilterProfanityResponseEEENS4_INS2_18ResponseHeaderBaseEEEE6finishEv(); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_30CommunicationRestrictionStatus2V338CommunicationRestrictionStatusResponseEEENS4_INS2_18ResponseHeaderBaseEEEE28setResponseInformationOptionEP37SceNpWebApi2ResponseInformationOption(); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_30CommunicationRestrictionStatus2V338CommunicationRestrictionStatusResponseEEENS4_INS2_18ResponseHeaderBaseEEEE5startEPNS2_10LibContextE(); +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(); +int APS5_VABI _ZNK3sce2Np9CppWebApi15ProfanityFilter2V223FilterProfanityResponse10getMessageEv(); +int APS5_VABI _ZNK3sce2Np9CppWebApi30CommunicationRestrictionStatus2V338CommunicationRestrictionStatusResponse13getRestrictedEv(); +void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_11UserProfile2V113BasicPresenceEEptEv(const IntrusivePtr* self); +void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_11UserProfile2V118GetFriendsResponseEEptEv(const IntrusivePtr* self); +void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_11UserProfile2V124GetBlockingUsersResponseEEptEv(const IntrusivePtr* self); +void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_11UserProfile2V125GetBasicPresencesResponseEEptEv(const IntrusivePtr* self); +void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_15ProfanityFilter2V223FilterProfanityResponseEEptEv(const IntrusivePtr* self); +void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_30CommunicationRestrictionStatus2V338CommunicationRestrictionStatusResponseEEptEv(const IntrusivePtr* self); +void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS2_18ResponseHeaderBaseEE3getEv(const IntrusivePtr* self); +void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS2_18ResponseHeaderBaseEEptEv(const IntrusivePtr* self); +void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6StringEE3getEv(const IntrusivePtr* self); +void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6StringEEptEv(const IntrusivePtr* self); +void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS3_INS1_11UserProfile2V113BasicPresenceEEEEEEdeEv(const IntrusivePtr* self); +void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS3_INS1_11UserProfile2V113BasicPresenceEEEEEEptEv(const IntrusivePtr* self); +void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorImEEEdeEv(const IntrusivePtr* self); +void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorImEEEptEv(const IntrusivePtr* self); +int APS5_VABI _ZNK3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_11UserProfile2V118GetFriendsResponseEEENS4_INS2_18ResponseHeaderBaseEEEE18getResponseHeadersERSA_(); +int APS5_VABI _ZNK3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_11UserProfile2V124GetBlockingUsersResponseEEENS4_INS2_18ResponseHeaderBaseEEEE18getResponseHeadersERSA_(); +int APS5_VABI _ZNK3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_11UserProfile2V125GetBasicPresencesResponseEEENS4_INS2_18ResponseHeaderBaseEEEE18getResponseHeadersERSA_(); +int APS5_VABI _ZNK3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_15ProfanityFilter2V223FilterProfanityResponseEEENS4_INS2_18ResponseHeaderBaseEEEE18getResponseHeadersERSA_(); +int APS5_VABI _ZNK3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_30CommunicationRestrictionStatus2V338CommunicationRestrictionStatusResponseEEENS4_INS2_18ResponseHeaderBaseEEEE18getResponseHeadersERSA_(); +int APS5_VABI _ZNK3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_11UserProfile2V113BasicPresenceEEEE4sizeEv(); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V129GetPlayerSessionsResponseBodyEED1Ev(IntrusivePtr* self); +int APS5_VABI _ZNK3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_14SessionManager2V120PlayerSessionForReadEEEE5emptyEv(const IntrusivePtr* 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); +void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V127ResponsePlayerSessionPlayerEEptEv(const IntrusivePtr* self); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_14SessionManager2V150PostPlayerSessionsSessionIdInvitationsResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEEC1Ev(void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_14SessionManager2V150PostPlayerSessionsSessionIdInvitationsResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEE5startEPNS2_10LibContextE(); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V139PatchPlayerSessionsSessionIdRequestBodyEED1Ev(IntrusivePtr* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS3_INS1_14SessionManager2V113PlayerSessionEEEEEEaSERKSA_(IntrusivePtr* self, const IntrusivePtr* source); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V12ToEEC1ERS7_(IntrusivePtr* self, const IntrusivePtr* source); +void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS3_INS1_14SessionManager2V113PlayerSessionEEEEEE3getEv(const IntrusivePtr* self); +void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V149PostPlayerSessionsSessionIdInvitationsRequestBodyEEptEv(const IntrusivePtr* self); +void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS3_INS1_14SessionManager2V127ResponsePlayerSessionPlayerEEEEEE3getEv(const IntrusivePtr* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_14SessionManager2V112JoinableUserEEEEC1EPNS2_10LibContextE(IntrusivePtr* self, void* libContext); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V130RequestPlayerSessionInvitationEED1Ev(IntrusivePtr* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_14SessionManager2V127ResponsePlayerSessionPlayerEEEEC1EPNS2_10LibContextE(IntrusivePtr* self, void* libContext); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V129GetPlayerSessionsResponseBodyEEC1Ev(IntrusivePtr* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V160PostPlayerSessionsSessionIdJoinableSpecifiedUsersRequestBodyEEC1Ev(IntrusivePtr* self); +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(); +int APS5_VABI _ZNK3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_14SessionManager2V129GetPlayerSessionsResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEE5getIdEv(); +int APS5_VABI _ZNK3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_11UserProfile2V113BasicPresenceEEEEdeEv(); +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); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common13ConstIteratorINS2_12IntrusivePtrINS1_14SessionManager2V120PlayerSessionForReadEEEED2Ev(void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_14SessionManager2V150PostPlayerSessionsSessionIdInvitationsResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEED1Ev(void* self); +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_(); +void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V139PatchPlayerSessionsSessionIdRequestBodyEEptEv(const IntrusivePtr* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V113PlayerSessionEED1Ev(IntrusivePtr* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V139PatchPlayerSessionsSessionIdRequestBodyEEC1Ev(IntrusivePtr* self); +void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V113PlayerSessionEE3getEv(const IntrusivePtr* self); +int APS5_VABI _ZNK3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_14SessionManager2V161PostPlayerSessionsSessionIdJoinableSpecifiedUsersResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEE11hasResponseEv(); +int APS5_VABI _ZNK3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_14SessionManager2V150PostPlayerSessionsSessionIdInvitationsResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEE11hasResponseEv(); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V133ResponsePlayerSessionMemberPlayerEED1Ev(IntrusivePtr* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V130RequestPlayerSessionInvitationEEC1Ev(IntrusivePtr* self); +void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V133ResponsePlayerSessionMemberPlayerEEptEv(const IntrusivePtr* self); +int APS5_VABI _ZNK3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_14SessionManager2V129GetPlayerSessionsResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEE11getResponseERS8_(); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V113PlayerSessionEEC1Ev(IntrusivePtr* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_14SessionManager2V130RequestPlayerSessionInvitationEEEEC1EPNS2_10LibContextE(IntrusivePtr* self, void* libContext); +int APS5_VABI _ZNK3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_14SessionManager2V161PostPlayerSessionsSessionIdJoinableSpecifiedUsersResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEE5getIdEv(); +int APS5_VABI _ZNK3sce2Np9CppWebApi6Common8IteratorImEdeEv(); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V118LeaderWithOnlineIdEED1Ev(IntrusivePtr* self); +int APS5_VABI _ZNK3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_14SessionManager2V130PostPlayerSessionsResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEE5getIdEv(); +int APS5_VABI _ZNK3sce2Np9CppWebApi6Common8IteratorImEneERKS4_(); +std::uint64_t APS5_VABI _ZNK3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_14SessionManager2V127ResponsePlayerSessionPlayerEEEE4sizeEv(const IntrusivePtr* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS3_INS1_14SessionManager2V120PlayerSessionForReadEEEEEED1Ev(IntrusivePtr* self); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_14SessionManager2V120PlayerSessionForReadEEEE5beginEv(); +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(); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V149PostPlayerSessionsSessionIdInvitationsRequestBodyEED1Ev(IntrusivePtr* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_14SessionManager2V130RequestPlayerSessionInvitationEEEED1Ev(IntrusivePtr* self); +void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V120PlayerSessionForReadEEptEv(const IntrusivePtr* self); +int APS5_VABI _ZNK3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_14SessionManager2V152PostPlayerSessionsSessionIdMemberPlayersResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEE5getIdEv(); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_14SessionManager2V127ResponsePlayerSessionPlayerEEEE8copyFromERKS9_(); +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(); +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(); +int APS5_VABI _ZN3sce2Np9CppWebApi13InGameCatalog2V512ContainerApi23ParameterToGetContainer9setoffsetEi(); +int APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V57Product16releaseDateIsSetEv(); +int APS5_VABI _ZN3sce2Np9CppWebApi13InGameCatalog2V512ContainerApi23ParameterToGetContainer15setcontainerIdsEPKc(); +int APS5_VABI _ZN3sce2Np9CppWebApi13InGameCatalog2V512ContainerApi23ParameterToGetContainer8setlimitEi(); +int APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V53Sku17displayPriceIsSetEv(); +int APS5_VABI _ZNK3sce2Np9CppWebApi13InGameCatalog2V57Product5getIdEv(); +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 _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 _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 _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS3_INS1_13InGameCatalog2V53SkuEEEEEEdeEv(const IntrusivePtr* self); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_13InGameCatalog2V53SkuEEEEppEv(); +int APS5_VABI _ZNK3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_13InGameCatalog2V59ContainerEEEE5emptyEv(const IntrusivePtr* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS3_INS1_13InGameCatalog2V59ContainerEEEEEEaSERKSA_(IntrusivePtr* self, const IntrusivePtr* source); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common8IteratorINS2_6StringEEppEv(); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorImEEEC1Ev(IntrusivePtr* self); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorImEEED1Ev(IntrusivePtr* self); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common13ConstIteratorINS2_6StringEED2Ev(void* self); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_6StringEE8copyFromERKS5_(); +void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorImEEE3getEv(const IntrusivePtr* self); +int APS5_VABI _ZNK3sce2Np9CppWebApi6Common8IteratorINS2_6StringEEneERKS5_(); +int APS5_VABI _ZNK3sce2Np9CppWebApi6Common11TransactionINS2_15DefaultResponseENS2_12IntrusivePtrINS2_18ResponseHeaderBaseEEEE11hasResponseEv(); +void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS2_6StringEEEEptEv(const IntrusivePtr* self); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_6StringEE3endEv(); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common6StringeqEPKc(const CommonString* self, const char* other); +int APS5_VABI _ZNK3sce2Np9CppWebApi6Common15TransactionBaseINS2_15DefaultResponseENS2_12IntrusivePtrINS2_18ResponseHeaderBaseEEEE5getIdEv(); +void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorImEEEaSERS6_(IntrusivePtr* self, const IntrusivePtr* source); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_15DefaultResponseENS2_12IntrusivePtrINS2_18ResponseHeaderBaseEEEE5abortEv(); +int APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_6StringEE5beginEv(); +int APS5_VABI _ZNK3sce2Np9CppWebApi6Common6String5emptyEv(const CommonString* self); +void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS2_6StringEEEE3getEv(const IntrusivePtr* self); +int APS5_VABI _ZNK3sce2Np9CppWebApi6Common8IteratorINS2_6StringEEdeEv(); + +} diff --git a/core/libs/prx/libSceNpCppWebApi/libSceNpCppWebApi.hpp b/core/libs/prx/libSceNpCppWebApi/libSceNpCppWebApi.hpp new file mode 100644 index 0000000000..450f928feb --- /dev/null +++ b/core/libs/prx/libSceNpCppWebApi/libSceNpCppWebApi.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceNpCppWebApi/include/Api.hpp" diff --git a/core/libs/prx/libSceNpEntitlementAccess/Export.cpp b/core/libs/prx/libSceNpEntitlementAccess/Export.cpp index 683dde7c84..e0593d4afb 100644 --- a/core/libs/prx/libSceNpEntitlementAccess/Export.cpp +++ b/core/libs/prx/libSceNpEntitlementAccess/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNpEntitlementAccess/include/Api.hpp" #include #include #include "SceTypes.hpp" @@ -145,12 +146,10 @@ int APS5_VABI sceNpEntitlementAccessRequestConsumeUnifiedEntitlement(std::int32_ return SCE_NP_ERROR_SIGNED_OUT; } - int APS5_VABI sceNpEntitlementAccessRequestConsumeServiceEntitlement(std::int32_t userId, std::uint32_t serviceLabel, const NpServiceEntitlementLabel* entitlementLabel, const NpEntitlementAccessTransactionId* transactionId, std::int32_t count, std::int64_t* requestId) { return SCE_NP_ERROR_SIGNED_OUT; } - int APS5_VABI sceNpEntitlementAccessPollServiceEntitlementInfo(std::int64_t requestId, std::int32_t* result, NpEntitlementAccessServiceInfo* info) { return SCE_NP_ERROR_SIGNED_OUT; } diff --git a/core/libs/prx/libSceNpEntitlementAccess/include/Api.hpp b/core/libs/prx/libSceNpEntitlementAccess/include/Api.hpp new file mode 100644 index 0000000000..d68d483b87 --- /dev/null +++ b/core/libs/prx/libSceNpEntitlementAccess/include/Api.hpp @@ -0,0 +1,33 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceNpEntitlementAccessGetAddcontEntitlementInfo(uint32_t serviceLabel, const NpUnifiedEntitlementLabel* entitlementLabel, NpEntitlementAccessAddcontEntitlementInfo* info); +int APS5_VABI sceNpEntitlementAccessGetAddcontEntitlementInfoList(uint32_t serviceLabel, NpEntitlementAccessAddcontEntitlementInfo* list, uint32_t listNum, uint32_t* hitNum); +int APS5_VABI sceNpEntitlementAccessGetSkuFlag(uint32_t* skuFlag); +int APS5_VABI sceNpEntitlementAccessGetEntitlementKey( uint32_t serviceLabel, const NpUnifiedEntitlementLabel* entitlementLabel, NpEntitlementAccessEntitlementKey* key); +int APS5_VABI sceNpEntitlementAccessInitialize(const NpEntitlementAccessInitParam* initParam, NpEntitlementAccessBootParam* bootParam); +int APS5_VABI sceNpEntitlementAccessAbortRequest(std::int64_t requestId); +int APS5_VABI sceNpEntitlementAccessDeleteRequest(std::int64_t requestId); +int APS5_VABI sceNpEntitlementAccessGenerateTransactionId(NpEntitlementAccessTransactionId* transactionId); +int APS5_VABI sceNpEntitlementAccessPollConsumeEntitlement(std::int64_t requestId, std::int32_t* result, std::int32_t* countResult); +int APS5_VABI sceNpEntitlementAccessRequestConsumeUnifiedEntitlement(std::int32_t userId, std::uint32_t serviceLabel, const NpUnifiedEntitlementLabel* entitlementLabel, const NpEntitlementAccessTransactionId* transactionId, std::int32_t count, std::int64_t* requestId); +int APS5_VABI sceNpEntitlementAccessRequestConsumeServiceEntitlement(std::int32_t userId, std::uint32_t serviceLabel, const NpServiceEntitlementLabel* entitlementLabel, const NpEntitlementAccessTransactionId* transactionId, std::int32_t count, std::int64_t* requestId); +int APS5_VABI sceNpEntitlementAccessPollServiceEntitlementInfo(std::int64_t requestId, std::int32_t* result, NpEntitlementAccessServiceInfo* info); +int APS5_VABI sceNpEntitlementAccessPollUnifiedEntitlementInfo(std::int64_t requestId, std::int32_t* result, NpEntitlementAccessUnifiedInfo* info); +int APS5_VABI sceNpEntitlementAccessRequestServiceEntitlementInfo(std::int32_t userId, std::uint32_t serviceLabel, const NpServiceEntitlementLabel* entitlementLabel, std::int64_t* requestId); +int APS5_VABI sceNpEntitlementAccessRequestUnifiedEntitlementInfo(std::int32_t userId, std::uint32_t serviceLabel, const NpUnifiedEntitlementLabel* entitlementLabel, std::int64_t* requestId); +int APS5_VABI sceNpEntitlementAccessGetPftFlag(uint32_t* flag); +int APS5_VABI sceNpEntitlementAccessGetGameTrialsFlag(uint32_t* flag); +int APS5_VABI sceNpEntitlementAccessPollServiceEntitlementInfoList(std::int64_t requestId, std::int32_t* result, NpEntitlementAccessServiceInfo* infos, std::uint32_t capacity, std::int32_t* firstResult, std::int32_t* secondResult, std::int32_t* thirdResult); +int APS5_VABI sceNpEntitlementAccessPollUnifiedEntitlementInfoList(std::int64_t requestId, std::int32_t* result, NpEntitlementAccessUnifiedInfo* infos, std::uint32_t capacity, std::int32_t* firstResult, std::int32_t* secondResult, std::int32_t* thirdResult); +int APS5_VABI sceNpEntitlementAccessRequestServiceEntitlementInfoList(std::int32_t userId, std::uint32_t serviceLabel, const NpServiceEntitlementLabel* entitlementLabels, std::uint32_t labelCount, const NpEntitlementAccessListParameter* parameter, std::int64_t* requestId); +int APS5_VABI sceNpEntitlementAccessRequestUnifiedEntitlementInfoList(std::int32_t userId, std::uint32_t serviceLabel, const NpUnifiedEntitlementLabel* entitlementLabels, std::uint32_t labelCount, const NpEntitlementAccessListParameter* parameter, std::int64_t* requestId); +int APS5_VABI sceNpEntitlementAccessGetAddcontEntitlementInfoIndividual(); +int APS5_VABI sceNpEntitlementAccessPollConsumableEntitlementInfo(); +int APS5_VABI sceNpEntitlementAccessRequestConsumableEntitlementInfo(); +int APS5_VABI sceNpEntitlementAccessRequestConsumeEntitlement(); + +} diff --git a/core/libs/prx/libSceNpEntitlementAccess/libSceNpEntitlementAccess.hpp b/core/libs/prx/libSceNpEntitlementAccess/libSceNpEntitlementAccess.hpp new file mode 100644 index 0000000000..e8590281af --- /dev/null +++ b/core/libs/prx/libSceNpEntitlementAccess/libSceNpEntitlementAccess.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceNpEntitlementAccess/include/Api.hpp" diff --git a/core/libs/prx/libSceNpEulaDialog/Export.cpp b/core/libs/prx/libSceNpEulaDialog/Export.cpp index 1b666cc199..99b4499d54 100644 --- a/core/libs/prx/libSceNpEulaDialog/Export.cpp +++ b/core/libs/prx/libSceNpEulaDialog/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNpEulaDialog/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceNpEulaDialog/include/Api.hpp b/core/libs/prx/libSceNpEulaDialog/include/Api.hpp new file mode 100644 index 0000000000..fc29d6fa96 --- /dev/null +++ b/core/libs/prx/libSceNpEulaDialog/include/Api.hpp @@ -0,0 +1,17 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceNpEulaDialogCheckVersion(); +int APS5_VABI sceNpEulaDialogCheckVersionAbort(); +int APS5_VABI sceNpEulaDialogClose(); +int APS5_VABI sceNpEulaDialogGetResult(); +int APS5_VABI sceNpEulaDialogGetStatus(); +int APS5_VABI sceNpEulaDialogInitialize(); +int APS5_VABI sceNpEulaDialogOpen(); +int APS5_VABI sceNpEulaDialogTerminate(); +int APS5_VABI sceNpEulaDialogUpdateStatus(); + +} diff --git a/core/libs/prx/libSceNpEulaDialog/libSceNpEulaDialog.hpp b/core/libs/prx/libSceNpEulaDialog/libSceNpEulaDialog.hpp new file mode 100644 index 0000000000..6f2a34108c --- /dev/null +++ b/core/libs/prx/libSceNpEulaDialog/libSceNpEulaDialog.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceNpEulaDialog/include/Api.hpp" diff --git a/core/libs/prx/libSceNpFriendListDialog/Export.cpp b/core/libs/prx/libSceNpFriendListDialog/Export.cpp index 4ca7288353..aee6fb1edf 100644 --- a/core/libs/prx/libSceNpFriendListDialog/Export.cpp +++ b/core/libs/prx/libSceNpFriendListDialog/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNpFriendListDialog/include/Api.hpp" #include #include #include diff --git a/core/libs/prx/libSceNpFriendListDialog/include/Api.hpp b/core/libs/prx/libSceNpFriendListDialog/include/Api.hpp new file mode 100644 index 0000000000..2bdd0742ab --- /dev/null +++ b/core/libs/prx/libSceNpFriendListDialog/include/Api.hpp @@ -0,0 +1,17 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceNpFriendListDialogInitialize(void); +int APS5_VABI sceNpFriendListDialogOpenA(const void* param); +int APS5_VABI sceNpFriendListDialogUpdateStatus(void); +int APS5_VABI sceNpFriendListDialogGetStatus(void); +int APS5_VABI sceNpFriendListDialogGetResultA(void* result); +int APS5_VABI sceNpFriendListDialogClose(void); +int APS5_VABI sceNpFriendListDialogTerminate(void); +int APS5_VABI sceNpFriendListDialogGetResult(); +int APS5_VABI sceNpFriendListDialogOpen(); + +} diff --git a/core/libs/prx/libSceNpFriendListDialog/libSceNpFriendListDialog.hpp b/core/libs/prx/libSceNpFriendListDialog/libSceNpFriendListDialog.hpp new file mode 100644 index 0000000000..d1b45137ee --- /dev/null +++ b/core/libs/prx/libSceNpFriendListDialog/libSceNpFriendListDialog.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceNpFriendListDialog/include/Api.hpp" diff --git a/core/libs/prx/libSceNpGameIntent/Export.cpp b/core/libs/prx/libSceNpGameIntent/Export.cpp index c8be4b9f09..751b4b1c5b 100644 --- a/core/libs/prx/libSceNpGameIntent/Export.cpp +++ b/core/libs/prx/libSceNpGameIntent/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNpGameIntent/include/Api.hpp" #include #include #include @@ -12,7 +13,6 @@ constexpr int NpGameIntentErrorIntentNotFound = -2141898746; constexpr int NpGameIntentErrorValueNotFound = -2141898745; constexpr int NpGameIntentUserIdInvalid = -1; - } extern "C" { diff --git a/core/libs/prx/libSceNpGameIntent/include/Api.hpp b/core/libs/prx/libSceNpGameIntent/include/Api.hpp new file mode 100644 index 0000000000..abd369f817 --- /dev/null +++ b/core/libs/prx/libSceNpGameIntent/include/Api.hpp @@ -0,0 +1,26 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceNpGameIntentGetPropertyValueString(const NpGameIntentData* intentData, const char* key, char* valueBuf, size_t bufSize); +int APS5_VABI sceNpGameIntentInitialize(const void* initParam); +int APS5_VABI sceNpGameIntentReceiveIntent(NpGameIntentInfo* intentInfo); +int APS5_VABI sceNpGameIntentTerminate(void); +int APS5_VABI sceNpGameIntentInitParamInit(NpGameIntentInitParam* param); +int APS5_VABI sceNpGameIntentInfoInit(NpGameIntentInfo* info); +int APS5_VABI sceNpGameIntentVshInitialize(void); +int APS5_VABI sceNpGameIntentVshTerminate(void); +int APS5_VABI sceNpAppLauncherInitialize(const void* initParam); +int APS5_VABI sceNpAppLauncherLaunchApp(); +int APS5_VABI sceNpAppLauncherTerminate(); +int APS5_VABI sceNpGameIntentGetUdsNpComId(); +int APS5_VABI sceNpGameIntentLaunchApp(); +int APS5_VABI sceNpGameIntentLaunchApp2(); +int APS5_VABI sceNpGameIntentNotifyAppLaunched(); +int APS5_VABI sceNpSessionServiceGetJoinedPartySession(); +int APS5_VABI sceNpSessionServiceGetRunningGamePlayerSession(); +int APS5_VABI sceNpSessionServiceSendPlayerSessionInvitations(); + +} diff --git a/core/libs/prx/libSceNpGameIntent/libSceNpGameIntent.hpp b/core/libs/prx/libSceNpGameIntent/libSceNpGameIntent.hpp new file mode 100644 index 0000000000..7c0f3b8b2e --- /dev/null +++ b/core/libs/prx/libSceNpGameIntent/libSceNpGameIntent.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceNpGameIntent/include/Api.hpp" diff --git a/core/libs/prx/libSceNpManager/Export.cpp b/core/libs/prx/libSceNpManager/Export.cpp index c50ab5b01f..55f1c4c5c8 100644 --- a/core/libs/prx/libSceNpManager/Export.cpp +++ b/core/libs/prx/libSceNpManager/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNpManager/include/Api.hpp" #include #include #include "SceTypes.hpp" @@ -44,9 +45,6 @@ int SignedOutRequest(int reqId) { return liveRequests.count(reqId) ? SCE_NP_ERROR_SIGNED_OUT : SCE_NP_ERROR_REQUEST_NOT_FOUND; } -using NpStateCallbackA = void (APS5_VABI *)(int userId, uint32_t state, void* userdata); -using NpStateCallback = void (APS5_VABI *)(int userId, uint32_t state, NpId* npId, void* userdata); - constexpr int NP_STATE_CALLBACK_MAX = 8; struct StateCallbackA { @@ -998,7 +996,6 @@ int APS5_VABI sceNpUnknown_WxLcN76q19o(void) { return 0; } - int APS5_VABI sceNpCheckCallbackForLib() { return sceNpCheckCallback(); } diff --git a/core/libs/prx/libSceNpManager/include/Api.hpp b/core/libs/prx/libSceNpManager/include/Api.hpp new file mode 100644 index 0000000000..11a6828eb8 --- /dev/null +++ b/core/libs/prx/libSceNpManager/include/Api.hpp @@ -0,0 +1,218 @@ +#pragma once + +#include "SceTypes.hpp" + +using NpStateCallback = void (APS5_VABI *)(int userId, uint32_t state, NpId* npId, void* userdata); + +using NpStateCallbackA = void (APS5_VABI *)(int userId, uint32_t state, void* userdata); + +extern "C" { + +int APS5_VABI sceNpAsmAbort(void); +int APS5_VABI sceNpAsmClientAbortRequest(void); +int APS5_VABI sceNpAsmClientClearNpTitleToken(void); +int APS5_VABI sceNpAsmClientClearNpTitleTokenA(void); +int APS5_VABI sceNpAsmClientCreateRequest2(void); +int APS5_VABI sceNpAsmClientCreateResourceContext(void); +int APS5_VABI sceNpAsmClientCreateResourceContext2(void); +int APS5_VABI sceNpAsmClientDeleteRequest(void); +int APS5_VABI sceNpAsmClientDeleteResourceContext(void); +int APS5_VABI sceNpAsmClientDeleteResourceContext2(void); +int APS5_VABI sceNpAsmClientGetAppId(void); +int APS5_VABI sceNpAsmClientGetCacheControlMaxAge(void); +int APS5_VABI sceNpAsmClientGetGameNpTitleInfo(void); +int APS5_VABI sceNpAsmClientGetGameNpTitleToken(void); +int APS5_VABI sceNpAsmClientGetGameTitleBanInfo(void); +int APS5_VABI sceNpAsmClientGetNpComInfo2(void); +int APS5_VABI sceNpAsmClientGetNpComInfo2A(void); +int APS5_VABI sceNpAsmClientGetNpComInfo3(void); +int APS5_VABI sceNpAsmClientGetNpComInfo4(void); +int APS5_VABI sceNpAsmClientGetNpTitleId(void); +int APS5_VABI sceNpAsmClientGetNpTitleToken(void); +int APS5_VABI sceNpAsmClientGetNpTitleToken2(void); +int APS5_VABI sceNpAsmClientGetNpTitleTokenA(void); +int APS5_VABI sceNpAsmClientGetRelatedGameNpTitleIds(void); +int APS5_VABI sceNpAsmClientGetRelatedGameNpTitleIdsA(void); +int APS5_VABI sceNpAsmClientGetRelatedGameNpTitleIdsResult(void); +int APS5_VABI sceNpAsmClientGetServiceBaseUrl(void); +int APS5_VABI sceNpAsmClientGetServiceBaseUrlA(void); +int APS5_VABI sceNpAsmClientGetServiceBaseUrlWithNpTitleId(void); +int APS5_VABI sceNpAsmClientGetServiceBaseUrlWithNpTitleIdA(void); +int APS5_VABI sceNpAsmClientGetServiceIdInfo(void); +int APS5_VABI sceNpAsmClientGetServiceIdInfoA(void); +int APS5_VABI sceNpAsmClientInitialize(void); +int APS5_VABI sceNpAsmClientSetNpTitleId(void); +int APS5_VABI sceNpAsmClientTerminate(void); +int APS5_VABI sceNpAsmCreateConnection(void); +int APS5_VABI sceNpAsmCreateRequest(void); +int APS5_VABI sceNpAsmDeleteConnection(void); +int APS5_VABI sceNpAsmDeleteRequest(void); +int APS5_VABI sceNpAsmGenerateNpTitleToken(void); +int APS5_VABI sceNpAsmGenerateNpTitleToken2(void); +int APS5_VABI sceNpAsmGetNpCommInfo(void); +int APS5_VABI sceNpAsmGetNpCommInfo2(void); +int APS5_VABI sceNpAsmGetRelatedGameNpTitleIds(void); +int APS5_VABI sceNpAsmGetServiceBaseUrl(void); +int APS5_VABI sceNpAsmGetServiceIdInfo(void); +int APS5_VABI sceNpAsmInitialize(void); +int APS5_VABI sceNpAsmTerminate(void); +int APS5_VABI sceNpCheckNpAvailabilityA(int reqId, int userId); +int APS5_VABI sceNpGetAccountDateOfBirthA(int userId, void* dateOfBirth); +int APS5_VABI sceNpGetAccountLanguageA(int reqId, int userId, void* language); +int APS5_VABI sceNpGetGamePresenceStatus(const NpOnlineId* onlineId, uint32_t* status); +int APS5_VABI sceNpGetGamePresenceStatusA(int userId, uint32_t* status); +int APS5_VABI sceNpGetParentalControlInfoA(int reqId, int userId, int8_t* age, void* info); +int APS5_VABI sceNpIdMapperAbortRequest(void); +int APS5_VABI sceNpIdMapperAccountIdToNpId(void); +int APS5_VABI sceNpIdMapperAccountIdToOnlineId(void); +int APS5_VABI sceNpIdMapperCreateRequest(void); +int APS5_VABI sceNpIdMapperDeleteRequest(void); +int APS5_VABI sceNpIdMapperNpIdToAccountId(void); +int APS5_VABI sceNpIdMapperOnlineIdToAccountId(void); +int APS5_VABI sceNpInGameMessageAbortHandle(void); +int APS5_VABI sceNpInGameMessageCheckCallback(void); +int APS5_VABI sceNpInGameMessageGetMemoryPoolStatistics(void); +int APS5_VABI sceNpInGameMessagePrepareA(void); +int APS5_VABI sceNpInGameMessageSendDataA(void); +int APS5_VABI sceNpIntGetAppType(void); +int APS5_VABI sceNpIntGetGamePresenceStatus(void); +int APS5_VABI sceNpIntGetNpTitleId(void); +int APS5_VABI sceNpIntGetNpTitleIdSecret(void); +int APS5_VABI sceNpIntRegisterCheckCallback(void); +int APS5_VABI sceNpIntRegisterGamePresenceCallback(void); +int APS5_VABI sceNpIsPlusMember(int, bool* isMember); +int APS5_VABI sceNpManagerIntAbortRequest(void); +int APS5_VABI sceNpManagerIntAddActiveSigninStateCallback(void); +int APS5_VABI sceNpManagerIntAddOnlineIdChangeCallback(void); +int APS5_VABI sceNpManagerIntAddPlusMemberTypeCallback(void); +int APS5_VABI sceNpManagerIntAddSigninStateCallback(void); +int APS5_VABI sceNpManagerIntAuthGetAuthorizationCode(void); +int APS5_VABI sceNpManagerIntAuthGetIdToken(void); +int APS5_VABI sceNpManagerIntCheckNpAvailability(void); +int APS5_VABI sceNpManagerIntCheckNpAvailabilityByPid(void); +int APS5_VABI sceNpManagerIntCheckNpState(void); +int APS5_VABI sceNpManagerIntCheckNpStateA(void); +int APS5_VABI sceNpManagerIntClearGameAccessToken(void); +int APS5_VABI sceNpManagerIntClearOnlineIdChangeFlag(void); +int APS5_VABI sceNpManagerIntClearTicket(void); +int APS5_VABI sceNpManagerIntClearUsedFlag(void); +int APS5_VABI sceNpManagerIntClearVshAccessToken(void); +int APS5_VABI sceNpManagerIntCreateAuthenticationTicket(void); +int APS5_VABI sceNpManagerIntCreateLoginContext(void); +int APS5_VABI sceNpManagerIntCreateLoginRequest(void); +int APS5_VABI sceNpManagerIntCreateRequest(void); +int APS5_VABI sceNpManagerIntDeleteLoginContext(void); +int APS5_VABI sceNpManagerIntDeleteRequest(void); +int APS5_VABI sceNpManagerIntGetAccessTokenViaImplicitFlow(void); +int APS5_VABI sceNpManagerIntGetAccountAge(void); +int APS5_VABI sceNpManagerIntGetAccountCountry(void); +int APS5_VABI sceNpManagerIntGetAccountCountryA(void); +int APS5_VABI sceNpManagerIntGetAccountCountrySdk(void); +int APS5_VABI sceNpManagerIntGetAccountDateOfBirthSdk(void); +int APS5_VABI sceNpManagerIntGetAccountId(void); +int APS5_VABI sceNpManagerIntGetAccountIdSdk(void); +int APS5_VABI sceNpManagerIntGetAccountLanguage(void); +int APS5_VABI sceNpManagerIntGetAccountLanguageA(void); +int APS5_VABI sceNpManagerIntGetAccountNpEnv(void); +int APS5_VABI sceNpManagerIntGetAccountType(void); +int APS5_VABI sceNpManagerIntGetActiveSigninState(void); +int APS5_VABI sceNpManagerIntGetAuthServerErrorFlag(void); +int APS5_VABI sceNpManagerIntGetAuthorizationCode(void); +int APS5_VABI sceNpManagerIntGetAuthorizationCodeWithPsnoUri(void); +int APS5_VABI sceNpManagerIntGetClientCredentialAccessToken(void); +int APS5_VABI sceNpManagerIntGetCommunicationRestrictionStatus(void); +int APS5_VABI sceNpManagerIntGetGameAccessToken(void); +int APS5_VABI sceNpManagerIntGetIssuerId(void); +int APS5_VABI sceNpManagerIntGetNpEnv(void); +int APS5_VABI sceNpManagerIntGetNpId(void); +int APS5_VABI sceNpManagerIntGetNpIdByOnlineId(void); +int APS5_VABI sceNpManagerIntGetNpIdSdk(void); +int APS5_VABI sceNpManagerIntGetOfflineAccountId(void); +int APS5_VABI sceNpManagerIntGetOnlineId(void); +int APS5_VABI sceNpManagerIntGetOnlineIdChangeFlag(void); +int APS5_VABI sceNpManagerIntGetOnlineIdSdk(void); +int APS5_VABI sceNpManagerIntGetParentalControlFlag(void); +int APS5_VABI sceNpManagerIntGetParentalControlInfo(void); +int APS5_VABI sceNpManagerIntGetPlusMemberType(void); +int APS5_VABI sceNpManagerIntGetPlusMemberTypeNB(void); +int APS5_VABI sceNpManagerIntGetServerError(void); +int APS5_VABI sceNpManagerIntGetSigninState(void); +int APS5_VABI sceNpManagerIntGetSigninTelemetryInfo(void); +int APS5_VABI sceNpManagerIntGetTicket(void); +int APS5_VABI sceNpManagerIntGetTicketA(void); +int APS5_VABI sceNpManagerIntGetTitleToken(void); +int APS5_VABI sceNpManagerIntGetTitleTokenWithCheck(void); +int APS5_VABI sceNpManagerIntGetUserIdByAccountId(void); +int APS5_VABI sceNpManagerIntGetUserIdByNpId(void); +int APS5_VABI sceNpManagerIntGetUserIdByOnlineId(void); +int APS5_VABI sceNpManagerIntGetUserIdByOnlineIdSdk(void); +int APS5_VABI sceNpManagerIntGetUserList(void); +int APS5_VABI sceNpManagerIntGetUserNum(void); +int APS5_VABI sceNpManagerIntGetVshAccessToken(void); +int APS5_VABI sceNpManagerIntGetVshAccessTokenWithCheck(void); +int APS5_VABI sceNpManagerIntGetVshClientId(void); +int APS5_VABI sceNpManagerIntIsSubAccount(void); +int APS5_VABI sceNpManagerIntIsTemporarySignout(void); +int APS5_VABI sceNpManagerIntIsUnregisteredClientError(void); +int APS5_VABI sceNpManagerIntLoginAuthenticate(void); +int APS5_VABI sceNpManagerIntLoginBind(void); +int APS5_VABI sceNpManagerIntLoginCreateAuthenticationTicket(void); +int APS5_VABI sceNpManagerIntLoginGetAccessToken(void); +int APS5_VABI sceNpAbortRequest(int reqId); +int APS5_VABI sceNpCheckCallback(void); +int APS5_VABI sceNpCheckNpAvailability(std::int32_t requestId, const NpOnlineId* onlineId, std::uint8_t* available); +int APS5_VABI sceNpCheckNpReachability(int reqId, int userId); +int APS5_VABI sceNpCheckPremium(int reqId, const NpCheckPremiumParameter* param, NpCheckPremiumResult* result); +int APS5_VABI sceNpCreateAsyncRequest(const NpCreateAsyncRequestParameter* param); +int APS5_VABI sceNpCreateRequest(void); +int APS5_VABI sceNpDeleteRequest(int reqId); +int APS5_VABI sceNpGetAccountAge(int reqId, int userId, uint8_t* age); +int APS5_VABI sceNpGetAccountCountry(const NpOnlineId* onlineId, void* countryCode); +int APS5_VABI sceNpGetAccountDateOfBirth(const NpOnlineId* onlineId, void* dateOfBirth); +int APS5_VABI sceNpGetAccountLanguage(int reqId, const NpOnlineId* onlineId, void* language); +int APS5_VABI sceNpGetParentalControlInfo(int reqId, const NpOnlineId* onlineId, int8_t* age, void* info); +int APS5_VABI sceNpGetUserIdByOnlineId(const NpOnlineId* onlineId, int* userId); +int APS5_VABI sceNpCheckPlus(int reqId, const void* param, void* result); +int APS5_VABI sceNpNotifyPlusFeature(const void* param); +int APS5_VABI sceNpGetAccountId(const NpOnlineId* onlineId, uint64_t* accountId); +int APS5_VABI sceNpSetGamePresenceOnline(int reqId, const NpOnlineId* onlineId, uint32_t presence); +int APS5_VABI sceNpGetAccountCountryA(int userId, void* countryCode); +int APS5_VABI sceNpGetAccountIdA(int userId, uint64_t* accountId); +int APS5_VABI sceNpGetNpId(int userId, NpId* npId); +int APS5_VABI sceNpGetNpReachabilityState(int userId, uint32_t* state); +int APS5_VABI sceNpGetOnlineId(int userId, NpOnlineId* onlineId); +int APS5_VABI sceNpGetState(int userId, uint32_t* state); +int APS5_VABI sceNpHasSignedUp(int userId, bool* hasSignedUp); +int APS5_VABI sceNpPollAsync(int reqId, int* result); +void APS5_VABI sceNpRegisterGamePresenceCallback(void* callback, void* userdata); +int APS5_VABI sceNpRegisterNpReachabilityStateCallback(void* callback, void* userdata); +int APS5_VABI sceNpUnregisterNpReachabilityStateCallback(void); +int APS5_VABI sceNpRegisterPlusEventCallback(void* callback, void* userdata); +int APS5_VABI sceNpRegisterPremiumEventCallback(void* callback, void* userdata); +int APS5_VABI sceNpRegisterStateCallback(NpStateCallback callback, void* userdata); +int APS5_VABI sceNpSetContentRestriction(const NpContentRestriction* restriction); +int APS5_VABI sceNpSetNpTitleId(const NpTitleId* titleId, const NpTitleSecret* titleSecret); +int APS5_VABI sceNpSetTimeout(int reqId, int32_t resolveRetry, uint32_t resolveTimeout, uint32_t connTimeout, uint32_t sendTimeout, uint32_t recvTimeout); +int APS5_VABI sceNpUnregisterStateCallback(void); +int APS5_VABI sceNpGetAccountLanguage2(int reqId, int userId, void* language); +int APS5_VABI sceNpNotifyPremiumFeature(const void* param); +int APS5_VABI sceNpRegisterStateCallbackA(NpStateCallbackA callback, void* userdata); +int APS5_VABI sceNpUnregisterStateCallbackA(int callbackId); +int APS5_VABI sceNpUnregisterPremiumEventCallback(void); +int APS5_VABI sceNpUnregisterPlusEventCallback(void); +int APS5_VABI sceNpGetUserIdByAccountId(uint64_t accountId, int* userId); +int APS5_VABI sceNpGetSandboxInfo(void* sandboxInfo); +int APS5_VABI sceNpUnknown_8weiQyIdI3A(int userId, const NpOnlineId* buffer); +int APS5_VABI sceNpUnknown_WxLcN76q19o(void); +int APS5_VABI sceNpCheckCallbackForLib(); +int APS5_VABI sceNpInGameMessageCreateHandle(); +int APS5_VABI sceNpInGameMessageDeleteHandle(); +int APS5_VABI sceNpInGameMessageInitialize(); +int APS5_VABI sceNpInGameMessagePrepare(); +int APS5_VABI sceNpInGameMessageSendData(); +int APS5_VABI sceNpInGameMessageTerminate(); +int APS5_VABI sceNpSnsFacebookCreateRequest(); +int APS5_VABI sceNpSnsFacebookDeleteRequest(); +int APS5_VABI sceNpSnsFacebookGetAccessToken(); + +} diff --git a/core/libs/prx/libSceNpManager/libSceNpManager.hpp b/core/libs/prx/libSceNpManager/libSceNpManager.hpp new file mode 100644 index 0000000000..5fa5fa4390 --- /dev/null +++ b/core/libs/prx/libSceNpManager/libSceNpManager.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceNpManager/include/Api.hpp" diff --git a/core/libs/prx/libSceNpMatching2/Export.cpp b/core/libs/prx/libSceNpMatching2/Export.cpp index c7dd08b7af..3797bf7136 100644 --- a/core/libs/prx/libSceNpMatching2/Export.cpp +++ b/core/libs/prx/libSceNpMatching2/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNpMatching2/include/Api.hpp" #include #include #include @@ -17,25 +18,9 @@ static constexpr std::uint64_t CREATE_CONTEXT_PARAMETER_SIZE = 0x28; namespace { -struct NpMatching2InitializeParameter { - std::uint64_t poolSize; - std::uint64_t cpuAffinityMask; - std::int32_t threadPriority; - std::uint8_t padding[4]; - std::uint64_t threadStackSize; - std::uint64_t size; - std::uint64_t sslPoolSize; -}; static_assert(offsetof(NpMatching2InitializeParameter, size) == 0x20); static_assert(sizeof(NpMatching2InitializeParameter) == 0x30); -struct NpMatching2CreateContextParameter { - const void* npId; - const void* npCommunicationId; - const void* npPassphrase; - std::uint32_t serviceLabel; - std::uint64_t size; -}; static_assert(sizeof(NpMatching2CreateContextParameter) == CREATE_CONTEXT_PARAMETER_SIZE); std::mutex matching2Mutex; diff --git a/core/libs/prx/libSceNpMatching2/include/Api.hpp b/core/libs/prx/libSceNpMatching2/include/Api.hpp new file mode 100644 index 0000000000..e7aca1bb5d --- /dev/null +++ b/core/libs/prx/libSceNpMatching2/include/Api.hpp @@ -0,0 +1,55 @@ +#pragma once + +#include "SceTypes.hpp" + +struct NpMatching2InitializeParameter { + std::uint64_t poolSize; + std::uint64_t cpuAffinityMask; + std::int32_t threadPriority; + std::uint8_t padding[4]; + std::uint64_t threadStackSize; + std::uint64_t size; + std::uint64_t sslPoolSize; +}; + +struct NpMatching2CreateContextParameter { + const void* npId; + const void* npCommunicationId; + const void* npPassphrase; + std::uint32_t serviceLabel; + std::uint64_t size; +}; + +extern "C" { + +int APS5_VABI sceNpMatching2ContextStart(std::uint16_t ctxId, std::uint64_t timeout); +int APS5_VABI sceNpMatching2ContextStop(std::uint16_t ctxId); +int APS5_VABI sceNpMatching2CreateContext(const NpMatching2CreateContextParameter* param, std::uint16_t* ctxId); +int APS5_VABI sceNpMatching2CreateJoinRoom(); +int APS5_VABI sceNpMatching2DestroyContext(std::uint16_t ctxId); +int APS5_VABI sceNpMatching2GetRoomDataExternalList(); +int APS5_VABI sceNpMatching2GetRoomDataInternal(); +int APS5_VABI sceNpMatching2GetRoomMemberDataInternal(); +int APS5_VABI sceNpMatching2GetServerId(); +int APS5_VABI sceNpMatching2GetUserInfoList(); +int APS5_VABI sceNpMatching2GetWorldInfoList(); +int APS5_VABI sceNpMatching2Initialize(const NpMatching2InitializeParameter* param); +int APS5_VABI sceNpMatching2JoinRoom(); +int APS5_VABI sceNpMatching2KickoutRoomMember(); +int APS5_VABI sceNpMatching2LeaveRoom(); +int APS5_VABI sceNpMatching2RegisterContextCallback(void* callback, void* userdata); +int APS5_VABI sceNpMatching2RegisterRoomEventCallback(std::uint16_t ctxId, void* callback, void* userdata); +int APS5_VABI sceNpMatching2RegisterRoomMessageCallback(std::uint16_t ctxId, void* callback, void* userdata); +int APS5_VABI sceNpMatching2RegisterSignalingCallback(std::uint16_t ctxId, void* callback, void* userdata); +int APS5_VABI sceNpMatching2SearchRoom(); +int APS5_VABI sceNpMatching2SendRoomChatMessage(); +int APS5_VABI sceNpMatching2SendRoomMessage(); +int APS5_VABI sceNpMatching2SetDefaultRequestOptParam(std::uint16_t ctxId, const void* requestOpt); +int APS5_VABI sceNpMatching2SetRoomDataExternal(); +int APS5_VABI sceNpMatching2SetRoomDataInternal(); +int APS5_VABI sceNpMatching2SetRoomMemberDataInternal(); +int APS5_VABI sceNpMatching2SetUserInfo(); +int APS5_VABI sceNpMatching2SignalingGetConnectionInfo(); +int APS5_VABI sceNpMatching2Terminate(void); + +} diff --git a/core/libs/prx/libSceNpMatching2/libSceNpMatching2.hpp b/core/libs/prx/libSceNpMatching2/libSceNpMatching2.hpp new file mode 100644 index 0000000000..9819896e2b --- /dev/null +++ b/core/libs/prx/libSceNpMatching2/libSceNpMatching2.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceNpMatching2/include/Api.hpp" diff --git a/core/libs/prx/libSceNpPartner001/Export.cpp b/core/libs/prx/libSceNpPartner001/Export.cpp index d4dbeeefd9..2a4635c7c8 100644 --- a/core/libs/prx/libSceNpPartner001/Export.cpp +++ b/core/libs/prx/libSceNpPartner001/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNpPartner001/include/Api.hpp" #include "prx/libc/include/General.hpp" #include #include diff --git a/core/libs/prx/libSceNpPartner001/include/Api.hpp b/core/libs/prx/libSceNpPartner001/include/Api.hpp new file mode 100644 index 0000000000..7254f21010 --- /dev/null +++ b/core/libs/prx/libSceNpPartner001/include/Api.hpp @@ -0,0 +1,11 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceNpEAAccessInitialize(void); +int APS5_VABI sceNpEAAccessTerminate(void); +int APS5_VABI sceNpHasEAAccessSubscription(int userId, bool* result); + +} diff --git a/core/libs/prx/libSceNpPartner001/libSceNpPartner001.hpp b/core/libs/prx/libSceNpPartner001/libSceNpPartner001.hpp new file mode 100644 index 0000000000..83c567edd0 --- /dev/null +++ b/core/libs/prx/libSceNpPartner001/libSceNpPartner001.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceNpPartner001/include/Api.hpp" diff --git a/core/libs/prx/libSceNpParty/Export.cpp b/core/libs/prx/libSceNpParty/Export.cpp index 305da3f6cc..4f00ce3699 100644 --- a/core/libs/prx/libSceNpParty/Export.cpp +++ b/core/libs/prx/libSceNpParty/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNpParty/include/Api.hpp" #include #include #include diff --git a/core/libs/prx/libSceNpParty/include/Api.hpp b/core/libs/prx/libSceNpParty/include/Api.hpp new file mode 100644 index 0000000000..6ac3a20bc7 --- /dev/null +++ b/core/libs/prx/libSceNpParty/include/Api.hpp @@ -0,0 +1,34 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceNpPartyGetState(std::uint16_t* state); +int APS5_VABI sceNpPartyCheckCallback(void); +int APS5_VABI sceNpPartyCreate(void); +int APS5_VABI sceNpPartyCreateA(void); +int APS5_VABI sceNpPartyGetId(void* id); +int APS5_VABI sceNpPartyGetMemberInfo(void); +int APS5_VABI sceNpPartyGetMemberInfoA(std::uint16_t, void* memberInfo); +int APS5_VABI sceNpPartyGetMemberSessionInfo(std::uint16_t, void* memberGameSessionInfo); +int APS5_VABI sceNpPartyGetMemberVoiceInfo(std::uint16_t, std::uint16_t, std::uint8_t* memberVoiceState); +int APS5_VABI sceNpPartyGetMembers(void); +int APS5_VABI sceNpPartyGetMembersA(void* memberList); +int APS5_VABI sceNpPartyGetStateAsUser(void); +int APS5_VABI sceNpPartyGetStateAsUserA(std::int32_t, std::uint16_t* state); +int APS5_VABI sceNpPartyGetVoiceChatPriority(void); +int APS5_VABI sceNpPartyInitialize(const void* param); +int APS5_VABI sceNpPartyJoin(void); +int APS5_VABI sceNpPartyLeave(void); +int APS5_VABI sceNpPartyRegisterHandler(void); +int APS5_VABI sceNpPartyRegisterHandlerA(const void* handlers, void*); +int APS5_VABI sceNpPartyRegisterPrivateHandler(void); +int APS5_VABI sceNpPartySendBinaryMessage(const void* sendParams); +int APS5_VABI sceNpPartySetVoiceChatPriority(void); +int APS5_VABI sceNpPartyShowInvitationList(void); +int APS5_VABI sceNpPartyShowInvitationListA(void); +int APS5_VABI sceNpPartyTerminate(void); +int APS5_VABI sceNpPartyUnregisterPrivateHandler(void); + +} diff --git a/core/libs/prx/libSceNpParty/libSceNpParty.hpp b/core/libs/prx/libSceNpParty/libSceNpParty.hpp new file mode 100644 index 0000000000..0b7c65e697 --- /dev/null +++ b/core/libs/prx/libSceNpParty/libSceNpParty.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceNpParty/include/Api.hpp" diff --git a/core/libs/prx/libSceNpProfileDialog/Export.cpp b/core/libs/prx/libSceNpProfileDialog/Export.cpp index a9112db530..3ece49618f 100644 --- a/core/libs/prx/libSceNpProfileDialog/Export.cpp +++ b/core/libs/prx/libSceNpProfileDialog/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNpProfileDialog/include/Api.hpp" #include #include #include @@ -20,24 +21,9 @@ constexpr int COMMON_DIALOG_RESULT_USER_CANCELED = 1; constexpr std::uint32_t NP_PROFILE_DIALOG_MODE_NORMAL = 1; constexpr std::uint32_t NP_PROFILE_DIALOG_MODE_GRIEF_REPORT = 4; -struct SceCommonDialogBaseParam { - std::uint64_t size; - std::uint8_t reserved[36]; - std::uint32_t magic; -}; static_assert(offsetof(SceCommonDialogBaseParam, magic) == 44); static_assert(sizeof(SceCommonDialogBaseParam) == 48); -struct SceNpProfileDialogParam { - SceCommonDialogBaseParam baseParam; - std::uint64_t size; - std::uint32_t mode; - std::int32_t userId; - NpOnlineId targetOnlineId; - std::uint8_t padding[4]; - void* userData; - std::uint8_t reserved[32]; -}; static_assert(offsetof(SceNpProfileDialogParam, size) == 48); static_assert(offsetof(SceNpProfileDialogParam, mode) == 56); static_assert(offsetof(SceNpProfileDialogParam, userId) == 60); @@ -45,16 +31,6 @@ static_assert(offsetof(SceNpProfileDialogParam, targetOnlineId) == 64); static_assert(offsetof(SceNpProfileDialogParam, userData) == 88); static_assert(sizeof(SceNpProfileDialogParam) == 128); -struct SceNpProfileDialogParamA { - SceCommonDialogBaseParam baseParam; - std::uint64_t size; - std::uint32_t mode; - std::int32_t userId; - std::uint64_t targetAccountId; - std::uint8_t padding[8]; - void* userData; - std::uint8_t reserved[32]; -}; static_assert(offsetof(SceNpProfileDialogParamA, size) == 48); static_assert(offsetof(SceNpProfileDialogParamA, mode) == 56); static_assert(offsetof(SceNpProfileDialogParamA, userId) == 60); @@ -62,12 +38,6 @@ static_assert(offsetof(SceNpProfileDialogParamA, targetAccountId) == 64); static_assert(offsetof(SceNpProfileDialogParamA, userData) == 80); static_assert(sizeof(SceNpProfileDialogParamA) == 120); -struct SceNpProfileDialogResult { - std::int32_t result; - std::int32_t userAction; - void* userData; - std::uint8_t reserved[32]; -}; static_assert(offsetof(SceNpProfileDialogResult, userAction) == 4); static_assert(offsetof(SceNpProfileDialogResult, userData) == 8); static_assert(offsetof(SceNpProfileDialogResult, reserved) == 16); diff --git a/core/libs/prx/libSceNpProfileDialog/include/Api.hpp b/core/libs/prx/libSceNpProfileDialog/include/Api.hpp new file mode 100644 index 0000000000..b505733fc0 --- /dev/null +++ b/core/libs/prx/libSceNpProfileDialog/include/Api.hpp @@ -0,0 +1,56 @@ +#pragma once + +#include "SceTypes.hpp" +#include +#include +#include +#include +#include + +struct SceCommonDialogBaseParam { + std::uint64_t size; + std::uint8_t reserved[36]; + std::uint32_t magic; +}; + +struct SceNpProfileDialogParam { + SceCommonDialogBaseParam baseParam; + std::uint64_t size; + std::uint32_t mode; + std::int32_t userId; + NpOnlineId targetOnlineId; + std::uint8_t padding[4]; + void* userData; + std::uint8_t reserved[32]; +}; + +struct SceNpProfileDialogParamA { + SceCommonDialogBaseParam baseParam; + std::uint64_t size; + std::uint32_t mode; + std::int32_t userId; + std::uint64_t targetAccountId; + std::uint8_t padding[8]; + void* userData; + std::uint8_t reserved[32]; +}; + +struct SceNpProfileDialogResult { + std::int32_t result; + std::int32_t userAction; + void* userData; + std::uint8_t reserved[32]; +}; + +extern "C" { + +int APS5_VABI sceNpProfileDialogInitialize(void); +int APS5_VABI sceNpProfileDialogTerminate(void); +int APS5_VABI sceNpProfileDialogUpdateStatus(void); +int APS5_VABI sceNpProfileDialogGetStatus(void); +int APS5_VABI sceNpProfileDialogOpen(const SceNpProfileDialogParam* param); +int APS5_VABI sceNpProfileDialogOpenA(const SceNpProfileDialogParamA* param); +int APS5_VABI sceNpProfileDialogClose(void); +int APS5_VABI sceNpProfileDialogGetResult(SceNpProfileDialogResult* result); + +} diff --git a/core/libs/prx/libSceNpProfileDialog/libSceNpProfileDialog.hpp b/core/libs/prx/libSceNpProfileDialog/libSceNpProfileDialog.hpp new file mode 100644 index 0000000000..8cfbbcbcd4 --- /dev/null +++ b/core/libs/prx/libSceNpProfileDialog/libSceNpProfileDialog.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceNpProfileDialog/include/Api.hpp" diff --git a/core/libs/prx/libSceNpRemotePlaySessionSignaling/Export.cpp b/core/libs/prx/libSceNpRemotePlaySessionSignaling/Export.cpp index 766da74191..a0f12e3e85 100644 --- a/core/libs/prx/libSceNpRemotePlaySessionSignaling/Export.cpp +++ b/core/libs/prx/libSceNpRemotePlaySessionSignaling/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNpRemotePlaySessionSignaling/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceNpRemotePlaySessionSignaling/include/Api.hpp b/core/libs/prx/libSceNpRemotePlaySessionSignaling/include/Api.hpp new file mode 100644 index 0000000000..9aeae0ac11 --- /dev/null +++ b/core/libs/prx/libSceNpRemotePlaySessionSignaling/include/Api.hpp @@ -0,0 +1,18 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceNpRemotePlaySessionSignalingCreateJoinSession(); +int APS5_VABI sceNpRemotePlaySessionSignalingGetConnectionStatus(); +int APS5_VABI sceNpRemotePlaySessionSignalingGetCustomProperty(); +int APS5_VABI sceNpRemotePlaySessionSignalingGetLocalNetInfo(); +int APS5_VABI sceNpRemotePlaySessionSignalingGetMemoryInfo(); +int APS5_VABI sceNpRemotePlaySessionSignalingInitialize(); +int APS5_VABI sceNpRemotePlaySessionSignalingJoinSession(); +int APS5_VABI sceNpRemotePlaySessionSignalingLeaveSession(); +int APS5_VABI sceNpRemotePlaySessionSignalingSetCustomProperty(); +int APS5_VABI sceNpRemotePlaySessionSignalingTerminate(); + +} diff --git a/core/libs/prx/libSceNpRemotePlaySessionSignaling/libSceNpRemotePlaySessionSignaling.hpp b/core/libs/prx/libSceNpRemotePlaySessionSignaling/libSceNpRemotePlaySessionSignaling.hpp new file mode 100644 index 0000000000..4c78dfe8e5 --- /dev/null +++ b/core/libs/prx/libSceNpRemotePlaySessionSignaling/libSceNpRemotePlaySessionSignaling.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceNpRemotePlaySessionSignaling/include/Api.hpp" diff --git a/core/libs/prx/libSceNpScoreRanking/Export.cpp b/core/libs/prx/libSceNpScoreRanking/Export.cpp index 47690794d0..1edb9c64ca 100644 --- a/core/libs/prx/libSceNpScoreRanking/Export.cpp +++ b/core/libs/prx/libSceNpScoreRanking/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNpScoreRanking/include/Api.hpp" #include #include #include @@ -30,18 +31,8 @@ static constexpr std::uint64_t FRIEND_RANKING_OPTION_SIZE = 24; static constexpr int POLL_FINISHED = 0; static constexpr int POLL_RUNNING = 1; -struct NpScoreGameInfo { - std::uint64_t infoSize; - std::uint8_t data[189]; - std::uint8_t pad[3]; -}; static_assert(sizeof(NpScoreGameInfo) == GAME_INFO_SIZE); -struct NpScoreFriendRankingOption { - std::uint64_t size; - const std::uint32_t* startSerialRank; - const std::uint32_t* hits; -}; static_assert(sizeof(NpScoreFriendRankingOption) == FRIEND_RANKING_OPTION_SIZE); namespace { diff --git a/core/libs/prx/libSceNpScoreRanking/include/Api.hpp b/core/libs/prx/libSceNpScoreRanking/include/Api.hpp new file mode 100644 index 0000000000..3a665215ec --- /dev/null +++ b/core/libs/prx/libSceNpScoreRanking/include/Api.hpp @@ -0,0 +1,35 @@ +#pragma once + +#include "SceTypes.hpp" + +struct NpScoreFriendRankingOption { + std::uint64_t size; + const std::uint32_t* startSerialRank; + const std::uint32_t* hits; +}; + +struct NpScoreGameInfo { + std::uint64_t infoSize; + std::uint8_t data[189]; + std::uint8_t pad[3]; +}; + +extern "C" { + +int APS5_VABI sceNpScoreAbortRequest(int reqId); +int APS5_VABI sceNpScoreCreateNpTitleCtx(std::uint32_t serviceLabel, const void* selfNpId); +int APS5_VABI sceNpScoreCreateRequest(int titleCtxId); +int APS5_VABI sceNpScoreDeleteNpTitleCtx(int titleCtxId); +int APS5_VABI sceNpScoreDeleteRequest(int reqId); +int APS5_VABI sceNpScoreGetBoardInfo(int reqId, std::uint32_t boardId, void* boardInfo, void* option); +int APS5_VABI sceNpScoreGetFriendsRanking(int reqId, std::uint32_t boardId, int includeSelf, void* rankArray, std::uint64_t rankArraySize, void* commentArray, std::uint64_t commentArraySize, void* infoArray, std::uint64_t infoArraySize, std::uint64_t arrayNum, void* lastSortDate, void* totalRecord, const NpScoreFriendRankingOption* option); +int APS5_VABI sceNpScoreGetFriendsRankingAsync(int reqId, std::uint32_t boardId, int includeSelf, void* rankArray, std::uint64_t rankArraySize, void* commentArray, std::uint64_t commentArraySize, void* infoArray, std::uint64_t infoArraySize, std::uint64_t arrayNum, void* lastSortDate, void* totalRecord, const NpScoreFriendRankingOption* option); +int APS5_VABI sceNpScoreGetRankingByNpId(int reqId, std::uint32_t boardId, const void* npIdArray, std::uint64_t npIdArraySize, void* rankArray, std::uint64_t rankArraySize, void* commentArray, std::uint64_t commentArraySize, void* infoArray, std::uint64_t infoArraySize, std::uint64_t arrayNum, void* lastSortDate, void* totalRecord, void* option); +int APS5_VABI sceNpScoreGetRankingByNpIdAsync(int reqId, std::uint32_t boardId, const void* npIdArray, std::uint64_t npIdArraySize, void* rankArray, std::uint64_t rankArraySize, void* commentArray, std::uint64_t commentArraySize, void* infoArray, std::uint64_t infoArraySize, std::uint64_t arrayNum, void* lastSortDate, void* totalRecord, void* option); +int APS5_VABI sceNpScoreGetRankingByRange(int reqId, std::uint32_t boardId, std::uint32_t startSerialRank, void* rankArray, std::uint64_t rankArraySize, void* commentArray, std::uint64_t commentArraySize, void* infoArray, std::uint64_t infoArraySize, std::uint64_t arrayNum, void* lastSortDate, void* totalRecord, void* option); +int APS5_VABI sceNpScoreGetRankingByRangeAsync(int reqId, std::uint32_t boardId, std::uint32_t startSerialRank, void* rankArray, std::uint64_t rankArraySize, void* commentArray, std::uint64_t commentArraySize, void* infoArray, std::uint64_t infoArraySize, std::uint64_t arrayNum, void* lastSortDate, void* totalRecord, void* option); +int APS5_VABI sceNpScorePollAsync(int reqId, int* result); +int APS5_VABI sceNpScoreRecordScore(int reqId, std::uint32_t boardId, std::int64_t score, const void* scoreComment, const NpScoreGameInfo* gameInfo, std::uint32_t* tmpRank, const void* compareDate, void* option); +int APS5_VABI sceNpScoreRecordScoreAsync(int reqId, std::uint32_t boardId, std::int64_t score, const void* scoreComment, const NpScoreGameInfo* gameInfo, std::uint32_t* tmpRank, const void* compareDate, void* option); + +} diff --git a/core/libs/prx/libSceNpScoreRanking/libSceNpScoreRanking.hpp b/core/libs/prx/libSceNpScoreRanking/libSceNpScoreRanking.hpp new file mode 100644 index 0000000000..312ac2276e --- /dev/null +++ b/core/libs/prx/libSceNpScoreRanking/libSceNpScoreRanking.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceNpScoreRanking/include/Api.hpp" diff --git a/core/libs/prx/libSceNpSessionSignaling/Export.cpp b/core/libs/prx/libSceNpSessionSignaling/Export.cpp index 3e6da147ed..1123e55333 100644 --- a/core/libs/prx/libSceNpSessionSignaling/Export.cpp +++ b/core/libs/prx/libSceNpSessionSignaling/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNpSessionSignaling/include/Api.hpp" #include #include #include "SceTypes.hpp" @@ -25,79 +26,6 @@ static std::mutex g_mutex; static bool g_initialized = false; static std::array g_contexts{}; -struct SessionSignalingInitParam { - std::int32_t userId; - std::uint64_t poolSize; - std::uint64_t affinityMask; - std::int32_t threadPriority; - std::uint64_t stackSize; -}; - -struct SessionSignalingMemoryInfo { - std::uint64_t poolSize; - std::uint64_t usedSize; - std::uint64_t peakUsedSize; -}; - -struct SessionSignalingPeerAddress { - std::uint64_t accountId; - std::uint32_t platform; -}; - -struct SessionSignalingSessionParam { - std::uint32_t mode; - std::uint32_t option; -}; - -struct SessionSignalingNetAddress { - std::uint32_t address; - std::uint16_t port; -}; - -union SessionSignalingConnectionInfo { - std::uint32_t value; - SessionSignalingNetAddress netAddress; - SessionSignalingPeerAddress peerAddress; -}; - -struct SessionSignalingLocalNetInfo { - std::uint32_t localAddress; - std::uint32_t mappedAddress; - std::uint32_t mappedPort; - std::uint32_t mappingStatus; -}; - -using SessionSignalingEventCallback = void (APS5_VABI *)(std::uint32_t, std::uint32_t, std::int32_t, const SessionSignalingPeerAddress*, std::int32_t, void*); -using SessionSignalingConnectionCallback = void (APS5_VABI *)(std::uint32_t, std::uint32_t, std::int32_t, std::int32_t, void*); -using SessionSignalingConnectionCallback2 = void (APS5_VABI *)(std::uint32_t, std::uint32_t, std::uint32_t, std::int32_t, std::int32_t, void*); - -template -struct SessionSignalingContextParam { - std::int32_t userId; - std::uint32_t serviceLabel; - SessionSignalingEventCallback prepareCallback; - void* prepareUserData; - SessionSignalingEventCallback sessionCallback; - void* sessionUserData; - TConnectionCallback connectionCallback; - void* connectionUserData; -}; - -using SessionSignalingContextParam1 = SessionSignalingContextParam; -using SessionSignalingContextParam2 = SessionSignalingContextParam; - -struct SessionSignalingConnectionStatistics { - std::uint32_t peakConnectionCount; - std::uint32_t connectionCount; - std::uint32_t connectingCount; - std::uint32_t connectedCount; -}; - -struct SessionSignalingGroupInfo { - std::uint32_t connectionIds[64]; - std::uint64_t connectionCount; -}; - static_assert(sizeof(SessionSignalingMemoryInfo) == 24); static_assert(sizeof(SessionSignalingInitParam) == 40); static_assert(offsetof(SessionSignalingInitParam, poolSize) == 8); diff --git a/core/libs/prx/libSceNpSessionSignaling/include/Api.hpp b/core/libs/prx/libSceNpSessionSignaling/include/Api.hpp new file mode 100644 index 0000000000..948b313253 --- /dev/null +++ b/core/libs/prx/libSceNpSessionSignaling/include/Api.hpp @@ -0,0 +1,114 @@ +#pragma once + +#include "SceTypes.hpp" +#include +#include +#include +#include + +struct SessionSignalingInitParam { + std::int32_t userId; + std::uint64_t poolSize; + std::uint64_t affinityMask; + std::int32_t threadPriority; + std::uint64_t stackSize; +}; + +struct SessionSignalingMemoryInfo { + std::uint64_t poolSize; + std::uint64_t usedSize; + std::uint64_t peakUsedSize; +}; + +struct SessionSignalingPeerAddress { + std::uint64_t accountId; + std::uint32_t platform; +}; + +struct SessionSignalingSessionParam { + std::uint32_t mode; + std::uint32_t option; +}; + +struct SessionSignalingNetAddress { + std::uint32_t address; + std::uint16_t port; +}; + +union SessionSignalingConnectionInfo { + std::uint32_t value; + SessionSignalingNetAddress netAddress; + SessionSignalingPeerAddress peerAddress; +}; + +struct SessionSignalingLocalNetInfo { + std::uint32_t localAddress; + std::uint32_t mappedAddress; + std::uint32_t mappedPort; + std::uint32_t mappingStatus; +}; + +using SessionSignalingEventCallback = void (APS5_VABI *)(std::uint32_t, std::uint32_t, std::int32_t, const SessionSignalingPeerAddress*, std::int32_t, void*); + +using SessionSignalingConnectionCallback = void (APS5_VABI *)(std::uint32_t, std::uint32_t, std::int32_t, std::int32_t, void*); + +using SessionSignalingConnectionCallback2 = void (APS5_VABI *)(std::uint32_t, std::uint32_t, std::uint32_t, std::int32_t, std::int32_t, void*); + +template +struct SessionSignalingContextParam { + std::int32_t userId; + std::uint32_t serviceLabel; + SessionSignalingEventCallback prepareCallback; + void* prepareUserData; + SessionSignalingEventCallback sessionCallback; + void* sessionUserData; + TConnectionCallback connectionCallback; + void* connectionUserData; +}; + +using SessionSignalingContextParam1 = SessionSignalingContextParam; + +using SessionSignalingContextParam2 = SessionSignalingContextParam; + +struct SessionSignalingConnectionStatistics { + std::uint32_t peakConnectionCount; + std::uint32_t connectionCount; + std::uint32_t connectingCount; + std::uint32_t connectedCount; +}; + +struct SessionSignalingGroupInfo { + std::uint32_t connectionIds[64]; + std::uint64_t connectionCount; +}; + +extern "C" { + +int APS5_VABI sceNpSessionSignalingInitialize(const SessionSignalingInitParam* param); +int APS5_VABI sceNpSessionSignalingActivateSession(std::uint32_t contextId, const char* sessionId, std::uint32_t sessionType, const SessionSignalingSessionParam* param, std::uint32_t* groupId); +int APS5_VABI sceNpSessionSignalingCreateContext2(const SessionSignalingContextParam2* param, std::uint32_t* contextId); +int APS5_VABI sceNpSessionSignalingCreateContext(const SessionSignalingContextParam1* param, std::uint32_t* contextId); +int APS5_VABI sceNpSessionSignalingDeactivate(std::uint32_t contextId, std::uint32_t connectionId); +int APS5_VABI sceNpSessionSignalingDestroyContext(std::uint32_t contextId); +int APS5_VABI sceNpSessionSignalingGetConnectionInfo(std::uint32_t contextId, std::uint32_t connectionId, std::uint32_t code, SessionSignalingConnectionInfo* info); +int APS5_VABI sceNpSessionSignalingActivateUser(std::uint32_t contextId, const SessionSignalingPeerAddress* peerAddress, std::uint32_t* connectionId); +int APS5_VABI sceNpSessionSignalingGetConnectionFromPeerAddress2(std::uint32_t contextId, std::uint32_t groupId, const SessionSignalingPeerAddress* peerAddress, std::uint32_t* connectionId); +int APS5_VABI sceNpSessionSignalingTerminate(void); +int32_t APS5_VABI sceNpSessionSignalingGetConnectionStatus(std::uint32_t contextId, std::uint32_t connectionId, std::int32_t* status, std::uint32_t* peerAddress, std::uint16_t* peerPort); +int32_t APS5_VABI sceNpSessionSignalingGetLocalNetInfo(std::uint32_t contextId, SessionSignalingLocalNetInfo* info); +int APS5_VABI sceNpSessionSignalingRequestPrepare(uint32_t contextId, uint32_t* requestId); +int APS5_VABI sceNpSessionSignalingGetMemoryInfo(SessionSignalingMemoryInfo* memoryInfo); +int APS5_VABI sceNpSessionSignalingGetConnectionStatistics(SessionSignalingConnectionStatistics* statistics); +int APS5_VABI sceNpSessionSignalingGetConnectionFromPeerAddress(std::uint32_t contextId, const SessionSignalingPeerAddress* peerAddress, std::uint32_t* connectionId); +int APS5_VABI sceNpSessionSignalingGetGroupFromSessionId(std::uint32_t contextId, const char* sessionId, std::uint32_t* groupId); +int APS5_VABI sceNpSessionSignalingGetGroupInfo(std::uint32_t contextId, std::uint32_t groupId, SessionSignalingGroupInfo* groupInfo); +int APS5_VABI sceNpSessionSignalingGetConnectionFromNetAddress2(std::uint32_t contextId, std::uint32_t groupId, std::uint32_t address, std::uint16_t port, std::uint32_t* connectionId); +int APS5_VABI sceNpSessionSignalingCreateJoinActivate(); +int APS5_VABI sceNpSessionSignalingGetConnectionFromNetAddress(std::uint32_t contextId, std::uint32_t address, std::uint16_t port, std::uint32_t* connectionId); +int APS5_VABI sceNpSessionSignalingGetCustomProperty(); +int APS5_VABI sceNpSessionSignalingGetGroupFromPeerAddress(); +int APS5_VABI sceNpSessionSignalingInitializeWithPort(); +int APS5_VABI sceNpSessionSignalingJoinActivate(); +int APS5_VABI sceNpSessionSignalingSetCustomProperty(); + +} diff --git a/core/libs/prx/libSceNpSessionSignaling/libSceNpSessionSignaling.hpp b/core/libs/prx/libSceNpSessionSignaling/libSceNpSessionSignaling.hpp new file mode 100644 index 0000000000..8cdf796fb6 --- /dev/null +++ b/core/libs/prx/libSceNpSessionSignaling/libSceNpSessionSignaling.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceNpSessionSignaling/include/Api.hpp" diff --git a/core/libs/prx/libSceNpSignaling/Export.cpp b/core/libs/prx/libSceNpSignaling/Export.cpp index fda78ee09a..00f307beb5 100644 --- a/core/libs/prx/libSceNpSignaling/Export.cpp +++ b/core/libs/prx/libSceNpSignaling/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNpSignaling/include/Api.hpp" #include #include #include @@ -161,9 +162,12 @@ int APS5_VABI sceNpSignalingTerminateConnection(int ctxId, int connId) { return SCE_NP_SIGNALING_ERROR_CONN_NOT_FOUND; } -int APS5_VABI sceNpSignalingDeactivateConnection(void) { - NotImplemented_nid_no_patch(__func__); - return 0; +int APS5_VABI sceNpSignalingDeactivateConnection(int ctxId, int connId) { + (void)connId; + std::lock_guard lock(signalingMutex); + if (!initialized) return SCE_NP_SIGNALING_ERROR_NOT_INITIALIZED; + if (!FindContext(ctxId)) return SCE_NP_SIGNALING_ERROR_CTX_NOT_FOUND; + return SCE_NP_SIGNALING_ERROR_CONN_NOT_FOUND; } } diff --git a/core/libs/prx/libSceNpSignaling/include/Api.hpp b/core/libs/prx/libSceNpSignaling/include/Api.hpp new file mode 100644 index 0000000000..d11753e6d8 --- /dev/null +++ b/core/libs/prx/libSceNpSignaling/include/Api.hpp @@ -0,0 +1,17 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceNpSignalingActivateConnection(int ctxId, const void* peerNpId, int* outConnId); +int APS5_VABI sceNpSignalingCreateContext(const void* npId, void* callback, void* callbackArg, int* outContextId); +int APS5_VABI sceNpSignalingDeleteContext(int ctxId); +int APS5_VABI sceNpSignalingGetConnectionInfo(int ctxId, int connId, int infoCode, void* outInfo); +int APS5_VABI sceNpSignalingInitialize(std::int64_t memorySize, int threadPriority, int cpuAffinityMask, std::int64_t threadStackSize); +int APS5_VABI sceNpSignalingSetContextOption(int ctxId, int optionId, int optionValue); +int APS5_VABI sceNpSignalingTerminate(); +int APS5_VABI sceNpSignalingTerminateConnection(int ctxId, int connId); +int APS5_VABI sceNpSignalingDeactivateConnection(int ctxId, int connId); + +} diff --git a/core/libs/prx/libSceNpSignaling/libSceNpSignaling.hpp b/core/libs/prx/libSceNpSignaling/libSceNpSignaling.hpp new file mode 100644 index 0000000000..4ab0459137 --- /dev/null +++ b/core/libs/prx/libSceNpSignaling/libSceNpSignaling.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceNpSignaling/include/Api.hpp" diff --git a/core/libs/prx/libSceNpSns/Export.cpp b/core/libs/prx/libSceNpSns/Export.cpp index c6647c709c..8fe590490d 100644 --- a/core/libs/prx/libSceNpSns/Export.cpp +++ b/core/libs/prx/libSceNpSns/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNpSns/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceNpSns/include/Api.hpp b/core/libs/prx/libSceNpSns/include/Api.hpp new file mode 100644 index 0000000000..201afcfef4 --- /dev/null +++ b/core/libs/prx/libSceNpSns/include/Api.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceNpSnsFacebookAbortRequest(); +int APS5_VABI sceNpSnsIntAbortRequest(); +int APS5_VABI sceNpSnsIntCreateRequest(); +int APS5_VABI sceNpSnsIntDeleteRequest(); +int APS5_VABI sceNpSnsIntFbGetGameAccessToken(); +int APS5_VABI sceNpSnsIntFbGetGameAccessTokenAllowed(); +int APS5_VABI sceNpSnsIntFbGetSystemAccessToken(); +int APS5_VABI sceNpSnsIntFbGetTitleInfo(); +int APS5_VABI sceNpSnsIntLinkedStatus(); +int APS5_VABI sceNpSnsIntTwGetSystemAccessToken(); +int APS5_VABI sceNpSnsIntUnlink(); +int APS5_VABI sceNpSnsIntYtGetAccessToken(); +int APS5_VABI sceNpSnsIntYtRefreshMasterToken(); +int APS5_VABI sceNpSnsTwitchAbortRequest(); +int APS5_VABI sceNpSnsTwitchCreateRequest(); +int APS5_VABI sceNpSnsTwitchDeleteRequest(); +int APS5_VABI sceNpSnsTwitchGetAccessToken(); +int APS5_VABI sceNpSnsYouTubeAbortRequest(); +int APS5_VABI sceNpSnsYouTubeCreateRequest(); +int APS5_VABI sceNpSnsYouTubeDeleteRequest(); +int APS5_VABI sceNpSnsYouTubeGetAccessToken(); + +} diff --git a/core/libs/prx/libSceNpSns/libSceNpSns.hpp b/core/libs/prx/libSceNpSns/libSceNpSns.hpp new file mode 100644 index 0000000000..24cb3940ad --- /dev/null +++ b/core/libs/prx/libSceNpSns/libSceNpSns.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceNpSns/include/Api.hpp" diff --git a/core/libs/prx/libSceNpSnsFacebookDialog/Export.cpp b/core/libs/prx/libSceNpSnsFacebookDialog/Export.cpp index e61b490597..ebad76b2f2 100644 --- a/core/libs/prx/libSceNpSnsFacebookDialog/Export.cpp +++ b/core/libs/prx/libSceNpSnsFacebookDialog/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNpSnsFacebookDialog/include/Api.hpp" #include #include #include diff --git a/core/libs/prx/libSceNpSnsFacebookDialog/include/Api.hpp b/core/libs/prx/libSceNpSnsFacebookDialog/include/Api.hpp new file mode 100644 index 0000000000..e201d488c8 --- /dev/null +++ b/core/libs/prx/libSceNpSnsFacebookDialog/include/Api.hpp @@ -0,0 +1,15 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceNpSnsFacebookDialogInitialize(void); +int APS5_VABI sceNpSnsFacebookDialogOpen(const void* param); +int APS5_VABI sceNpSnsFacebookDialogUpdateStatus(void); +int APS5_VABI sceNpSnsFacebookDialogGetStatus(void); +int APS5_VABI sceNpSnsFacebookDialogGetResult(void* result); +int APS5_VABI sceNpSnsFacebookDialogClose(void); +int APS5_VABI sceNpSnsFacebookDialogTerminate(void); + +} diff --git a/core/libs/prx/libSceNpSnsFacebookDialog/libSceNpSnsFacebookDialog.hpp b/core/libs/prx/libSceNpSnsFacebookDialog/libSceNpSnsFacebookDialog.hpp new file mode 100644 index 0000000000..0401a2b8be --- /dev/null +++ b/core/libs/prx/libSceNpSnsFacebookDialog/libSceNpSnsFacebookDialog.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceNpSnsFacebookDialog/include/Api.hpp" diff --git a/core/libs/prx/libSceNpSnsYouTubeDialog/Export.cpp b/core/libs/prx/libSceNpSnsYouTubeDialog/Export.cpp index e1b07d4bfc..8aacd8784b 100644 --- a/core/libs/prx/libSceNpSnsYouTubeDialog/Export.cpp +++ b/core/libs/prx/libSceNpSnsYouTubeDialog/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNpSnsYouTubeDialog/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceNpSnsYouTubeDialog/include/Api.hpp b/core/libs/prx/libSceNpSnsYouTubeDialog/include/Api.hpp new file mode 100644 index 0000000000..f2283cb2cf --- /dev/null +++ b/core/libs/prx/libSceNpSnsYouTubeDialog/include/Api.hpp @@ -0,0 +1,15 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceNpSnsYouTubeDialogClose(); +int APS5_VABI sceNpSnsYouTubeDialogGetResult(); +int APS5_VABI sceNpSnsYouTubeDialogGetStatus(); +int APS5_VABI sceNpSnsYouTubeDialogInitialize(); +int APS5_VABI sceNpSnsYouTubeDialogOpen(); +int APS5_VABI sceNpSnsYouTubeDialogTerminate(); +int APS5_VABI sceNpSnsYouTubeDialogUpdateStatus(); + +} diff --git a/core/libs/prx/libSceNpSnsYouTubeDialog/libSceNpSnsYouTubeDialog.hpp b/core/libs/prx/libSceNpSnsYouTubeDialog/libSceNpSnsYouTubeDialog.hpp new file mode 100644 index 0000000000..138afadcec --- /dev/null +++ b/core/libs/prx/libSceNpSnsYouTubeDialog/libSceNpSnsYouTubeDialog.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceNpSnsYouTubeDialog/include/Api.hpp" diff --git a/core/libs/prx/libSceNpSpeechToText/libSceNpSpeechToText.hpp b/core/libs/prx/libSceNpSpeechToText/libSceNpSpeechToText.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceNpSpeechToText/libSceNpSpeechToText.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceNpTcs/Export.cpp b/core/libs/prx/libSceNpTcs/Export.cpp index 483b8fa844..f496f8ffbf 100644 --- a/core/libs/prx/libSceNpTcs/Export.cpp +++ b/core/libs/prx/libSceNpTcs/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNpTcs/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceNpTcs/include/Api.hpp b/core/libs/prx/libSceNpTcs/include/Api.hpp new file mode 100644 index 0000000000..656b047bae --- /dev/null +++ b/core/libs/prx/libSceNpTcs/include/Api.hpp @@ -0,0 +1,11 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceNpTcsIntDownloadData(); +int APS5_VABI sceNpTcsIntUploadDataToNewSlotAbort(); +int APS5_VABI sceNpTcsIntUploadDataToNewSlotBegin(); + +} diff --git a/core/libs/prx/libSceNpTcs/libSceNpTcs.hpp b/core/libs/prx/libSceNpTcs/libSceNpTcs.hpp new file mode 100644 index 0000000000..cf84369ec2 --- /dev/null +++ b/core/libs/prx/libSceNpTcs/libSceNpTcs.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceNpTcs/include/Api.hpp" diff --git a/core/libs/prx/libSceNpTextToSpeech/libSceNpTextToSpeech.hpp b/core/libs/prx/libSceNpTextToSpeech/libSceNpTextToSpeech.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceNpTextToSpeech/libSceNpTextToSpeech.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceNpTrophy/Export.cpp b/core/libs/prx/libSceNpTrophy/Export.cpp index c7823fd4c5..80fa87ee3f 100644 --- a/core/libs/prx/libSceNpTrophy/Export.cpp +++ b/core/libs/prx/libSceNpTrophy/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNpTrophy/include/Api.hpp" #include #include #include @@ -30,88 +31,25 @@ constexpr int NP_TROPHY_ERROR_INVALID_TRP_FILE_FORMAT = static_cast(0x80551 constexpr int NP_TROPHY_ERROR_TROPHY_NOT_UNLOCKED = static_cast(0x8055161au); constexpr int NP_TROPHY_ERROR_TITLE_CONF_NOT_INSTALLED = static_cast(0x80551626u); constexpr int NP_TROPHY_INVALID_ID = -1; -constexpr int NP_TROPHY_NUM_MAX = 128; + constexpr int NP_TROPHY_GRADE_UNKNOWN = 0; constexpr int NP_TROPHY_BASE_GAME_GROUP_ID = -1; constexpr std::uint32_t TrpMagic = 0xdca24d00u; constexpr std::size_t TrpHeaderBytes = 0x60; constexpr std::size_t TrpEntryBytes = 0x40; -struct GameDetails { - std::uint64_t size; - std::uint32_t numGroups; - std::uint32_t numTrophies; - std::uint32_t numPlatinum; - std::uint32_t numGold; - std::uint32_t numSilver; - std::uint32_t numBronze; - char title[128]; - char description[1024]; -}; static_assert(sizeof(GameDetails) == 0x4a0); -struct GameData { - std::uint64_t size; - std::uint32_t unlockedTrophies; - std::uint32_t unlockedPlatinum; - std::uint32_t unlockedGold; - std::uint32_t unlockedSilver; - std::uint32_t unlockedBronze; - std::uint32_t progressPercentage; -}; static_assert(sizeof(GameData) == 0x20); -struct GroupDetails { - std::uint64_t size; - std::int32_t groupId; - std::uint32_t numTrophies; - std::uint32_t numPlatinum; - std::uint32_t numGold; - std::uint32_t numSilver; - std::uint32_t numBronze; - char title[128]; - char description[1024]; -}; static_assert(sizeof(GroupDetails) == 0x4a0); -struct GroupData { - std::uint64_t size; - std::int32_t groupId; - std::uint32_t unlockedTrophies; - std::uint32_t unlockedPlatinum; - std::uint32_t unlockedGold; - std::uint32_t unlockedSilver; - std::uint32_t unlockedBronze; - std::uint32_t progressPercentage; - std::uint8_t reserved[4]; -}; static_assert(sizeof(GroupData) == 0x28); -struct TrophyDetails { - std::uint64_t size; - std::int32_t trophyId; - std::int32_t trophyGrade; - std::int32_t groupId; - bool hidden; - std::uint8_t reserved[3]; - char name[128]; - char description[1024]; -}; static_assert(sizeof(TrophyDetails) == 0x498); -struct TrophyData { - std::uint64_t size; - std::int32_t trophyId; - bool unlocked; - std::uint8_t reserved[3]; - std::uint64_t timestamp; -}; static_assert(sizeof(TrophyData) == 0x18); -struct TrophyFlagArray { - std::uint32_t bits[NP_TROPHY_NUM_MAX / 32]; -}; - struct TrpEntry { std::uint64_t offset; std::uint64_t size; diff --git a/core/libs/prx/libSceNpTrophy/include/Api.hpp b/core/libs/prx/libSceNpTrophy/include/Api.hpp new file mode 100644 index 0000000000..6360184288 --- /dev/null +++ b/core/libs/prx/libSceNpTrophy/include/Api.hpp @@ -0,0 +1,92 @@ +#pragma once + +#include "SceTypes.hpp" + +inline constexpr int NP_TROPHY_NUM_MAX = 128; + +struct GameData { + std::uint64_t size; + std::uint32_t unlockedTrophies; + std::uint32_t unlockedPlatinum; + std::uint32_t unlockedGold; + std::uint32_t unlockedSilver; + std::uint32_t unlockedBronze; + std::uint32_t progressPercentage; +}; + +struct GameDetails { + std::uint64_t size; + std::uint32_t numGroups; + std::uint32_t numTrophies; + std::uint32_t numPlatinum; + std::uint32_t numGold; + std::uint32_t numSilver; + std::uint32_t numBronze; + char title[128]; + char description[1024]; +}; + +struct GroupData { + std::uint64_t size; + std::int32_t groupId; + std::uint32_t unlockedTrophies; + std::uint32_t unlockedPlatinum; + std::uint32_t unlockedGold; + std::uint32_t unlockedSilver; + std::uint32_t unlockedBronze; + std::uint32_t progressPercentage; + std::uint8_t reserved[4]; +}; + +struct GroupDetails { + std::uint64_t size; + std::int32_t groupId; + std::uint32_t numTrophies; + std::uint32_t numPlatinum; + std::uint32_t numGold; + std::uint32_t numSilver; + std::uint32_t numBronze; + char title[128]; + char description[1024]; +}; + +struct TrophyData { + std::uint64_t size; + std::int32_t trophyId; + bool unlocked; + std::uint8_t reserved[3]; + std::uint64_t timestamp; +}; + +struct TrophyDetails { + std::uint64_t size; + std::int32_t trophyId; + std::int32_t trophyGrade; + std::int32_t groupId; + bool hidden; + std::uint8_t reserved[3]; + char name[128]; + char description[1024]; +}; + +struct TrophyFlagArray { + std::uint32_t bits[NP_TROPHY_NUM_MAX / 32]; +}; + +extern "C" { + +int APS5_VABI sceNpTrophyCreateContext(int* context, int userId, std::uint32_t serviceLabel, std::uint64_t options); +int APS5_VABI sceNpTrophyDestroyContext(int context); +int APS5_VABI sceNpTrophyCreateHandle(int* handle); +int APS5_VABI sceNpTrophyDestroyHandle(int handle); +int APS5_VABI sceNpTrophyRegisterContext(int contextId, int handle, std::uint64_t options); +int APS5_VABI sceNpTrophyGetTrophyUnlockState(int contextId, int handle, TrophyFlagArray* flags, std::uint32_t* count); +int APS5_VABI sceNpTrophyUnlockTrophy(int contextId, int handle, int trophyId, int* platinumId); +int APS5_VABI sceNpTrophyGetGameIcon(int contextId, int handle, void* buffer, std::uint64_t* size); +int APS5_VABI sceNpTrophyGetGroupIcon(int contextId, int handle, int groupId, void* buffer, std::uint64_t* size); +int APS5_VABI sceNpTrophyGetTrophyIcon(int contextId, int handle, int trophyId, void* buffer, std::uint64_t* size); +int APS5_VABI sceNpTrophyGetGameInfo(int contextId, int handle, GameDetails* details, GameData* data); +int APS5_VABI sceNpTrophyGetGroupInfo(int contextId, int handle, int groupId, GroupDetails* details, GroupData* data); +int APS5_VABI sceNpTrophyGetTrophyInfo(int contextId, int handle, int trophyId, TrophyDetails* details, TrophyData* data); + +} diff --git a/core/libs/prx/libSceNpTrophy/libSceNpTrophy.hpp b/core/libs/prx/libSceNpTrophy/libSceNpTrophy.hpp new file mode 100644 index 0000000000..f808efbd11 --- /dev/null +++ b/core/libs/prx/libSceNpTrophy/libSceNpTrophy.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceNpTrophy/include/Api.hpp" diff --git a/core/libs/prx/libSceNpTrophy2/Export.cpp b/core/libs/prx/libSceNpTrophy2/Export.cpp index 9befeb73c9..8a46b8a803 100644 --- a/core/libs/prx/libSceNpTrophy2/Export.cpp +++ b/core/libs/prx/libSceNpTrophy2/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNpTrophy2/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceNpTrophy2/include/Api.hpp b/core/libs/prx/libSceNpTrophy2/include/Api.hpp new file mode 100644 index 0000000000..052446ff82 --- /dev/null +++ b/core/libs/prx/libSceNpTrophy2/include/Api.hpp @@ -0,0 +1,50 @@ +#pragma once + +#include "prx/libSceNpTrophy2/include/NpTrophy2Types.hpp" +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceNpTrophy2SystemAbortHandle(void); +int APS5_VABI sceNpTrophy2SystemBuildGroupIconUri(void); +int APS5_VABI sceNpTrophy2SystemBuildRewardIconUri(void); +int APS5_VABI sceNpTrophy2SystemBuildTrophyIconUri(void); +int APS5_VABI sceNpTrophy2SystemCheckCallback(void); +int APS5_VABI sceNpTrophy2SystemCheckNetSyncTitles(void); +int APS5_VABI sceNpTrophy2SystemCreateContext(void); +int APS5_VABI sceNpTrophy2SystemCreateHandle(void); +int APS5_VABI sceNpTrophy2SystemDebugLockTrophy(void); +int APS5_VABI sceNpTrophy2SystemDebugUnlockTrophy(void); +int APS5_VABI sceNpTrophy2SystemDestroyContext(void); +int APS5_VABI sceNpTrophy2SystemGetTrophyDetails(void); +int APS5_VABI sceNpTrophy2SystemGetTrophyGroupConf(void); +int APS5_VABI sceNpTrophy2SystemGetTrophySetArray(void); +int APS5_VABI sceNpTrophy2SystemGetTrophyTitleConf(void); +int APS5_VABI sceNpTrophy2SystemGetTrophyTitleDetails(void); +int APS5_VABI sceNpTrophy2SystemGetTrpIconByUri(void); +int APS5_VABI sceNpTrophy2SystemIsServerAvailable(void); +int APS5_VABI sceNpTrophy2SystemRegisterTitleSyncedCallback(void); +int APS5_VABI sceNpTrophy2SystemRegisterTitleUpdateCallback(void); +int APS5_VABI sceNpTrophy2SystemRemoveAll(void); +int APS5_VABI sceNpTrophy2SystemRemoveTitleData(void); +int APS5_VABI sceNpTrophy2SystemRemoveUserData(void); +int APS5_VABI sceNpTrophy2CreateContext(int* context, int userId, uint32_t serviceLabel, uint64_t options); +int APS5_VABI sceNpTrophy2DestroyContext(int context); +int APS5_VABI sceNpTrophy2RegisterContext(int context, int handle, uint64_t options); +int APS5_VABI sceNpTrophy2UnregisterUnlockCallback(); +int APS5_VABI sceNpTrophy2GetRewardIcon(int context, int handle, int rewardId, void* buffer, size_t* size); +int APS5_VABI sceNpTrophy2ShowTrophyList(int context); +int APS5_VABI sceNpTrophy2GetGameInfo(int context, int handle, NpTrophy2GameDetails* details, NpTrophy2GameData* data); +int APS5_VABI sceNpTrophy2GetGameIcon(int context, int handle, void* buffer, size_t* size); +int APS5_VABI sceNpTrophy2RegisterUnlockCallback(void* callback, void* userdata); +int APS5_VABI sceNpTrophy2GetGroupInfo(int context, int handle, int groupId, NpTrophy2GroupDetails* details, NpTrophy2GroupData* data); +int APS5_VABI sceNpTrophy2GetGroupInfoArray(int context, int handle, uint32_t offset, uint32_t limit, NpTrophy2GroupDetails* detailsArray, NpTrophy2GroupData* dataArray, uint32_t* count); +int APS5_VABI sceNpTrophy2GetGroupIcon(int context, int handle, int groupId, void* buffer, size_t* size); +int APS5_VABI sceNpTrophy2CreateHandle(int* handle); +int APS5_VABI sceNpTrophy2DestroyHandle(int handle); +int APS5_VABI sceNpTrophy2AbortHandle(int handle); +int APS5_VABI sceNpTrophy2GetTrophyInfo(int context, int handle, int trophyId, NpTrophy2Details* details, NpTrophy2Data* data); +int APS5_VABI sceNpTrophy2GetTrophyInfoArray(int context, int handle, uint32_t offset, uint32_t limit, NpTrophy2Details* detailsArray, NpTrophy2Data* dataArray, uint32_t* count); +int APS5_VABI sceNpTrophy2GetTrophyIcon(int context, int handle, int trophyId, void* buffer, size_t* size); + +} diff --git a/core/libs/prx/libSceNpTrophy2/libSceNpTrophy2.hpp b/core/libs/prx/libSceNpTrophy2/libSceNpTrophy2.hpp new file mode 100644 index 0000000000..09c653d06d --- /dev/null +++ b/core/libs/prx/libSceNpTrophy2/libSceNpTrophy2.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceNpTrophy2/include/Api.hpp" diff --git a/core/libs/prx/libSceNpTrophy2/src/Context.cpp b/core/libs/prx/libSceNpTrophy2/src/Context.cpp index f59a014de6..8e623d8c36 100644 --- a/core/libs/prx/libSceNpTrophy2/src/Context.cpp +++ b/core/libs/prx/libSceNpTrophy2/src/Context.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNpTrophy2/include/Api.hpp" #include #include #include @@ -77,7 +78,6 @@ int APS5_VABI sceNpTrophy2UnregisterUnlockCallback() { return SCE_NP_TROPHY2_OK; } - int APS5_VABI sceNpTrophy2GetRewardIcon(int context, int handle, int reward_id, void* buffer, size_t* size) { (void)context; (void)handle; diff --git a/core/libs/prx/libSceNpTrophy2/src/GameInfo.cpp b/core/libs/prx/libSceNpTrophy2/src/GameInfo.cpp index dc11f536ef..4e7c771003 100644 --- a/core/libs/prx/libSceNpTrophy2/src/GameInfo.cpp +++ b/core/libs/prx/libSceNpTrophy2/src/GameInfo.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNpTrophy2/include/Api.hpp" #include #include #include diff --git a/core/libs/prx/libSceNpTrophy2/src/GroupInfo.cpp b/core/libs/prx/libSceNpTrophy2/src/GroupInfo.cpp index 887423ddc8..d06dc60177 100644 --- a/core/libs/prx/libSceNpTrophy2/src/GroupInfo.cpp +++ b/core/libs/prx/libSceNpTrophy2/src/GroupInfo.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNpTrophy2/include/Api.hpp" #include #include #include diff --git a/core/libs/prx/libSceNpTrophy2/src/Handle.cpp b/core/libs/prx/libSceNpTrophy2/src/Handle.cpp index 3f65f5887e..64013be3d6 100644 --- a/core/libs/prx/libSceNpTrophy2/src/Handle.cpp +++ b/core/libs/prx/libSceNpTrophy2/src/Handle.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNpTrophy2/include/Api.hpp" #include #include diff --git a/core/libs/prx/libSceNpTrophy2/src/TrophyInfo.cpp b/core/libs/prx/libSceNpTrophy2/src/TrophyInfo.cpp index cc32a75483..1cabae19e7 100644 --- a/core/libs/prx/libSceNpTrophy2/src/TrophyInfo.cpp +++ b/core/libs/prx/libSceNpTrophy2/src/TrophyInfo.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNpTrophy2/include/Api.hpp" #include #include #include diff --git a/core/libs/prx/libSceNpTrophy2/tests/TrophyStore.cpp b/core/libs/prx/libSceNpTrophy2/tests/TrophyStore.cpp index 10352c9edf..5a70852cc0 100644 --- a/core/libs/prx/libSceNpTrophy2/tests/TrophyStore.cpp +++ b/core/libs/prx/libSceNpTrophy2/tests/TrophyStore.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNpTrophy2/include/Api.hpp" #include "prx/libSceNpTrophy2/include/NpTrophy2Types.hpp" #include "prx/libSceNpTrophy2/include/TitleTrophies.hpp" #include "prx/libSceNpTrophy2/include/TrophyStore.hpp" @@ -23,14 +24,6 @@ #include #endif -extern "C" { -int APS5_VABI sceNpTrophy2CreateContext(int*, int, uint32_t, uint64_t); -int APS5_VABI sceNpTrophy2DestroyContext(int); -int APS5_VABI sceNpTrophy2GetGameInfo(int, int, NpTrophy2GameDetails*, NpTrophy2GameData*); -int APS5_VABI sceNpTrophy2GetTrophyInfo(int, int, int, NpTrophy2Details*, NpTrophy2Data*); -int APS5_VABI sceNpTrophy2GetTrophyInfoArray(int, int, uint32_t, uint32_t, NpTrophy2Details*, NpTrophy2Data*, uint32_t*); -} - namespace { constexpr std::int32_t InitialUser = 0x10000000; @@ -246,7 +239,6 @@ void testQueries() { check(sceNpTrophy2DestroyContext(context) == 0 && sceNpTrophy2DestroyContext(other) == 0, "contexts were not destroyed"); } - void testPostedUnlockRules() { std::filesystem::create_directories("app0/sce_sys/trophy2"); std::filesystem::create_directories("app0/sce_sys/uds"); diff --git a/core/libs/prx/libSceNpTus/Export.cpp b/core/libs/prx/libSceNpTus/Export.cpp index da02e06801..6bf0782927 100644 --- a/core/libs/prx/libSceNpTus/Export.cpp +++ b/core/libs/prx/libSceNpTus/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNpTus/include/Api.hpp" #include #include #include diff --git a/core/libs/prx/libSceNpTus/include/Api.hpp b/core/libs/prx/libSceNpTus/include/Api.hpp new file mode 100644 index 0000000000..b4e6807d5e --- /dev/null +++ b/core/libs/prx/libSceNpTus/include/Api.hpp @@ -0,0 +1,150 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceNpTusCreateNpTitleCtxA(std::uint32_t serviceLabel, int userId); +int APS5_VABI sceNpTusCreateRequest(int titleCtxId); +int APS5_VABI sceNpTusDeleteNpTitleCtx(int titleCtxId); +int APS5_VABI sceNpTusDeleteRequest(int reqId); +int APS5_VABI sceNpTusAbortRequest(int reqId); +int APS5_VABI sceNpTusPollAsync(int reqId, int* result); +int APS5_VABI sceNpTusGetMultiSlotVariableAAsync(int reqId, std::uint64_t targetAccountId, const std::int32_t* slotIds, void* variableArray, std::uint64_t variableArraySize, int arrayLen, void* option); +int APS5_VABI sceNpTusSetMultiSlotVariableAAsync(int reqId, std::uint64_t targetAccountId, const std::int32_t* slotIds, const std::int64_t* variableArray, int arrayLen, void* option); +int APS5_VABI sceNpTusDeleteMultiSlotVariableAAsync(int reqId, std::uint64_t targetAccountId, const std::int32_t* slotIds, int arrayLen, void* option); +int APS5_VABI sceNpTusAddAndGetVariableAAsync(int reqId, std::uint64_t targetAccountId, std::int32_t slotId, std::int64_t inVariable, const std::uint64_t* isLastChangedAuthor, const void* isLastChangedDate, void* outVariable, std::uint64_t outVariableSize, void* option); +int APS5_VABI sceNpTusSetThreadParam(void); +int APS5_VABI sceNpTssCreateNpTitleCtx(std::uint32_t serviceLabel, const NpId* npId); +int APS5_VABI sceNpTssCreateNpTitleCtxA(std::uint32_t serviceLabel, int userId); +int APS5_VABI sceNpTusCreateTitleCtx(void); +int APS5_VABI sceNpTusSetTimeout(void); +int APS5_VABI sceNpTusChangeModeForOtherSaveDataOwners(void); +int APS5_VABI sceNpTusWaitAsync(int reqId, int* result); +int APS5_VABI sceNpTusGetMultiSlotVariableA(int reqId, std::uint64_t targetAccountId, const std::int32_t* slotIds, void* variableArray, std::uint64_t variableArraySize, int arrayLen, void* option); +int APS5_VABI sceNpTusGetMultiSlotVariableAsync(int reqId, const void* targetNpId, const std::int32_t* slotIds, void* variableArray, std::uint64_t variableArraySize, int arrayLen, void* option); +int APS5_VABI sceNpTusGetMultiSlotVariableVUserAsync(int reqId, const NpOnlineId* targetVirtualUserId, const std::int32_t* slotIds, void* variableArray, std::uint64_t variableArraySize, int arrayLen, void* option); +int APS5_VABI sceNpTusGetMultiSlotVariableAVUserAsync(int reqId, const NpOnlineId* targetVirtualUserId, const std::int32_t* slotIds, void* variableArray, std::uint64_t variableArraySize, int arrayLen, void* option); +int APS5_VABI sceNpTusGetMultiSlotVariableAVUser(int reqId, const NpOnlineId* targetVirtualUserId, const std::int32_t* slotIds, void* variableArray, std::uint64_t variableArraySize, int arrayLen, void* option); +int APS5_VABI sceNpTusGetMultiSlotVariableForCrossSaveAsync(int reqId, std::uint64_t targetAccountId, const std::int32_t* slotIds, void* variableArray, std::uint64_t variableArraySize, int arrayLen, void* option); +int APS5_VABI sceNpTusGetMultiSlotVariableForCrossSave(int reqId, std::uint64_t targetAccountId, const std::int32_t* slotIds, void* variableArray, std::uint64_t variableArraySize, int arrayLen, void* option); +int APS5_VABI sceNpTusGetMultiSlotVariableForCrossSaveVUserAsync(int reqId, const NpOnlineId* targetVirtualUserId, const std::int32_t* slotIds, void* variableArray, std::uint64_t variableArraySize, int arrayLen, void* option); +int APS5_VABI sceNpTusGetMultiSlotVariableForCrossSaveVUser(int reqId, const NpOnlineId* targetVirtualUserId, const std::int32_t* slotIds, void* variableArray, std::uint64_t variableArraySize, int arrayLen, void* option); +int APS5_VABI sceNpTusSetMultiSlotVariableA(int reqId, std::uint64_t targetAccountId, const std::int32_t* slotIds, const std::int64_t* variableArray, int arrayLen, void* option); +int APS5_VABI sceNpTusSetMultiSlotVariableAsync(int reqId, const void* targetNpId, const std::int32_t* slotIds, const std::int64_t* variableArray, int arrayLen, void* option); +int APS5_VABI sceNpTusSetMultiSlotVariableVUserAsync(int reqId, const NpOnlineId* targetVirtualUserId, const std::int32_t* slotIds, const std::int64_t* variableArray, int arrayLen, void* option); +int APS5_VABI sceNpTusDeleteMultiSlotVariableA(int reqId, std::uint64_t targetAccountId, const std::int32_t* slotIds, int arrayLen, void* option); +int APS5_VABI sceNpTusDeleteMultiSlotVariableAsync(int reqId, const void* targetNpId, const std::int32_t* slotIds, int arrayLen, void* option); +int APS5_VABI sceNpTusDeleteMultiSlotVariable(int reqId, const void* targetNpId, const std::int32_t* slotIds, int arrayLen, void* option); +int APS5_VABI sceNpTusDeleteMultiSlotVariableVUserAsync(int reqId, const NpOnlineId* targetVirtualUserId, const std::int32_t* slotIds, int arrayLen, void* option); +int APS5_VABI sceNpTusDeleteMultiSlotVariableVUser(int reqId, const NpOnlineId* targetVirtualUserId, const std::int32_t* slotIds, int arrayLen, void* option); +int APS5_VABI sceNpTusDeleteMultiSlotDataVUser(void); +int APS5_VABI sceNpTusDeleteMultiSlotDataVUserAsync(void); +int APS5_VABI sceNpTssGetStorage(void); +int APS5_VABI sceNpTssGetStorageAsync(void); +int APS5_VABI sceNpTssGetDataAsync(void); +int APS5_VABI sceNpTusGetDataForCrossSaveVUser(void); +int APS5_VABI sceNpTusGetDataForCrossSaveVUserAsync(void); +int APS5_VABI sceNpTusGetMultiUserVariableForCrossSave(void); +int APS5_VABI sceNpTusGetFriendsVariableA(void); +int APS5_VABI sceNpTusGetFriendsVariableAAsync(void); +int APS5_VABI sceNpTusGetFriendsVariableForCrossSave(void); +int APS5_VABI sceNpTusGetFriendsVariableForCrossSaveAsync(void); +int APS5_VABI sceNpTusGetFriendsDataStatusA(void); +int APS5_VABI sceNpTusGetFriendsDataStatusAAsync(void); +int APS5_VABI sceNpTusGetFriendsDataStatusForCrossSave(void); +int APS5_VABI sceNpTusGetFriendsDataStatusForCrossSaveAsync(void); +int APS5_VABI sceNpTssGetSmallStorageAsync(int reqId, void* data, std::uint64_t maxSize, std::uint64_t* contentLength, void* option); +int APS5_VABI sceNpTusAddAndGetVariableAVUserAsync(int reqId, const NpOnlineId* targetVirtualUserId, std::int32_t slotId, std::int64_t inVariable, const std::uint64_t* isLastChangedAuthor, const void* isLastChangedDate, void* outVariable, std::uint64_t outVariableSize, void* option); +int APS5_VABI sceNpTusAddAndGetVariableAsync(int reqId, const void* targetNpId, std::int32_t slotId, std::int64_t inVariable, const void* isLastChangedAuthor, const void* isLastChangedDate, void* outVariable, std::uint64_t outVariableSize, void* option); +int APS5_VABI sceNpTusAddAndGetVariableForCrossSaveAsync(int reqId, std::uint64_t targetAccountId, std::int32_t slotId, std::int64_t inVariable, const std::uint64_t* isLastChangedAuthor, const void* isLastChangedDate, void* outVariable, std::uint64_t outVariableSize, void* option); +int APS5_VABI sceNpTusAddAndGetVariableForCrossSaveVUserAsync(int reqId, const NpOnlineId* targetVirtualUserId, std::int32_t slotId, std::int64_t inVariable, const std::uint64_t* isLastChangedAuthor, const void* isLastChangedDate, void* outVariable, std::uint64_t outVariableSize, void* option); +int APS5_VABI sceNpTusAddAndGetVariableVUserAsync(int reqId, const NpOnlineId* targetVirtualUserId, std::int32_t slotId, std::int64_t inVariable, const void* isLastChangedAuthor, const void* isLastChangedDate, void* outVariable, std::uint64_t outVariableSize, void* option); +int APS5_VABI sceNpTusDeleteMultiSlotDataAAsync(int reqId, std::uint64_t targetAccountId, const std::int32_t* slotIds, int arrayLen, void* option); +int APS5_VABI sceNpTusDeleteMultiSlotDataAsync(int reqId, const void* targetNpId, const std::int32_t* slotIds, int arrayLen, void* option); +int APS5_VABI sceNpTusGetDataAAsync(int reqId, std::uint64_t targetAccountId, std::int32_t slotId, void* dataStatus, std::uint64_t dataStatusSize, void* data, std::uint64_t recvSize, void* option); +int APS5_VABI sceNpTusGetDataAVUserAsync(int reqId, const NpOnlineId* targetVirtualUserId, std::int32_t slotId, void* dataStatus, std::uint64_t dataStatusSize, void* data, std::uint64_t recvSize, void* option); +int APS5_VABI sceNpTusGetDataAsync(int reqId, const void* targetNpId, std::int32_t slotId, void* dataStatus, std::uint64_t dataStatusSize, void* data, std::uint64_t recvSize, void* option); +int APS5_VABI sceNpTusGetDataForCrossSaveAsync(int reqId, std::uint64_t targetAccountId, std::int32_t slotId, void* dataStatus, std::uint64_t dataStatusSize, void* data, std::uint64_t recvSize, void* option); +int APS5_VABI sceNpTusGetDataVUserAsync(int reqId, const NpOnlineId* targetVirtualUserId, std::int32_t slotId, void* dataStatus, std::uint64_t dataStatusSize, void* data, std::uint64_t recvSize, void* option); +int APS5_VABI sceNpTusGetFriendsDataStatusAsync(int reqId, std::int32_t slotId, std::int32_t includeSelf, std::int32_t sortType, void* statusArray, std::uint64_t statusArraySize, int arrayLen, void* option); +int APS5_VABI sceNpTusGetFriendsVariableAsync(int reqId, std::int32_t slotId, std::int32_t includeSelf, std::int32_t sortType, void* variableArray, std::uint64_t variableArraySize, int arrayLen, void* option); +int APS5_VABI sceNpTusGetMultiSlotDataStatusAAsync(int reqId, std::uint64_t targetAccountId, const std::int32_t* slotIds, void* statusArray, std::uint64_t statusArraySize, int arrayLen, void* option); +int APS5_VABI sceNpTusGetMultiSlotDataStatusAVUserAsync(int reqId, const NpOnlineId* targetVirtualUserId, const std::int32_t* slotIds, void* statusArray, std::uint64_t statusArraySize, int arrayLen, void* option); +int APS5_VABI sceNpTusGetMultiSlotDataStatusAsync(int reqId, const void* targetNpId, const std::int32_t* slotIds, void* statusArray, std::uint64_t statusArraySize, int arrayLen, void* option); +int APS5_VABI sceNpTusGetMultiSlotDataStatusForCrossSaveAsync(int reqId, std::uint64_t targetAccountId, const std::int32_t* slotIds, void* statusArray, std::uint64_t statusArraySize, int arrayLen, void* option); +int APS5_VABI sceNpTusGetMultiSlotDataStatusForCrossSaveVUserAsync(int reqId, const NpOnlineId* targetVirtualUserId, const std::int32_t* slotIds, void* statusArray, std::uint64_t statusArraySize, int arrayLen, void* option); +int APS5_VABI sceNpTusGetMultiSlotDataStatusVUserAsync(int reqId, const NpOnlineId* targetVirtualUserId, const std::int32_t* slotIds, void* statusArray, std::uint64_t statusArraySize, int arrayLen, void* option); +int APS5_VABI sceNpTusGetMultiUserDataStatusAAsync(int reqId, const std::uint64_t* targetAccountIdArray, std::int32_t slotId, void* statusArray, std::uint64_t statusArraySize, int arrayLen, void* option); +int APS5_VABI sceNpTusGetMultiUserDataStatusAVUserAsync(int reqId, const NpOnlineId* targetVirtualUserIdArray, std::int32_t slotId, void* statusArray, std::uint64_t statusArraySize, int arrayLen, void* option); +int APS5_VABI sceNpTusGetMultiUserDataStatusAsync(int reqId, const void* targetNpIdArray, std::int32_t slotId, void* statusArray, std::uint64_t statusArraySize, int arrayLen, void* option); +int APS5_VABI sceNpTusGetMultiUserDataStatusForCrossSaveAsync(int reqId, const std::uint64_t* targetAccountIdArray, std::int32_t slotId, void* statusArray, std::uint64_t statusArraySize, int arrayLen, void* option); +int APS5_VABI sceNpTusGetMultiUserDataStatusForCrossSaveVUserAsync(int reqId, const NpOnlineId* targetVirtualUserIdArray, std::int32_t slotId, void* statusArray, std::uint64_t statusArraySize, int arrayLen, void* option); +int APS5_VABI sceNpTusGetMultiUserDataStatusVUserAsync(int reqId, const NpOnlineId* targetVirtualUserIdArray, std::int32_t slotId, void* statusArray, std::uint64_t statusArraySize, int arrayLen, void* option); +int APS5_VABI sceNpTusGetMultiUserVariableAAsync(int reqId, const std::uint64_t* targetAccountIdArray, std::int32_t slotId, void* variableArray, std::uint64_t variableArraySize, int arrayLen, void* option); +int APS5_VABI sceNpTusGetMultiUserVariableAVUserAsync(int reqId, const NpOnlineId* targetVirtualUserIdArray, std::int32_t slotId, void* variableArray, std::uint64_t variableArraySize, int arrayLen, void* option); +int APS5_VABI sceNpTusGetMultiUserVariableAsync(int reqId, const void* targetNpIdArray, std::int32_t slotId, void* variableArray, std::uint64_t variableArraySize, int arrayLen, void* option); +int APS5_VABI sceNpTusGetMultiUserVariableForCrossSaveAsync(int reqId, const std::uint64_t* targetAccountIdArray, std::int32_t slotId, void* variableArray, std::uint64_t variableArraySize, int arrayLen, void* option); +int APS5_VABI sceNpTusGetMultiUserVariableForCrossSaveVUserAsync(int reqId, const NpOnlineId* targetVirtualUserIdArray, std::int32_t slotId, void* variableArray, std::uint64_t variableArraySize, int arrayLen, void* option); +int APS5_VABI sceNpTusGetMultiUserVariableVUserAsync(int reqId, const NpOnlineId* targetVirtualUserIdArray, std::int32_t slotId, void* variableArray, std::uint64_t variableArraySize, int arrayLen, void* option); +int APS5_VABI sceNpTusSetDataAAsync(int reqId, std::uint64_t targetAccountId, std::int32_t slotId, std::uint64_t totalSize, std::uint64_t sendSize, const void* data, const void* info, std::uint64_t infoStructSize, const std::uint64_t* isLastChangedAuthor, const void* isLastChangedDate, void* option); +int APS5_VABI sceNpTusSetDataAVUserAsync(int reqId, const NpOnlineId* targetVirtualUserId, std::int32_t slotId, std::uint64_t totalSize, std::uint64_t sendSize, const void* data, const void* info, std::uint64_t infoStructSize, const std::uint64_t* isLastChangedAuthor, const void* isLastChangedDate, void* option); +int APS5_VABI sceNpTusSetDataAsync(int reqId, const void* targetNpId, std::int32_t slotId, std::uint64_t totalSize, std::uint64_t sendSize, const void* data, const void* info, std::uint64_t infoStructSize, const void* isLastChangedAuthor, const void* isLastChangedDate, void* option); +int APS5_VABI sceNpTusSetDataVUserAsync(int reqId, const NpOnlineId* targetVirtualUserId, std::int32_t slotId, std::uint64_t totalSize, std::uint64_t sendSize, const void* data, const void* info, std::uint64_t infoStructSize, const void* isLastChangedAuthor, const void* isLastChangedDate, void* option); +int APS5_VABI sceNpTusTryAndSetVariableAAsync(int reqId, std::uint64_t targetAccountId, std::int32_t slotId, std::int32_t opeType, std::int64_t variable, const std::int64_t* compareValue, const std::uint64_t* isLastChangedAuthor, const void* isLastChangedDate, void* resultVariable, std::uint64_t resultVariableSize, void* option); +int APS5_VABI sceNpTusTryAndSetVariableAVUserAsync(int reqId, const NpOnlineId* targetVirtualUserId, std::int32_t slotId, std::int32_t opeType, std::int64_t variable, const std::int64_t* compareValue, const std::uint64_t* isLastChangedAuthor, const void* isLastChangedDate, void* resultVariable, std::uint64_t resultVariableSize, void* option); +int APS5_VABI sceNpTusTryAndSetVariableAsync(int reqId, const void* targetNpId, std::int32_t slotId, std::int32_t opeType, std::int64_t variable, const std::int64_t* compareValue, const void* isLastChangedAuthor, const void* isLastChangedDate, void* resultVariable, std::uint64_t resultVariableSize, void* option); +int APS5_VABI sceNpTusTryAndSetVariableForCrossSaveAsync(int reqId, std::uint64_t targetAccountId, std::int32_t slotId, std::int32_t opeType, std::int64_t variable, const std::int64_t* compareValue, const std::uint64_t* isLastChangedAuthor, const void* isLastChangedDate, void* resultVariable, std::uint64_t resultVariableSize, void* option); +int APS5_VABI sceNpTusTryAndSetVariableForCrossSaveVUserAsync(int reqId, const NpOnlineId* targetVirtualUserId, std::int32_t slotId, std::int32_t opeType, std::int64_t variable, const std::int64_t* compareValue, const std::uint64_t* isLastChangedAuthor, const void* isLastChangedDate, void* resultVariable, std::uint64_t resultVariableSize, void* option); +int APS5_VABI sceNpTusTryAndSetVariableVUserAsync(int reqId, const NpOnlineId* targetVirtualUserId, std::int32_t slotId, std::int32_t opeType, std::int64_t variable, const std::int64_t* compareValue, const void* isLastChangedAuthor, const void* isLastChangedDate, void* resultVariable, std::uint64_t resultVariableSize, void* option); +int APS5_VABI sceNpTssGetSmallStorage(int reqId, void* data, std::uint64_t maxSize, std::uint64_t* contentLength, void* option); +int APS5_VABI sceNpTusAddAndGetVariable(int reqId, const void* targetNpId, std::int32_t slotId, std::int64_t inVariable, const void* isLastChangedAuthor, const void* isLastChangedDate, void* outVariable, std::uint64_t outVariableSize, void* option); +int APS5_VABI sceNpTusAddAndGetVariableA(int reqId, std::uint64_t targetAccountId, std::int32_t slotId, std::int64_t inVariable, const std::uint64_t* isLastChangedAuthor, const void* isLastChangedDate, void* outVariable, std::uint64_t outVariableSize, void* option); +int APS5_VABI sceNpTusAddAndGetVariableAVUser(int reqId, const NpOnlineId* targetVirtualUserId, std::int32_t slotId, std::int64_t inVariable, const std::uint64_t* isLastChangedAuthor, const void* isLastChangedDate, void* outVariable, std::uint64_t outVariableSize, void* option); +int APS5_VABI sceNpTusAddAndGetVariableForCrossSave(int reqId, std::uint64_t targetAccountId, std::int32_t slotId, std::int64_t inVariable, const std::uint64_t* isLastChangedAuthor, const void* isLastChangedDate, void* outVariable, std::uint64_t outVariableSize, void* option); +int APS5_VABI sceNpTusAddAndGetVariableForCrossSaveVUser(int reqId, const NpOnlineId* targetVirtualUserId, std::int32_t slotId, std::int64_t inVariable, const std::uint64_t* isLastChangedAuthor, const void* isLastChangedDate, void* outVariable, std::uint64_t outVariableSize, void* option); +int APS5_VABI sceNpTusAddAndGetVariableVUser(int reqId, const NpOnlineId* targetVirtualUserId, std::int32_t slotId, std::int64_t inVariable, const void* isLastChangedAuthor, const void* isLastChangedDate, void* outVariable, std::uint64_t outVariableSize, void* option); +int APS5_VABI sceNpTusDeleteMultiSlotData(int reqId, const void* targetNpId, const std::int32_t* slotIds, int arrayLen, void* option); +int APS5_VABI sceNpTusDeleteMultiSlotDataA(int reqId, std::uint64_t targetAccountId, const std::int32_t* slotIds, int arrayLen, void* option); +int APS5_VABI sceNpTusGetDataA(int reqId, std::uint64_t targetAccountId, std::int32_t slotId, void* dataStatus, std::uint64_t dataStatusSize, void* data, std::uint64_t recvSize, void* option); +int APS5_VABI sceNpTusGetDataAVUser(int reqId, const NpOnlineId* targetVirtualUserId, std::int32_t slotId, void* dataStatus, std::uint64_t dataStatusSize, void* data, std::uint64_t recvSize, void* option); +int APS5_VABI sceNpTusGetDataForCrossSave(int reqId, std::uint64_t targetAccountId, std::int32_t slotId, void* dataStatus, std::uint64_t dataStatusSize, void* data, std::uint64_t recvSize, void* option); +int APS5_VABI sceNpTusGetFriendsDataStatus(int reqId, std::int32_t slotId, std::int32_t includeSelf, std::int32_t sortType, void* statusArray, std::uint64_t statusArraySize, int arrayLen, void* option); +int APS5_VABI sceNpTusGetFriendsVariable(int reqId, std::int32_t slotId, std::int32_t includeSelf, std::int32_t sortType, void* variableArray, std::uint64_t variableArraySize, int arrayLen, void* option); +int APS5_VABI sceNpTusGetMultiSlotDataStatus(int reqId, const void* targetNpId, const std::int32_t* slotIds, void* statusArray, std::uint64_t statusArraySize, int arrayLen, void* option); +int APS5_VABI sceNpTusGetMultiSlotDataStatusA(int reqId, std::uint64_t targetAccountId, const std::int32_t* slotIds, void* statusArray, std::uint64_t statusArraySize, int arrayLen, void* option); +int APS5_VABI sceNpTusGetMultiSlotDataStatusAVUser(int reqId, const NpOnlineId* targetVirtualUserId, const std::int32_t* slotIds, void* statusArray, std::uint64_t statusArraySize, int arrayLen, void* option); +int APS5_VABI sceNpTusGetMultiSlotDataStatusForCrossSave(int reqId, std::uint64_t targetAccountId, const std::int32_t* slotIds, void* statusArray, std::uint64_t statusArraySize, int arrayLen, void* option); +int APS5_VABI sceNpTusGetMultiSlotDataStatusForCrossSaveVUser(int reqId, const NpOnlineId* targetVirtualUserId, const std::int32_t* slotIds, void* statusArray, std::uint64_t statusArraySize, int arrayLen, void* option); +int APS5_VABI sceNpTusGetMultiSlotDataStatusVUser(int reqId, const NpOnlineId* targetVirtualUserId, const std::int32_t* slotIds, void* statusArray, std::uint64_t statusArraySize, int arrayLen, void* option); +int APS5_VABI sceNpTusGetMultiUserDataStatus(int reqId, const void* targetNpIdArray, std::int32_t slotId, void* statusArray, std::uint64_t statusArraySize, int arrayLen, void* option); +int APS5_VABI sceNpTusGetMultiUserDataStatusA(int reqId, const std::uint64_t* targetAccountIdArray, std::int32_t slotId, void* statusArray, std::uint64_t statusArraySize, int arrayLen, void* option); +int APS5_VABI sceNpTusGetMultiUserDataStatusAVUser(int reqId, const NpOnlineId* targetVirtualUserIdArray, std::int32_t slotId, void* statusArray, std::uint64_t statusArraySize, int arrayLen, void* option); +int APS5_VABI sceNpTusGetMultiUserDataStatusForCrossSave(int reqId, const std::uint64_t* targetAccountIdArray, std::int32_t slotId, void* statusArray, std::uint64_t statusArraySize, int arrayLen, void* option); +int APS5_VABI sceNpTusGetMultiUserDataStatusForCrossSaveVUser(int reqId, const NpOnlineId* targetVirtualUserIdArray, std::int32_t slotId, void* statusArray, std::uint64_t statusArraySize, int arrayLen, void* option); +int APS5_VABI sceNpTusGetMultiUserDataStatusVUser(int reqId, const NpOnlineId* targetVirtualUserIdArray, std::int32_t slotId, void* statusArray, std::uint64_t statusArraySize, int arrayLen, void* option); +int APS5_VABI sceNpTusGetMultiUserVariable(int reqId, const void* targetNpIdArray, std::int32_t slotId, void* variableArray, std::uint64_t variableArraySize, int arrayLen, void* option); +int APS5_VABI sceNpTusGetMultiUserVariableA(int reqId, const std::uint64_t* targetAccountIdArray, std::int32_t slotId, void* variableArray, std::uint64_t variableArraySize, int arrayLen, void* option); +int APS5_VABI sceNpTusGetMultiUserVariableAVUser(int reqId, const NpOnlineId* targetVirtualUserIdArray, std::int32_t slotId, void* variableArray, std::uint64_t variableArraySize, int arrayLen, void* option); +int APS5_VABI sceNpTusGetMultiUserVariableForCrossSaveVUser(int reqId, const NpOnlineId* targetVirtualUserIdArray, std::int32_t slotId, void* variableArray, std::uint64_t variableArraySize, int arrayLen, void* option); +int APS5_VABI sceNpTusGetMultiUserVariableVUser(int reqId, const NpOnlineId* targetVirtualUserIdArray, std::int32_t slotId, void* variableArray, std::uint64_t variableArraySize, int arrayLen, void* option); +int APS5_VABI sceNpTusSetDataA(int reqId, std::uint64_t targetAccountId, std::int32_t slotId, std::uint64_t totalSize, std::uint64_t sendSize, const void* data, const void* info, std::uint64_t infoStructSize, const std::uint64_t* isLastChangedAuthor, const void* isLastChangedDate, void* option); +int APS5_VABI sceNpTusSetDataAVUser(int reqId, const NpOnlineId* targetVirtualUserId, std::int32_t slotId, std::uint64_t totalSize, std::uint64_t sendSize, const void* data, const void* info, std::uint64_t infoStructSize, const std::uint64_t* isLastChangedAuthor, const void* isLastChangedDate, void* option); +int APS5_VABI sceNpTusTryAndSetVariable(int reqId, const void* targetNpId, std::int32_t slotId, std::int32_t opeType, std::int64_t variable, const std::int64_t* compareValue, const void* isLastChangedAuthor, const void* isLastChangedDate, void* resultVariable, std::uint64_t resultVariableSize, void* option); +int APS5_VABI sceNpTusTryAndSetVariableA(int reqId, std::uint64_t targetAccountId, std::int32_t slotId, std::int32_t opeType, std::int64_t variable, const std::int64_t* compareValue, const std::uint64_t* isLastChangedAuthor, const void* isLastChangedDate, void* resultVariable, std::uint64_t resultVariableSize, void* option); +int APS5_VABI sceNpTusTryAndSetVariableAVUser(int reqId, const NpOnlineId* targetVirtualUserId, std::int32_t slotId, std::int32_t opeType, std::int64_t variable, const std::int64_t* compareValue, const std::uint64_t* isLastChangedAuthor, const void* isLastChangedDate, void* resultVariable, std::uint64_t resultVariableSize, void* option); +int APS5_VABI sceNpTusTryAndSetVariableForCrossSave(int reqId, std::uint64_t targetAccountId, std::int32_t slotId, std::int32_t opeType, std::int64_t variable, const std::int64_t* compareValue, const std::uint64_t* isLastChangedAuthor, const void* isLastChangedDate, void* resultVariable, std::uint64_t resultVariableSize, void* option); +int APS5_VABI sceNpTusTryAndSetVariableForCrossSaveVUser(int reqId, const NpOnlineId* targetVirtualUserId, std::int32_t slotId, std::int32_t opeType, std::int64_t variable, const std::int64_t* compareValue, const std::uint64_t* isLastChangedAuthor, const void* isLastChangedDate, void* resultVariable, std::uint64_t resultVariableSize, void* option); +int APS5_VABI sceNpTusTryAndSetVariableVUser(int reqId, const NpOnlineId* targetVirtualUserId, std::int32_t slotId, std::int32_t opeType, std::int64_t variable, const std::int64_t* compareValue, const void* isLastChangedAuthor, const void* isLastChangedDate, void* resultVariable, std::uint64_t resultVariableSize, void* option); +int APS5_VABI sceNpTssGetData(); +int APS5_VABI sceNpTusCreateNpTitleCtx(); +int APS5_VABI sceNpTusGetData(); +int APS5_VABI sceNpTusGetDataVUser(); +int APS5_VABI sceNpTusGetMultiSlotVariable(); +int APS5_VABI sceNpTusGetMultiSlotVariableVUser(); +int APS5_VABI sceNpTusSetData(); +int APS5_VABI sceNpTusSetDataVUser(); +int APS5_VABI sceNpTusSetMultiSlotVariable(); +int APS5_VABI sceNpTusSetMultiSlotVariableVUser(); + +} diff --git a/core/libs/prx/libSceNpTus/libSceNpTus.hpp b/core/libs/prx/libSceNpTus/libSceNpTus.hpp new file mode 100644 index 0000000000..5cf1eba7a1 --- /dev/null +++ b/core/libs/prx/libSceNpTus/libSceNpTus.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceNpTus/include/Api.hpp" diff --git a/core/libs/prx/libSceNpUniversalDataSystem/Export.cpp b/core/libs/prx/libSceNpUniversalDataSystem/Export.cpp index 0231b0cf03..28b17e212b 100644 --- a/core/libs/prx/libSceNpUniversalDataSystem/Export.cpp +++ b/core/libs/prx/libSceNpUniversalDataSystem/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNpUniversalDataSystem/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceNpUniversalDataSystem/include/Api.hpp b/core/libs/prx/libSceNpUniversalDataSystem/include/Api.hpp new file mode 100644 index 0000000000..c0d1ad66ea --- /dev/null +++ b/core/libs/prx/libSceNpUniversalDataSystem/include/Api.hpp @@ -0,0 +1,94 @@ +#pragma once + +#include "prx/libSceNpUniversalDataSystem/include/UdsEvent.hpp" +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceNpUniversalDataSystemIntAbortHandle(void); +int APS5_VABI sceNpUniversalDataSystemIntCheckNetSyncTitles(void); +int APS5_VABI sceNpUniversalDataSystemIntCreateContext(void); +int APS5_VABI sceNpUniversalDataSystemIntCreateHandle(void); +int APS5_VABI sceNpUniversalDataSystemIntDeleteAllData(void); +int APS5_VABI sceNpUniversalDataSystemIntDeleteUserDataWithServerData(void); +int APS5_VABI sceNpUniversalDataSystemIntDestroyContext(void); +int APS5_VABI sceNpUniversalDataSystemIntDestroyHandle(void); +int APS5_VABI sceNpUniversalDataSystemIntInitialize(void); +int APS5_VABI sceNpUniversalDataSystemIntNetSyncTitles(void); +int APS5_VABI sceNpUniversalDataSystemIntTerminate(void); +int APS5_VABI sceNpUniversalDataSystemCreateContext(int* context, int userId, uint32_t serviceLabel, uint64_t options); +int APS5_VABI sceNpUniversalDataSystemDestroyContext(int context); +int APS5_VABI sceNpUniversalDataSystemRegisterContext(int context, int handle, uint64_t options); +int APS5_VABI sceNpUniversalDataSystemCreateEvent( const char* eventName, const NpUniversalDataSystemEventPropertyObject* prop, NpUniversalDataSystemEvent** newEvent, NpUniversalDataSystemEventPropertyObject** propPtr); +int APS5_VABI sceNpUniversalDataSystemDestroyEvent(NpUniversalDataSystemEvent* event); +int APS5_VABI sceNpUniversalDataSystemPostEvent(int context, int handle, const void* event, uint64_t options); +int APS5_VABI sceNpUniversalDataSystemEventEstimateSize(const NpUniversalDataSystemEvent* event, size_t* size); +int APS5_VABI sceNpUniversalDataSystemEventToString( const NpUniversalDataSystemEvent* event, char* buf, size_t bufSize, size_t* stringSize); +int APS5_VABI sceNpUniversalDataSystemCreateEventPropertyArray(NpUniversalDataSystemEventPropertyArray** newArray); +int APS5_VABI sceNpUniversalDataSystemDestroyEventPropertyArray(NpUniversalDataSystemEventPropertyArray* array); +int APS5_VABI sceNpUniversalDataSystemEventPropertyArraySetString( NpUniversalDataSystemEventPropertyArray* array, const char* value); +int APS5_VABI sceNpUniversalDataSystemEventPropertyArraySetInt32( NpUniversalDataSystemEventPropertyArray* array, int32_t value); +int APS5_VABI sceNpUniversalDataSystemEventPropertyArraySetUInt32( NpUniversalDataSystemEventPropertyArray* array, uint32_t value); +int APS5_VABI sceNpUniversalDataSystemEventPropertyArraySetInt64( NpUniversalDataSystemEventPropertyArray* array, int64_t value); +int APS5_VABI sceNpUniversalDataSystemEventPropertyArraySetUInt64( NpUniversalDataSystemEventPropertyArray* array, uint64_t value); +int APS5_VABI sceNpUniversalDataSystemEventPropertyArraySetFloat32( NpUniversalDataSystemEventPropertyArray* array, float value); +int APS5_VABI sceNpUniversalDataSystemEventPropertyArraySetFloat64( NpUniversalDataSystemEventPropertyArray* array, double value); +int APS5_VABI sceNpUniversalDataSystemEventPropertyArraySetBool( NpUniversalDataSystemEventPropertyArray* array, bool value); +int APS5_VABI sceNpUniversalDataSystemEventPropertyArraySetBinary( NpUniversalDataSystemEventPropertyArray* array, const void* value, size_t valueSize); +int APS5_VABI sceNpUniversalDataSystemEventPropertyArraySetObject( NpUniversalDataSystemEventPropertyArray* array, const NpUniversalDataSystemEventPropertyObject* value, NpUniversalDataSystemEventPropertyObject** valuePtr); +int APS5_VABI sceNpUniversalDataSystemEventPropertyArraySetArray( NpUniversalDataSystemEventPropertyArray* array, const NpUniversalDataSystemEventPropertyArray* value, NpUniversalDataSystemEventPropertyArray** valuePtr); +int APS5_VABI sceNpUniversalDataSystemCreateEventPropertyObject(NpUniversalDataSystemEventPropertyObject** newObject); +int APS5_VABI sceNpUniversalDataSystemDestroyEventPropertyObject(NpUniversalDataSystemEventPropertyObject* object); +int APS5_VABI sceNpUniversalDataSystemEventPropertyObjectSetString( NpUniversalDataSystemEventPropertyObject* object, const char* key, const char* value); +int APS5_VABI sceNpUniversalDataSystemEventPropertyObjectSetInt32( NpUniversalDataSystemEventPropertyObject* object, const char* key, int32_t value); +int APS5_VABI sceNpUniversalDataSystemEventPropertyObjectSetUInt32( NpUniversalDataSystemEventPropertyObject* object, const char* key, uint32_t value); +int APS5_VABI sceNpUniversalDataSystemEventPropertyObjectSetInt64( NpUniversalDataSystemEventPropertyObject* object, const char* key, int64_t value); +int APS5_VABI sceNpUniversalDataSystemEventPropertyObjectSetUInt64( NpUniversalDataSystemEventPropertyObject* object, const char* key, uint64_t value); +int APS5_VABI sceNpUniversalDataSystemEventPropertyObjectSetFloat32( NpUniversalDataSystemEventPropertyObject* object, const char* key, float value); +int APS5_VABI sceNpUniversalDataSystemEventPropertyObjectSetFloat64( NpUniversalDataSystemEventPropertyObject* object, const char* key, double value); +int APS5_VABI sceNpUniversalDataSystemEventPropertyObjectSetBool( NpUniversalDataSystemEventPropertyObject* object, const char* key, bool value); +int APS5_VABI sceNpUniversalDataSystemEventPropertyObjectSetBinary( NpUniversalDataSystemEventPropertyObject* object, const char* key, const void* value, size_t valueSize); +int APS5_VABI sceNpUniversalDataSystemEventPropertyObjectSetObject( NpUniversalDataSystemEventPropertyObject* object, const char* key, const NpUniversalDataSystemEventPropertyObject* value, NpUniversalDataSystemEventPropertyObject** valuePtr); +int APS5_VABI sceNpUniversalDataSystemEventPropertyObjectSetArray( NpUniversalDataSystemEventPropertyObject* object, const char* key, const NpUniversalDataSystemEventPropertyArray* value, NpUniversalDataSystemEventPropertyArray** valuePtr); +int APS5_VABI sceNpUniversalDataSystemCreateHandle(int* handle); +int APS5_VABI sceNpUniversalDataSystemDestroyHandle(int handle); +int APS5_VABI sceNpUniversalDataSystemAbortHandle(int handle); +int APS5_VABI sceNpUniversalDataSystemInitialize(const NpUniversalDataSystemInitParam* param); +int APS5_VABI sceNpUniversalDataSystemTerminate(void); +int APS5_VABI sceNpUniversalDataSystemGetMemoryStat(NpUniversalDataSystemMemoryStat* stat); +int APS5_VABI sceNpUniversalDataSystemGetStorageStat(int context, NpUniversalDataSystemStorageStat* stat); + +int APS5_VABI sceNpUniversalDataSystemIntCreateRecordArray(); +int APS5_VABI sceNpUniversalDataSystemIntCreateRecordData(); +int APS5_VABI sceNpUniversalDataSystemIntCreateRecordObject(); +int APS5_VABI sceNpUniversalDataSystemIntDeleteAllRecord(); +int APS5_VABI sceNpUniversalDataSystemIntDestroyRecordArray(); +int APS5_VABI sceNpUniversalDataSystemIntDestroyRecordData(); +int APS5_VABI sceNpUniversalDataSystemIntDestroyRecordObject(); +int APS5_VABI sceNpUniversalDataSystemIntGetMemoryStat(); +int APS5_VABI sceNpUniversalDataSystemIntPostRecordData(); +int APS5_VABI sceNpUniversalDataSystemIntRecordArraySetArray(); +int APS5_VABI sceNpUniversalDataSystemIntRecordArraySetBinary(); +int APS5_VABI sceNpUniversalDataSystemIntRecordArraySetBool(); +int APS5_VABI sceNpUniversalDataSystemIntRecordArraySetFloat32(); +int APS5_VABI sceNpUniversalDataSystemIntRecordArraySetFloat64(); +int APS5_VABI sceNpUniversalDataSystemIntRecordArraySetInt32(); +int APS5_VABI sceNpUniversalDataSystemIntRecordArraySetInt64(); +int APS5_VABI sceNpUniversalDataSystemIntRecordArraySetObject(); +int APS5_VABI sceNpUniversalDataSystemIntRecordArraySetString(); +int APS5_VABI sceNpUniversalDataSystemIntRecordArraySetUInt32(); +int APS5_VABI sceNpUniversalDataSystemIntRecordArraySetUInt64(); +int APS5_VABI sceNpUniversalDataSystemIntRecordDataEstimateSize(); +int APS5_VABI sceNpUniversalDataSystemIntRecordObjectSetArray(); +int APS5_VABI sceNpUniversalDataSystemIntRecordObjectSetBinary(); +int APS5_VABI sceNpUniversalDataSystemIntRecordObjectSetBool(); +int APS5_VABI sceNpUniversalDataSystemIntRecordObjectSetFloat32(); +int APS5_VABI sceNpUniversalDataSystemIntRecordObjectSetFloat64(); +int APS5_VABI sceNpUniversalDataSystemIntRecordObjectSetInt32(); +int APS5_VABI sceNpUniversalDataSystemIntRecordObjectSetInt64(); +int APS5_VABI sceNpUniversalDataSystemIntRecordObjectSetObject(); +int APS5_VABI sceNpUniversalDataSystemIntRecordObjectSetString(); +int APS5_VABI sceNpUniversalDataSystemIntRecordObjectSetUInt32(); +int APS5_VABI sceNpUniversalDataSystemIntRecordObjectSetUInt64(); + +} diff --git a/core/libs/prx/libSceNpUniversalDataSystem/libSceNpUniversalDataSystem.hpp b/core/libs/prx/libSceNpUniversalDataSystem/libSceNpUniversalDataSystem.hpp new file mode 100644 index 0000000000..e72fd1c696 --- /dev/null +++ b/core/libs/prx/libSceNpUniversalDataSystem/libSceNpUniversalDataSystem.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceNpUniversalDataSystem/include/Api.hpp" diff --git a/core/libs/prx/libSceNpUniversalDataSystem/src/Context.cpp b/core/libs/prx/libSceNpUniversalDataSystem/src/Context.cpp index f73c4a2cb2..e6f9c0a4c2 100644 --- a/core/libs/prx/libSceNpUniversalDataSystem/src/Context.cpp +++ b/core/libs/prx/libSceNpUniversalDataSystem/src/Context.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNpUniversalDataSystem/include/Api.hpp" #include #include #include diff --git a/core/libs/prx/libSceNpUniversalDataSystem/src/Event.cpp b/core/libs/prx/libSceNpUniversalDataSystem/src/Event.cpp index be7df0ae46..942a5f9450 100644 --- a/core/libs/prx/libSceNpUniversalDataSystem/src/Event.cpp +++ b/core/libs/prx/libSceNpUniversalDataSystem/src/Event.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNpUniversalDataSystem/include/Api.hpp" #include #include #include diff --git a/core/libs/prx/libSceNpUniversalDataSystem/src/EventPropertyArray.cpp b/core/libs/prx/libSceNpUniversalDataSystem/src/EventPropertyArray.cpp index 57e985ba8f..c7552e6a4b 100644 --- a/core/libs/prx/libSceNpUniversalDataSystem/src/EventPropertyArray.cpp +++ b/core/libs/prx/libSceNpUniversalDataSystem/src/EventPropertyArray.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNpUniversalDataSystem/include/Api.hpp" #include #include #include diff --git a/core/libs/prx/libSceNpUniversalDataSystem/src/EventPropertyObject.cpp b/core/libs/prx/libSceNpUniversalDataSystem/src/EventPropertyObject.cpp index d316c1ea30..20fd5f38e1 100644 --- a/core/libs/prx/libSceNpUniversalDataSystem/src/EventPropertyObject.cpp +++ b/core/libs/prx/libSceNpUniversalDataSystem/src/EventPropertyObject.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNpUniversalDataSystem/include/Api.hpp" #include #include #include diff --git a/core/libs/prx/libSceNpUniversalDataSystem/src/Handle.cpp b/core/libs/prx/libSceNpUniversalDataSystem/src/Handle.cpp index b2aa8ce9fd..331873010e 100644 --- a/core/libs/prx/libSceNpUniversalDataSystem/src/Handle.cpp +++ b/core/libs/prx/libSceNpUniversalDataSystem/src/Handle.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNpUniversalDataSystem/include/Api.hpp" #include "NpUniversalDataSystem.hpp" #include "SceTypes.hpp" #include "prx/libc/include/General.hpp" diff --git a/core/libs/prx/libSceNpUniversalDataSystem/src/System.cpp b/core/libs/prx/libSceNpUniversalDataSystem/src/System.cpp index 92f91ceedf..6bc49f4f07 100644 --- a/core/libs/prx/libSceNpUniversalDataSystem/src/System.cpp +++ b/core/libs/prx/libSceNpUniversalDataSystem/src/System.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNpUniversalDataSystem/include/Api.hpp" #include #include #include diff --git a/core/libs/prx/libSceNpUniversalDataSystem/tests/Events.cpp b/core/libs/prx/libSceNpUniversalDataSystem/tests/Events.cpp index 73128d5ff0..992af0fe45 100644 --- a/core/libs/prx/libSceNpUniversalDataSystem/tests/Events.cpp +++ b/core/libs/prx/libSceNpUniversalDataSystem/tests/Events.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNpUniversalDataSystem/include/Api.hpp" #include "NpUniversalDataSystem.hpp" #include "prx/libSceNpTrophy2/include/TrophyStore.hpp" #include "prx/libc/include/general/VabiMacros.hpp" @@ -13,40 +14,6 @@ #include #include -extern "C" { -int APS5_VABI sceNpUniversalDataSystemCreateContext(int*, int, uint32_t, uint64_t); -int APS5_VABI sceNpUniversalDataSystemDestroyContext(int); -int APS5_VABI sceNpUniversalDataSystemCreateEvent(const char*, const NpUniversalDataSystemEventPropertyObject*, NpUniversalDataSystemEvent**, NpUniversalDataSystemEventPropertyObject**); -int APS5_VABI sceNpUniversalDataSystemDestroyEvent(NpUniversalDataSystemEvent*); -int APS5_VABI sceNpUniversalDataSystemPostEvent(int, int, const void*, uint64_t); -int APS5_VABI sceNpUniversalDataSystemCreateEventPropertyObject(NpUniversalDataSystemEventPropertyObject**); -int APS5_VABI sceNpUniversalDataSystemDestroyEventPropertyObject(NpUniversalDataSystemEventPropertyObject*); -int APS5_VABI sceNpUniversalDataSystemEventPropertyObjectSetString(NpUniversalDataSystemEventPropertyObject*, const char*, const char*); -int APS5_VABI sceNpUniversalDataSystemEventPropertyObjectSetInt32(NpUniversalDataSystemEventPropertyObject*, const char*, int32_t); -int APS5_VABI sceNpUniversalDataSystemEventPropertyObjectSetUInt32(NpUniversalDataSystemEventPropertyObject*, const char*, uint32_t); -int APS5_VABI sceNpUniversalDataSystemEventPropertyObjectSetInt64(NpUniversalDataSystemEventPropertyObject*, const char*, int64_t); -int APS5_VABI sceNpUniversalDataSystemEventPropertyObjectSetUInt64(NpUniversalDataSystemEventPropertyObject*, const char*, uint64_t); -int APS5_VABI sceNpUniversalDataSystemEventPropertyObjectSetFloat32(NpUniversalDataSystemEventPropertyObject*, const char*, float); -int APS5_VABI sceNpUniversalDataSystemEventPropertyObjectSetFloat64(NpUniversalDataSystemEventPropertyObject*, const char*, double); -int APS5_VABI sceNpUniversalDataSystemEventPropertyObjectSetBool(NpUniversalDataSystemEventPropertyObject*, const char*, bool); -int APS5_VABI sceNpUniversalDataSystemEventPropertyObjectSetBinary(NpUniversalDataSystemEventPropertyObject*, const char*, const void*, size_t); -int APS5_VABI sceNpUniversalDataSystemEventPropertyObjectSetObject(NpUniversalDataSystemEventPropertyObject*, const char*, const NpUniversalDataSystemEventPropertyObject*, NpUniversalDataSystemEventPropertyObject**); -int APS5_VABI sceNpUniversalDataSystemEventPropertyObjectSetArray(NpUniversalDataSystemEventPropertyObject*, const char*, const NpUniversalDataSystemEventPropertyArray*, NpUniversalDataSystemEventPropertyArray**); -int APS5_VABI sceNpUniversalDataSystemCreateEventPropertyArray(NpUniversalDataSystemEventPropertyArray**); -int APS5_VABI sceNpUniversalDataSystemDestroyEventPropertyArray(NpUniversalDataSystemEventPropertyArray*); -int APS5_VABI sceNpUniversalDataSystemEventPropertyArraySetString(NpUniversalDataSystemEventPropertyArray*, const char*); -int APS5_VABI sceNpUniversalDataSystemEventPropertyArraySetInt32(NpUniversalDataSystemEventPropertyArray*, int32_t); -int APS5_VABI sceNpUniversalDataSystemEventPropertyArraySetUInt32(NpUniversalDataSystemEventPropertyArray*, uint32_t); -int APS5_VABI sceNpUniversalDataSystemEventPropertyArraySetInt64(NpUniversalDataSystemEventPropertyArray*, int64_t); -int APS5_VABI sceNpUniversalDataSystemEventPropertyArraySetUInt64(NpUniversalDataSystemEventPropertyArray*, uint64_t); -int APS5_VABI sceNpUniversalDataSystemEventPropertyArraySetFloat32(NpUniversalDataSystemEventPropertyArray*, float); -int APS5_VABI sceNpUniversalDataSystemEventPropertyArraySetFloat64(NpUniversalDataSystemEventPropertyArray*, double); -int APS5_VABI sceNpUniversalDataSystemEventPropertyArraySetBool(NpUniversalDataSystemEventPropertyArray*, bool); -int APS5_VABI sceNpUniversalDataSystemEventPropertyArraySetBinary(NpUniversalDataSystemEventPropertyArray*, const void*, size_t); -int APS5_VABI sceNpUniversalDataSystemEventPropertyArraySetObject(NpUniversalDataSystemEventPropertyArray*, const NpUniversalDataSystemEventPropertyObject*, NpUniversalDataSystemEventPropertyObject**); -int APS5_VABI sceNpUniversalDataSystemEventPropertyArraySetArray(NpUniversalDataSystemEventPropertyArray*, const NpUniversalDataSystemEventPropertyArray*, NpUniversalDataSystemEventPropertyArray**); -} - namespace { constexpr int InitialUser = 0x10000000; @@ -172,6 +139,7 @@ void testEvents() { check(throwsInvalidArgument([] { NpUniversalDataSystemEvent* unnamed = nullptr; sceNpUniversalDataSystemCreateEvent(nullptr, nullptr, &unnamed, nullptr); + }), "an event without a name was created"); } diff --git a/core/libs/prx/libSceNpUtility/Export.cpp b/core/libs/prx/libSceNpUtility/Export.cpp index aae2f22f12..7f5e3bbf94 100644 --- a/core/libs/prx/libSceNpUtility/Export.cpp +++ b/core/libs/prx/libSceNpUtility/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNpUtility/include/Api.hpp" #include #include #include diff --git a/core/libs/prx/libSceNpUtility/include/Api.hpp b/core/libs/prx/libSceNpUtility/include/Api.hpp new file mode 100644 index 0000000000..73d099655b --- /dev/null +++ b/core/libs/prx/libSceNpUtility/include/Api.hpp @@ -0,0 +1,105 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceNpBandwidthTestAbort(int contextId); +int APS5_VABI sceNpBandwidthTestGetStatus(int contextId, int* status); +int APS5_VABI sceNpBandwidthTestInitStartDownload(const void* param); +int APS5_VABI sceNpBandwidthTestInitStartUpload(const void* param); +int APS5_VABI sceNpBandwidthTestShutdown(int contextId, void* result); +int APS5_VABI sceNpBandwidthTestInitStart(); +int APS5_VABI sceNpLookupCreateRequest(int titleCtxId); +int APS5_VABI sceNpLookupCreateTitleCtx(const void* selfNpId); +int APS5_VABI sceNpLookupDeleteRequest(int reqId); +int APS5_VABI sceNpLookupDeleteTitleCtx(int titleCtxId); +int APS5_VABI sceNpLookupNpId(int reqId, const NpOnlineId* onlineId, void* npId, void* option); +int APS5_VABI sceNpWordFilterAbortRequest(int reqId); +int APS5_VABI sceNpWordFilterCensorComment(int reqId, const char* comment, void* option); +int APS5_VABI sceNpWordFilterCreateAsyncRequest(int titleCtxId, const std::uint64_t* param); +int APS5_VABI sceNpWordFilterCreateRequest(int titleCtxId); +int APS5_VABI sceNpWordFilterCreateTitleCtx(const void* selfNpId); +int APS5_VABI sceNpWordFilterDeleteRequest(int reqId); +int APS5_VABI sceNpWordFilterDeleteTitleCtx(int titleCtxId); +int APS5_VABI sceNpWordFilterPollAsync(int reqId, int* result); +int APS5_VABI sceNpWordFilterSanitizeComment(int reqId, const char* comment, char* sanitizedComment, void* option); + +int APS5_VABI sceNpAppInfoIntAbortRequest(); +int APS5_VABI sceNpAppInfoIntCheckAvailability(); +int APS5_VABI sceNpAppInfoIntCheckAvailabilityA(); +int APS5_VABI sceNpAppInfoIntCheckAvailabilityAll(); +int APS5_VABI sceNpAppInfoIntCheckAvailabilityAllA(); +int APS5_VABI sceNpAppInfoIntCheckServiceAvailability(); +int APS5_VABI sceNpAppInfoIntCheckServiceAvailabilityA(); +int APS5_VABI sceNpAppInfoIntCheckServiceAvailabilityAll(); +int APS5_VABI sceNpAppInfoIntCheckServiceAvailabilityAllA(); +int APS5_VABI sceNpAppInfoIntCreateRequest(); +int APS5_VABI sceNpAppInfoIntDestroyRequest(); +int APS5_VABI sceNpAppInfoIntFinalize(); +int APS5_VABI sceNpAppInfoIntInitialize(); +int APS5_VABI sceNpAppLaunchLink2IntAbortRequest(); +int APS5_VABI sceNpAppLaunchLink2IntCreateRequest(); +int APS5_VABI sceNpAppLaunchLink2IntDestroyRequest(); +int APS5_VABI sceNpAppLaunchLink2IntFinalize(); +int APS5_VABI sceNpAppLaunchLink2IntGetCompatibleTitleIdList(); +int APS5_VABI sceNpAppLaunchLink2IntGetCompatibleTitleIdNum(); +int APS5_VABI sceNpAppLaunchLink2IntInitialize(); +int APS5_VABI sceNpAppLaunchLinkIntAbortRequest(); +int APS5_VABI sceNpAppLaunchLinkIntCreateRequest(); +int APS5_VABI sceNpAppLaunchLinkIntDestroyRequest(); +int APS5_VABI sceNpAppLaunchLinkIntFinalize(); +int APS5_VABI sceNpAppLaunchLinkIntGetCompatibleTitleIdList(); +int APS5_VABI sceNpAppLaunchLinkIntGetCompatibleTitleIdNum(); +int APS5_VABI sceNpAppLaunchLinkIntInitialize(); +int APS5_VABI sceNpBandwidthTestShutdownWithDetailedInfo(); +int APS5_VABI sceNpLookupAbortRequest(); +int APS5_VABI sceNpLookupCreateAsyncRequest(); +int APS5_VABI sceNpLookupCreateTitleCtxA(); +int APS5_VABI sceNpLookupNetAbortRequest(); +int APS5_VABI sceNpLookupNetCensorComment(); +int APS5_VABI sceNpLookupNetConvertJidToNpId(); +int APS5_VABI sceNpLookupNetConvertNpIdToJid(); +int APS5_VABI sceNpLookupNetCreateRequest(); +int APS5_VABI sceNpLookupNetCreateTitleCtx(); +int APS5_VABI sceNpLookupNetDeleteRequest(); +int APS5_VABI sceNpLookupNetDeleteTitleCtx(); +int APS5_VABI sceNpLookupNetInit(); +int APS5_VABI sceNpLookupNetInitWithFunctionPointer(); +int APS5_VABI sceNpLookupNetInitWithMemoryPool(); +int APS5_VABI sceNpLookupNetIsInit(); +int APS5_VABI sceNpLookupNetNpId(); +int APS5_VABI sceNpLookupNetSanitizeComment(); +int APS5_VABI sceNpLookupNetSetTimeout(); +int APS5_VABI sceNpLookupNetTerm(); +int APS5_VABI sceNpLookupPollAsync(); +int APS5_VABI sceNpLookupSetTimeout(); +int APS5_VABI sceNpLookupWaitAsync(); +int APS5_VABI sceNpServiceChecker2IntAbortRequest(); +int APS5_VABI sceNpServiceChecker2IntCreateRequest(); +int APS5_VABI sceNpServiceChecker2IntDestroyRequest(); +int APS5_VABI sceNpServiceChecker2IntFinalize(); +int APS5_VABI sceNpServiceChecker2IntGetServiceAvailability(); +int APS5_VABI sceNpServiceChecker2IntGetServiceAvailabilityA(); +int APS5_VABI sceNpServiceChecker2IntInitialize(); +int APS5_VABI sceNpServiceChecker2IntIsSetServiceType(); +int APS5_VABI sceNpServiceCheckerIntAbortRequest(); +int APS5_VABI sceNpServiceCheckerIntCreateRequest(); +int APS5_VABI sceNpServiceCheckerIntDestroyRequest(); +int APS5_VABI sceNpServiceCheckerIntFinalize(); +int APS5_VABI sceNpServiceCheckerIntGetAvailability(); +int APS5_VABI sceNpServiceCheckerIntGetAvailabilityList(); +int APS5_VABI sceNpServiceCheckerIntInitialize(); +int APS5_VABI sceNpServiceCheckerIntIsCached(); +int APS5_VABI sceNpTitleMetadataIntAbortRequest(); +int APS5_VABI sceNpTitleMetadataIntCreateRequest(); +int APS5_VABI sceNpTitleMetadataIntDeleteRequest(); +int APS5_VABI sceNpTitleMetadataIntGetInfo(); +int APS5_VABI sceNpTitleMetadataIntGetNpTitleId(); +int APS5_VABI sceNpUtilityInit(); +int APS5_VABI sceNpUtilityTerm(); +int APS5_VABI sceNpWordFilterCreateTitleCtxA(); +int APS5_VABI sceNpWordFilterSetTimeout(); +int APS5_VABI sceNpWordFilterWaitAsync(); + +} diff --git a/core/libs/prx/libSceNpUtility/libSceNpUtility.hpp b/core/libs/prx/libSceNpUtility/libSceNpUtility.hpp new file mode 100644 index 0000000000..01af5539aa --- /dev/null +++ b/core/libs/prx/libSceNpUtility/libSceNpUtility.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceNpUtility/include/Api.hpp" diff --git a/core/libs/prx/libSceNpWebApi/Export.cpp b/core/libs/prx/libSceNpWebApi/Export.cpp index 1aece4e185..c78414d680 100644 --- a/core/libs/prx/libSceNpWebApi/Export.cpp +++ b/core/libs/prx/libSceNpWebApi/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNpWebApi/include/Api.hpp" #include "SceTypes.hpp" #include "prx/libc/include/General.hpp" #include diff --git a/core/libs/prx/libSceNpWebApi/include/Api.hpp b/core/libs/prx/libSceNpWebApi/include/Api.hpp new file mode 100644 index 0000000000..567364a9bf --- /dev/null +++ b/core/libs/prx/libSceNpWebApi/include/Api.hpp @@ -0,0 +1,31 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceNpWebApiAbortRequest(); +int APS5_VABI sceNpWebApiCreateContext(); +int APS5_VABI sceNpWebApiCreateHandle(int libCtxId); +int APS5_VABI sceNpWebApiCreatePushEventFilter(int libCtxId, const void* filterParam, std::size_t filterParamNum); +int APS5_VABI sceNpWebApiCreateRequest(); +int APS5_VABI sceNpWebApiCreateServicePushEventFilter(int libCtxId, int handleId, const char* npServiceName, std::uint32_t npServiceLabel, const void* filterParam, std::size_t filterParamNum); +int APS5_VABI sceNpWebApiDeleteContext(); +int APS5_VABI sceNpWebApiDeleteHandle(int libCtxId, int handleId); +int APS5_VABI sceNpWebApiDeletePushEventFilter(int libCtxId, int filterId); +int APS5_VABI sceNpWebApiDeleteRequest(); +int APS5_VABI sceNpWebApiDeleteServicePushEventFilter(int libCtxId, int filterId); +int APS5_VABI sceNpWebApiGetHttpResponseHeaderValue(); +int APS5_VABI sceNpWebApiGetHttpResponseHeaderValueLength(); +int APS5_VABI sceNpWebApiGetHttpStatusCode(); +int APS5_VABI sceNpWebApiInitialize(int libHttpCtxId, std::size_t poolSize); +int APS5_VABI sceNpWebApiReadData(); +int APS5_VABI sceNpWebApiRegisterPushEventCallback(); +int APS5_VABI sceNpWebApiRegisterServicePushEventCallback(); +int APS5_VABI sceNpWebApiSendRequest(); +int APS5_VABI sceNpWebApiTerminate(int libCtxId); +int APS5_VABI sceNpWebApiUnregisterPushEventCallback(); +int APS5_VABI sceNpWebApiUnregisterServicePushEventCallback(); +int APS5_VABI sceNpWebApiUtilityParseNpId(); + +} diff --git a/core/libs/prx/libSceNpWebApi/libSceNpWebApi.hpp b/core/libs/prx/libSceNpWebApi/libSceNpWebApi.hpp new file mode 100644 index 0000000000..3688862c87 --- /dev/null +++ b/core/libs/prx/libSceNpWebApi/libSceNpWebApi.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceNpWebApi/include/Api.hpp" diff --git a/core/libs/prx/libSceNpWebApi2/Export.cpp b/core/libs/prx/libSceNpWebApi2/Export.cpp index daef37aa53..66a26fe70b 100644 --- a/core/libs/prx/libSceNpWebApi2/Export.cpp +++ b/core/libs/prx/libSceNpWebApi2/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNpWebApi2/include/Api.hpp" #include #include #include "SceTypes.hpp" @@ -15,19 +16,8 @@ static constexpr int SCE_NP_WEBAPI2_ERROR_INVALID_CONTEXT = static_cast(0x8 static constexpr int SCE_NP_WEBAPI2_ERROR_INVALID_HANDLE = static_cast(0x8055340D); static std::atomic g_nextHandle{1}; -struct NpWebApi2PushContextId { - char value[37]; -}; - static_assert(sizeof(NpWebApi2PushContextId) == 37); -struct NpWebApi2MemoryPoolStats { - size_t pool_size; - size_t max_inuse_size; - size_t current_inuse_size; - int32_t reserved; -}; - static_assert(sizeof(NpWebApi2MemoryPoolStats) == 32); static std::mutex g_poolsMutex; diff --git a/core/libs/prx/libSceNpWebApi2/include/Api.hpp b/core/libs/prx/libSceNpWebApi2/include/Api.hpp new file mode 100644 index 0000000000..c528b23c20 --- /dev/null +++ b/core/libs/prx/libSceNpWebApi2/include/Api.hpp @@ -0,0 +1,58 @@ +#pragma once + +#include "SceTypes.hpp" + +struct NpWebApi2MemoryPoolStats { + size_t pool_size; + size_t max_inuse_size; + size_t current_inuse_size; + int32_t reserved; +}; + +struct NpWebApi2PushContextId { + char value[37]; +}; + +extern "C" { + +int APS5_VABI sceNpWebApi2AbortRequest(int64_t requestId); +int APS5_VABI sceNpWebApi2AddHttpRequestHeader(int64_t requestId, const char* fieldName, const char* value); +int APS5_VABI sceNpWebApi2AddWebTraceTag(std::int64_t requestId, const char* value); +void APS5_VABI sceNpWebApi2CheckTimeout(void); +int APS5_VABI sceNpWebApi2CreateRequest(int userContextId, const char* apiGroup, const char* path, const char* method, const void* contentParameter, int64_t* requestId); +int APS5_VABI sceNpWebApi2CreateUserContext(int libCtxId, int userId); +int APS5_VABI sceNpWebApi2DeleteRequest(int64_t requestId); +int APS5_VABI sceNpWebApi2DeleteUserContext(int userContextId); +int APS5_VABI sceNpWebApi2GetHttpResponseHeaderValue(int64_t requestId, const char* fieldName, char* value, size_t valueSize); +int APS5_VABI sceNpWebApi2GetHttpResponseHeaderValueLength(int64_t requestId, const char* fieldName, size_t* valueLength); +int APS5_VABI sceNpWebApi2Initialize(int libHttpCtxId, size_t poolSize); +int APS5_VABI sceNpWebApi2GetMemoryPoolStats(int libraryContextId, NpWebApi2MemoryPoolStats* stats); +int APS5_VABI sceNpWebApi2PushEventCreateFilter(int libCtxId, int handleId, const char* npServiceName, uint32_t npServiceLabel, const void* filterParam, size_t filterParamNum); +int APS5_VABI sceNpWebApi2PushEventCreateHandle(int libraryContextId); +int APS5_VABI sceNpWebApi2PushEventAbortHandle(int libraryContextId, int handleId); +int APS5_VABI sceNpWebApi2PushEventDeleteHandle(int libraryContextId, int handleId); +int APS5_VABI sceNpWebApi2PushEventDeletePushContext(int userContextId, const void* pushContextId); +int APS5_VABI sceNpWebApi2PushEventRegisterCallback(int userContextId, int filterId, void* callback, void* userArg); +int APS5_VABI sceNpWebApi2ReadData(int64_t requestId, void* data, size_t size); +int APS5_VABI sceNpWebApi2SendRequest(int64_t requestId, const void* data, size_t dataSize, NpWebApi2ResponseInformationOption* responseInfoOption); +int APS5_VABI sceNpWebApi2Terminate(int libCtxId); +int APS5_VABI sceNpWebApi2PushEventCreatePushContext(std::int32_t userContextId, NpWebApi2PushContextId* pushContextId); +int APS5_VABI sceNpWebApi2PushEventDeleteFilter(std::int32_t libraryContextId, std::int32_t filterId); +int APS5_VABI sceNpWebApi2PushEventSetHandleTimeout(int libraryContextId, int handleId, std::uint32_t timeout); +int APS5_VABI sceNpWebApi2PushEventRegisterPushContextCallback(); +int APS5_VABI sceNpWebApi2PushEventStartPushContextCallback(std::int32_t userContextId, const NpWebApi2PushContextId* pushContextId); +int APS5_VABI sceNpWebApi2PushEventUnregisterCallback(std::int32_t userContextId, std::int32_t callbackId); +int APS5_VABI sceNpWebApi2PushEventUnregisterPushContextCallback(std::int32_t userContextId, std::int32_t callbackId); +int APS5_VABI sceNpWebApi2SetRequestTimeout(int64_t requestId, uint32_t timeout); +int APS5_VABI sceNpWebApi2AddMultipartPart(); +int APS5_VABI sceNpWebApi2CreateMultipartRequest(int userCtxId, const char* apiGroup, const char* path, const char* method, int64_t* requestId); +int APS5_VABI sceNpWebApi2InitializeForPresence(int libHttpCtxId, uint64_t poolSize); +int APS5_VABI sceNpWebApi2IntCreateRequest(); +int APS5_VABI sceNpWebApi2IntInitialize(const NpWebApi2IntInitializeArgs* args); +int APS5_VABI sceNpWebApi2IntInitialize2(const NpWebApi2IntInitialize2Args* args); +int APS5_VABI sceNpWebApi2IntPushEventCreateCtxIndFilter(); +int APS5_VABI sceNpWebApi2IntPushEventCreateDestPs4CtxIndFilter(); +int APS5_VABI sceNpWebApi2SendMultipartRequest(int64_t requestId, int partIndex, void* data, uint64_t dataSize, void* respInfoOption); +int APS5_VABI sceNpWebApi2SetMultipartContentType(); + +} diff --git a/core/libs/prx/libSceNpWebApi2/libSceNpWebApi2.hpp b/core/libs/prx/libSceNpWebApi2/libSceNpWebApi2.hpp new file mode 100644 index 0000000000..6c299c3731 --- /dev/null +++ b/core/libs/prx/libSceNpWebApi2/libSceNpWebApi2.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceNpWebApi2/include/Api.hpp" diff --git a/core/libs/prx/libSceOpusCeltDec/Export.cpp b/core/libs/prx/libSceOpusCeltDec/Export.cpp index 5f40c01b3c..41ef6ba1a0 100644 --- a/core/libs/prx/libSceOpusCeltDec/Export.cpp +++ b/core/libs/prx/libSceOpusCeltDec/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceOpusCeltDec/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libSceOpusDec/include/OpusDecoder.hpp" #include diff --git a/core/libs/prx/libSceOpusCeltDec/include/Api.hpp b/core/libs/prx/libSceOpusCeltDec/include/Api.hpp new file mode 100644 index 0000000000..2cbb6f7599 --- /dev/null +++ b/core/libs/prx/libSceOpusCeltDec/include/Api.hpp @@ -0,0 +1,19 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceOpusCeltDecInitialize(std::uint32_t* context); +int APS5_VABI sceOpusCeltDecTerminate(const std::uint32_t* context); +int APS5_VABI sceOpusCeltDecGetSize(int channels); +int APS5_VABI sceOpusCeltDecCreateEx(const std::uint32_t* context, void* state, int sampleRate, int channels); +int APS5_VABI sceOpusCeltDecDecode(void* state, const std::uint8_t* data, int bytes, std::int16_t* pcm, int capacity); +int APS5_VABI sceOpusCeltDecDestroy(void* state); +int APS5_VABI sceOpusCeltDecCreate(); +int APS5_VABI sceOpusCeltDecCtl(); +int APS5_VABI sceOpusCeltDecDecodeFloat(); +int APS5_VABI sceOpusCeltDecDecodeFloatWithPriority(); +int APS5_VABI sceOpusCeltDecDecodeWithPriority(); + +} diff --git a/core/libs/prx/libSceOpusCeltDec/libSceOpusCeltDec.hpp b/core/libs/prx/libSceOpusCeltDec/libSceOpusCeltDec.hpp new file mode 100644 index 0000000000..47b7b5511c --- /dev/null +++ b/core/libs/prx/libSceOpusCeltDec/libSceOpusCeltDec.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceOpusCeltDec/include/Api.hpp" diff --git a/core/libs/prx/libSceOpusCeltEnc/Export.cpp b/core/libs/prx/libSceOpusCeltEnc/Export.cpp index bcbe6e9029..5f837e73e4 100644 --- a/core/libs/prx/libSceOpusCeltEnc/Export.cpp +++ b/core/libs/prx/libSceOpusCeltEnc/Export.cpp @@ -1,10 +1,9 @@ +#include "prx/libSceOpusCeltEnc/include/Api.hpp" #include #include #include "SceTypes.hpp" #include "prx/libc/include/General.hpp" -struct OpusCeltEncoder; - extern "C" { int APS5_VABI sceOpusCeltEncCreate(OpusCeltEncoder* encoder, std::int32_t sampleRate, std::int32_t channels, std::int32_t application) { diff --git a/core/libs/prx/libSceOpusCeltEnc/include/Api.hpp b/core/libs/prx/libSceOpusCeltEnc/include/Api.hpp new file mode 100644 index 0000000000..5a38483d1d --- /dev/null +++ b/core/libs/prx/libSceOpusCeltEnc/include/Api.hpp @@ -0,0 +1,21 @@ +#pragma once + +#include "SceTypes.hpp" + +struct OpusCeltEncoder; + +extern "C" { + +int APS5_VABI sceOpusCeltEncCreate(OpusCeltEncoder* encoder, std::int32_t sampleRate, std::int32_t channels, std::int32_t application); +int APS5_VABI sceOpusCeltEncCreateEx(const std::uint32_t* contextId, OpusCeltEncoder* encoder, std::int32_t sampleRate, std::int32_t channels, std::int32_t application); +int APS5_VABI sceOpusCeltEncCtl(OpusCeltEncoder* encoder, std::int32_t request, ...); +int APS5_VABI sceOpusCeltEncDestroy(OpusCeltEncoder* encoder); +int APS5_VABI sceOpusCeltEncEncode(OpusCeltEncoder* encoder, const std::int16_t* samples, std::int32_t frameSize, std::uint8_t* data, std::int32_t maxDataBytes); +int APS5_VABI sceOpusCeltEncEncodeFloat(OpusCeltEncoder* encoder, const float* samples, std::int32_t frameSize, std::uint8_t* data, std::int32_t maxDataBytes); +int APS5_VABI sceOpusCeltEncEncodeFloatWithPriority(OpusCeltEncoder* encoder, const float* samples, std::int32_t frameSize, std::uint8_t* data, std::int32_t maxDataBytes, std::uint32_t priority); +int APS5_VABI sceOpusCeltEncEncodeWithPriority(OpusCeltEncoder* encoder, const std::int16_t* samples, std::int32_t frameSize, std::uint8_t* data, std::int32_t maxDataBytes, std::uint32_t priority); +int APS5_VABI sceOpusCeltEncGetSize(std::int32_t channels); +int APS5_VABI sceOpusCeltEncInitialize(std::uint32_t* contextId); +int APS5_VABI sceOpusCeltEncTerminate(const std::uint32_t* contextId); + +} diff --git a/core/libs/prx/libSceOpusCeltEnc/libSceOpusCeltEnc.hpp b/core/libs/prx/libSceOpusCeltEnc/libSceOpusCeltEnc.hpp new file mode 100644 index 0000000000..9a54c5f490 --- /dev/null +++ b/core/libs/prx/libSceOpusCeltEnc/libSceOpusCeltEnc.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceOpusCeltEnc/include/Api.hpp" diff --git a/core/libs/prx/libSceOpusDec/Export.cpp b/core/libs/prx/libSceOpusDec/Export.cpp index ebf78206f4..f190172797 100644 --- a/core/libs/prx/libSceOpusDec/Export.cpp +++ b/core/libs/prx/libSceOpusDec/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceOpusDec/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libSceOpusDec/include/OpusDecoder.hpp" #include diff --git a/core/libs/prx/libSceOpusDec/include/Api.hpp b/core/libs/prx/libSceOpusDec/include/Api.hpp new file mode 100644 index 0000000000..3bf7ca2885 --- /dev/null +++ b/core/libs/prx/libSceOpusDec/include/Api.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceOpusDecInitialize(std::uint32_t* context); +int APS5_VABI sceOpusDecTerminate(const std::uint32_t* context); +int APS5_VABI sceOpusDecGetSize(int channels); +int APS5_VABI sceOpusDecCreateEx(const std::uint32_t* context, void* state, int sampleRate, int channels); +int APS5_VABI sceOpusDecDecode(void* state, const std::uint8_t* data, int bytes, std::int16_t* pcm, int capacity); +int APS5_VABI sceOpusDecDestroy(void* state); +int APS5_VABI sceOpusDecCancel(); +int APS5_VABI sceOpusDecCreate(); +int APS5_VABI sceOpusDecCtl(); +int APS5_VABI sceOpusDecDecodeFloat(); +int APS5_VABI sceOpusDecDecodeFloatWithPriority(); +int APS5_VABI sceOpusDecDecodeFloatWithPriorityAndTimeout(); +int APS5_VABI sceOpusDecDecodeWithPriority(); +int APS5_VABI sceOpusDecDecodeWithPriorityAndTimeout(); + +} diff --git a/core/libs/prx/libSceOpusDec/libSceOpusDec.hpp b/core/libs/prx/libSceOpusDec/libSceOpusDec.hpp new file mode 100644 index 0000000000..fd17892819 --- /dev/null +++ b/core/libs/prx/libSceOpusDec/libSceOpusDec.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceOpusDec/include/Api.hpp" diff --git a/core/libs/prx/libSceOpusSilkEnc/Export.cpp b/core/libs/prx/libSceOpusSilkEnc/Export.cpp index 4e741a3bf9..71bb17fe68 100644 --- a/core/libs/prx/libSceOpusSilkEnc/Export.cpp +++ b/core/libs/prx/libSceOpusSilkEnc/Export.cpp @@ -1,10 +1,9 @@ +#include "prx/libSceOpusSilkEnc/include/Api.hpp" #include #include #include "SceTypes.hpp" #include "prx/libc/include/General.hpp" -struct OpusSilkEncoder; - extern "C" { int APS5_VABI sceOpusSilkEncCancel(OpusSilkEncoder* encoder, std::uint32_t batchId) { diff --git a/core/libs/prx/libSceOpusSilkEnc/include/Api.hpp b/core/libs/prx/libSceOpusSilkEnc/include/Api.hpp new file mode 100644 index 0000000000..01202c6ad9 --- /dev/null +++ b/core/libs/prx/libSceOpusSilkEnc/include/Api.hpp @@ -0,0 +1,24 @@ +#pragma once + +#include "SceTypes.hpp" + +struct OpusSilkEncoder; + +extern "C" { + +int APS5_VABI sceOpusSilkEncCancel(OpusSilkEncoder* encoder, std::uint32_t batchId); +int APS5_VABI sceOpusSilkEncCreate(OpusSilkEncoder* encoder, std::int32_t sampleRate, std::int32_t channels, std::int32_t application); +int APS5_VABI sceOpusSilkEncCreateEx(const std::uint32_t* contextId, OpusSilkEncoder* encoder, std::int32_t sampleRate, std::int32_t channels, std::int32_t application); +int APS5_VABI sceOpusSilkEncCtl(OpusSilkEncoder* encoder, std::int32_t request, ...); +int APS5_VABI sceOpusSilkEncDestroy(OpusSilkEncoder* encoder); +int APS5_VABI sceOpusSilkEncEncode(OpusSilkEncoder* encoder, const std::int16_t* samples, std::int32_t frameSize, std::uint8_t* data, std::int32_t maxDataBytes); +int APS5_VABI sceOpusSilkEncEncodeFloat(OpusSilkEncoder* encoder, const float* samples, std::int32_t frameSize, std::uint8_t* data, std::int32_t maxDataBytes); +int APS5_VABI sceOpusSilkEncEncodeFloatWithPriority(OpusSilkEncoder* encoder, const float* samples, std::int32_t frameSize, std::uint8_t* data, std::int32_t maxDataBytes, std::uint32_t priority); +int APS5_VABI sceOpusSilkEncEncodeFloatWithPriorityAndTimeout(OpusSilkEncoder* encoder, const float* samples, std::int32_t frameSize, std::uint8_t* data, std::int32_t maxDataBytes, std::uint32_t priority, std::uint32_t timeout, std::uint32_t* batchId); +int APS5_VABI sceOpusSilkEncEncodeWithPriority(OpusSilkEncoder* encoder, const std::int16_t* samples, std::int32_t frameSize, std::uint8_t* data, std::int32_t maxDataBytes, std::uint32_t priority); +int APS5_VABI sceOpusSilkEncEncodeWithPriorityAndTimeout(OpusSilkEncoder* encoder, const std::int16_t* samples, std::int32_t frameSize, std::uint8_t* data, std::int32_t maxDataBytes, std::uint32_t priority, std::uint32_t timeout, std::uint32_t* batchId); +int APS5_VABI sceOpusSilkEncGetSize(std::int32_t channels); +int APS5_VABI sceOpusSilkEncInitialize(std::uint32_t* contextId); +int APS5_VABI sceOpusSilkEncTerminate(const std::uint32_t* contextId); + +} diff --git a/core/libs/prx/libSceOpusSilkEnc/libSceOpusSilkEnc.hpp b/core/libs/prx/libSceOpusSilkEnc/libSceOpusSilkEnc.hpp new file mode 100644 index 0000000000..c11f4f27cd --- /dev/null +++ b/core/libs/prx/libSceOpusSilkEnc/libSceOpusSilkEnc.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceOpusSilkEnc/include/Api.hpp" diff --git a/core/libs/prx/libSceOrbisCompat/libSceOrbisCompat.hpp b/core/libs/prx/libSceOrbisCompat/libSceOrbisCompat.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceOrbisCompat/libSceOrbisCompat.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libScePad/Export.cpp b/core/libs/prx/libScePad/Export.cpp index 15cc1a4805..0787a07dbf 100644 --- a/core/libs/prx/libScePad/Export.cpp +++ b/core/libs/prx/libScePad/Export.cpp @@ -12,40 +12,6 @@ #include "prx/libScePad/include/Pad.hpp" #include "prx/libScePad/include/PadState.hpp" -struct PadStickTuningParameter; -struct PadTriggerTuningParameter; -struct PadHuntProfile; -struct PadLeonardoProfile; -struct PadProfileInfo; -struct PadActiveProfileInfo; -struct PadSavedSettingInfo; -struct PadUsbDetectionState; -struct PadVrUsbConnectionStatus; -struct PadDeviceInfo; -struct PadLicenseControllerInformation; -struct PadRemoteSetting; -struct PadVirtualTriggerSetting; -struct PadProcessFocusParameter; -struct PadDataExtended; -struct PadVrControllerData { - std::uint32_t buttons; - std::uint8_t stick[2]; - std::uint8_t unused6[2]; - std::uint8_t triggers[2]; - std::uint8_t unused10[2]; - std::uint32_t touchButtons; - std::uint8_t touchValues[4]; - float acceleration[3]; - float angularVelocity[3]; - float orientation[4]; - std::uint8_t unused60[4]; - std::uint8_t connected; - std::uint8_t connectedCount; - std::uint8_t unused66[6]; - std::uint64_t timestamp; - std::uint8_t unused80[24]; -}; - static_assert(sizeof(PadVrControllerData) == 104); static_assert(offsetof(PadVrControllerData, triggers) == 8); static_assert(offsetof(PadVrControllerData, touchButtons) == 12); @@ -54,51 +20,11 @@ static_assert(offsetof(PadVrControllerData, angularVelocity) == 32); static_assert(offsetof(PadVrControllerData, orientation) == 44); static_assert(offsetof(PadVrControllerData, connected) == 64); static_assert(offsetof(PadVrControllerData, timestamp) == 72); -struct PadVrControllerDeviceInformation; -struct PadVrTriggerEffect; -struct PadVrTriggerEffects; -struct PadTriggerEffectExtended; -struct PadExtensionReport; -struct PadExtensionUnitInfo; -struct PadTriggerInternalState; -struct PadTrackerData; -struct PadBlasterTrackerData; -struct PadAstonTrackerData; -struct PadUiData; -struct PadUiTuningData; -struct PadLotusButtonData; -struct PadVersionInfo; -struct PadTelemetryInfo; -struct PadPortInfo; -struct PadVrControllerCombinedState; -struct PadLeonardoData; -struct PadLeonardoUniqueData; -struct PadHistoryData; -struct PadUpdateParameter; -struct PadVirtualDeviceParameter; -struct PadVirtualDeviceId; -struct PadVirtualDeviceComponentInformation; - -struct PadVirtualTriggerInternalState { - std::uint32_t states[2]; - std::uint8_t mode; - std::uint8_t flags[2]; -}; static_assert(sizeof(PadVirtualTriggerInternalState) == 12); static_assert(offsetof(PadVirtualTriggerInternalState, mode) == 8); static_assert(offsetof(PadVirtualTriggerInternalState, flags) == 9); -struct PadLightBarBlinkingParameter { - std::uint8_t values[3]; -}; - -struct PadButtonRemappingInfo { - std::uint8_t mapping[14]; - std::uint8_t reserved; - std::uint8_t mode; -}; - static_assert(sizeof(PadLightBarBlinkingParameter) == 3); static_assert(sizeof(PadButtonRemappingInfo) == 16); static_assert(offsetof(PadButtonRemappingInfo, mode) == 15); @@ -109,6 +35,9 @@ constexpr int PAD_ERROR_DEVICE_NOT_CONNECTED = static_cast(0x80920007); constexpr int PAD_ERROR_DEVICE_NO_HANDLE = static_cast(0x80920008); constexpr int PAD_ERROR_ALREADY_OPENED = static_cast(0x80920004); constexpr int PAD_ERROR_UNKNOWN_USER = static_cast(0x809b0081); +constexpr int PAD_ERROR_INVALID_USER_ID = static_cast(0x809b0001); +constexpr int PAD_ERROR_INVALID_PORT_INDEX = static_cast(0x809b0003); +constexpr int PAD_USER_ID_INVALID = -1; std::array g_opened{false}; std::array g_everOpened{false}; @@ -171,20 +100,9 @@ bool ValidPort(int userId, int type, int index) { } -struct PadUpdateData { - std::size_t size; - std::uint8_t data[32768]; -}; - static_assert(sizeof(PadUpdateData) == 32776); static_assert(offsetof(PadUpdateData, data) == 8); -struct PadMotionSensorPosition { - float x; - float y; - float z; -}; - static_assert(sizeof(PadMotionSensorPosition) == 12); extern "C" { @@ -343,9 +261,12 @@ int APS5_VABI scePadInit_nid_postfix(void) { int APS5_VABI scePadOpen_nid_postfix(int userId, int type, int index, const void* param) { (void)param; - if (!ValidPort(userId, type, index)) { - return PAD_ERROR_INVALID_ARG; - } + const bool unknownType = type == 3 || type == 4; + const bool knownType = type == PAD_PORT_TYPE_STANDARD || type == PAD_PORT_TYPE_SPECIAL || SystemRemote(userId, type); + if (!unknownType && !knownType) return PAD_ERROR_INVALID_ARG; + if (userId == PAD_USER_ID_INVALID) return PAD_ERROR_INVALID_USER_ID; + if (unknownType) NotImplemented_nid_no_patch(__func__); + if (index != 0) return PAD_ERROR_INVALID_PORT_INDEX; if (type == PAD_PORT_TYPE_SPECIAL) { if (SpecialHandleOf(userId) != PAD_ERROR_DEVICE_NO_HANDLE) return PAD_ERROR_ALREADY_OPENED; for (int slot = 0; slot < PAD_SPECIAL_HANDLE_COUNT; ++slot) { @@ -534,7 +455,6 @@ int APS5_VABI scePadIsRemoteController(int handle, bool* remote) { return 0; } - int APS5_VABI scePadSetAngularVelocityBiasCorrectionState(int handle, bool enabled) { if (!KnownHandle(handle)) return PAD_ERROR_INVALID_HANDLE; if (enabled) NotImplemented_nid_no_patch(__func__); @@ -706,8 +626,8 @@ int APS5_VABI scePadGetVersionInfo(std::int32_t handle, PadVersionInfo* info) { int APS5_VABI scePadGetControllerType(std::int32_t handle, std::int32_t* type) { if (!Pad::IsInitialized()) return PAD_ERROR_NOT_INITIALIZED; if (type == nullptr) return PAD_ERROR_INVALID_ARG; - if (PortOf(handle) < 0) return PAD_ERROR_INVALID_HANDLE; - *type = PAD_CONTROLLER_TYPE_DUAL_SENSE; + if (!KnownHandle(handle)) return PAD_ERROR_INVALID_HANDLE; + *type = SpecialHandle(handle) ? PAD_CONTROLLER_TYPE_UNKNOWN : PAD_CONTROLLER_TYPE_DUAL_SENSE; return PAD_OK; } diff --git a/core/libs/prx/libScePad/include/Pad.hpp b/core/libs/prx/libScePad/include/Pad.hpp index 03958f4eed..49154aa264 100644 --- a/core/libs/prx/libScePad/include/Pad.hpp +++ b/core/libs/prx/libScePad/include/Pad.hpp @@ -2,6 +2,7 @@ #define CORE_LIBS_PRX_LIBSCEPAD_PAD_HPP #include +#include "SceTypes.hpp" constexpr int PAD_OK = 0; constexpr int PAD_ERROR_INVALID_ARG = -2137915391; @@ -28,6 +29,7 @@ constexpr int PAD_DEVICE_TYPE_DUAL_SHOCK_4 = 2; constexpr int PAD_DEVICE_TYPE_DUAL_SENSE = 3; constexpr int PAD_DEVICE_TYPE_DUAL_SENSE_EDGE = 4; +constexpr int PAD_CONTROLLER_TYPE_UNKNOWN = 0; constexpr int PAD_CONTROLLER_TYPE_DUAL_SENSE = 2; constexpr int PAD_CONNECT_TYPE_UNREGISTERED = 0; @@ -51,4 +53,288 @@ struct PadInfo { }; static_assert(sizeof(PadInfo) == 0x59); +struct PadStickTuningParameter; +struct PadTriggerTuningParameter; +struct PadHuntProfile; +struct PadLeonardoProfile; +struct PadProfileInfo; +struct PadActiveProfileInfo; +struct PadSavedSettingInfo; +struct PadUsbDetectionState; +struct PadVrUsbConnectionStatus; +struct PadDeviceInfo; +struct PadLicenseControllerInformation; +struct PadRemoteSetting; +struct PadVirtualTriggerSetting; +struct PadProcessFocusParameter; +struct PadDataExtended; + +struct PadVrControllerData { + std::uint32_t buttons; + std::uint8_t stick[2]; + std::uint8_t unused6[2]; + std::uint8_t triggers[2]; + std::uint8_t unused10[2]; + std::uint32_t touchButtons; + std::uint8_t touchValues[4]; + float acceleration[3]; + float angularVelocity[3]; + float orientation[4]; + std::uint8_t unused60[4]; + std::uint8_t connected; + std::uint8_t connectedCount; + std::uint8_t unused66[6]; + std::uint64_t timestamp; + std::uint8_t unused80[24]; +}; + +struct PadVrControllerDeviceInformation; +struct PadVrTriggerEffect; +struct PadVrTriggerEffects; +struct PadTriggerEffectExtended; +struct PadExtensionReport; +struct PadExtensionUnitInfo; +struct PadTriggerInternalState; +struct PadTrackerData; +struct PadBlasterTrackerData; +struct PadAstonTrackerData; +struct PadUiData; +struct PadUiTuningData; +struct PadLotusButtonData; +struct PadVersionInfo; +struct PadTelemetryInfo; +struct PadPortInfo; +struct PadVrControllerCombinedState; +struct PadLeonardoData; +struct PadLeonardoUniqueData; +struct PadHistoryData; +struct PadUpdateParameter; +struct PadVirtualDeviceParameter; +struct PadVirtualDeviceId; +struct PadVirtualDeviceComponentInformation; + +struct PadVirtualTriggerInternalState { + std::uint32_t states[2]; + std::uint8_t mode; + std::uint8_t flags[2]; +}; + +struct PadLightBarBlinkingParameter { + std::uint8_t values[3]; +}; + +struct PadButtonRemappingInfo { + std::uint8_t mapping[14]; + std::uint8_t reserved; + std::uint8_t mode; +}; + +struct PadUpdateData { + std::size_t size; + std::uint8_t data[32768]; +}; + +struct PadMotionSensorPosition { + float x; + float y; + float z; +}; + +extern "C" { + +int APS5_VABI scePadClose_nid_postfix(int handle); +int APS5_VABI scePadVrControllerSetVibration(std::int32_t handle, std::uint8_t intensity); +int APS5_VABI scePadVrControllerSetVibrationMode(std::int32_t handle, std::uint32_t mode); +int APS5_VABI scePadVrControllerReadCombinedState(std::int32_t leftHandle, std::int32_t rightHandle, PadVrControllerCombinedState* state); +int APS5_VABI scePadDeviceClassGetExtendedInformation(int handle, PadDeviceClassExtendedInformation* info); +int APS5_VABI scePadDeviceClassParseData(int handle, const PadData* data, PadDeviceClassData* classData); +int APS5_VABI scePadGetControllerInformation(int handle, PadControllerInformation* info); +int APS5_VABI scePadGetHandle(int userId, int type, int index); +int APS5_VABI scePadGetInfo_nid_postfix(PadInfo* info); +int APS5_VABI scePadGetTriggerEffectState(int handle, PadTriggerEffectStateInformation* info); +int APS5_VABI scePadGetExtControllerInformation(int handle, void* info); +int APS5_VABI scePadSetProcessPrivilege(int privilege); +int APS5_VABI scePadSetParticularMode(bool mode); +int APS5_VABI scePadInit_nid_postfix(void); +int APS5_VABI scePadOpen_nid_postfix(int userId, int type, int index, const void* param); +int APS5_VABI scePadOpenExt(int userId, int type, int index, const void* param); +int APS5_VABI scePadReadExt(std::int32_t handle, PadDataExtended* data, std::int32_t count); +int APS5_VABI scePadGetFeatureReport(std::int32_t handle, std::uint8_t reportId, void* data, std::size_t size); +int APS5_VABI scePadSetFeatureReport(std::int32_t handle, std::uint8_t reportId, const void* data, std::size_t size); +int APS5_VABI scePadOutputReport(std::int32_t handle, std::uint8_t reportId, const void* data, std::uint64_t size); +int APS5_VABI scePadRead_nid_postfix(int handle, PadData* data, int num); +int APS5_VABI scePadReadState(int handle, PadData* data); +int APS5_VABI scePadResetLightBar(int handle); +int APS5_VABI scePadResetOrientation(int handle); +int APS5_VABI scePadSetAngularVelocityDeadbandState(int handle, bool enable); +int APS5_VABI scePadSetLightBar(int handle, const PadLightBarParam* param); +int APS5_VABI scePadSetMotionSensorState(int handle, bool enable); +int APS5_VABI scePadSetTiltCorrectionState(int handle, bool enabled); +int APS5_VABI scePadSetTriggerEffect(int handle, const void* param); +int APS5_VABI scePadSetVibration(int handle, const PadVibrationParam* param); +int APS5_VABI scePadSetVibrationMode(int handle, int mode); +int APS5_VABI scePadSetVibrationTriggerEffectWeakWhileEmbeddedMicInUse(bool enabled); +int APS5_VABI scePadVrControllerGetDeviceInformation(std::int32_t handle, PadVrControllerDeviceInformation* info); +int APS5_VABI scePadVrControllerRead(std::int32_t handle, PadVrControllerData* data, std::int32_t count); +int APS5_VABI scePadVrControllerGetTriggerEffectState(std::int32_t leftHandle, std::int32_t rightHandle, PadTriggerEffectStateInformation* states); +int APS5_VABI scePadVrControllerReadState(int handle, PadVrControllerData* state); +int APS5_VABI scePadVrControllerSetTriggerEffect(std::int32_t handle, const PadVrTriggerEffect* effect); +int APS5_VABI scePadVrControllerSetTriggerEffects(std::int32_t leftHandle, std::int32_t rightHandle, const PadVrTriggerEffects* effects); +int APS5_VABI scePadIsRemoteController(int handle, bool* remote); +int APS5_VABI scePadSetAngularVelocityBiasCorrectionState(int handle, bool enabled); +int APS5_VABI scePadUnknown_n3kSX62fgNo(); +int APS5_VABI scePadVrControllerGetTriggerEffectStates(std::int32_t leftHandle, std::int32_t rightHandle, PadTriggerEffectStateInformation* states); +int APS5_VABI scePadGetAccessibilityControllerState(int handle, std::uint32_t* state); +int APS5_VABI scePadSetTriggerEffectExt(std::int32_t handle, const PadTriggerEffectExtended* effect); +int APS5_VABI scePadLastLotusButtonData(std::int32_t handle, std::uint32_t parameter, PadLotusButtonData* data); +int APS5_VABI scePadReadStateExt(std::int32_t handle, PadDataExtended* data); +int APS5_VABI scePadSetExtensionReport(std::int32_t handle, const PadExtensionReport* report); +int APS5_VABI scePadGetExtensionUnitInfo(std::int32_t handle, PadExtensionUnitInfo* info); +int APS5_VABI scePadEnableExtensionPort(bool enabled); +int APS5_VABI scePadEnableSpecificDeviceClass(std::int32_t deviceClass); +int APS5_VABI scePadOpenExt2(std::uint64_t deviceId, std::int32_t type, const void* reserved); +int APS5_VABI scePadDeviceOpen(std::uint64_t deviceId, std::int32_t type, std::int32_t index); +int APS5_VABI scePadGetDataInternal(std::uint8_t port, PadData* data); +int APS5_VABI scePadSetUserColor(std::int32_t handle, std::uint32_t color); +int APS5_VABI scePadDisableVibration(std::int32_t handle, bool disabled); +int APS5_VABI scePadSetVibrationStrength(std::int32_t handle, std::uint32_t strength); +int APS5_VABI scePadSetLightBarBaseBrightness(std::int32_t handle, std::uint32_t brightness); +int APS5_VABI scePadSetLightBarBlinking(std::int32_t handle, const PadLightBarBlinkingParameter* parameter); +std::uint64_t APS5_VABI scePadGetIdleCount(std::int32_t userId); +int APS5_VABI scePadGetControllerIdleCount(std::int32_t handle, std::uint64_t* count); +int APS5_VABI scePadSetPowerSavingState(std::int32_t handle, std::uint8_t state); +int APS5_VABI scePadSetAutoPowerOffCount(std::int32_t count); +int APS5_VABI scePadEnableUsbConnection(bool enabled); +int APS5_VABI scePadEnableAutoDetect(bool enabled); +int APS5_VABI scePadEnablePlayPauseEmulation(bool enabled); +int APS5_VABI scePadDisableTrackingLedBatterySaver(bool disabled); +int APS5_VABI scePadSetLoginUserNumber(std::int32_t number); +int APS5_VABI scePadGetCapability(std::int32_t deviceId, std::uint32_t* capability); +int APS5_VABI scePadShareOutputData(std::int32_t source, std::int32_t destination); +int APS5_VABI scePadShareOutputDataWithFunctionType(std::int32_t source, std::int32_t destination, std::uint32_t functionType); +int APS5_VABI scePadSetVibrationForce(std::int32_t handle, const PadVibrationParam* param); +int APS5_VABI scePadGetVersionInfo(std::int32_t handle, PadVersionInfo* info); +int APS5_VABI scePadGetControllerType(std::int32_t handle, std::int32_t* type); +int APS5_VABI scePadDisableDataConversion(std::int32_t handle, bool disabled); +int APS5_VABI scePadSetButtonRemappingInfo(std::int32_t handle, const PadButtonRemappingInfo* info); +int APS5_VABI scePadSetProcessPrivilegeOfButtonRemapping(bool enabled); +int APS5_VABI scePadSetForceIntercepted(bool enabled); +int APS5_VABI scePadIsLightBarBaseBrightnessControllable(std::int32_t handle); +int APS5_VABI scePadSwitchConnection(std::int32_t handle, std::uint32_t flags); +int APS5_VABI scePadDisableTriggerEffect(std::int32_t handle, bool disabled); +int APS5_VABI scePadSetTriggerEffectStrength(std::int32_t handle, std::uint32_t strength); +int APS5_VABI scePadGetTriggerEffectInternalState(std::int32_t handle, PadTriggerInternalState* state); +int APS5_VABI scePadSetUserNumber(std::int32_t handle, std::int32_t number); +int APS5_VABI scePadDisableTransportButtons(bool disabled); +int APS5_VABI scePadSetLotusIrCodeSetStart(std::int32_t handle, std::uint8_t codeSet, std::uint16_t code, std::size_t dataSize); +int APS5_VABI scePadSetLotusIrCodeSetData(std::int32_t handle, std::uint8_t packetIndex, const void* data, std::size_t dataSize); +int APS5_VABI scePadSetLotusIrCodeSetEnd(std::int32_t handle); +int APS5_VABI scePadGetLotusIrCodeSetResult(std::int32_t handle, std::int32_t* result, std::uint8_t* deviceResult); +int APS5_VABI scePadSetLotusEnableIrKey(std::int32_t handle); +int APS5_VABI scePadSetLotusDisableIrKey(std::int32_t handle); +int APS5_VABI scePadGetUsbDetectionState(std::int32_t deviceId, PadUsbDetectionState* state); +int APS5_VABI scePadUiReadState(std::int32_t handle, PadUiData* data); +int APS5_VABI scePadUiReadStateForTuning(std::int32_t handle, PadUiTuningData* data); +int APS5_VABI scePadSetStickTriggerTuningMode(std::int32_t handle, std::uint32_t mode); +int APS5_VABI scePadSetStickTuningParam(std::int32_t handle, std::uint32_t stick, const PadStickTuningParameter* parameter); +int APS5_VABI scePadSetTriggerTuningParam(std::int32_t handle, const PadTriggerTuningParameter* parameter); +int APS5_VABI scePadGetProfileHunt(std::int32_t handle, std::int32_t profileId, PadHuntProfile* profile); +int APS5_VABI scePadSetProfileHunt(std::int32_t handle, std::int32_t profileId, PadHuntProfile* profile, std::uint32_t* result); +int APS5_VABI scePadResetHunt(std::int32_t handle); +int APS5_VABI scePadGetProfileInfo(std::int32_t deviceId, std::int32_t profileId, PadProfileInfo* info); +int APS5_VABI scePadGetActiveProfileInfo(std::int32_t handle, PadActiveProfileInfo* info); +int APS5_VABI scePadDisableActiveProfileChange(std::int32_t handle, bool disabled); +int APS5_VABI scePadDisableActiveProfileChangeByDeviceId(std::int32_t deviceId, bool disabled); +int APS5_VABI scePadSetActiveProfileSlot(std::int32_t deviceId, std::uint32_t slot); +int APS5_VABI scePadGetSavedSettingInfo(std::int32_t handle, PadSavedSettingInfo* info); +int APS5_VABI scePadSetSavedSettingInfo(std::int32_t handle, const PadSavedSettingInfo* info); +int APS5_VABI scePadVrControllerGetPhysicalUsbConnectionStatus(PadVrUsbConnectionStatus* status); +int APS5_VABI scePadParseUniqueDataLeonardo(std::int32_t handle, const PadLeonardoData* data, PadLeonardoUniqueData* uniqueData); +int APS5_VABI scePadGetControllerTypeLeonardo(std::int32_t deviceId, std::int32_t* controllerType); +int APS5_VABI scePadSetControllerTypeLeonardo(std::int32_t deviceId, std::int32_t controllerType); +int APS5_VABI scePadGetProfileLeonardo(std::int32_t handle, std::int32_t profileId, PadLeonardoProfile* profile); +int APS5_VABI scePadSetProfileLeonardo(std::int32_t handle, std::int32_t profileId, PadLeonardoProfile* profile, std::uint32_t* result); +int APS5_VABI scePadResetLeonardo(std::int32_t handle); +int APS5_VABI scePadSetProfileEditMode(std::int32_t handle, bool enabled, std::uint32_t profile); +int APS5_VABI scePadGetProfileEditMode(std::int32_t handle, std::int32_t* mode); +int APS5_VABI scePadGetProfileEditModeLeonardo(std::int32_t handle); +int APS5_VABI scePadSetSelectButtonCustomizeMode(std::int32_t handle, bool enabled); +int APS5_VABI scePadGetSelectButtonCustomizeMode(std::int32_t handle); +int APS5_VABI scePadSetToggleAllReleaseLeonardo(std::int32_t handle); +int APS5_VABI scePadEnableControllerIndicator(std::int32_t handle); +int APS5_VABI scePadEnableProfileIndicator(std::int32_t handle); +int APS5_VABI scePadSetProfileIndicatorAnimation(std::int32_t handle, std::uint8_t animation); +int APS5_VABI scePadIsCoPilot(std::int32_t handle); +int APS5_VABI scePadSetIsCoPilot(std::int32_t handle, bool enabled); +int APS5_VABI scePadRegisterCollaboInputMgrProcess(void); +int APS5_VABI scePadGetTelemetryInfo(std::int32_t handle, PadTelemetryInfo* info); +int APS5_VABI scePadGetActiveTime(std::int32_t handle, std::int32_t type, std::uint64_t* activeTime); +int APS5_VABI scePadGetDeviceId(std::int32_t handle, std::int32_t* deviceId); +int APS5_VABI scePadGetInfoByPortType(std::int32_t type, PadPortInfo* info); +int APS5_VABI scePadResetLightBarAll(void); +int APS5_VABI scePadResetLightBarAllByPortType(std::uint32_t portType); +int APS5_VABI scePadSetLightBarForTracker(std::int32_t handle, const PadLightBarParam* color); +int APS5_VABI scePadReadForTracker(std::int32_t handle, PadTrackerData* data, std::int32_t count); +int APS5_VABI scePadReadBlasterForTracker(std::int32_t handle, PadBlasterTrackerData* data, std::int32_t count); +int APS5_VABI scePadResetOrientationForTracker(std::int32_t handle); +int APS5_VABI scePadGetMotionTimerUnit(std::int32_t handle, float* unit); +int APS5_VABI scePadSetVrTrackingMode(std::uint8_t mode); +int APS5_VABI scePadGetMotionSensorPosition(std::int32_t handle, PadMotionSensorPosition* position); +int APS5_VABI scePadGetSphereRadius(std::int32_t handle, float* radius); +bool APS5_VABI scePadIsValidHandle(std::int32_t handle, std::int32_t portType); +bool APS5_VABI scePadIsDS4Connected(std::int32_t handle); +bool APS5_VABI scePadIsBlasterConnected(std::int32_t handle); +bool APS5_VABI scePadIsMoveConnected(std::int32_t handle); +int APS5_VABI scePadGetBluetoothAddress(std::int32_t handle, std::uint64_t* address); +int APS5_VABI scePadIsMoveReproductionModel(std::int32_t handle); +int APS5_VABI scePadReadAstonForTracker(std::int32_t handle, PadAstonTrackerData* data, std::int32_t count); +int APS5_VABI scePadGetAstonModel(std::int32_t handle); +int APS5_VABI scePadMbusInit(void); +int APS5_VABI scePadMbusTerm(void); +int APS5_VABI scePadConnectPort(std::int32_t userId, std::int32_t portType); +int APS5_VABI scePadDisconnectPort(std::int32_t userId, std::int32_t portType); +int APS5_VABI scePadDisconnectDevice(std::int32_t deviceId); +int APS5_VABI scePadGetDeviceInfo(std::int32_t deviceId, PadDeviceInfo* info); +int APS5_VABI scePadSetProcessFocus(const PadProcessFocusParameter* parameter); +int APS5_VABI scePadVertualDeviceAddDevice(const PadVirtualDeviceParameter* parameter, PadVirtualDeviceId* deviceId); +int APS5_VABI scePadVirtualDeviceAddDevice(const PadVirtualDeviceParameter* parameter, PadVirtualDeviceId* deviceId); +int APS5_VABI scePadVirtualDeviceDeleteDevice(std::int32_t deviceId); +int APS5_VABI scePadVirtualDeviceInsertData(std::int32_t deviceId, const PadData* data); +int APS5_VABI scePadVirtualDeviceInsertTriggerInternalState(std::int32_t deviceId, const PadVirtualTriggerInternalState* state); +int APS5_VABI scePadVirtualDeviceGetRemoteSetting(std::int32_t deviceId, PadRemoteSetting* setting); +int APS5_VABI scePadVirtualDeviceSetTriggerEffectSetting(std::int32_t handle, const PadVirtualTriggerSetting* setting); +int APS5_VABI scePadVirtualDeviceDisableButtonRemapping(bool disabled); +int APS5_VABI scePadSetShareButtonMaskForRemotePlay(std::uint8_t mask); +int APS5_VABI scePadSetPS4BcVibrationMode(std::uint8_t mode); +int APS5_VABI scePadSetVirtualDeviceComponentInformation(std::int32_t deviceId, const PadVirtualDeviceComponentInformation* info); +int APS5_VABI scePadEnablePs4CompatibleMode(std::int32_t handle, bool enabled); +int APS5_VABI scePadGetLicenseControllerInformation(std::int32_t handle, PadLicenseControllerInformation* info); +int APS5_VABI scePadReadHistory(std::int32_t handle, PadHistoryData* data, std::int32_t count); +int APS5_VABI scePadStartRecording(void); +int APS5_VABI scePadStopRecording(void); +int APS5_VABI scePadRemoteControlInsertData(const std::uint8_t* data); +int APS5_VABI scePadRemoteControlInsertDataForAston(const std::uint8_t* data); +int APS5_VABI scePadGetFeatureReport2(std::int32_t handle, std::uint8_t reportId, void* data, std::size_t size); +int APS5_VABI scePadSetFeatureReport2(std::int32_t handle, std::uint8_t reportId, const void* data, std::size_t size); +int APS5_VABI scePadSetMuteLed(std::int32_t handle, std::uint32_t mode); +int APS5_VABI scePadBondUpdateInit(void); +int APS5_VABI scePadBondUpdateIsReady(std::int32_t deviceId, std::int32_t* ready); +int APS5_VABI scePadBondUpdateStart(std::int32_t handle, const PadUpdateParameter* parameter); +int APS5_VABI scePadBondUpdateGetStatus(std::int32_t deviceId, std::int32_t* status); +int APS5_VABI scePadBondUpdateSendData(std::int32_t deviceId, const PadUpdateData* data); +int APS5_VABI scePadBondUpdateResetBond(std::int32_t deviceId); +int APS5_VABI scePadBondUpdateGetReconnectStatus(std::int32_t* status); +int APS5_VABI scePadBondUpdateTerm(void); +int APS5_VABI scePadControllerUpdateInit(void); +int APS5_VABI scePadControllerUpdateIsUpdateNeeded2(std::int32_t deviceId, const std::uint32_t* version, std::uint16_t* status); +int APS5_VABI scePadControllerUpdateIsReady(std::int32_t deviceId, std::int32_t* ready); +int APS5_VABI scePadControllerUpdateStart(std::int32_t handle, const PadUpdateParameter* parameter); +int APS5_VABI scePadControllerUpdateGetStatus(std::int32_t deviceId, std::int32_t* status); +int APS5_VABI scePadControllerUpdateSendData(std::int32_t deviceId, const PadUpdateData* data); +int APS5_VABI scePadControllerUpdateResetController(std::int32_t deviceId); +int APS5_VABI scePadControllerUpdateGetReconnectStatus(std::int32_t* status); +int APS5_VABI scePadControllerUpdateTerm(void); + +} + #endif diff --git a/core/libs/prx/libScePad/libScePad.hpp b/core/libs/prx/libScePad/libScePad.hpp new file mode 100644 index 0000000000..12aecdf76c --- /dev/null +++ b/core/libs/prx/libScePad/libScePad.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libScePad/include/Pad.hpp" diff --git a/core/libs/prx/libScePadTracker/Export.cpp b/core/libs/prx/libScePadTracker/Export.cpp index e43ebed776..e48d78bdda 100644 --- a/core/libs/prx/libScePadTracker/Export.cpp +++ b/core/libs/prx/libScePadTracker/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libScePadTracker/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libScePadTracker/include/Api.hpp b/core/libs/prx/libScePadTracker/include/Api.hpp new file mode 100644 index 0000000000..825991c114 --- /dev/null +++ b/core/libs/prx/libScePadTracker/include/Api.hpp @@ -0,0 +1,14 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI scePadTrackerCalibrate(); +int APS5_VABI scePadTrackerGetWorkingMemorySize(); +int APS5_VABI scePadTrackerInit(); +int APS5_VABI scePadTrackerReadState(); +int APS5_VABI scePadTrackerTerm(); +int APS5_VABI scePadTrackerUpdate(); + +} diff --git a/core/libs/prx/libScePadTracker/libScePadTracker.hpp b/core/libs/prx/libScePadTracker/libScePadTracker.hpp new file mode 100644 index 0000000000..18b6ca49c9 --- /dev/null +++ b/core/libs/prx/libScePadTracker/libScePadTracker.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libScePadTracker/include/Api.hpp" diff --git a/core/libs/prx/libScePatchCheckerClient/Export.cpp b/core/libs/prx/libScePatchCheckerClient/Export.cpp index 3cce60d2e7..e10db5258f 100644 --- a/core/libs/prx/libScePatchCheckerClient/Export.cpp +++ b/core/libs/prx/libScePatchCheckerClient/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libScePatchCheckerClient/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libScePatchCheckerClient/include/Api.hpp b/core/libs/prx/libScePatchCheckerClient/include/Api.hpp new file mode 100644 index 0000000000..25f7bdc95a --- /dev/null +++ b/core/libs/prx/libScePatchCheckerClient/include/Api.hpp @@ -0,0 +1,20 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI scePatchCheckerCancel(); +int APS5_VABI scePatchCheckerCheckPatch(); +int APS5_VABI scePatchCheckerCreateHandler(); +int APS5_VABI scePatchCheckerDestroyHandler(); +int APS5_VABI scePatchCheckerDisableAutoDownload(); +int APS5_VABI scePatchCheckerEnableAutoDownload(); +int APS5_VABI scePatchCheckerGetApplicableTick(); +int APS5_VABI scePatchCheckerGetPackageInfo(); +int APS5_VABI scePatchCheckerInitialize(); +int APS5_VABI scePatchCheckerRequestCheckPatch(); +int APS5_VABI scePatchCheckerRequestCheckPatchByType(); +int APS5_VABI scePatchCheckerTerminate(); + +} diff --git a/core/libs/prx/libScePatchCheckerClient/libScePatchCheckerClient.hpp b/core/libs/prx/libScePatchCheckerClient/libScePatchCheckerClient.hpp new file mode 100644 index 0000000000..dab24e28c7 --- /dev/null +++ b/core/libs/prx/libScePatchCheckerClient/libScePatchCheckerClient.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libScePatchCheckerClient/include/Api.hpp" diff --git a/core/libs/prx/libScePerf/libScePerf.hpp b/core/libs/prx/libScePerf/libScePerf.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libScePerf/libScePerf.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libScePlayGo/Export.cpp b/core/libs/prx/libScePlayGo/Export.cpp index 9fae1d940e..eb53f29aec 100644 --- a/core/libs/prx/libScePlayGo/Export.cpp +++ b/core/libs/prx/libScePlayGo/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libScePlayGo/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libScePlayGo/include/Api.hpp b/core/libs/prx/libScePlayGo/include/Api.hpp new file mode 100644 index 0000000000..e7f2e0a879 --- /dev/null +++ b/core/libs/prx/libScePlayGo/include/Api.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI scePlayGoClose(int handle); +int APS5_VABI scePlayGoGetChunkId(int handle, uint16_t* outChunkIdList, uint32_t numberOfEntries, uint32_t* outEntries); +int APS5_VABI scePlayGoGetEta(int handle, const uint16_t* chunkIds, uint32_t numberOfEntries, int64_t* outEta); +int APS5_VABI scePlayGoGetInstallChunkId(int handle, uint16_t* outChunkIdList, uint32_t numberOfEntries, uint32_t* outEntries); +int APS5_VABI scePlayGoGetInstallSpeed(int handle, int32_t* outSpeed); +int APS5_VABI scePlayGoGetLanguageMask(int handle, uint64_t* outLanguageMask); +int APS5_VABI scePlayGoGetLocus(int handle, const uint16_t* chunkIds, uint32_t numberOfEntries, int8_t* outLoci); +int APS5_VABI scePlayGoGetOptionalChunk(int handle, std::uint32_t type, PlayGoOptionalChunk* option); +int APS5_VABI scePlayGoGetProgress(int handle, const uint16_t* chunkIds, uint32_t numberOfEntries, PlayGoProgress* outProgress); +int APS5_VABI scePlayGoGetSupportedOptionalChunk(int handle, std::uint32_t type, PlayGoOptionalChunk* option); +int APS5_VABI scePlayGoGetToDoList(int handle, PlayGoToDo* outTodoList, uint32_t numberOfEntries, uint32_t* outEntries); +int APS5_VABI scePlayGoInitialize(const PlayGoInitParams* init); +int APS5_VABI scePlayGoOpen(int* outHandle, const void* param); +int APS5_VABI scePlayGoPrefetch(int handle, const uint16_t* chunkIds, uint32_t numberOfEntries, int8_t minimumLocus); +int APS5_VABI scePlayGoPrefetchOptionalChunk(int handle, int32_t type, const PlayGoOptionalChunk* option); +int APS5_VABI scePlayGoSetInstallSpeed(int handle, int32_t speed); +int APS5_VABI scePlayGoSetToDoList(int handle, const PlayGoToDo* todoList, uint32_t numberOfEntries); +int APS5_VABI scePlayGoTerminate(void); +int APS5_VABI scePlayGoRequestNextChunk(); +int APS5_VABI scePlayGoSetLanguageMask(int handle, uint64_t languageMask); +int APS5_VABI scePlayGoSnapshot(); + +} diff --git a/core/libs/prx/libScePlayGo/libScePlayGo.hpp b/core/libs/prx/libScePlayGo/libScePlayGo.hpp new file mode 100644 index 0000000000..be60245c2e --- /dev/null +++ b/core/libs/prx/libScePlayGo/libScePlayGo.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libScePlayGo/include/Api.hpp" diff --git a/core/libs/prx/libScePlayGoDialog/Export.cpp b/core/libs/prx/libScePlayGoDialog/Export.cpp index e341d17b84..084d94c5b3 100644 --- a/core/libs/prx/libScePlayGoDialog/Export.cpp +++ b/core/libs/prx/libScePlayGoDialog/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libScePlayGoDialog/include/Api.hpp" #include #include #include diff --git a/core/libs/prx/libScePlayGoDialog/include/Api.hpp b/core/libs/prx/libScePlayGoDialog/include/Api.hpp new file mode 100644 index 0000000000..99f0428e67 --- /dev/null +++ b/core/libs/prx/libScePlayGoDialog/include/Api.hpp @@ -0,0 +1,15 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI scePlayGoDialogInitialize(void); +int APS5_VABI scePlayGoDialogTerminate(void); +int APS5_VABI scePlayGoDialogOpen(const void* param); +int APS5_VABI scePlayGoDialogClose(void); +int APS5_VABI scePlayGoDialogUpdateStatus(void); +int APS5_VABI scePlayGoDialogGetResult(PlayGoDialogResult* result); +int APS5_VABI scePlayGoDialogGetStatus(void); + +} diff --git a/core/libs/prx/libScePlayGoDialog/libScePlayGoDialog.hpp b/core/libs/prx/libScePlayGoDialog/libScePlayGoDialog.hpp new file mode 100644 index 0000000000..3b805577f0 --- /dev/null +++ b/core/libs/prx/libScePlayGoDialog/libScePlayGoDialog.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libScePlayGoDialog/include/Api.hpp" diff --git a/core/libs/prx/libScePlayReady/Export.cpp b/core/libs/prx/libScePlayReady/Export.cpp index 59330d9d35..fa7958b257 100644 --- a/core/libs/prx/libScePlayReady/Export.cpp +++ b/core/libs/prx/libScePlayReady/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libScePlayReady/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libScePlayReady/include/Api.hpp b/core/libs/prx/libScePlayReady/include/Api.hpp new file mode 100644 index 0000000000..6fb478bbda --- /dev/null +++ b/core/libs/prx/libScePlayReady/include/Api.hpp @@ -0,0 +1,58 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceBufferAlloc(); +int APS5_VABI sceBufferDup(); +int APS5_VABI sceBufferFree(); +int APS5_VABI sceBufferInit(); +int APS5_VABI sceBufferRealloc(); +int APS5_VABI scePlayReadyApiInitializeInitParams(); +int APS5_VABI scePlayReadyApiIsStarted(); +int APS5_VABI scePlayReadyApiStart(); +int APS5_VABI scePlayReadyApiStop(); +int APS5_VABI scePlayReadyApiVersion(); +int APS5_VABI scePlayReadyApiVersionString(); +int APS5_VABI scePlayReadyBufferFree(); +int APS5_VABI scePlayReadyBufferInit(); +int APS5_VABI scePlayReadyBufferMalloc(); +int APS5_VABI scePlayReadyBufferRealloc(); +int APS5_VABI scePlayReadyContentGetProperty(); +int APS5_VABI scePlayReadyContentSetProperty(); +int APS5_VABI scePlayReadyDomainCertEnumFini(); +int APS5_VABI scePlayReadyDomainCertEnumInit(); +int APS5_VABI scePlayReadyDomainCertEnumNext(); +int APS5_VABI scePlayReadyDomainCertFind(); +int APS5_VABI scePlayReadyDomainJoinGenerateChallenge(); +int APS5_VABI scePlayReadyDomainJoinProcessResponse(); +int APS5_VABI scePlayReadyDomainLeaveGenerateChallenge(); +int APS5_VABI scePlayReadyDomainLeaveProcessResponse(); +int APS5_VABI scePlayReadyEnvelopeClose(); +int APS5_VABI scePlayReadyEnvelopeGetSize(); +int APS5_VABI scePlayReadyEnvelopeInitializeRead(); +int APS5_VABI scePlayReadyEnvelopeOpen(); +int APS5_VABI scePlayReadyEnvelopeRead(); +int APS5_VABI scePlayReadyEnvelopeSeek(); +int APS5_VABI scePlayReadyFinalize(); +int APS5_VABI scePlayReadyFreeDecryptContext(); +int APS5_VABI scePlayReadyInitialize(); +int APS5_VABI scePlayReadyInitializeInitParams(); +int APS5_VABI scePlayReadyLicenseAcqGenerateAck(); +int APS5_VABI scePlayReadyLicenseAcqGenerateChallenge(); +int APS5_VABI scePlayReadyLicenseAcqGetAdditionalResponseData(); +int APS5_VABI scePlayReadyLicenseAcqProcessAckResponse(); +int APS5_VABI scePlayReadyLicenseAcqProcessResponse(); +int APS5_VABI scePlayReadyMemAlloc(); +int APS5_VABI scePlayReadyMemFree(); +int APS5_VABI scePlayReadyMemGetStats(); +int APS5_VABI scePlayReadyMemRealloc(); +int APS5_VABI scePlayReadyNewDecryptContext(); +int APS5_VABI scePlayReadyReaderBind(); +int APS5_VABI scePlayReadyReaderCommit(); +int APS5_VABI scePlayReadyReaderDecrypt(); +int APS5_VABI scePlayReadyReset(); +int APS5_VABI scePlayReadyStoreCleanup(); + +} diff --git a/core/libs/prx/libScePlayReady/libScePlayReady.hpp b/core/libs/prx/libScePlayReady/libScePlayReady.hpp new file mode 100644 index 0000000000..3138b60f6b --- /dev/null +++ b/core/libs/prx/libScePlayReady/libScePlayReady.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libScePlayReady/include/Api.hpp" diff --git a/core/libs/prx/libScePlayReady2/Export.cpp b/core/libs/prx/libScePlayReady2/Export.cpp index 2b08a30037..0ad7e3f73d 100644 --- a/core/libs/prx/libScePlayReady2/Export.cpp +++ b/core/libs/prx/libScePlayReady2/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libScePlayReady2/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libScePlayReady2/include/Api.hpp b/core/libs/prx/libScePlayReady2/include/Api.hpp new file mode 100644 index 0000000000..3e388e5dc6 --- /dev/null +++ b/core/libs/prx/libScePlayReady2/include/Api.hpp @@ -0,0 +1,24 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI scePlayReadyBufferInitWithData(); +int APS5_VABI scePlayReadyCloneDecryptContext(); +int APS5_VABI scePlayReadyDebugPrintf(); +int APS5_VABI scePlayReadyDebugSetLevel(); +int APS5_VABI scePlayReadyLicenseDelete(); +int APS5_VABI scePlayReadyLicenseDeleteInMemory(); +int APS5_VABI scePlayReadyLicenseGetExpirationTime(); +int APS5_VABI scePlayReadyLicenseGetProperty(); +int APS5_VABI scePlayReadyReaderClose(); +int APS5_VABI scePlayReadyReaderDecryptMultiple(); +int APS5_VABI scePlayReadyReaderDecryptMultipleOpaque(); +int APS5_VABI scePlayReadyReaderDecryptOpaque(); +int APS5_VABI scePlayReadyReaderDecrypt_Legacy(); +int APS5_VABI scePlayReadyReaderFreeOpaqueContent(); +int APS5_VABI scePlayReadyReaderRetrieveOpaqueContent(); +int APS5_VABI scePlayReadyReinitialize(); + +} diff --git a/core/libs/prx/libScePlayReady2/libScePlayReady2.hpp b/core/libs/prx/libScePlayReady2/libScePlayReady2.hpp new file mode 100644 index 0000000000..48fc0e9766 --- /dev/null +++ b/core/libs/prx/libScePlayReady2/libScePlayReady2.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libScePlayReady2/include/Api.hpp" diff --git a/core/libs/prx/libScePlayReady4/Export.cpp b/core/libs/prx/libScePlayReady4/Export.cpp index 0454139571..9d4bbeea93 100644 --- a/core/libs/prx/libScePlayReady4/Export.cpp +++ b/core/libs/prx/libScePlayReady4/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libScePlayReady4/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libScePlayReady4/include/Api.hpp b/core/libs/prx/libScePlayReady4/include/Api.hpp new file mode 100644 index 0000000000..cef37c1859 --- /dev/null +++ b/core/libs/prx/libScePlayReady4/include/Api.hpp @@ -0,0 +1,43 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI scePlayReadyApiPlatform(); +int APS5_VABI scePlayReadyCdmiClose(); +int APS5_VABI scePlayReadyCdmiCreateMediaKeySession(); +int APS5_VABI scePlayReadyCdmiCreateMediaKeySystemAccess(); +int APS5_VABI scePlayReadyCdmiCreateMediaKeys(); +int APS5_VABI scePlayReadyCdmiDecryptMultipleOpaque(); +int APS5_VABI scePlayReadyCdmiDecryptOpaque(); +int APS5_VABI scePlayReadyCdmiDecryptOpaque2(); +int APS5_VABI scePlayReadyCdmiDestroyMediaKeySession(); +int APS5_VABI scePlayReadyCdmiDestroyMediaKeySystemAccess(); +int APS5_VABI scePlayReadyCdmiDestroyMediaKeys(); +int APS5_VABI scePlayReadyCdmiFreeOpaqueDecryptedContent(); +int APS5_VABI scePlayReadyCdmiGenerateRequest(); +int APS5_VABI scePlayReadyCdmiGetConfiguration(); +int APS5_VABI scePlayReadyCdmiGetExpiration(); +int APS5_VABI scePlayReadyCdmiGetKeySystem(); +int APS5_VABI scePlayReadyCdmiGetMediaKeyCount(); +int APS5_VABI scePlayReadyCdmiGetMediaKeyStatus(); +int APS5_VABI scePlayReadyCdmiGetSessionAppContext(); +int APS5_VABI scePlayReadyCdmiGetSessionId(); +int APS5_VABI scePlayReadyCdmiIsLicenseAckRequired(); +int APS5_VABI scePlayReadyCdmiLoad(); +int APS5_VABI scePlayReadyCdmiRemove(); +int APS5_VABI scePlayReadyCdmiRetrieveOpaqueDecryptedContent(); +int APS5_VABI scePlayReadyCdmiSetServerCertificate(); +int APS5_VABI scePlayReadyCdmiSetSessionCallbacks(); +int APS5_VABI scePlayReadyCdmiUpdate(); +int APS5_VABI scePlayReadyLicenseCount(); +int APS5_VABI scePlayReadyProfileClear(); +int APS5_VABI scePlayReadyProfileEnter(); +int APS5_VABI scePlayReadyProfileLeave(); +int APS5_VABI scePlayReadyProfilePause(); +int APS5_VABI scePlayReadyProfileResume(); +int APS5_VABI scePlayReadyProfileStart(); +int APS5_VABI scePlayReadyProfileStop(); + +} diff --git a/core/libs/prx/libScePlayReady4/libScePlayReady4.hpp b/core/libs/prx/libScePlayReady4/libScePlayReady4.hpp new file mode 100644 index 0000000000..97c4cdd3e7 --- /dev/null +++ b/core/libs/prx/libScePlayReady4/libScePlayReady4.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libScePlayReady4/include/Api.hpp" diff --git a/core/libs/prx/libScePlayerInvitationDialog/Export.cpp b/core/libs/prx/libScePlayerInvitationDialog/Export.cpp index 86095da370..0f78112135 100644 --- a/core/libs/prx/libScePlayerInvitationDialog/Export.cpp +++ b/core/libs/prx/libScePlayerInvitationDialog/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libScePlayerInvitationDialog/libScePlayerInvitationDialog.h" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libScePlayerInvitationDialog/libScePlayerInvitationDialog.hpp b/core/libs/prx/libScePlayerInvitationDialog/libScePlayerInvitationDialog.hpp new file mode 100644 index 0000000000..be74cdea73 --- /dev/null +++ b/core/libs/prx/libScePlayerInvitationDialog/libScePlayerInvitationDialog.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libScePlayerInvitationDialog/libScePlayerInvitationDialog.h" diff --git a/core/libs/prx/libScePlayerSelectionDialog/Export.cpp b/core/libs/prx/libScePlayerSelectionDialog/Export.cpp index 06df01e1c8..52b3363adb 100644 --- a/core/libs/prx/libScePlayerSelectionDialog/Export.cpp +++ b/core/libs/prx/libScePlayerSelectionDialog/Export.cpp @@ -1,3 +1,5 @@ +#include "prx/libScePlayerSelectionDialog/include/Api.hpp" +#include "prx/libSceUserService/UserService.hpp" #include #include #include @@ -6,8 +8,6 @@ #include "prx/libSceCommonDialog/CommonDialog.hpp" #include "prx/libc/include/General.hpp" -extern "C" int APS5_VABI sceUserServiceGetLoginUserIdList(UserServiceLoginUserIdList* users); - namespace { constexpr int COMMON_DIALOG_STATUS_NONE = 0; diff --git a/core/libs/prx/libScePlayerSelectionDialog/include/Api.hpp b/core/libs/prx/libScePlayerSelectionDialog/include/Api.hpp new file mode 100644 index 0000000000..baf1617f53 --- /dev/null +++ b/core/libs/prx/libScePlayerSelectionDialog/include/Api.hpp @@ -0,0 +1,17 @@ +#pragma once + +#include "prx/libSceCommonDialog/CommonDialog.hpp" +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI scePlayerSelectionDialogInitialize(void); +int APS5_VABI scePlayerSelectionDialogOpen(const PlayerSelectionDialogParam* param); +int APS5_VABI scePlayerSelectionDialogClose(void); +int APS5_VABI scePlayerSelectionDialogUpdateStatus(void); +int APS5_VABI scePlayerSelectionDialogGetStatus(void); +int APS5_VABI scePlayerSelectionDialogGetResult(PlayerSelectionDialogResult* result); +int APS5_VABI scePlayerSelectionDialogParamInitialize(void* param); +int APS5_VABI scePlayerSelectionDialogTerminate(void); + +} diff --git a/core/libs/prx/libScePlayerSelectionDialog/libScePlayerSelectionDialog.hpp b/core/libs/prx/libScePlayerSelectionDialog/libScePlayerSelectionDialog.hpp new file mode 100644 index 0000000000..2e72898b93 --- /dev/null +++ b/core/libs/prx/libScePlayerSelectionDialog/libScePlayerSelectionDialog.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libScePlayerSelectionDialog/include/Api.hpp" diff --git a/core/libs/prx/libScePngDec/Export.cpp b/core/libs/prx/libScePngDec/Export.cpp index 8ff5827de0..3599cef8d3 100644 --- a/core/libs/prx/libScePngDec/Export.cpp +++ b/core/libs/prx/libScePngDec/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libScePngDec/include/Api.hpp" #include #include #include diff --git a/core/libs/prx/libScePngDec/include/Api.hpp b/core/libs/prx/libScePngDec/include/Api.hpp new file mode 100644 index 0000000000..1440fbcf5a --- /dev/null +++ b/core/libs/prx/libScePngDec/include/Api.hpp @@ -0,0 +1,14 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int32_t APS5_VABI scePngDecCreate(const PngDecCreateParam* param, void* memoryAddress, uint32_t memorySize, void** handle); +int32_t APS5_VABI scePngDecDecode(void* handle, const PngDecDecodeParam* param, PngDecImageInfo* imageInfo); +int32_t APS5_VABI scePngDecDelete(void* handle); +int32_t APS5_VABI scePngDecParseHeader(const PngDecParseParam* param, PngDecImageInfo* imageInfo); +int32_t APS5_VABI scePngDecQueryMemorySize(const PngDecCreateParam* param); +int APS5_VABI scePngDecDecodeWithInputControl(); + +} diff --git a/core/libs/prx/libScePngDec/libScePngDec.hpp b/core/libs/prx/libScePngDec/libScePngDec.hpp new file mode 100644 index 0000000000..27bf3452a2 --- /dev/null +++ b/core/libs/prx/libScePngDec/libScePngDec.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libScePngDec/include/Api.hpp" diff --git a/core/libs/prx/libScePngEnc/Export.cpp b/core/libs/prx/libScePngEnc/Export.cpp index c6e3c9532a..75f4ad13f1 100644 --- a/core/libs/prx/libScePngEnc/Export.cpp +++ b/core/libs/prx/libScePngEnc/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libScePngEnc/include/Api.hpp" #include #include #include diff --git a/core/libs/prx/libScePngEnc/include/Api.hpp b/core/libs/prx/libScePngEnc/include/Api.hpp new file mode 100644 index 0000000000..b279f174e8 --- /dev/null +++ b/core/libs/prx/libScePngEnc/include/Api.hpp @@ -0,0 +1,12 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI scePngEncQueryMemorySize(const PngEncCreateParam* param); +int APS5_VABI scePngEncCreate(const PngEncCreateParam* param, void* memoryAddress, uint32_t memorySize, void** handle); +int APS5_VABI scePngEncDelete(void* handle); +int APS5_VABI scePngEncEncode(void* handle, const PngEncEncodeParam* param, PngEncOutputInfo* outputInfo); + +} diff --git a/core/libs/prx/libScePngEnc/libScePngEnc.hpp b/core/libs/prx/libScePngEnc/libScePngEnc.hpp new file mode 100644 index 0000000000..2355570756 --- /dev/null +++ b/core/libs/prx/libScePngEnc/libScePngEnc.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libScePngEnc/include/Api.hpp" diff --git a/core/libs/prx/libScePngParser/libScePngParser.hpp b/core/libs/prx/libScePngParser/libScePngParser.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libScePngParser/libScePngParser.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libScePosixForWebKit/CMakeLists.txt b/core/libs/prx/libScePosixForWebKit/CMakeLists.txt index 036eb0577d..59d7ed5e61 100644 --- a/core/libs/prx/libScePosixForWebKit/CMakeLists.txt +++ b/core/libs/prx/libScePosixForWebKit/CMakeLists.txt @@ -45,4 +45,14 @@ if(BUILD_TESTING) set_tests_properties(guest_service_database PROPERTIES ENVIRONMENT_MODIFICATION "PATH=path_list_prepend:$") endif() + add_test_executable(guest_posix_thread_name_tests ${LIBS_INCLUDE_DIR}/tests/GuestPosixThreadName.cpp) + target_include_directories(guest_posix_thread_name_tests PRIVATE ${LIBS_INCLUDE_DIR}) + target_link_libraries(guest_posix_thread_name_tests PRIVATE libScePosixForWebKit libkernel libc) + configure_windows_unwind(guest_posix_thread_name_tests) + add_test(NAME guest_posix_thread_name COMMAND guest_posix_thread_name_tests) + set_tests_properties(guest_posix_thread_name PROPERTIES TIMEOUT 30) + if(WIN32) + set_tests_properties(guest_posix_thread_name PROPERTIES ENVIRONMENT_MODIFICATION + "PATH=path_list_prepend:$") + endif() endif() diff --git a/core/libs/prx/libScePosixForWebKit/Export.cpp b/core/libs/prx/libScePosixForWebKit/Export.cpp index 240518b089..9f7f7de9a5 100644 --- a/core/libs/prx/libScePosixForWebKit/Export.cpp +++ b/core/libs/prx/libScePosixForWebKit/Export.cpp @@ -1,24 +1,25 @@ +#include "prx/libkernel/Time/include/Time.hpp" +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" +#include "prx/libScePosixForWebKit/include/Api.hpp" #include "SceTypes.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libc/include/HostEntropy.hpp" #include "prx/libc/include/General.hpp" +#include "prx/libkernel/Pthread/include/Pthread.hpp" #include #include #include #include +#include #include -extern "C" { -int APS5_VABI access_nid_postfix(const char*, int); -int APS5_VABI clock_gettime_nid_postfix(int, KernelTimespec*); -char* APS5_VABI getcwd_nid_postfix(char*, std::size_t); -char* APS5_VABI getenv_nid_postfix(const char*); -int APS5_VABI lstat_nid_postfix(const char*, FileStat*); -void* APS5_VABI mmap_nid_postfix(void*, std::size_t, int, int, int, std::int64_t) noexcept; -} - namespace { +constexpr int ThreadNameInvalid = 22; +constexpr int ThreadNameTooLong = 63; +constexpr std::size_t ThreadNameCapacity = 32; + constexpr int FnmNomatch = 1; constexpr int FnmNoescape = 0x01; constexpr int FnmPathname = 0x02; @@ -188,6 +189,7 @@ void APS5_VABI arc4random_buf_nid_postfix(void* buffer, std::size_t size) { std::uint32_t APS5_VABI arc4random_nid_postfix() { std::uint32_t value; arc4random_buf_nid_postfix(&value, sizeof(value)); + return value; } @@ -282,4 +284,12 @@ int APS5_VABI scePosixForWebKit_sysinfo() { return 0; } +int APS5_VABI pthread_setname_np_nid_postfix(Pthread thread, const char* name) { + if (thread == nullptr || name == nullptr) return ThreadNameInvalid; + if (std::strlen(name) >= ThreadNameCapacity) return ThreadNameTooLong; + std::lock_guard lock(thread->nameLock); + thread->name = name; + return 0; +} + } diff --git a/core/libs/prx/libScePosixForWebKit/Filesystem.cpp b/core/libs/prx/libScePosixForWebKit/Filesystem.cpp index a7e6f01754..10dfa7eed6 100644 --- a/core/libs/prx/libScePosixForWebKit/Filesystem.cpp +++ b/core/libs/prx/libScePosixForWebKit/Filesystem.cpp @@ -1,3 +1,6 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" +#include "prx/libScePosixForWebKit/include/Api.hpp" #include "prx/libc/include/GuestArena.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libkernel/File/include/FileFlags.hpp" @@ -14,11 +17,6 @@ extern "C" _invalid_parameter_handler _set_thread_local_invalid_parameter_handle #include #endif -extern "C" { -int* APS5_VABI __error_nid_postfix(); -int APS5_VABI open_nid_postfix(const char*, int, int); -} - namespace { constexpr char Characters[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; diff --git a/core/libs/prx/libScePosixForWebKit/Resolver.cpp b/core/libs/prx/libScePosixForWebKit/Resolver.cpp index f9b8a2acc2..6b0007a4b9 100644 --- a/core/libs/prx/libScePosixForWebKit/Resolver.cpp +++ b/core/libs/prx/libScePosixForWebKit/Resolver.cpp @@ -1,3 +1,5 @@ +#include "prx/libScePosixForWebKit/include/Api.hpp" +#include "prx/libSceNet/include/Net.hpp" #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN #include @@ -21,8 +23,6 @@ #include #include "GuestResolver.hpp" -extern "C" int* APS5_VABI sceNetErrnoLoc(); - namespace { struct HostLookup { GuestResolver::HostEntry entry{}; diff --git a/core/libs/prx/libScePosixForWebKit/include/Api.hpp b/core/libs/prx/libScePosixForWebKit/include/Api.hpp new file mode 100644 index 0000000000..bff7385004 --- /dev/null +++ b/core/libs/prx/libScePosixForWebKit/include/Api.hpp @@ -0,0 +1,41 @@ +#pragma once + +#include "prx/libScePosixForWebKit/GuestResolver.hpp" +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI fnmatch_nid_postfix(const char* pattern, const char* string, int flags); +char* APS5_VABI strcasestr_nid_postfix(const char* text, const char* needle); +void APS5_VABI arc4random_buf_nid_postfix(void* buffer, std::size_t size); +std::uint32_t APS5_VABI arc4random_nid_postfix(); +int APS5_VABI __wrap_access(const char* path, int mode); +int APS5_VABI __wrap_clock_gettime(int clockId, KernelTimespec* tp); +int APS5_VABI __wrap_fchown(); +char* APS5_VABI __wrap_getcwd(char* buffer, std::size_t size); +char* APS5_VABI __wrap_getenv(const char* name); +int APS5_VABI __wrap_link(); +int APS5_VABI __wrap_lstat(const char* path, FileStat* sb); +void* APS5_VABI __wrap_mmap(void* address, std::size_t length, int protection, int flags, int descriptor, std::int64_t offset); +int APS5_VABI __wrap_readlink(); +int APS5_VABI __wrap_statvfs(); +int APS5_VABI __wrap_symlink(); +int APS5_VABI clock_gettime_np(); +int APS5_VABI getenv_np(); +int APS5_VABI scePosixForWebKit_gethostbyname_r(); +int APS5_VABI pthread_setname_np_nid_postfix(Pthread thread, const char* name); +int APS5_VABI mmap_np(); +int APS5_VABI msetname(); +int APS5_VABI pthread_setschedparam_np(); +int APS5_VABI setenv_np(); +int APS5_VABI scePosixForWebKit_sysinfo(); +int APS5_VABI mkstemp_nid_postfix(char* pattern); +int APS5_VABI isatty_nid_postfix(int descriptor); +GuestResolver::HostEntry* APS5_VABI gethostbyname_nid_postfix(const char* name); +GuestResolver::ServiceEntry* APS5_VABI getservbyname_nid_postfix(const char* name, const char* protocol); +void APS5_VABI freeaddrinfo_nid_postfix(GuestResolver::AddressInfo* first); +int APS5_VABI getaddrinfo_nid_postfix(const char* node, const char* service, const GuestResolver::AddressInfo* hints, GuestResolver::AddressInfo** output); +int APS5_VABI getnameinfo_nid_postfix(const void* address, std::uint32_t length, char* host, std::uint32_t hostLength, char* service, std::uint32_t serviceLength, int flags); +const char* APS5_VABI gai_strerror_nid_postfix(int error); + +} diff --git a/core/libs/prx/libScePosixForWebKit/libScePosixForWebKit.hpp b/core/libs/prx/libScePosixForWebKit/libScePosixForWebKit.hpp new file mode 100644 index 0000000000..0f4456a5e2 --- /dev/null +++ b/core/libs/prx/libScePosixForWebKit/libScePosixForWebKit.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libScePosixForWebKit/include/Api.hpp" diff --git a/core/libs/prx/libSceProprietaryVoiceChatHelperPrx/Export.cpp b/core/libs/prx/libSceProprietaryVoiceChatHelperPrx/Export.cpp index d1c11f4133..45c16b6916 100644 --- a/core/libs/prx/libSceProprietaryVoiceChatHelperPrx/Export.cpp +++ b/core/libs/prx/libSceProprietaryVoiceChatHelperPrx/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceProprietaryVoiceChatHelperPrx/include/Api.hpp" #include #include #include diff --git a/core/libs/prx/libSceProprietaryVoiceChatHelperPrx/include/Api.hpp b/core/libs/prx/libSceProprietaryVoiceChatHelperPrx/include/Api.hpp new file mode 100644 index 0000000000..991a8ea2d2 --- /dev/null +++ b/core/libs/prx/libSceProprietaryVoiceChatHelperPrx/include/Api.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceProprietaryVoiceChatHelperInitialize(void); +int APS5_VABI sceProprietaryVoiceChatHelperTerminate(void); +int APS5_VABI sceProprietaryVoiceChatHelperSetVoiceChatState(void); +int APS5_VABI sceProprietaryVoiceChatHelperGetVoiceChatUsageState(void); +int APS5_VABI sceProprietaryVoiceChatHelperGetVoiceChat(void); + +} diff --git a/core/libs/prx/libSceProprietaryVoiceChatHelperPrx/libSceProprietaryVoiceChatHelperPrx.hpp b/core/libs/prx/libSceProprietaryVoiceChatHelperPrx/libSceProprietaryVoiceChatHelperPrx.hpp new file mode 100644 index 0000000000..9302848829 --- /dev/null +++ b/core/libs/prx/libSceProprietaryVoiceChatHelperPrx/libSceProprietaryVoiceChatHelperPrx.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceProprietaryVoiceChatHelperPrx/include/Api.hpp" diff --git a/core/libs/prx/libScePs2EmuMenuDialog/Export.cpp b/core/libs/prx/libScePs2EmuMenuDialog/Export.cpp index 99db1f489a..a27fb265fc 100644 --- a/core/libs/prx/libScePs2EmuMenuDialog/Export.cpp +++ b/core/libs/prx/libScePs2EmuMenuDialog/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libScePs2EmuMenuDialog/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libScePs2EmuMenuDialog/include/Api.hpp b/core/libs/prx/libScePs2EmuMenuDialog/include/Api.hpp new file mode 100644 index 0000000000..de66779d90 --- /dev/null +++ b/core/libs/prx/libScePs2EmuMenuDialog/include/Api.hpp @@ -0,0 +1,15 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI scePs2EmuMenuDialogClose(); +int APS5_VABI scePs2EmuMenuDialogGetResult(); +int APS5_VABI scePs2EmuMenuDialogGetStatus(); +int APS5_VABI scePs2EmuMenuDialogInitialize(); +int APS5_VABI scePs2EmuMenuDialogOpen(); +int APS5_VABI scePs2EmuMenuDialogTerminate(); +int APS5_VABI scePs2EmuMenuDialogUpdateStatus(); + +} diff --git a/core/libs/prx/libScePs2EmuMenuDialog/libScePs2EmuMenuDialog.hpp b/core/libs/prx/libScePs2EmuMenuDialog/libScePs2EmuMenuDialog.hpp new file mode 100644 index 0000000000..f09948b438 --- /dev/null +++ b/core/libs/prx/libScePs2EmuMenuDialog/libScePs2EmuMenuDialog.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libScePs2EmuMenuDialog/include/Api.hpp" diff --git a/core/libs/prx/libScePsm/libScePsm.hpp b/core/libs/prx/libScePsm/libScePsm.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libScePsm/libScePsm.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libScePsmUtil/Export.cpp b/core/libs/prx/libScePsmUtil/Export.cpp index 0a7d7939be..422f3863b3 100644 --- a/core/libs/prx/libScePsmUtil/Export.cpp +++ b/core/libs/prx/libScePsmUtil/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libScePsmUtil/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libScePsmUtil/include/Api.hpp b/core/libs/prx/libScePsmUtil/include/Api.hpp new file mode 100644 index 0000000000..15c45087d9 --- /dev/null +++ b/core/libs/prx/libScePsmUtil/include/Api.hpp @@ -0,0 +1,12 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI scePsmUtilFinalize(); +int APS5_VABI scePsmUtilGetPsmIniFile(); +int APS5_VABI scePsmUtilInitialize(); +int APS5_VABI scePsmUtilRegisterCallbacks(); + +} diff --git a/core/libs/prx/libScePsmUtil/libScePsmUtil.hpp b/core/libs/prx/libScePsmUtil/libScePsmUtil.hpp new file mode 100644 index 0000000000..5c21b12f80 --- /dev/null +++ b/core/libs/prx/libScePsmUtil/libScePsmUtil.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libScePsmUtil/include/Api.hpp" diff --git a/core/libs/prx/libScePsml/libScePsml.hpp b/core/libs/prx/libScePsml/libScePsml.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libScePsml/libScePsml.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libScePsml_debug/Export.cpp b/core/libs/prx/libScePsml_debug/Export.cpp index 44021762c2..02677de85c 100644 --- a/core/libs/prx/libScePsml_debug/Export.cpp +++ b/core/libs/prx/libScePsml_debug/Export.cpp @@ -1,3 +1,5 @@ +#include "prx/libScePsml_debug/include/Api.hpp" +#include "prx/libkernel/libkernel.hpp" #include #include #include @@ -16,89 +18,19 @@ namespace { constexpr std::int32_t SCE_PSML_ERROR_NOT_INITIALIZED = static_cast(0x8A810001); constexpr std::int32_t SCE_PSML_ERROR_INVALID_ARGUMENT = static_cast(0x8A810005); constexpr std::int32_t SCE_PSML_ERROR_NULL_OUTPUT = static_cast(0x8A810009); +constexpr std::int32_t Mfsr2ErrorNotInitialized = static_cast(0x8A8A0001); +constexpr std::int32_t Mfsr2ErrorUnsupportedConsole = static_cast(0x8A8A0012); constexpr std::uint64_t MfsrBlockBytes = 0x200000; constexpr std::uint64_t MfsrBlockCount = 4; constexpr std::uint32_t MfsrDispatchPacketDwords = 0x600; constexpr std::uint64_t MfsrSharedBlockCount = 52; -struct MfsrRequirement { - std::uint64_t blockBytes; - std::uint64_t alignment; - std::uint64_t blockCount; -}; - -struct MfsrBlock { - std::uint64_t address; - std::uint64_t bytes; -}; - -struct MfsrSharedResourcesParam { - std::uint32_t type; - std::uint32_t reserved; - const MfsrBlock* blocks; - std::uint64_t blockCount; - std::uint64_t reserved2; -}; - -struct Mfsr2SharedResourcesParam { - std::uint32_t type; - std::uint32_t reserved0; - const MfsrBlock* blocks; - std::uint64_t blockCount; - std::uint16_t width; - std::uint16_t height; - std::uint32_t reserved1; -}; - static_assert(sizeof(Mfsr2SharedResourcesParam) == 32); static_assert(offsetof(Mfsr2SharedResourcesParam, blocks) == 8); static_assert(offsetof(Mfsr2SharedResourcesParam, blockCount) == 16); static_assert(offsetof(Mfsr2SharedResourcesParam, width) == 24); static_assert(offsetof(Mfsr2SharedResourcesParam, reserved1) == 28); -struct Mfsr2ContextParam { - std::uint32_t profile; - std::uint32_t reserved0; - void* sharedResources; - const MfsrBlock* blocks; - std::uint64_t blockCount; - std::uint64_t reserved1; - std::uint16_t outputWidth; - std::uint16_t outputHeight; - std::uint32_t inputColorSpace; -}; - -struct MfsrCommandBuffer { - std::uint32_t* cursor; - std::uint32_t sizeInDwords; -}; - -struct MfsrTextureDescriptor { - std::uint32_t words[8]; -}; - -struct Mfsr2DispatchParam { - const MfsrTextureDescriptor* outputColor; - const MfsrTextureDescriptor* color; - const MfsrTextureDescriptor* motionVectors; - const MfsrTextureDescriptor* depth; - const MfsrTextureDescriptor* exposure; - std::uint64_t reserved0; - float preExposure; - std::uint32_t renderX; - std::uint32_t renderY; - std::uint32_t renderWidth; - std::uint32_t renderHeight; - float jitter[2]; - float motionVectorScale[2]; - float motionVectorOffset[2]; - float depthRange[2]; - std::uint8_t resetHistory; - std::uint8_t reserved1[3]; - std::uint32_t optionFlags; - float sharpness; -}; - static_assert(sizeof(Mfsr2ContextParam) == 48); static_assert(offsetof(Mfsr2ContextParam, sharedResources) == 8); static_assert(offsetof(Mfsr2ContextParam, blocks) == 16); @@ -117,19 +49,6 @@ static_assert(offsetof(Mfsr2DispatchParam, resetHistory) == 100); static_assert(offsetof(Mfsr2DispatchParam, optionFlags) == 104); static_assert(offsetof(Mfsr2DispatchParam, sharpness) == 108); -struct MfsrContextParam { - std::uint32_t reserved0[2]; - const MfsrBlock* blocks; - std::uint64_t blockCount; - std::uint16_t inputWidth; - std::uint16_t inputHeight; - std::uint32_t reserved1; - const void* descriptor0; - const void* descriptor1; - std::uint32_t reserved2[2]; - void* sharedResources; -}; - static_assert(sizeof(MfsrRequirement) == 0x18); static_assert(sizeof(MfsrSharedResourcesParam) == 0x20); static_assert(offsetof(MfsrContextParam, blocks) == 0x08); @@ -352,49 +271,57 @@ std::int32_t APS5_VABI scePsmlMfsrGetDispatchMfsrPacket900(void* context, void* return SCE_PSML_ERROR_NOT_INITIALIZED; } -int APS5_VABI scePsmlMfsr2ReleaseSharedResources(void* sharedResources) { - NotImplemented_nid_no_patch(__func__); - return 0; +std::int32_t APS5_VABI scePsmlMfsr2ReleaseSharedResources(void* sharedResources) { + (void)sharedResources; + return Mfsr2ErrorNotInitialized; } -int APS5_VABI scePsmlMfsr2GetSharedResourcesInitRequirement(MfsrRequirement* requirement, const Mfsr2SharedResourcesParam* param) { - NotImplemented_nid_no_patch(__func__); - return 0; +std::int32_t APS5_VABI scePsmlMfsr2GetSharedResourcesInitRequirement(MfsrRequirement* requirement, const Mfsr2SharedResourcesParam* param) { + (void)requirement; + (void)param; + return Mfsr2ErrorNotInitialized; } -int APS5_VABI scePsmlMfsr2GetContextInitRequirement(MfsrRequirement* requirement, const Mfsr2ContextParam* param) { - NotImplemented_nid_no_patch(__func__); - return 0; +std::int32_t APS5_VABI scePsmlMfsr2GetContextInitRequirement(MfsrRequirement* requirement, const Mfsr2ContextParam* param) { + (void)requirement; + (void)param; + return Mfsr2ErrorNotInitialized; } -int APS5_VABI scePsmlMfsr2ReleaseContext(void* context) { - NotImplemented_nid_no_patch(__func__); - return 0; +std::int32_t APS5_VABI scePsmlMfsr2ReleaseContext(void* context) { + (void)context; + return Mfsr2ErrorNotInitialized; } -int APS5_VABI scePsmlMfsr2GetDispatchPacketsSizeInDwords() { - NotImplemented_nid_no_patch(__func__); - return 0; +std::int32_t APS5_VABI scePsmlMfsr2GetDispatchPacketsSizeInDwords(void* context, std::uint32_t* packetSizeInDwords) { + (void)context; + (void)packetSizeInDwords; + return Mfsr2ErrorNotInitialized; } -int APS5_VABI scePsmlMfsr2CreateSharedResources(void** sharedResources, const Mfsr2SharedResourcesParam* param) { - NotImplemented_nid_no_patch(__func__); - return 0; +std::int32_t APS5_VABI scePsmlMfsr2CreateSharedResources(void** sharedResources, const Mfsr2SharedResourcesParam* param) { + (void)sharedResources; + (void)param; + return Mfsr2ErrorNotInitialized; } -int APS5_VABI scePsmlMfsr2GetDispatchPackets(void* context, const MfsrCommandBuffer* commandBuffer, const Mfsr2DispatchParam* param) { - NotImplemented_nid_no_patch(__func__); - return 0; +std::int32_t APS5_VABI scePsmlMfsr2GetDispatchPackets(void* context, const MfsrCommandBuffer* commandBuffer, const Mfsr2DispatchParam* param) { + (void)context; + (void)commandBuffer; + (void)param; + return Mfsr2ErrorNotInitialized; } -int APS5_VABI scePsmlMfsr2CreateContext(void** context, const Mfsr2ContextParam* param) { - NotImplemented_nid_no_patch(__func__); - return 0; +std::int32_t APS5_VABI scePsmlMfsr2CreateContext(void** context, const Mfsr2ContextParam* param) { + (void)context; + (void)param; + return Mfsr2ErrorNotInitialized; } -int APS5_VABI scePsmlMfsr2Init() { - NotImplemented_nid_no_patch(__func__); - return 0; +std::int32_t APS5_VABI scePsmlMfsr2Init() { + if (sceKernelIsTrinityMode() == 0) return Mfsr2ErrorUnsupportedConsole; + NotImplemented_nid_no_patch(__func__); + return 0; } int APS5_VABI scePsmlMfsrEnableSpecularAA() { diff --git a/core/libs/prx/libScePsml_debug/include/Api.hpp b/core/libs/prx/libScePsml_debug/include/Api.hpp new file mode 100644 index 0000000000..4a79a346d5 --- /dev/null +++ b/core/libs/prx/libScePsml_debug/include/Api.hpp @@ -0,0 +1,133 @@ +#pragma once + +#include "SceTypes.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct MfsrRequirement { + std::uint64_t blockBytes; + std::uint64_t alignment; + std::uint64_t blockCount; +}; + +struct MfsrBlock { + std::uint64_t address; + std::uint64_t bytes; +}; + +struct MfsrSharedResourcesParam { + std::uint32_t type; + std::uint32_t reserved; + const MfsrBlock* blocks; + std::uint64_t blockCount; + std::uint64_t reserved2; +}; + +struct Mfsr2SharedResourcesParam { + std::uint32_t type; + std::uint32_t reserved0; + const MfsrBlock* blocks; + std::uint64_t blockCount; + std::uint16_t width; + std::uint16_t height; + std::uint32_t reserved1; +}; + +struct Mfsr2ContextParam { + std::uint32_t profile; + std::uint32_t reserved0; + void* sharedResources; + const MfsrBlock* blocks; + std::uint64_t blockCount; + std::uint64_t reserved1; + std::uint16_t outputWidth; + std::uint16_t outputHeight; + std::uint32_t inputColorSpace; +}; + +struct MfsrCommandBuffer { + std::uint32_t* cursor; + std::uint32_t sizeInDwords; +}; + +struct MfsrTextureDescriptor { + std::uint32_t words[8]; +}; + +struct Mfsr2DispatchParam { + const MfsrTextureDescriptor* outputColor; + const MfsrTextureDescriptor* color; + const MfsrTextureDescriptor* motionVectors; + const MfsrTextureDescriptor* depth; + const MfsrTextureDescriptor* exposure; + std::uint64_t reserved0; + float preExposure; + std::uint32_t renderX; + std::uint32_t renderY; + std::uint32_t renderWidth; + std::uint32_t renderHeight; + float jitter[2]; + float motionVectorScale[2]; + float motionVectorOffset[2]; + float depthRange[2]; + std::uint8_t resetHistory; + std::uint8_t reserved1[3]; + std::uint32_t optionFlags; + float sharpness; +}; + +struct MfsrContextParam { + std::uint32_t reserved0[2]; + const MfsrBlock* blocks; + std::uint64_t blockCount; + std::uint16_t inputWidth; + std::uint16_t inputHeight; + std::uint32_t reserved1; + const void* descriptor0; + const void* descriptor1; + std::uint32_t reserved2[2]; + void* sharedResources; +}; + +extern "C" { + +std::int32_t APS5_VABI scePsmlMfsrGetContextBufferRequirement1100(void* requirement, const void* param); +std::int32_t APS5_VABI scePsmlMfsrCreateContext1100(void** context, const void* param); +std::int32_t APS5_VABI scePsmlMfsrGetDispatchMfsrPacket1100(void* context, void* commandBuffer, const void* param); +std::int32_t APS5_VABI scePsmlMfsrInit(); +std::int32_t APS5_VABI scePsmlMfsrGetSharedResourcesInitRequirement(MfsrRequirement* requirement, const MfsrSharedResourcesParam* param); +std::int32_t APS5_VABI scePsmlMfsrCreateSharedResources(void** sharedResources, const MfsrSharedResourcesParam* param); +std::int32_t APS5_VABI scePsmlMfsrReleaseSharedResources(void* sharedResources); +std::int32_t APS5_VABI scePsmlMfsrGetContextBufferRequirement800M3_2(MfsrRequirement* requirement, const MfsrContextParam* param); +std::int32_t APS5_VABI scePsmlMfsrCreateContext800M3_2(void** context, const MfsrContextParam* param); +std::int32_t APS5_VABI scePsmlMfsrReleaseContext(void* context); +std::int32_t APS5_VABI scePsmlMfsrCreateContext1300(void** context, const void* param); +std::int32_t APS5_VABI scePsmlMfsrGetDispatchMfsrPacket1300(void* context, void* commandBuffer, const void* param); +std::int32_t APS5_VABI scePsmlMfsrGetDispatchMfsrPacketSizeInDwords(void* context, std::uint32_t* packetSizeInDwords); +std::int32_t APS5_VABI scePsmlMfsrSelectConfig(void* config); +std::int32_t APS5_VABI scePsmlMfsrGetMipmapBias(void* context, float* bias, std::uint32_t dimension); +std::int32_t APS5_VABI scePsmlMfsrRequestCapture(void* context); +std::int32_t APS5_VABI scePsmlMfsrIsCaptureInProgress(void* context); +std::int32_t APS5_VABI scePsmlMfsrGetDispatchMfsrPacket1000(void* context, void* commandBuffer, const void* param); +std::int32_t APS5_VABI scePsmlMfsrGetDispatchMfsrPacket900(void* context, void* commandBuffer, const void* param); +std::int32_t APS5_VABI scePsmlMfsr2ReleaseSharedResources(void* sharedResources); +std::int32_t APS5_VABI scePsmlMfsr2GetSharedResourcesInitRequirement(MfsrRequirement* requirement, const Mfsr2SharedResourcesParam* param); +std::int32_t APS5_VABI scePsmlMfsr2GetContextInitRequirement(MfsrRequirement* requirement, const Mfsr2ContextParam* param); +std::int32_t APS5_VABI scePsmlMfsr2ReleaseContext(void* context); +std::int32_t APS5_VABI scePsmlMfsr2GetDispatchPacketsSizeInDwords(void* context, std::uint32_t* packetSizeInDwords); +std::int32_t APS5_VABI scePsmlMfsr2CreateSharedResources(void** sharedResources, const Mfsr2SharedResourcesParam* param); +std::int32_t APS5_VABI scePsmlMfsr2GetDispatchPackets(void* context, const MfsrCommandBuffer* commandBuffer, const Mfsr2DispatchParam* param); +std::int32_t APS5_VABI scePsmlMfsr2CreateContext(void** context, const Mfsr2ContextParam* param); +std::int32_t APS5_VABI scePsmlMfsr2Init(); +int APS5_VABI scePsmlMfsrEnableSpecularAA(); +int APS5_VABI scePsmlMfsrEnableQuality8K(); + +} diff --git a/core/libs/prx/libScePsml_debug/libScePsml_debug.hpp b/core/libs/prx/libScePsml_debug/libScePsml_debug.hpp new file mode 100644 index 0000000000..fc5eb2ba99 --- /dev/null +++ b/core/libs/prx/libScePsml_debug/libScePsml_debug.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libScePsml_debug/include/Api.hpp" diff --git a/core/libs/prx/libSceRandom/Export.cpp b/core/libs/prx/libSceRandom/Export.cpp index c61ffc4d53..2fcda9cfb5 100644 --- a/core/libs/prx/libSceRandom/Export.cpp +++ b/core/libs/prx/libSceRandom/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceRandom/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceRandom/include/Api.hpp b/core/libs/prx/libSceRandom/include/Api.hpp new file mode 100644 index 0000000000..ac26ff0d3b --- /dev/null +++ b/core/libs/prx/libSceRandom/include/Api.hpp @@ -0,0 +1,9 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceRandomGetRandomNumber(void* buf, size_t size); + +} diff --git a/core/libs/prx/libSceRandom/libSceRandom.hpp b/core/libs/prx/libSceRandom/libSceRandom.hpp new file mode 100644 index 0000000000..1697eb1bee --- /dev/null +++ b/core/libs/prx/libSceRandom/libSceRandom.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceRandom/include/Api.hpp" diff --git a/core/libs/prx/libSceRazorCpu/Export.cpp b/core/libs/prx/libSceRazorCpu/Export.cpp index defd9d798b..5c8e4f8df9 100644 --- a/core/libs/prx/libSceRazorCpu/Export.cpp +++ b/core/libs/prx/libSceRazorCpu/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceRazorCpu/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceRazorCpu/include/Api.hpp b/core/libs/prx/libSceRazorCpu/include/Api.hpp new file mode 100644 index 0000000000..1e6b94daff --- /dev/null +++ b/core/libs/prx/libSceRazorCpu/include/Api.hpp @@ -0,0 +1,43 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +uint32_t APS5_VABI sceRazorCpuIsCapturing(void); +int APS5_VABI sceRazorCpuJobManagerDispatch(const char* label, uint16_t firstId, uint16_t secondId, uint16_t firstCount, uint16_t secondCount, uint64_t firstValue, uint64_t secondValue); +int APS5_VABI sceRazorCpuJobManagerJob(uint16_t firstId, uint16_t secondId, uint16_t thirdId, uint16_t event); +int APS5_VABI sceRazorCpuJobManagerSequence(const char* label, uint16_t firstId, uint16_t secondId, uint16_t event); +int APS5_VABI sceRazorCpuPushMarker(const char* label, uint32_t color, uint32_t flags); +int APS5_VABI sceRazorCpuNamedSync(const char* label); +int APS5_VABI sceRazorCpuPushMarkerStatic(const char* name, uint32_t color, uint32_t flags); +int APS5_VABI sceRazorCpuPopMarker(void); +bool APS5_VABI sceRazorCpuFlushOccurred(uint64_t* timeSpentInFlush); +int APS5_VABI sceRazorCpuPlotValue(const char* series, float value); +int APS5_VABI sceRazorCpuWriteBookmark(const char* label, const char* description); +int APS5_VABI sceRazorCpuSync(void); +void APS5_VABI sceRazorCpuDisableFiberUserMarkers(void); +int APS5_VABI sceRazorCpuInitDataTags(void* buffer, size_t size); +int APS5_VABI sceRazorCpuShutdownDataTags(void); +size_t APS5_VABI sceRazorCpuGetDataTagStorageSize(uint32_t tagCount); +int APS5_VABI sceRazorCpuTagArray(const char* label, uint32_t category, void* array, size_t bufferSize, size_t elementSize); +int APS5_VABI sceRazorCpuTagBuffer(const char* label, uint32_t category, void* buffer, size_t bufferSize); +int APS5_VABI sceRazorCpuResizeTaggedBuffer(uint32_t category, void* buffer, size_t newBufferSize); +int APS5_VABI sceRazorCpuUnTagBuffer(uint32_t category, void* buffer); +int APS5_VABI sceRazorCpuBeginLogicalFileAccess(const char* filename, uint64_t tag, uint64_t size, uint8_t operation); +int APS5_VABI sceRazorCpuEndLogicalFileAccess(void); +int APS5_VABI sceRazorCpuFiberLogNameChange(void); +int APS5_VABI sceRazorCpuFiberSwitch(void); +int APS5_VABI sceRazorCpuGpuMarkerSync(void); +int APS5_VABI sceRazorCpuInitializeGpuMarkerContext(void); +int APS5_VABI sceRazorCpuInitializeInternal(void); +int APS5_VABI sceRazorCpuSetPopMarkerCallback(void); +int APS5_VABI sceRazorCpuSetPushMarkerCallback(void); +int APS5_VABI sceRazorCpuSetPushMarkerStaticCallback(void); +int APS5_VABI sceRazorCpuStartCaptureInternal(void); +int APS5_VABI sceRazorCpuStopCaptureInternal(void); +int APS5_VABI sceRazorCpuWorkloadRunBegin(void); +int APS5_VABI sceRazorCpuWorkloadRunEnd(void); +int APS5_VABI sceRazorCpuWorkloadSubmit(void); + +} diff --git a/core/libs/prx/libSceRazorCpu/libSceRazorCpu.hpp b/core/libs/prx/libSceRazorCpu/libSceRazorCpu.hpp new file mode 100644 index 0000000000..a734b0b85a --- /dev/null +++ b/core/libs/prx/libSceRazorCpu/libSceRazorCpu.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceRazorCpu/include/Api.hpp" diff --git a/core/libs/prx/libSceRazorCpu_debug/libSceRazorCpu_debug.hpp b/core/libs/prx/libSceRazorCpu_debug/libSceRazorCpu_debug.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceRazorCpu_debug/libSceRazorCpu_debug.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceRegMgr/Export.cpp b/core/libs/prx/libSceRegMgr/Export.cpp index 9d71463de6..d1efe47018 100644 --- a/core/libs/prx/libSceRegMgr/Export.cpp +++ b/core/libs/prx/libSceRegMgr/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceRegMgr/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceRegMgr/include/Api.hpp b/core/libs/prx/libSceRegMgr/include/Api.hpp new file mode 100644 index 0000000000..91e57f01f1 --- /dev/null +++ b/core/libs/prx/libSceRegMgr/include/Api.hpp @@ -0,0 +1,73 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceRegMgrGetBin(std::uint32_t optionId, void* data, std::size_t size); +int APS5_VABI sceRegMgrGetInt(int32_t optionId, int32_t* outInt); +int APS5_VABI sceRegMgrGetStr(int32_t optionId, char* outString, std::size_t stringLength); +int APS5_VABI sceRegMgrSetBin(std::uint32_t optionId, const void* data, std::size_t size); +int APS5_VABI sceRegMgrSetInt(int32_t optionId, int32_t inInt); +int APS5_VABI sceRegMgrSetStr(int32_t optionId, const char* inStirng, std::size_t stringLength); +std::int32_t APS5_VABI sceRegMgrNonSysGetInt(std::int64_t key, std::int32_t unk, std::int32_t* data); +int APS5_VABI sceRegMgrCheckError(void); +int APS5_VABI sceRegMgrCheckIntVal(void); +int APS5_VABI sceRegMgrGetBinInitVal(void); +int APS5_VABI sceRegMgrGetIntInitVal(void); +int APS5_VABI sceRegMgrGetStrInitVal(void); +int APS5_VABI sceRegMgrGetVersion(void); +int APS5_VABI sceRegMgrIsChange(void); +int APS5_VABI sceRegMgrEvtGetCnt(void); +int APS5_VABI sceRegMgrEvtGetRegId(void); +int APS5_VABI sceRegMgrResetVal(void); +int APS5_VABI sceRegMgrSetInitLevel(void); +int APS5_VABI sceRegMgrSrvCnvRegionInt(void); +int APS5_VABI sceRegMgrSrvCnvRegionStr(void); +int APS5_VABI sceRegMgrSrvGetMachineType(void); +int APS5_VABI sceRegMgrSrvGetQAFforReg(void); +int APS5_VABI sceRegMgrSrvGetRealMachineType(void); +int APS5_VABI sceRegMgrSrvGetRegion(void); +int APS5_VABI sceRegMgrSrvGetRegionStr(void); +int APS5_VABI sceRegMgrBackupNeedMem(void); +int APS5_VABI sceRegMgrBackupPullData(void); +int APS5_VABI sceRegMgrBackupPushData(void); +int APS5_VABI sceRegMgrBackupPullDataGkp(void); +int APS5_VABI sceRegMgrBackupPushDataGkp(void); +int APS5_VABI sceRegMgrCntlStart(void); +int APS5_VABI sceRegMgrCntlDeleteReg(void); +int APS5_VABI sceRegMgrCntlGetFilesCount(void); +int APS5_VABI sceRegMgrCntlGetFileName(void); +int APS5_VABI sceRegMgrCntSetInitReinst(void); +int APS5_VABI sceRegMgrIsInitOK(void); +int APS5_VABI sceRegMgrGetInitError(void); +int APS5_VABI sceRegMgrRecoverRegNvs(void); +int APS5_VABI sceRegMgrNonSysCheckError(void); +int APS5_VABI sceRegMgrNonSysGetBin(void); +int APS5_VABI sceRegMgrNonSysGetStr(void); +int APS5_VABI sceRegMgrNonSysSetBin(void); +int APS5_VABI sceRegMgrNonSysSetInt(void); +int APS5_VABI sceRegMgrNonSysSetStr(void); +int APS5_VABI sceRegMgrGetVersionForPS4(void); +int APS5_VABI sceRegMgrBackupNeedMemForPS4(void); +int APS5_VABI sceRegMgrBackupPullDataForPS4(void); +int APS5_VABI sceRegMgrBackupPushDataForPS4(void); +int APS5_VABI sceRegMgrEvtGetCntForPS4(void); +int APS5_VABI sceRegMgrEvtGetRegIdForPS4(void); +int APS5_VABI sceRegMgrStrncpy(void); +int APS5_VABI sceRegMgrMemset(void); +int APS5_VABI sceRegMgrSetbin(void); +int APS5_VABI sceRegMgrToolGetUpdateCnt(void); +int APS5_VABI sceRegMgrToolGetEntryCnt(void); +int APS5_VABI sceRegMgrToolDataCheckGet(void); +int APS5_VABI sceRegMgrDrvGetUpdateCnt(void); +int APS5_VABI sceRegMgrDrvGetEntCnt(void); +int APS5_VABI sceRegMgrDrvDataOpen(void); +int APS5_VABI sceRegMgrDrvDataCheckGet(void); +int APS5_VABI sceRegMgrDrvDataClose(void); +int APS5_VABI sceRegMgrToolGetInfo(void); +int APS5_VABI sceRegMgrLogPull(void); +int APS5_VABI sceRegMgrCntlStopHdd(void); +int APS5_VABI sceRegMgrPrintInfo(void); + +} diff --git a/core/libs/prx/libSceRegMgr/libSceRegMgr.hpp b/core/libs/prx/libSceRegMgr/libSceRegMgr.hpp new file mode 100644 index 0000000000..28b2427f86 --- /dev/null +++ b/core/libs/prx/libSceRegMgr/libSceRegMgr.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceRegMgr/include/Api.hpp" diff --git a/core/libs/prx/libSceRemotePlayClientIpc/libSceRemotePlayClientIpc.hpp b/core/libs/prx/libSceRemotePlayClientIpc/libSceRemotePlayClientIpc.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceRemotePlayClientIpc/libSceRemotePlayClientIpc.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceRemoteplay/Export.cpp b/core/libs/prx/libSceRemoteplay/Export.cpp index bc653c840f..c398ec2033 100644 --- a/core/libs/prx/libSceRemoteplay/Export.cpp +++ b/core/libs/prx/libSceRemoteplay/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceRemoteplay/include/Api.hpp" #include #include #include diff --git a/core/libs/prx/libSceRemoteplay/include/Api.hpp b/core/libs/prx/libSceRemoteplay/include/Api.hpp new file mode 100644 index 0000000000..a36c070176 --- /dev/null +++ b/core/libs/prx/libSceRemoteplay/include/Api.hpp @@ -0,0 +1,50 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceRemoteplayGetConnectionStatus(int userId, int* status); +int APS5_VABI sceRemoteplayInitialize(void* heap, size_t heapSize); +int APS5_VABI sceRemoteplayTerminate(void); +int APS5_VABI sceRemoteplayApprove(void); +int APS5_VABI sceRemoteplayClearAllRegistData(void); +int APS5_VABI sceRemoteplayClearConnectHistory(void); +int APS5_VABI sceRemoteplayConfirmDeviceRegist(void); +int APS5_VABI sceRemoteplayDisconnect(void); +int APS5_VABI sceRemoteplayGeneratePinCode(void); +int APS5_VABI sceRemoteplayGetApMode(void); +int APS5_VABI sceRemoteplayGetConnectHistory(void); +int APS5_VABI sceRemoteplayGetConnectUserId(void); +int APS5_VABI sceRemoteplayGetMbusDeviceInfo(void); +int APS5_VABI sceRemoteplayGetOperationStatus(void); +int APS5_VABI sceRemoteplayGetPrimaryUserId(void); +int APS5_VABI sceRemoteplayGetRemoteplayStatus(void); +int APS5_VABI sceRemoteplayGetRpMode(void); +int APS5_VABI sceRemoteplayImeClose(void); +int APS5_VABI sceRemoteplayImeFilterResult(void); +int APS5_VABI sceRemoteplayImeGetEvent(void); +int APS5_VABI sceRemoteplayImeNotify(void); +int APS5_VABI sceRemoteplayImeNotifyEventResult(void); +int APS5_VABI sceRemoteplayImeOpen(void); +int APS5_VABI sceRemoteplayImeSetCaret(void); +int APS5_VABI sceRemoteplayImeSetText(void); +int APS5_VABI sceRemoteplayIsRemoteOskReady(void); +int APS5_VABI sceRemoteplayIsRemotePlaying(void); +int APS5_VABI sceRemoteplayNotifyMbusDeviceRegistComplete(void); +int APS5_VABI sceRemoteplayNotifyNpPushWakeup(void); +int APS5_VABI sceRemoteplayNotifyPinCodeError(void); +int APS5_VABI sceRemoteplayNotifySubmitCode(void); +int APS5_VABI sceRemoteplayNotifyUserDelete(void); +int APS5_VABI sceRemoteplayPrintAllRegistData(void); +int APS5_VABI sceRemoteplayProhibit(void); +int APS5_VABI sceRemoteplayProhibitStreaming(void); +int APS5_VABI sceRemoteplayServerLock(void); +int APS5_VABI sceRemoteplayServerUnLock(void); +int APS5_VABI sceRemoteplaySetApMode(void); +int APS5_VABI sceRemoteplaySetLogLevel(void); +int APS5_VABI sceRemoteplaySetProhibition(void); +int APS5_VABI sceRemoteplaySetProhibitionForVsh(void); +int APS5_VABI sceRemoteplaySetRpMode(void); + +} diff --git a/core/libs/prx/libSceRemoteplay/libSceRemoteplay.hpp b/core/libs/prx/libSceRemoteplay/libSceRemoteplay.hpp new file mode 100644 index 0000000000..a04f3f394f --- /dev/null +++ b/core/libs/prx/libSceRemoteplay/libSceRemoteplay.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceRemoteplay/include/Api.hpp" diff --git a/core/libs/prx/libSceResourceArbitrator/libSceResourceArbitrator.hpp b/core/libs/prx/libSceResourceArbitrator/libSceResourceArbitrator.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceResourceArbitrator/libSceResourceArbitrator.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceRnpsAppMgr/Export.cpp b/core/libs/prx/libSceRnpsAppMgr/Export.cpp index a2fdcbc15d..389f33546a 100644 --- a/core/libs/prx/libSceRnpsAppMgr/Export.cpp +++ b/core/libs/prx/libSceRnpsAppMgr/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceRnpsAppMgr/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceRnpsAppMgr/include/Api.hpp b/core/libs/prx/libSceRnpsAppMgr/include/Api.hpp new file mode 100644 index 0000000000..95fc2a3856 --- /dev/null +++ b/core/libs/prx/libSceRnpsAppMgr/include/Api.hpp @@ -0,0 +1,35 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceRnpsAppMgrBlockAppInstall(); +int APS5_VABI sceRnpsAppMgrCreateUpdateRequest(); +int APS5_VABI sceRnpsAppMgrCreateUrlRequest(); +int APS5_VABI sceRnpsAppMgrDestroyBundle(); +int APS5_VABI sceRnpsAppMgrDestroyUpdateRequest(); +int APS5_VABI sceRnpsAppMgrFinishUrlRequest(); +int APS5_VABI sceRnpsAppMgrGetAppInfo(); +int APS5_VABI sceRnpsAppMgrGetAppInfoDebugString(); +int APS5_VABI sceRnpsAppMgrGetAppInfoList(); +int APS5_VABI sceRnpsAppMgrGetEventForShellUI(); +int APS5_VABI sceRnpsAppMgrGetUpdateProgress(); +int APS5_VABI sceRnpsAppMgrHasEventForShellUI(); +int APS5_VABI sceRnpsAppMgrInitialize(); +int APS5_VABI sceRnpsAppMgrPushEventForShellUI(); +int APS5_VABI sceRnpsAppMgrRecoverUfsImage(); +int APS5_VABI sceRnpsAppMgrRegisterShellUI(); +int APS5_VABI sceRnpsAppMgrRemoveApp(); +int APS5_VABI sceRnpsAppMgrRemoveAppOnSystemShutdown(); +int APS5_VABI sceRnpsAppMgrRemoveUfsImageOnSystemShutdown(); +int APS5_VABI sceRnpsAppMgrRequestUpdateCheck(); +int APS5_VABI sceRnpsAppMgrSetCrlUrl(); +int APS5_VABI sceRnpsAppMgrSetEventFlagForClients(); +int APS5_VABI sceRnpsAppMgrSetUpdateUrl(); +int APS5_VABI sceRnpsAppMgrStartService(); +int APS5_VABI sceRnpsAppMgrTerminate(); +int APS5_VABI sceRnpsAppMgrUnblockAppInstall(); +int APS5_VABI sceRnpsAppMgrUnregisterShellUI(); + +} diff --git a/core/libs/prx/libSceRnpsAppMgr/libSceRnpsAppMgr.hpp b/core/libs/prx/libSceRnpsAppMgr/libSceRnpsAppMgr.hpp new file mode 100644 index 0000000000..9fc9484de9 --- /dev/null +++ b/core/libs/prx/libSceRnpsAppMgr/libSceRnpsAppMgr.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceRnpsAppMgr/include/Api.hpp" diff --git a/core/libs/prx/libSceRnpsNKInjectedBundle/libSceRnpsNKInjectedBundle.hpp b/core/libs/prx/libSceRnpsNKInjectedBundle/libSceRnpsNKInjectedBundle.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceRnpsNKInjectedBundle/libSceRnpsNKInjectedBundle.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceRtc/Export.cpp b/core/libs/prx/libSceRtc/Export.cpp index 17ec53064c..91c6591395 100644 --- a/core/libs/prx/libSceRtc/Export.cpp +++ b/core/libs/prx/libSceRtc/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceRtc/include/Rtc.hpp" #include #include #include diff --git a/core/libs/prx/libSceRtc/include/Rtc.hpp b/core/libs/prx/libSceRtc/include/Rtc.hpp new file mode 100644 index 0000000000..7e84acf6b7 --- /dev/null +++ b/core/libs/prx/libSceRtc/include/Rtc.hpp @@ -0,0 +1,69 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceRtcCheckValid(const RtcDateTime* time); +int APS5_VABI sceRtcIsLeapYear(int year); +int APS5_VABI sceRtcGetDaysInMonth(int year, int month); +int APS5_VABI sceRtcGetDayOfWeek(int year, int month, int day); +int APS5_VABI sceRtcGetTickResolution(void); +int APS5_VABI sceRtcGetTick(const RtcDateTime* time, RtcTick* tick); +int APS5_VABI sceRtcSetTick(RtcDateTime* time, const RtcTick* tick); +int APS5_VABI sceRtcGetCurrentTick(RtcTick* tick); +int APS5_VABI sceRtcGetCurrentNetworkTick(RtcTick* tick); +int APS5_VABI sceRtcGetCurrentClock(RtcDateTime* time, int timeZoneMinutes); +int APS5_VABI sceRtcGetCurrentClockLocalTime(RtcDateTime* time); +int APS5_VABI sceRtcConvertUtcToLocalTime(const RtcTick* utc, RtcTick* localTime); +int APS5_VABI sceRtcConvertLocalTimeToUtc(const RtcTick* localTime, RtcTick* utc); +int APS5_VABI sceRtcGetTime_t(const RtcDateTime* time, int64_t* seconds); +int APS5_VABI sceRtcSetTime_t(RtcDateTime* time, int64_t seconds); +int APS5_VABI sceRtcGetWin32FileTime(const RtcDateTime* time, uint64_t* win32Time); +int APS5_VABI sceRtcSetWin32FileTime(RtcDateTime* time, uint64_t win32Time); +int APS5_VABI sceRtcGetDosTime(const RtcDateTime* time, uint32_t* dosTime); +int APS5_VABI sceRtcSetDosTime(RtcDateTime* time, uint32_t dosTime); +int APS5_VABI sceRtcGetYear(const RtcDateTime* time); +int APS5_VABI sceRtcSetYear(RtcDateTime* time, int year); +int APS5_VABI sceRtcGetMonth(const RtcDateTime* time); +int APS5_VABI sceRtcSetMonth(RtcDateTime* time, int month); +int APS5_VABI sceRtcGetDay(const RtcDateTime* time); +int APS5_VABI sceRtcSetDay(RtcDateTime* time, int day); +int APS5_VABI sceRtcGetHour(const RtcDateTime* time); +int APS5_VABI sceRtcSetHour(RtcDateTime* time, int hour); +int APS5_VABI sceRtcGetMinute(const RtcDateTime* time); +int APS5_VABI sceRtcSetMinute(RtcDateTime* time, int minute); +int APS5_VABI sceRtcGetSecond(const RtcDateTime* time); +int APS5_VABI sceRtcSetSecond(RtcDateTime* time, int second); +int APS5_VABI sceRtcGetMicrosecond(const RtcDateTime* time); +int APS5_VABI sceRtcSetMicrosecond(RtcDateTime* time, int microsecond); +int APS5_VABI sceRtcFormatRFC3339(char* dateTime, const RtcTick* utc, int timeZoneMinutes); +int APS5_VABI sceRtcFormatRFC3339LocalTime(char* dateTime, const RtcTick* utc); +int APS5_VABI sceRtcFormatRFC2822(char* dateTime, const RtcTick* utc, int timeZoneMinutes); +int APS5_VABI sceRtcFormatRFC2822LocalTime(char* dateTime, const RtcTick* utc); +int APS5_VABI sceRtcParseRFC3339(RtcTick* utc, const char* dateTime); +int APS5_VABI sceRtcParseDateTime(RtcTick* utc, const char* dateTime); +int APS5_VABI sceRtcTickAddTicks(RtcTick* dst, const RtcTick* src, int64_t ticks); +int APS5_VABI sceRtcTickAddMicroseconds(RtcTick* dst, const RtcTick* src, int64_t usec); +int APS5_VABI sceRtcTickAddSeconds(RtcTick* dst, const RtcTick* src, int64_t seconds); +int APS5_VABI sceRtcTickAddMinutes(RtcTick* dst, const RtcTick* src, int64_t minutes); +int APS5_VABI sceRtcTickAddHours(RtcTick* dst, const RtcTick* src, int32_t hours); +int APS5_VABI sceRtcTickAddDays(RtcTick* dst, const RtcTick* src, int32_t days); +int APS5_VABI sceRtcTickAddWeeks(RtcTick* dst, const RtcTick* src, int32_t weeks); +int APS5_VABI sceRtcTickAddMonths(RtcTick* dst, const RtcTick* src, int32_t months); +int APS5_VABI sceRtcTickAddYears(RtcTick* dst, const RtcTick* src, int16_t years); +int APS5_VABI sceRtcInit(void); +int APS5_VABI sceRtcEnd(void); +int APS5_VABI sceRtcCompareTick(const RtcTick* first, const RtcTick* second); +int APS5_VABI sceRtcGetCurrentRawNetworkTick(RtcTick* tick); +int APS5_VABI sceRtcGetCurrentAdNetworkTick(RtcTick* tick); +int APS5_VABI sceRtcGetCurrentDebugNetworkTick(RtcTick* tick); +int APS5_VABI sceRtcSetCurrentTick(const RtcTick* tick); +int APS5_VABI sceRtcSetCurrentNetworkTick(const RtcTick* tick); +int APS5_VABI sceRtcSetCurrentAdNetworkTick(const RtcTick* tick); +int APS5_VABI sceRtcSetCurrentDebugNetworkTick(const RtcTick* tick); +int APS5_VABI sceRtcSetConf(int first, int second, int third, int fourth); +int APS5_VABI sceRtcFormatRFC3339Precise(char* dateTime, const RtcTick* utc, int timeZoneMinutes, int precision); +int APS5_VABI sceRtcFormatRFC3339PreciseLocalTime(char* dateTime, const RtcTick* utc, int precision); + +} diff --git a/core/libs/prx/libSceRtc/libSceRtc.hpp b/core/libs/prx/libSceRtc/libSceRtc.hpp new file mode 100644 index 0000000000..6301e155c4 --- /dev/null +++ b/core/libs/prx/libSceRtc/libSceRtc.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceRtc/include/Rtc.hpp" diff --git a/core/libs/prx/libSceRudp/Export.cpp b/core/libs/prx/libSceRudp/Export.cpp index ce37e56c0e..dd4dd2c260 100644 --- a/core/libs/prx/libSceRudp/Export.cpp +++ b/core/libs/prx/libSceRudp/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceRudp/include/Api.hpp" #include #include #include @@ -57,8 +58,6 @@ enum RudpOption { RUDP_OPTION_KEEP_ALIVE_TIMEOUT = 19, }; -using GuestRudpEventHandler = RudpEventHandler; - std::mutex g_mutex; bool g_inited = false; int g_next_ctx = 0; @@ -92,7 +91,6 @@ struct RudpPoll { std::map entries; }; - int g_next_poll = 1; std::map g_polls; TimedWait::Condition g_polls_changed; diff --git a/core/libs/prx/libSceRudp/include/Api.hpp b/core/libs/prx/libSceRudp/include/Api.hpp new file mode 100644 index 0000000000..44b6881d58 --- /dev/null +++ b/core/libs/prx/libSceRudp/include/Api.hpp @@ -0,0 +1,44 @@ +#pragma once + +#include "SceTypes.hpp" + +using GuestRudpEventHandler = RudpEventHandler; + +extern "C" { + +int APS5_VABI sceRudpInit_nid_postfix(void* memPool, int memPoolSize); +int APS5_VABI sceRudpActivate(std::int32_t contextId, const void* address, std::uint32_t addressLength); +int APS5_VABI sceRudpGetStatus(void* status, std::size_t size); +int APS5_VABI sceRudpEnd(void); +int APS5_VABI sceRudpTerminate(int ctxId); +int APS5_VABI sceRudpEnableInternalIOThread(uint32_t stackSize, uint32_t priority); +int APS5_VABI sceRudpEnableInternalIOThread2(uint32_t stackSize, uint32_t priority, uint64_t affinity); +int APS5_VABI sceRudpSetEventHandler(GuestRudpEventHandler handler, void* arg); +int APS5_VABI sceRudpCreateContext(GuestRudpEventHandler handler, void* arg, int* ctxId); +int APS5_VABI sceRudpBind(int ctxId, uint16_t vport, int transport, uint16_t port); +int APS5_VABI sceRudpSetOption(int ctxId, int option, const void* value, uint32_t len); +int APS5_VABI sceRudpGetOption(int ctxId, int option, void* value, uint32_t len); +int APS5_VABI sceRudpInitiate(int ctxId, const void* to, uint32_t tolen, uint16_t vport); +int APS5_VABI sceRudpGetContextStatus(int ctxId, void* status, uint32_t size); +int APS5_VABI sceRudpGetRemoteInfo(int contextId, void* address, std::uint32_t* addressSize, std::uint16_t* virtualPort); +int APS5_VABI sceRudpGetNumberOfPacketsToRead(int ctxId); +int APS5_VABI sceRudpGetSizeWritable(int ctxId); +int APS5_VABI sceRudpGetSizeReadable(int ctxId); +int APS5_VABI sceRudpWrite(int ctxId, const void* data, uint32_t len, int flags); +int APS5_VABI sceRudpRead(int ctxId, void* data, uint32_t len, int flags, void* status); +int APS5_VABI sceRudpNetFlush(void); +int APS5_VABI sceRudpProcessEvents(std::uint64_t timeout); +int APS5_VABI sceRudpNetReceived(int socketId, const void* data, std::size_t dataSize, const void* sourceAddress, std::uint32_t sourceAddressSize); +int APS5_VABI sceRudpGetMaxSegmentSize(uint16_t* size); +int APS5_VABI sceRudpPollCreate(std::size_t size); +int APS5_VABI sceRudpPollControl(int pollId, int op, int ctxId, uint16_t events); +int APS5_VABI sceRudpPollWait(int pollId, RudpPollEvent* events, std::size_t eventLen, uint64_t timeout); +int APS5_VABI sceRudpPollDestroy(int pollId); +int APS5_VABI sceRudpAccept(); +int APS5_VABI sceRudpFlush(); +int APS5_VABI sceRudpGetLocalInfo(); +int APS5_VABI sceRudpListen(); +int APS5_VABI sceRudpPollCancel(); +int APS5_VABI sceRudpSetMaxSegmentSize(); + +} diff --git a/core/libs/prx/libSceRudp/libSceRudp.hpp b/core/libs/prx/libSceRudp/libSceRudp.hpp new file mode 100644 index 0000000000..934f85cb3c --- /dev/null +++ b/core/libs/prx/libSceRudp/libSceRudp.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceRudp/include/Api.hpp" diff --git a/core/libs/prx/libSceS3DConversion/libSceS3DConversion.hpp b/core/libs/prx/libSceS3DConversion/libSceS3DConversion.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceS3DConversion/libSceS3DConversion.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceS3da/Export.cpp b/core/libs/prx/libSceS3da/Export.cpp index 79ca9b7758..fcf0f1f9af 100644 --- a/core/libs/prx/libSceS3da/Export.cpp +++ b/core/libs/prx/libSceS3da/Export.cpp @@ -1,10 +1,9 @@ +#include "prx/libSceS3da/include/Api.hpp" #include #include #include "SceTypes.hpp" #include "prx/libc/include/General.hpp" -struct S3daInfo; - extern "C" { int APS5_VABI sceS3daClose(std::uint32_t port) { diff --git a/core/libs/prx/libSceS3da/include/Api.hpp b/core/libs/prx/libSceS3da/include/Api.hpp new file mode 100644 index 0000000000..d89f3a8dbb --- /dev/null +++ b/core/libs/prx/libSceS3da/include/Api.hpp @@ -0,0 +1,14 @@ +#pragma once + +#include "SceTypes.hpp" + +struct S3daInfo; + +extern "C" { + +int APS5_VABI sceS3daClose(std::uint32_t port); +int APS5_VABI sceS3daGetInfo(std::uint32_t port, S3daInfo* info); +int APS5_VABI sceS3daOpen(std::uint32_t port); +int APS5_VABI sceS3daSendData(std::uint32_t port, const void* data, std::uint32_t size); + +} diff --git a/core/libs/prx/libSceS3da/libSceS3da.hpp b/core/libs/prx/libSceS3da/libSceS3da.hpp new file mode 100644 index 0000000000..56ae159b9d --- /dev/null +++ b/core/libs/prx/libSceS3da/libSceS3da.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceS3da/include/Api.hpp" diff --git a/core/libs/prx/libSceSaveData.native/Export.cpp b/core/libs/prx/libSceSaveData.native/Export.cpp index c49454241b..916a9dbe26 100644 --- a/core/libs/prx/libSceSaveData.native/Export.cpp +++ b/core/libs/prx/libSceSaveData.native/Export.cpp @@ -1,3 +1,5 @@ +#include "prx/libSceSaveData.native/include/Api.hpp" +#include "prx/libSceSaveData/include/Api.hpp" #include #include #include @@ -1042,17 +1044,6 @@ int APS5_VABI sceSaveDataDebugTarget() { namespace { -struct SaveDataMountPs4 { - std::int32_t user_id; - std::int32_t pad; - const void* title_id; - const SceSaveDataDirName* dir_name; - const void* fingerprint; - std::uint64_t blocks; - std::uint32_t mount_mode; - std::uint8_t reserved[32]; -}; - } extern "C" { diff --git a/core/libs/prx/libSceSaveData.native/include/Api.hpp b/core/libs/prx/libSceSaveData.native/include/Api.hpp new file mode 100644 index 0000000000..00283d8bfd --- /dev/null +++ b/core/libs/prx/libSceSaveData.native/include/Api.hpp @@ -0,0 +1,55 @@ +#pragma once + +#include "SceTypes.hpp" + +struct SaveDataMountPs4 { + std::int32_t user_id; + std::int32_t pad; + const void* title_id; + const SceSaveDataDirName* dir_name; + const void* fingerprint; + std::uint64_t blocks; + std::uint32_t mount_mode; + std::uint8_t reserved[32]; +}; + +extern "C" { + +int APS5_VABI sceSaveDataCommit(const SaveDataCommitParam* param); +int APS5_VABI sceSaveDataCreateTransactionResource(uint32_t size); +int APS5_VABI sceSaveDataDelete(const SaveDataDelete* del); +int APS5_VABI sceSaveDataDeleteTransactionResource(int32_t resource); +int APS5_VABI sceSaveDataDirNameSearch(const SaveDataDirNameSearchCond* cond, SaveDataDirNameSearchResult* result); +int APS5_VABI sceSaveDataGetMountInfo(const SaveDataMountPoint* mountPoint, SaveDataMountInfo* info); +int APS5_VABI sceSaveDataGetParam(const SaveDataMountPoint* mountPoint, uint32_t paramType, void* paramBuf, size_t paramBufSize, size_t* gotSize); +int APS5_VABI sceSaveDataLoadIcon(const SaveDataMountPoint* mountPoint, SaveDataIcon* icon); +int APS5_VABI sceSaveDataMount3(const SaveDataMount3* mount, SaveDataMountResult* mountResult); +int APS5_VABI sceSaveDataPrepare(const SaveDataMountPoint* mountPoint, const SaveDataPrepareParam* param); +int APS5_VABI sceSaveDataSaveIcon(const SaveDataMountPoint* mountPoint, const SaveDataIcon* icon); +int APS5_VABI sceSaveDataSaveIconByPath(const SaveDataMountPoint* mountPoint, const char* path); +int APS5_VABI sceSaveDataSetParam(const SaveDataMountPoint* mountPoint, uint32_t paramType, const void* paramBuf, size_t paramBufSize); +int APS5_VABI sceSaveDataUmount2(uint32_t mode, const SaveDataMountPoint* mountPoint); +int APS5_VABI sceSaveDataTransferringMountPs4(const SaveDataTransferringMount* mount, SaveDataMountResult* mountResult); +int APS5_VABI sceSaveDataDirNameSearchPs4(const SaveDataDirNameSearchCond* cond, SaveDataDirNameSearchResult* result); +int APS5_VABI sceSaveDataConvert(const SaveDataConvert* param); +int APS5_VABI sceSaveDataGetConvertProgress(float* progress); +int APS5_VABI sceSaveDataCancel(std::uint32_t cancelArgument); +int APS5_VABI sceSaveDataDirNameSearch2(const SaveDataDirNameSearchCond* cond, SaveDataDirNameSearchResult* result); +int APS5_VABI sceSaveDataPrepareForTransferring(const SaveDataMountPoint* mountPoint, const SaveDataPrepareParam* param); +int APS5_VABI sceSaveDataCheckIpmiIfSize(); +int APS5_VABI sceSaveDataDebug(); +int APS5_VABI sceSaveDataDebugCheckBackupData(); +int APS5_VABI sceSaveDataDebugCleanMount(); +int APS5_VABI sceSaveDataDebugCompiledSdkVersion(); +int APS5_VABI sceSaveDataDebugCreateSaveDataRoot(); +int APS5_VABI sceSaveDataDebugProspero(); +int APS5_VABI sceSaveDataDebugRemoveSaveDataRoot(); +int APS5_VABI sceSaveDataDebugTarget(); +int APS5_VABI sceSaveDataInitialize(const void* init); +int APS5_VABI sceSaveDataMount(const SaveDataMountPs4* mount, SaveDataMountResult* mountResult); +int APS5_VABI sceSaveDataUmount(const SaveDataMountPoint* mountPoint); +int APS5_VABI sceSaveDataSetupSaveDataMemory(std::int32_t userId, std::size_t memorySize, const SaveDataParam* param); +int APS5_VABI sceSaveDataGetSaveDataMemory(std::int32_t userId, void* buf, std::size_t bufSize, std::int64_t offset); +int APS5_VABI sceSaveDataSetSaveDataMemory(std::int32_t userId, void* buf, std::size_t bufSize, std::int64_t offset); + +} diff --git a/core/libs/prx/libSceSaveData.native/libSceSaveData.native.hpp b/core/libs/prx/libSceSaveData.native/libSceSaveData.native.hpp new file mode 100644 index 0000000000..6cb55f8ca0 --- /dev/null +++ b/core/libs/prx/libSceSaveData.native/libSceSaveData.native.hpp @@ -0,0 +1,4 @@ +#pragma once + +#include "prx/libSceSaveData/include/Api.hpp" +#include "prx/libSceSaveData.native/include/Api.hpp" diff --git a/core/libs/prx/libSceSaveData/Export.cpp b/core/libs/prx/libSceSaveData/Export.cpp index f2a68ec989..6fbc7bb184 100644 --- a/core/libs/prx/libSceSaveData/Export.cpp +++ b/core/libs/prx/libSceSaveData/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceSaveData/include/Api.hpp" #include #include #include diff --git a/core/libs/prx/libSceSaveData/SaveDataCore.hpp b/core/libs/prx/libSceSaveData/SaveDataCore.hpp index 58afdfa721..1da806ac51 100644 --- a/core/libs/prx/libSceSaveData/SaveDataCore.hpp +++ b/core/libs/prx/libSceSaveData/SaveDataCore.hpp @@ -21,20 +21,13 @@ #include #include "SceTypes.hpp" +#include "prx/libkernel/include/Api.hpp" #include "prx/libc/include/General.hpp" #include "prx/libc/include/RemoveTree.hpp" #include "prx/libSceSaveData/SaveDataFile.hpp" namespace savedata { -extern "C" { -int APS5_VABI sceKernelCreateEventFlag(KernelEventFlag* ef, const char* name, std::uint32_t attr, - std::uint64_t init_pattern, const void* param); -int APS5_VABI sceKernelDeleteEventFlag(KernelEventFlag ef); -int APS5_VABI sceKernelSetEventFlag(KernelEventFlag ef, std::uint64_t bit_pattern); -int APS5_VABI sceKernelCancelEventFlag(KernelEventFlag ef, std::uint64_t set_pattern, int* num_wait_threads); -} - namespace { constexpr std::uint32_t SD_FACILITY = 0x809F0000u; diff --git a/core/libs/prx/libSceSaveData/include/Api.hpp b/core/libs/prx/libSceSaveData/include/Api.hpp new file mode 100644 index 0000000000..88067a68e5 --- /dev/null +++ b/core/libs/prx/libSceSaveData/include/Api.hpp @@ -0,0 +1,83 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceSaveDataInitialize3(const void* init); +int APS5_VABI sceSaveDataTerminate(void); +int APS5_VABI sceSaveDataBackup(const SaveDataBackup* backup); +int APS5_VABI sceSaveDataGetEventResult(const void* eventParam, SaveDataEvent* event); +int APS5_VABI sceSaveDataGetSaveDataMemory2(SaveDataMemoryGet2* getParam); +int APS5_VABI sceSaveDataSetSaveDataMemory2(const SaveDataMemorySet2* setParam); +int APS5_VABI sceSaveDataSetupSaveDataMemory2(const SaveDataMemorySetup2* setupParam, SaveDataMemorySetupResult* result); +int APS5_VABI sceSaveDataSyncSaveDataMemory(const void* syncParam); +int APS5_VABI sceSaveDataTransferringMount(const SaveDataTransferringMount* mount, SaveDataMountResult* mountResult); +int APS5_VABI sceSaveDataAbort(); +int APS5_VABI sceSaveDataBindPsnAccount(void); +int APS5_VABI sceSaveDataBindPsnAccountForSystemBackup(void); +int APS5_VABI sceSaveDataChangeDatabase(void); +int APS5_VABI sceSaveDataChangeInternal(void); +int APS5_VABI sceSaveDataCheckBackupData(void); +int APS5_VABI sceSaveDataCheckBackupDataForCdlg(void); +int APS5_VABI sceSaveDataCheckBackupDataInternal(void); +int APS5_VABI sceSaveDataCheckBackupDataLight(void); +int APS5_VABI sceSaveDataCheckCloudData(void); +int APS5_VABI sceSaveDataCheckSaveDataBroken(void); +int APS5_VABI sceSaveDataCheckSaveDataVersion(void); +int APS5_VABI sceSaveDataCheckSaveDataVersionLatest(void); +int APS5_VABI sceSaveDataClearProgress(); +int APS5_VABI sceSaveDataCreateUploadData(void); +int APS5_VABI sceSaveDataDebugGetThreadId(void); +int APS5_VABI sceSaveDataDeleteAllUser(void); +int APS5_VABI sceSaveDataDeleteBackupData(void); +int APS5_VABI sceSaveDataDeleteCloudData(void); +int APS5_VABI sceSaveDataDeleteProspero(void); +int APS5_VABI sceSaveDataDeleteTitle(void); +int APS5_VABI sceSaveDataDeleteUser(void); +int APS5_VABI sceSaveDataDirNameSearchInternal(void); +int APS5_VABI sceSaveDataDownload(void); +int APS5_VABI sceSaveDataGetAllSize(); +int APS5_VABI sceSaveDataGetAppLaunchedUser(void); +int APS5_VABI sceSaveDataGetAutoUploadConditions(void); +int APS5_VABI sceSaveDataGetAutoUploadRequestInfo(void); +int APS5_VABI sceSaveDataGetAutoUploadSetting(void); +int APS5_VABI sceSaveDataGetBoundPsnAccountCount(void); +int APS5_VABI sceSaveDataGetClientThreadPriority(void); +int APS5_VABI sceSaveDataGetCloudQuotaInfo(void); +int APS5_VABI sceSaveDataGetEventInfo(); +int APS5_VABI sceSaveDataGetMountedSaveDataCount(); +int APS5_VABI sceSaveDataGetProgress(); +int APS5_VABI sceSaveDataGetSaveDataCount(); +int APS5_VABI sceSaveDataGetSaveDataRootDir(void); +int APS5_VABI sceSaveDataGetSaveDataRootPath(void); +int APS5_VABI sceSaveDataGetSaveDataRootUsbPath(void); +int APS5_VABI sceSaveDataGetSavePoint(void); +int APS5_VABI sceSaveDataGetUpdatedDataCount(void); +int APS5_VABI sceSaveDataInitialize2(); +int APS5_VABI sceSaveDataInitializeForCdlg(void); +int APS5_VABI sceSaveDataIsDeletingUsbDb(void); +int APS5_VABI sceSaveDataIsMounted(); +int APS5_VABI sceSaveDataManualDelete(void); +int APS5_VABI sceSaveDataManualDownload(void); +int APS5_VABI sceSaveDataManualUpload(void); +int APS5_VABI sceSaveDataMount5(); +int APS5_VABI sceSaveDataMountInternal(void); +int APS5_VABI sceSaveDataMountSys(void); +int APS5_VABI sceSaveDataRebuildDatabase(void); +int APS5_VABI sceSaveDataRegisterEventCallback(); +int APS5_VABI sceSaveDataRestoreBackupData(void); +int APS5_VABI sceSaveDataRestoreBackupDataForCdlg(void); +int APS5_VABI sceSaveDataRestoreLoadSaveDataMemory(void); +int APS5_VABI sceSaveDataSetAutoUploadSetting(void); +int APS5_VABI sceSaveDataSetEventInfo(); +int APS5_VABI sceSaveDataSetSaveDataLibraryUser(void); +int APS5_VABI sceSaveDataShutdownStart(void); +int APS5_VABI sceSaveDataSupportedFakeBrokenStatus(void); +int APS5_VABI sceSaveDataSyncCloudList(void); +int APS5_VABI sceSaveDataUmountSys(void); +int APS5_VABI sceSaveDataUmountWithBackup(void); +int APS5_VABI sceSaveDataUnregisterEventCallback(); +int APS5_VABI sceSaveDataUpload(void); + +} diff --git a/core/libs/prx/libSceSaveData/libSceSaveData.hpp b/core/libs/prx/libSceSaveData/libSceSaveData.hpp new file mode 100644 index 0000000000..72713a0e1f --- /dev/null +++ b/core/libs/prx/libSceSaveData/libSceSaveData.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceSaveData/include/Api.hpp" diff --git a/core/libs/prx/libSceSaveDataDialog.native/Export.cpp b/core/libs/prx/libSceSaveDataDialog.native/Export.cpp index 0a07c63d79..4e173f20c5 100644 --- a/core/libs/prx/libSceSaveDataDialog.native/Export.cpp +++ b/core/libs/prx/libSceSaveDataDialog.native/Export.cpp @@ -1,3 +1,5 @@ +#include "prx/libSceSaveDataDialog.native/include/Api.hpp" +#include "prx/libSceSaveDataDialog/include/Api.hpp" #include #include #include diff --git a/core/libs/prx/libSceSaveDataDialog.native/include/Api.hpp b/core/libs/prx/libSceSaveDataDialog.native/include/Api.hpp new file mode 100644 index 0000000000..838a41d62b --- /dev/null +++ b/core/libs/prx/libSceSaveDataDialog.native/include/Api.hpp @@ -0,0 +1,10 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceSaveDataDialogGetStatus(void); +int APS5_VABI sceSaveDataDialogUpdateStatus(void); + +} diff --git a/core/libs/prx/libSceSaveDataDialog.native/libSceSaveDataDialog.native.hpp b/core/libs/prx/libSceSaveDataDialog.native/libSceSaveDataDialog.native.hpp new file mode 100644 index 0000000000..483cb011af --- /dev/null +++ b/core/libs/prx/libSceSaveDataDialog.native/libSceSaveDataDialog.native.hpp @@ -0,0 +1,4 @@ +#pragma once + +#include "prx/libSceSaveDataDialog/include/Api.hpp" +#include "prx/libSceSaveDataDialog.native/include/Api.hpp" diff --git a/core/libs/prx/libSceSaveDataDialog/Export.cpp b/core/libs/prx/libSceSaveDataDialog/Export.cpp index 068c96f145..1ad8a50883 100644 --- a/core/libs/prx/libSceSaveDataDialog/Export.cpp +++ b/core/libs/prx/libSceSaveDataDialog/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceSaveDataDialog/include/Api.hpp" #include #include #include @@ -6,7 +7,6 @@ #include "prx/libSceSaveDataDialog.native/SaveDataDialog.hpp" #include "prx/libc/include/General.hpp" - namespace { // Throwing from these reaches std::terminate and aborts the game process. int SoftFailNp(const char* func) { diff --git a/core/libs/prx/libSceSaveDataDialog/include/Api.hpp b/core/libs/prx/libSceSaveDataDialog/include/Api.hpp new file mode 100644 index 0000000000..40baa8c043 --- /dev/null +++ b/core/libs/prx/libSceSaveDataDialog/include/Api.hpp @@ -0,0 +1,16 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceSaveDataDialogClose(const void* closeParam); +int APS5_VABI sceSaveDataDialogGetResult(void* result); +int APS5_VABI sceSaveDataDialogInitialize(void); +int APS5_VABI sceSaveDataDialogIsReadyToDisplay(void); +int APS5_VABI sceSaveDataDialogOpen(const void* param); +int APS5_VABI sceSaveDataDialogProgressBarInc(int target, uint32_t delta); +int APS5_VABI sceSaveDataDialogProgressBarSetValue(int target, uint32_t rate); +int APS5_VABI sceSaveDataDialogTerminate(void); + +} diff --git a/core/libs/prx/libSceSaveDataDialog/libSceSaveDataDialog.hpp b/core/libs/prx/libSceSaveDataDialog/libSceSaveDataDialog.hpp new file mode 100644 index 0000000000..06b3b4f0f0 --- /dev/null +++ b/core/libs/prx/libSceSaveDataDialog/libSceSaveDataDialog.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceSaveDataDialog/include/Api.hpp" diff --git a/core/libs/prx/libSceScm/libSceScm.hpp b/core/libs/prx/libSceScm/libSceScm.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceScm/libSceScm.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceScreenShot/Export.cpp b/core/libs/prx/libSceScreenShot/Export.cpp index dbc4cf09af..b9335af525 100644 --- a/core/libs/prx/libSceScreenShot/Export.cpp +++ b/core/libs/prx/libSceScreenShot/Export.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libSceScreenShot/include/Api.hpp" #include #include #include @@ -7,8 +9,6 @@ #include "prx/libc/include/General.hpp" #include "prx/libkernel/File/include/File.hpp" -extern "C" int APS5_VABI sceKernelFstat(int d, FileStat* sb); - namespace { constexpr int ErrorArgument = static_cast(0x80BE0001); @@ -43,6 +43,7 @@ int SetOverlayImage(const char* path, int offsetX, int offsetY) { result = stat.st_size > 0 && stat.st_size <= maxSize ? 0 : ErrorOverlaySize; } sceKernelClose(descriptor); + return result; } diff --git a/core/libs/prx/libSceScreenShot/include/Api.hpp b/core/libs/prx/libSceScreenShot/include/Api.hpp new file mode 100644 index 0000000000..98d5829a2c --- /dev/null +++ b/core/libs/prx/libSceScreenShot/include/Api.hpp @@ -0,0 +1,21 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceScreenShotSetOverlayImage(const char* path, int offsetX, int offsetY); +int APS5_VABI sceScreenShotSetOverlayImageWithOrigin(const char* path, int offsetX, int offsetY, int origin); +int APS5_VABI sceScreenShotDisable(); +int APS5_VABI sceScreenShotEnable(); +int APS5_VABI sceScreenShotIsDisabled(int id, int* isDisabled); +int APS5_VABI sceScreenShotDisableNotification(); +int APS5_VABI sceScreenShotEnableNotification(); +int APS5_VABI sceScreenShotCapture(); +int APS5_VABI sceScreenShotGetAppInfo(); +int APS5_VABI sceScreenShotGetDrcParam(); +int APS5_VABI sceScreenShotIsVshScreenCaptureDisabled(); +int APS5_VABI sceScreenShotSetDrcParam(); +int APS5_VABI sceScreenShotSetParam(); + +} diff --git a/core/libs/prx/libSceScreenShot/libSceScreenShot.hpp b/core/libs/prx/libSceScreenShot/libSceScreenShot.hpp new file mode 100644 index 0000000000..4deaf512f2 --- /dev/null +++ b/core/libs/prx/libSceScreenShot/libSceScreenShot.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceScreenShot/include/Api.hpp" diff --git a/core/libs/prx/libSceSdma/Export.cpp b/core/libs/prx/libSceSdma/Export.cpp index 97a2ea23cc..1e67f3a5bb 100644 --- a/core/libs/prx/libSceSdma/Export.cpp +++ b/core/libs/prx/libSceSdma/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceSdma/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceSdma/include/Api.hpp b/core/libs/prx/libSceSdma/include/Api.hpp new file mode 100644 index 0000000000..1245319f43 --- /dev/null +++ b/core/libs/prx/libSceSdma/include/Api.hpp @@ -0,0 +1,34 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceSdmaBeginQueueMode(void); +int APS5_VABI sceSdmaCancelQueue(void); +int APS5_VABI sceSdmaClose(void); +int APS5_VABI sceSdmaConstantFill(void); +int APS5_VABI sceSdmaConstantFillNonBlocking(void); +int APS5_VABI sceSdmaCopyLinear(void); +int APS5_VABI sceSdmaCopyLinearNonBlocking(void); +int APS5_VABI sceSdmaCopyTiled(void); +int APS5_VABI sceSdmaCopyTiledNonBlocking(void); +int APS5_VABI sceSdmaCopyWindowL2L(void); +int APS5_VABI sceSdmaCopyWindowL2LNonBlocking(void); +int APS5_VABI sceSdmaCopyWindowT2T(void); +int APS5_VABI sceSdmaCopyWindowT2TNonBlocking(void); +int APS5_VABI sceSdmaCopyWindowTiled(void); +int APS5_VABI sceSdmaCopyWindowTiledNonBlocking(void); +int APS5_VABI sceSdmaEndQueueMode(void); +int APS5_VABI sceSdmaFenceNonBlocking(void); +int APS5_VABI sceSdmaFinalize(void); +int APS5_VABI sceSdmaFlushAll(void); +int APS5_VABI sceSdmaFlushAllWithEvent(void); +int APS5_VABI sceSdmaInitialize(void); +int APS5_VABI sceSdmaKickQueue(void); +int APS5_VABI sceSdmaOpen(void); +int APS5_VABI sceSdmaQueryWorkingBufferSize(void); +int APS5_VABI sceSdmaTryFlush(void); +int APS5_VABI sceSdmaWaitForEvent(void); + +} diff --git a/core/libs/prx/libSceSdma/libSceSdma.hpp b/core/libs/prx/libSceSdma/libSceSdma.hpp new file mode 100644 index 0000000000..fdaa4a04c9 --- /dev/null +++ b/core/libs/prx/libSceSdma/libSceSdma.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceSdma/include/Api.hpp" diff --git a/core/libs/prx/libSceShare.native/libSceShare.native.hpp b/core/libs/prx/libSceShare.native/libSceShare.native.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceShare.native/libSceShare.native.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceShare/Export.cpp b/core/libs/prx/libSceShare/Export.cpp index 375682887e..e2f486e7f1 100644 --- a/core/libs/prx/libSceShare/Export.cpp +++ b/core/libs/prx/libSceShare/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceShare/include/Api.hpp" #include #include #include @@ -6,22 +7,6 @@ // Capture and sharing are not emulated; policy and parameter calls are accepted. -struct ShareScreenshotParamExtended { - std::uint64_t size; - std::uint32_t source; - std::uint32_t mode; - const char* text; -}; - -struct ShareVideoClipParamExtended { - std::uint64_t size; - std::uint64_t value8; - std::uint64_t value16; - std::uint32_t mode; - std::uint32_t reserved; - const char* text; -}; - static_assert(sizeof(ShareScreenshotParamExtended) == 24); static_assert(offsetof(ShareScreenshotParamExtended, text) == 16); static_assert(sizeof(ShareVideoClipParamExtended) == 40); diff --git a/core/libs/prx/libSceShare/include/Api.hpp b/core/libs/prx/libSceShare/include/Api.hpp new file mode 100644 index 0000000000..bb612024b1 --- /dev/null +++ b/core/libs/prx/libSceShare/include/Api.hpp @@ -0,0 +1,41 @@ +#pragma once + +#include "SceTypes.hpp" + +struct ShareScreenshotParamExtended { + std::uint64_t size; + std::uint32_t source; + std::uint32_t mode; + const char* text; +}; + +struct ShareVideoClipParamExtended { + std::uint64_t size; + std::uint64_t value8; + std::uint64_t value16; + std::uint32_t mode; + std::uint32_t reserved; + const char* text; +}; + +extern "C" { + +int APS5_VABI sceShareCaptureScreenshot(const void* param, int32_t* reqId); +int APS5_VABI sceShareCaptureVideoClip(const void* param, int32_t* reqId); +int APS5_VABI sceShareFeaturePermit(uint32_t featureFlags); +int APS5_VABI sceShareFeatureProhibit(uint32_t featureFlags); +int APS5_VABI sceShareGetCurrentStatus(uint32_t featureFlag, ShareCurrentStatus* status); +int APS5_VABI sceShareInitialize(size_t heapSize, int threadPriority, uint64_t affinityMask); +int APS5_VABI sceShareOpenMenuForContent(const void* contentId); +int APS5_VABI sceShareRegisterContentEventCallback(void* callback, void* userData); +int APS5_VABI sceShareSetCaptureSource(uint32_t featureFlags, const void* tapPoint); +int APS5_VABI sceShareSetContentParam(const char* contentParam); +int APS5_VABI sceShareSetScreenshotOverlayImage(const char* filePath, int32_t marginX, int32_t marginY, int32_t origin); +int APS5_VABI sceShareTerminate(void); +int APS5_VABI sceShareUnregisterContentEventCallback(void* callback); +int APS5_VABI sceShareCaptureScreenshotExtended(const ShareScreenshotParamExtended* param, std::int32_t* requestId); +int APS5_VABI sceShareCaptureVideoClipExtended(const ShareVideoClipParamExtended* param, std::int32_t* requestId); +int APS5_VABI sceShareGetRunningStatus(uint32_t* status); +int APS5_VABI sceShareSetContentParamForApplicationTitle(const char* applicationTitle); + +} diff --git a/core/libs/prx/libSceShare/libSceShare.hpp b/core/libs/prx/libSceShare/libSceShare.hpp new file mode 100644 index 0000000000..ee79c2f96a --- /dev/null +++ b/core/libs/prx/libSceShare/libSceShare.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceShare/include/Api.hpp" diff --git a/core/libs/prx/libSceShareFactoryUtil/Export.cpp b/core/libs/prx/libSceShareFactoryUtil/Export.cpp index ca9e3680ad..e4b1de17d3 100644 --- a/core/libs/prx/libSceShareFactoryUtil/Export.cpp +++ b/core/libs/prx/libSceShareFactoryUtil/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceShareFactoryUtil/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceShareFactoryUtil/include/Api.hpp b/core/libs/prx/libSceShareFactoryUtil/include/Api.hpp new file mode 100644 index 0000000000..23f6bad23e --- /dev/null +++ b/core/libs/prx/libSceShareFactoryUtil/include/Api.hpp @@ -0,0 +1,14 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceShareFactoryUtilBackToGameFromShareFactory(); +int APS5_VABI sceShareFactoryUtilGetLaunchStatus(); +int APS5_VABI sceShareFactoryUtilGetLaunchStatusOfShareFactory(); +int APS5_VABI sceShareFactoryUtilInitialize(); +int APS5_VABI sceShareFactoryUtilLaunchShareFactory(); +int APS5_VABI sceShareFactoryUtilTerminate(); + +} diff --git a/core/libs/prx/libSceShareFactoryUtil/libSceShareFactoryUtil.hpp b/core/libs/prx/libSceShareFactoryUtil/libSceShareFactoryUtil.hpp new file mode 100644 index 0000000000..7d666fde94 --- /dev/null +++ b/core/libs/prx/libSceShareFactoryUtil/libSceShareFactoryUtil.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceShareFactoryUtil/include/Api.hpp" diff --git a/core/libs/prx/libSceShareInternal.native/libSceShareInternal.native.hpp b/core/libs/prx/libSceShareInternal.native/libSceShareInternal.native.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceShareInternal.native/libSceShareInternal.native.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceSharePlay/Export.cpp b/core/libs/prx/libSceSharePlay/Export.cpp index 848b32427a..05910a7c56 100644 --- a/core/libs/prx/libSceSharePlay/Export.cpp +++ b/core/libs/prx/libSceSharePlay/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceSharePlay/include/Api.hpp" #include #include #include diff --git a/core/libs/prx/libSceSharePlay/include/Api.hpp b/core/libs/prx/libSceSharePlay/include/Api.hpp new file mode 100644 index 0000000000..6336eae897 --- /dev/null +++ b/core/libs/prx/libSceSharePlay/include/Api.hpp @@ -0,0 +1,28 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceSharePlayInitialize(void* heap, size_t heapSize); +int APS5_VABI sceSharePlayTerminate(void); +int APS5_VABI sceSharePlayGetCurrentConnectionInfoA(SharePlayConnectionInfoA* info); +int APS5_VABI sceSharePlayProhibitController(std::uint8_t prohibited); +int APS5_VABI sceSharePlayCrashDaemon(void); +int APS5_VABI sceSharePlayGetCurrentConnectionInfo(void); +int APS5_VABI sceSharePlayGetCurrentInfo(void); +int APS5_VABI sceSharePlayGetEvent(void); +int APS5_VABI sceSharePlayNotifyDialogOpen(void); +int APS5_VABI sceSharePlayNotifyForceCloseForCdlg(void); +int APS5_VABI sceSharePlayResumeScreenForCdlg(void); +int APS5_VABI sceSharePlayServerLock(void); +int APS5_VABI sceSharePlayServerUnLock(void); +int APS5_VABI sceSharePlaySetMode(void); +int APS5_VABI sceSharePlaySetProhibition(void); +int APS5_VABI sceSharePlaySetProhibitionModeWithAppId(void); +int APS5_VABI sceSharePlayStartStandby(void); +int APS5_VABI sceSharePlayStartStreaming(void); +int APS5_VABI sceSharePlayStopStandby(void); +int APS5_VABI sceSharePlayStopStreaming(void); + +} diff --git a/core/libs/prx/libSceSharePlay/libSceSharePlay.hpp b/core/libs/prx/libSceSharePlay/libSceSharePlay.hpp new file mode 100644 index 0000000000..c68e519720 --- /dev/null +++ b/core/libs/prx/libSceSharePlay/libSceSharePlay.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceSharePlay/include/Api.hpp" diff --git a/core/libs/prx/libSceShareUtility/Export.cpp b/core/libs/prx/libSceShareUtility/Export.cpp index b8d35a3625..a6cf891afd 100644 --- a/core/libs/prx/libSceShareUtility/Export.cpp +++ b/core/libs/prx/libSceShareUtility/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceShareUtility/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceShareUtility/include/Api.hpp b/core/libs/prx/libSceShareUtility/include/Api.hpp new file mode 100644 index 0000000000..9ea97606cc --- /dev/null +++ b/core/libs/prx/libSceShareUtility/include/Api.hpp @@ -0,0 +1,30 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceShareUtilityAdvanceFromFileWithContentIdList(); +int APS5_VABI sceShareUtilityAdvanceFromFileWithTitleIdList(); +int APS5_VABI sceShareUtilityAdvanceGetServiceInfo(); +int APS5_VABI sceShareUtilityAdvanceInitialize(); +int APS5_VABI sceShareUtilityAdvanceQueryServiceInfo(); +int APS5_VABI sceShareUtilityAdvanceQueryServiceInfoA(); +int APS5_VABI sceShareUtilityAdvanceResetPlayingContent(); +int APS5_VABI sceShareUtilityAdvanceSetPlayingContent(); +int APS5_VABI sceShareUtilityAdvanceSetUploadContentData(); +int APS5_VABI sceShareUtilityAdvanceTerminate(); +int APS5_VABI sceShareUtilityAdvanceValidateContents(); +int APS5_VABI sceShareUtilityAdvanceWakeUpShareMenu(); +int APS5_VABI sceShareUtilityAdvanceWakeUpShareMenuBroadcast(); +int APS5_VABI sceShareUtilityAdvanceWakeUpShareMenuDefault(); +int APS5_VABI sceShareUtilityAdvanceWakeUpShareMenuForShareContent(); +int APS5_VABI sceShareUtilityInitialize(); +int APS5_VABI sceShareUtilityInitializeEx2(); +int APS5_VABI sceShareUtilityOpenShareMenu(); +int APS5_VABI sceShareUtilityOpenShareMenuBroadcast(); +int APS5_VABI sceShareUtilityOpenShareMenuDefault(); +int APS5_VABI sceShareUtilityOpenShareMenuForShareContent(); +int APS5_VABI sceShareUtilityTerminate(); + +} diff --git a/core/libs/prx/libSceShareUtility/libSceShareUtility.hpp b/core/libs/prx/libSceShareUtility/libSceShareUtility.hpp new file mode 100644 index 0000000000..90968950c3 --- /dev/null +++ b/core/libs/prx/libSceShareUtility/libSceShareUtility.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceShareUtility/include/Api.hpp" diff --git a/core/libs/prx/libSceShellUIUtil/Export.cpp b/core/libs/prx/libSceShellUIUtil/Export.cpp index 2837093a4f..3381c8bd7f 100644 --- a/core/libs/prx/libSceShellUIUtil/Export.cpp +++ b/core/libs/prx/libSceShellUIUtil/Export.cpp @@ -1,10 +1,9 @@ +#include "prx/libSceShellUIUtil/include/Api.hpp" #include #include #include "SceTypes.hpp" #include "prx/libc/include/General.hpp" -struct ShellUIUtilLaunchParameter; - extern "C" { int APS5_VABI sceShellUIUtilCreateTaskToken() { diff --git a/core/libs/prx/libSceShellUIUtil/include/Api.hpp b/core/libs/prx/libSceShellUIUtil/include/Api.hpp new file mode 100644 index 0000000000..fe2e641916 --- /dev/null +++ b/core/libs/prx/libSceShellUIUtil/include/Api.hpp @@ -0,0 +1,16 @@ +#pragma once + +#include "SceTypes.hpp" + +struct ShellUIUtilLaunchParameter; + +extern "C" { + +int APS5_VABI sceShellUIUtilCreateTaskToken(); +int APS5_VABI sceShellUIUtilGetAppUrl(const char* application, const char* parameter, char* output, std::uint32_t capacity, std::uint32_t* outputSize); +int APS5_VABI sceShellUIUtilInitialize(); +int APS5_VABI sceShellUIUtilLaunchByUri(const char* uri, const ShellUIUtilLaunchParameter* parameter); +int APS5_VABI sceShellUIUtilLaunchTask(std::int32_t taskToken, const char* uri, char* output, std::uint32_t capacity); +int APS5_VABI sceShellUIUtilTerminate(); + +} diff --git a/core/libs/prx/libSceShellUIUtil/libSceShellUIUtil.hpp b/core/libs/prx/libSceShellUIUtil/libSceShellUIUtil.hpp new file mode 100644 index 0000000000..0b7294088c --- /dev/null +++ b/core/libs/prx/libSceShellUIUtil/libSceShellUIUtil.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceShellUIUtil/include/Api.hpp" diff --git a/core/libs/prx/libSceSigninDialog/Export.cpp b/core/libs/prx/libSceSigninDialog/Export.cpp index 761bf33308..cd55802e70 100644 --- a/core/libs/prx/libSceSigninDialog/Export.cpp +++ b/core/libs/prx/libSceSigninDialog/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceSigninDialog/include/Api.hpp" #include #include #include diff --git a/core/libs/prx/libSceSigninDialog/include/Api.hpp b/core/libs/prx/libSceSigninDialog/include/Api.hpp new file mode 100644 index 0000000000..5d9a45ed41 --- /dev/null +++ b/core/libs/prx/libSceSigninDialog/include/Api.hpp @@ -0,0 +1,15 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceSigninDialogClose(void); +int APS5_VABI sceSigninDialogGetResult(void* result); +int APS5_VABI sceSigninDialogGetStatus(void); +int APS5_VABI sceSigninDialogInitialize(void); +int APS5_VABI sceSigninDialogOpen(const void* param); +int APS5_VABI sceSigninDialogTerminate(void); +int APS5_VABI sceSigninDialogUpdateStatus(void); + +} diff --git a/core/libs/prx/libSceSigninDialog/libSceSigninDialog.hpp b/core/libs/prx/libSceSigninDialog/libSceSigninDialog.hpp new file mode 100644 index 0000000000..5791aba9bb --- /dev/null +++ b/core/libs/prx/libSceSigninDialog/libSceSigninDialog.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceSigninDialog/include/Api.hpp" diff --git a/core/libs/prx/libSceSmart/libSceSmart.hpp b/core/libs/prx/libSceSmart/libSceSmart.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceSmart/libSceSmart.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceSocialScreen/Export.cpp b/core/libs/prx/libSceSocialScreen/Export.cpp index ebaf31823a..31e90003c8 100644 --- a/core/libs/prx/libSceSocialScreen/Export.cpp +++ b/core/libs/prx/libSceSocialScreen/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceSocialScreen/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceSocialScreen/include/Api.hpp b/core/libs/prx/libSceSocialScreen/include/Api.hpp new file mode 100644 index 0000000000..77d98b1b85 --- /dev/null +++ b/core/libs/prx/libSceSocialScreen/include/Api.hpp @@ -0,0 +1,19 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceSocialScreenCloseSeparateMode(); +int APS5_VABI sceSocialScreenConfigureSeparateMode(); +int APS5_VABI sceSocialScreenCrashDaemon(); +int APS5_VABI sceSocialScreenGetIgnoreSeparateMode(); +int APS5_VABI sceSocialScreenInitialize(); +int APS5_VABI sceSocialScreenInitializeSeparateModeParameter(); +int APS5_VABI sceSocialScreenOpenSeparateMode(); +int APS5_VABI sceSocialScreenReserveHighFrameRateVideoCaptureRequest(); +int APS5_VABI sceSocialScreenSetIgnoreSeparateMode(); +int APS5_VABI sceSocialScreenSetMode(); +int APS5_VABI sceSocialScreenTerminate(); + +} diff --git a/core/libs/prx/libSceSocialScreen/libSceSocialScreen.hpp b/core/libs/prx/libSceSocialScreen/libSceSocialScreen.hpp new file mode 100644 index 0000000000..c3678800c1 --- /dev/null +++ b/core/libs/prx/libSceSocialScreen/libSceSocialScreen.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceSocialScreen/include/Api.hpp" diff --git a/core/libs/prx/libSceSocialScreenDialog/Export.cpp b/core/libs/prx/libSceSocialScreenDialog/Export.cpp index c3c5849381..b12bb6631e 100644 --- a/core/libs/prx/libSceSocialScreenDialog/Export.cpp +++ b/core/libs/prx/libSceSocialScreenDialog/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceSocialScreenDialog/include/Api.hpp" #include #include #include diff --git a/core/libs/prx/libSceSocialScreenDialog/include/Api.hpp b/core/libs/prx/libSceSocialScreenDialog/include/Api.hpp new file mode 100644 index 0000000000..1c02a641d8 --- /dev/null +++ b/core/libs/prx/libSceSocialScreenDialog/include/Api.hpp @@ -0,0 +1,15 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceSocialScreenDialogInitialize(void); +int APS5_VABI sceSocialScreenDialogOpen(const void* param); +int APS5_VABI sceSocialScreenDialogUpdateStatus(void); +int APS5_VABI sceSocialScreenDialogGetStatus(void); +int APS5_VABI sceSocialScreenDialogGetResult(void* result); +int APS5_VABI sceSocialScreenDialogClose(void); +int APS5_VABI sceSocialScreenDialogTerminate(void); + +} diff --git a/core/libs/prx/libSceSocialScreenDialog/libSceSocialScreenDialog.hpp b/core/libs/prx/libSceSocialScreenDialog/libSceSocialScreenDialog.hpp new file mode 100644 index 0000000000..91b1893527 --- /dev/null +++ b/core/libs/prx/libSceSocialScreenDialog/libSceSocialScreenDialog.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceSocialScreenDialog/include/Api.hpp" diff --git a/core/libs/prx/libSceSpSysCallWrapper/CMakeLists.txt b/core/libs/prx/libSceSpSysCallWrapper/CMakeLists.txt new file mode 100644 index 0000000000..5e407e9a37 --- /dev/null +++ b/core/libs/prx/libSceSpSysCallWrapper/CMakeLists.txt @@ -0,0 +1,16 @@ +add_library(libSceSpSysCallWrapper SHARED EXCLUDE_FROM_ALL Export.cpp) +target_include_directories(libSceSpSysCallWrapper PRIVATE ${LIBS_INCLUDE_DIR}) +target_link_libraries(libSceSpSysCallWrapper PRIVATE libSceNet) +configure_windows_unwind(libSceSpSysCallWrapper) + +if(BUILD_TESTING) + add_test_executable(guest_sp_syscall_wrapper_tests ${LIBS_INCLUDE_DIR}/tests/GuestSpSysCallWrapper.cpp) + target_include_directories(guest_sp_syscall_wrapper_tests PRIVATE ${LIBS_INCLUDE_DIR}) + target_link_libraries(guest_sp_syscall_wrapper_tests PRIVATE libSceSpSysCallWrapper libSceNet libkernel libc) + configure_windows_unwind(guest_sp_syscall_wrapper_tests) + add_test(NAME guest_sp_syscall_wrapper COMMAND guest_sp_syscall_wrapper_tests) + if(WIN32) + set_tests_properties(guest_sp_syscall_wrapper PROPERTIES ENVIRONMENT_MODIFICATION + "PATH=path_list_prepend:$") + endif() +endif() diff --git a/core/libs/prx/libSceSpSysCallWrapper/Export.cpp b/core/libs/prx/libSceSpSysCallWrapper/Export.cpp index e15c0a9054..f0db9348f5 100644 --- a/core/libs/prx/libSceSpSysCallWrapper/Export.cpp +++ b/core/libs/prx/libSceSpSysCallWrapper/Export.cpp @@ -1,3 +1,6 @@ +#include "prx/libSceSpSysCallWrapper/libSceSpSysCallWrapper.hpp" +#include "prx/libSceNet/libSceNet.hpp" +#include "prx/libkernel/libkernel.hpp" #include #include #include "SceTypes.hpp" @@ -5,219 +8,179 @@ extern "C" { +std::int64_t APS5_VABI GuestNetRecv_nid_no_patch(int s, void* buf, std::size_t len, int flags); +std::int64_t APS5_VABI GuestNetSend_nid_no_patch(int s, const void* buf, std::size_t len, int flags); + int APS5_VABI sceSpGetPid() { - NotImplemented_nid_no_patch(__func__); - return 0; + return getpid_nid_postfix(); } -int APS5_VABI sceSpKernelGettimeofday() { - NotImplemented_nid_no_patch(__func__); - return 0; +int APS5_VABI sceSpKernelGettimeofday(KernelTimeval* tp) { + return sceKernelGettimeofday(tp); } -int APS5_VABI sceSpKernelNanosleep() { - NotImplemented_nid_no_patch(__func__); - return 0; +int APS5_VABI sceSpKernelNanosleep(const KernelTimespec* rqtp, KernelTimespec* rmtp) { + return sceKernelNanosleep(rqtp, rmtp); } -int APS5_VABI sceSpNetConnect() { - NotImplemented_nid_no_patch(__func__); - return 0; +int APS5_VABI sceSpNetConnect(int s, const void* addr, std::uint32_t addrlen) { + return sceNetConnect(s, addr, addrlen); } -int APS5_VABI sceSpNetEpollAbort() { - NotImplemented_nid_no_patch(__func__); - return 0; +int APS5_VABI sceSpNetEpollAbort(int eid, int flags) { + return sceNetEpollAbort(eid, flags); } -int APS5_VABI sceSpNetEpollControl() { - NotImplemented_nid_no_patch(__func__); - return 0; +int APS5_VABI sceSpNetEpollControl(int eid, int op, int id, const void* event) { + return sceNetEpollControl(eid, op, id, static_cast(event)); } -int APS5_VABI sceSpNetEpollCreate() { - NotImplemented_nid_no_patch(__func__); - return 0; +int APS5_VABI sceSpNetEpollCreate(const char* name, int flags) { + return sceNetEpollCreate(name, flags); } -int APS5_VABI sceSpNetEpollDestroy() { - NotImplemented_nid_no_patch(__func__); - return 0; +int APS5_VABI sceSpNetEpollDestroy(int eid) { + return sceNetEpollDestroy(eid); } -int APS5_VABI sceSpNetEpollWait() { - NotImplemented_nid_no_patch(__func__); - return 0; +int APS5_VABI sceSpNetEpollWait(int eid, void* events, int maxevents, int timeout) { + return sceNetEpollWait(eid, static_cast(events), maxevents, timeout); } -int APS5_VABI sceSpNetErrnoLoc() { - NotImplemented_nid_no_patch(__func__); - return 0; +int* APS5_VABI sceSpNetErrnoLoc() { + return sceNetErrnoLoc(); } -int APS5_VABI sceSpNetPoolCreate() { - NotImplemented_nid_no_patch(__func__); - return 0; +int APS5_VABI sceSpNetPoolCreate(const char* name, int size, int flags) { + return sceNetPoolCreate(name, size, flags); } -int APS5_VABI sceSpNetPoolDestroy() { - NotImplemented_nid_no_patch(__func__); - return 0; +int APS5_VABI sceSpNetPoolDestroy(int memid) { + return sceNetPoolDestroy(memid); } -int APS5_VABI sceSpNetRecv() { - NotImplemented_nid_no_patch(__func__); - return 0; +std::int64_t APS5_VABI sceSpNetRecv(int s, void* buf, std::size_t len, int flags) { + return GuestNetRecv_nid_no_patch(s, buf, len, flags); } -int APS5_VABI sceSpNetResolverAbort() { - NotImplemented_nid_no_patch(__func__); - return 0; +int APS5_VABI sceSpNetResolverAbort(int rid, int flags) { + return sceNetResolverAbort(rid, flags); } -int APS5_VABI sceSpNetResolverCreate() { - NotImplemented_nid_no_patch(__func__); - return 0; +int APS5_VABI sceSpNetResolverCreate(const char* name, int memid, int flags) { + return sceNetResolverCreate(name, memid, flags); } -int APS5_VABI sceSpNetResolverDestroy() { - NotImplemented_nid_no_patch(__func__); - return 0; +int APS5_VABI sceSpNetResolverDestroy(int rid) { + return sceNetResolverDestroy(rid); } -int APS5_VABI sceSpNetResolverGetError() { - NotImplemented_nid_no_patch(__func__); - return 0; +int APS5_VABI sceSpNetResolverGetError(int rid, int* status) { + return sceNetResolverGetError(rid, status); } -int APS5_VABI sceSpNetResolverStartNtoa() { - NotImplemented_nid_no_patch(__func__); - return 0; +int APS5_VABI sceSpNetResolverStartNtoa(int rid, const char* hostname, void* addr, int timeout, int retry, int flags) { + return sceNetResolverStartNtoa(rid, hostname, addr, timeout, retry, flags); } -int APS5_VABI sceSpNetSend() { - NotImplemented_nid_no_patch(__func__); - return 0; +std::int64_t APS5_VABI sceSpNetSend(int s, const void* buf, std::size_t len, int flags) { + return GuestNetSend_nid_no_patch(s, buf, len, flags); } -int APS5_VABI sceSpNetSetsockopt() { - NotImplemented_nid_no_patch(__func__); - return 0; +int APS5_VABI sceSpNetSetsockopt(int s, int level, int optname, const void* optval, std::uint32_t optlen) { + return sceNetSetsockopt(s, level, optname, optval, optlen); } -int APS5_VABI sceSpNetSocket() { - NotImplemented_nid_no_patch(__func__); - return 0; +int APS5_VABI sceSpNetSocket(const char* name, int family, int type, int protocol) { + return sceNetSocket(name, family, type, protocol); } -int APS5_VABI sceSpNetSocketClose() { - NotImplemented_nid_no_patch(__func__); - return 0; +int APS5_VABI sceSpNetSocketClose(int s) { + return sceNetSocketClose(s); } -int APS5_VABI sceSpPthreadAttrDestroy() { - NotImplemented_nid_no_patch(__func__); - return 0; +int APS5_VABI sceSpPthreadAttrDestroy(PthreadAttr* attr) { + return scePthreadAttrDestroy(attr); } -int APS5_VABI sceSpPthreadAttrInit() { - NotImplemented_nid_no_patch(__func__); - return 0; +int APS5_VABI sceSpPthreadAttrInit(PthreadAttr* attr) { + return scePthreadAttrInit(attr); } -int APS5_VABI sceSpPthreadAttrSetinheritsched() { - NotImplemented_nid_no_patch(__func__); - return 0; +int APS5_VABI sceSpPthreadAttrSetinheritsched(PthreadAttr* attr, int inheritSched) { + return scePthreadAttrSetinheritsched(attr, inheritSched); } -int APS5_VABI sceSpPthreadAttrSetschedparam() { - NotImplemented_nid_no_patch(__func__); - return 0; +int APS5_VABI sceSpPthreadAttrSetschedparam(PthreadAttr* attr, const KernelSchedParam* param) { + return scePthreadAttrSetschedparam(attr, param); } -int APS5_VABI sceSpPthreadAttrSetstacksize() { - NotImplemented_nid_no_patch(__func__); - return 0; +int APS5_VABI sceSpPthreadAttrSetstacksize(PthreadAttr* attr, std::size_t stackSize) { + return scePthreadAttrSetstacksize(attr, stackSize); } -int APS5_VABI sceSpPthreadCondDestroy() { - NotImplemented_nid_no_patch(__func__); - return 0; +int APS5_VABI sceSpPthreadCondDestroy(PthreadCond* cond) { + return scePthreadCondDestroy(cond); } -int APS5_VABI sceSpPthreadCondInit() { - NotImplemented_nid_no_patch(__func__); - return 0; +int APS5_VABI sceSpPthreadCondInit(PthreadCond* cond, const PthreadCondattr* attr, const char* name) { + return scePthreadCondInit(cond, attr, name); } -int APS5_VABI sceSpPthreadCondSignal() { - NotImplemented_nid_no_patch(__func__); - return 0; +int APS5_VABI sceSpPthreadCondSignal(PthreadCond* cond) { + return scePthreadCondSignal(cond); } -int APS5_VABI sceSpPthreadCondWait() { - NotImplemented_nid_no_patch(__func__); - return 0; +int APS5_VABI sceSpPthreadCondWait(PthreadCond* cond, PthreadMutex* mutex) { + return scePthreadCondWait(cond, mutex); } -int APS5_VABI sceSpPthreadCondattrDestroy() { - NotImplemented_nid_no_patch(__func__); - return 0; +int APS5_VABI sceSpPthreadCondattrDestroy(PthreadCondattr* attr) { + return scePthreadCondattrDestroy(attr); } -int APS5_VABI sceSpPthreadCondattrInit() { - NotImplemented_nid_no_patch(__func__); - return 0; +int APS5_VABI sceSpPthreadCondattrInit(PthreadCondattr* attr) { + return scePthreadCondattrInit(attr); } -int APS5_VABI sceSpPthreadCreate() { - NotImplemented_nid_no_patch(__func__); - return 0; +int APS5_VABI sceSpPthreadCreate(Pthread* thread, const PthreadAttr* attr, PthreadEntry entry, void* arg, const char* name) { + return scePthreadCreate(thread, attr, entry, arg, name); } -int APS5_VABI sceSpPthreadDetach() { - NotImplemented_nid_no_patch(__func__); - return 0; +int APS5_VABI sceSpPthreadDetach(Pthread thread) { + return scePthreadDetach(thread); } -int APS5_VABI sceSpPthreadExit() { - NotImplemented_nid_no_patch(__func__); - return 0; +void APS5_VABI sceSpPthreadExit(void* retval) { + scePthreadExit(retval); } -int APS5_VABI sceSpPthreadJoin() { - NotImplemented_nid_no_patch(__func__); - return 0; +int APS5_VABI sceSpPthreadJoin(Pthread thread, void** retval) { + return scePthreadJoin(thread, retval); } -int APS5_VABI sceSpPthreadMutexDestroy() { - NotImplemented_nid_no_patch(__func__); - return 0; +int APS5_VABI sceSpPthreadMutexDestroy(PthreadMutex* mutex) { + return scePthreadMutexDestroy(mutex); } -int APS5_VABI sceSpPthreadMutexInit() { - NotImplemented_nid_no_patch(__func__); - return 0; +int APS5_VABI sceSpPthreadMutexInit(PthreadMutex* mutex, const PthreadMutexattr* attr, const char* name) { + return scePthreadMutexInit(mutex, attr, name); } -int APS5_VABI sceSpPthreadMutexLock() { - NotImplemented_nid_no_patch(__func__); - return 0; +int APS5_VABI sceSpPthreadMutexLock(PthreadMutex* mutex) { + return scePthreadMutexLock(mutex); } -int APS5_VABI sceSpPthreadMutexUnlock() { - NotImplemented_nid_no_patch(__func__); - return 0; +int APS5_VABI sceSpPthreadMutexUnlock(PthreadMutex* mutex) { + return scePthreadMutexUnlock(mutex); } -int APS5_VABI sceSpPthreadMutexattrDestroy() { - NotImplemented_nid_no_patch(__func__); - return 0; +int APS5_VABI sceSpPthreadMutexattrDestroy(PthreadMutexattr* attr) { + return scePthreadMutexattrDestroy(attr); } -int APS5_VABI sceSpPthreadMutexattrInit() { - NotImplemented_nid_no_patch(__func__); - return 0; +int APS5_VABI sceSpPthreadMutexattrInit(PthreadMutexattr* attr) { + return scePthreadMutexattrInit(attr); } int APS5_VABI sceSpPthreadMutexattrSetprioceiling() { @@ -225,24 +188,20 @@ int APS5_VABI sceSpPthreadMutexattrSetprioceiling() { return 0; } -int APS5_VABI sceSpPthreadMutexattrSetprotocol() { - NotImplemented_nid_no_patch(__func__); - return 0; +int APS5_VABI sceSpPthreadMutexattrSetprotocol(PthreadMutexattr* attr, int protocol) { + return scePthreadMutexattrSetprotocol(attr, protocol); } -int APS5_VABI sceSpPthreadMutexattrSettype() { - NotImplemented_nid_no_patch(__func__); - return 0; +int APS5_VABI sceSpPthreadMutexattrSettype(PthreadMutexattr* attr, int type) { + return scePthreadMutexattrSettype(attr, type); } -int APS5_VABI sceSpPthreadSetprio() { - NotImplemented_nid_no_patch(__func__); - return 0; +int APS5_VABI sceSpPthreadSetprio(Pthread thread, int prio) { + return scePthreadSetprio(thread, prio); } -int APS5_VABI sceSpSelect() { - NotImplemented_nid_no_patch(__func__); - return 0; +int APS5_VABI sceSpSelect(int nfds, void* readfds, void* writefds, void* exceptfds, const void* timeout) { + return select_nid_postfix(nfds, readfds, writefds, exceptfds, timeout); } } diff --git a/core/libs/prx/libSceSpSysCallWrapper/include/Api.hpp b/core/libs/prx/libSceSpSysCallWrapper/include/Api.hpp new file mode 100644 index 0000000000..10979d9d31 --- /dev/null +++ b/core/libs/prx/libSceSpSysCallWrapper/include/Api.hpp @@ -0,0 +1,58 @@ +#pragma once + +#include +#include +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceSpGetPid(); +int APS5_VABI sceSpKernelGettimeofday(KernelTimeval* tp); +int APS5_VABI sceSpKernelNanosleep(const KernelTimespec* rqtp, KernelTimespec* rmtp); +int APS5_VABI sceSpNetConnect(int s, const void* addr, std::uint32_t addrlen); +int APS5_VABI sceSpNetEpollAbort(int eid, int flags); +int APS5_VABI sceSpNetEpollControl(int eid, int op, int id, const void* event); +int APS5_VABI sceSpNetEpollCreate(const char* name, int flags); +int APS5_VABI sceSpNetEpollDestroy(int eid); +int APS5_VABI sceSpNetEpollWait(int eid, void* events, int maxevents, int timeout); +int* APS5_VABI sceSpNetErrnoLoc(); +int APS5_VABI sceSpNetPoolCreate(const char* name, int size, int flags); +int APS5_VABI sceSpNetPoolDestroy(int memid); +std::int64_t APS5_VABI sceSpNetRecv(int s, void* buf, std::size_t len, int flags); +int APS5_VABI sceSpNetResolverAbort(int rid, int flags); +int APS5_VABI sceSpNetResolverCreate(const char* name, int memid, int flags); +int APS5_VABI sceSpNetResolverDestroy(int rid); +int APS5_VABI sceSpNetResolverGetError(int rid, int* status); +int APS5_VABI sceSpNetResolverStartNtoa(int rid, const char* hostname, void* addr, int timeout, int retry, int flags); +std::int64_t APS5_VABI sceSpNetSend(int s, const void* buf, std::size_t len, int flags); +int APS5_VABI sceSpNetSetsockopt(int s, int level, int optname, const void* optval, std::uint32_t optlen); +int APS5_VABI sceSpNetSocket(const char* name, int family, int type, int protocol); +int APS5_VABI sceSpNetSocketClose(int s); +int APS5_VABI sceSpPthreadAttrDestroy(PthreadAttr* attr); +int APS5_VABI sceSpPthreadAttrInit(PthreadAttr* attr); +int APS5_VABI sceSpPthreadAttrSetinheritsched(PthreadAttr* attr, int inheritSched); +int APS5_VABI sceSpPthreadAttrSetschedparam(PthreadAttr* attr, const KernelSchedParam* param); +int APS5_VABI sceSpPthreadAttrSetstacksize(PthreadAttr* attr, std::size_t stackSize); +int APS5_VABI sceSpPthreadCondDestroy(PthreadCond* cond); +int APS5_VABI sceSpPthreadCondInit(PthreadCond* cond, const PthreadCondattr* attr, const char* name); +int APS5_VABI sceSpPthreadCondSignal(PthreadCond* cond); +int APS5_VABI sceSpPthreadCondWait(PthreadCond* cond, PthreadMutex* mutex); +int APS5_VABI sceSpPthreadCondattrDestroy(PthreadCondattr* attr); +int APS5_VABI sceSpPthreadCondattrInit(PthreadCondattr* attr); +int APS5_VABI sceSpPthreadCreate(Pthread* thread, const PthreadAttr* attr, PthreadEntry entry, void* arg, const char* name); +int APS5_VABI sceSpPthreadDetach(Pthread thread); +void APS5_VABI sceSpPthreadExit(void* retval); +int APS5_VABI sceSpPthreadJoin(Pthread thread, void** retval); +int APS5_VABI sceSpPthreadMutexDestroy(PthreadMutex* mutex); +int APS5_VABI sceSpPthreadMutexInit(PthreadMutex* mutex, const PthreadMutexattr* attr, const char* name); +int APS5_VABI sceSpPthreadMutexLock(PthreadMutex* mutex); +int APS5_VABI sceSpPthreadMutexUnlock(PthreadMutex* mutex); +int APS5_VABI sceSpPthreadMutexattrDestroy(PthreadMutexattr* attr); +int APS5_VABI sceSpPthreadMutexattrInit(PthreadMutexattr* attr); +int APS5_VABI sceSpPthreadMutexattrSetprioceiling(); +int APS5_VABI sceSpPthreadMutexattrSetprotocol(PthreadMutexattr* attr, int protocol); +int APS5_VABI sceSpPthreadMutexattrSettype(PthreadMutexattr* attr, int type); +int APS5_VABI sceSpPthreadSetprio(Pthread thread, int prio); +int APS5_VABI sceSpSelect(int nfds, void* readfds, void* writefds, void* exceptfds, const void* timeout); + +} diff --git a/core/libs/prx/libSceSpSysCallWrapper/libSceSpSysCallWrapper.hpp b/core/libs/prx/libSceSpSysCallWrapper/libSceSpSysCallWrapper.hpp new file mode 100644 index 0000000000..452ed7469c --- /dev/null +++ b/core/libs/prx/libSceSpSysCallWrapper/libSceSpSysCallWrapper.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceSpSysCallWrapper/include/Api.hpp" diff --git a/core/libs/prx/libSceSrcUtl/Export.cpp b/core/libs/prx/libSceSrcUtl/Export.cpp index fac2eada51..3494cee76b 100644 --- a/core/libs/prx/libSceSrcUtl/Export.cpp +++ b/core/libs/prx/libSceSrcUtl/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceSrcUtl/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceSrcUtl/include/Api.hpp b/core/libs/prx/libSceSrcUtl/include/Api.hpp new file mode 100644 index 0000000000..b4db4c7c48 --- /dev/null +++ b/core/libs/prx/libSceSrcUtl/include/Api.hpp @@ -0,0 +1,17 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceSrcUtilityFinalize(); +int APS5_VABI sceSrcUtilityFlush(); +int APS5_VABI sceSrcUtilityGetDelaySamples(); +int APS5_VABI sceSrcUtilityGetHandleSize(); +int APS5_VABI sceSrcUtilityGetPriority(); +int APS5_VABI sceSrcUtilityInitialize(); +int APS5_VABI sceSrcUtilityInitializeEx(); +int APS5_VABI sceSrcUtilityResample(); +int APS5_VABI sceSrcUtilitySetPriority(); + +} diff --git a/core/libs/prx/libSceSrcUtl/libSceSrcUtl.hpp b/core/libs/prx/libSceSrcUtl/libSceSrcUtl.hpp new file mode 100644 index 0000000000..cf118c2ada --- /dev/null +++ b/core/libs/prx/libSceSrcUtl/libSceSrcUtl.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceSrcUtl/include/Api.hpp" diff --git a/core/libs/prx/libSceSsl/CMakeLists.txt b/core/libs/prx/libSceSsl/CMakeLists.txt index cb39ff0e4c..8296a60735 100644 --- a/core/libs/prx/libSceSsl/CMakeLists.txt +++ b/core/libs/prx/libSceSsl/CMakeLists.txt @@ -90,9 +90,16 @@ if(BUILD_TESTING) target_link_libraries(guest_ssl_ps5_readers_tests PRIVATE libSceSsl libc) configure_windows_unwind(guest_ssl_ps5_readers_tests) add_test(NAME guest_ssl_ps5_readers COMMAND guest_ssl_ps5_readers_tests) + add_test_executable(guest_ssl_context_lifetime_tests ${LIBS_INCLUDE_DIR}/tests/SslContextLifetime.cpp) + target_include_directories(guest_ssl_context_lifetime_tests PRIVATE ${LIBS_INCLUDE_DIR}) + target_link_libraries(guest_ssl_context_lifetime_tests PRIVATE libc mbedtls mbedx509 mbedcrypto) + configure_windows_unwind(guest_ssl_context_lifetime_tests) + add_test(NAME guest_ssl_context_lifetime COMMAND guest_ssl_context_lifetime_tests) + set_tests_properties(guest_ssl_context_lifetime PROPERTIES TIMEOUT 30) if(WIN32) target_link_libraries(guest_ssl_transport_tests PRIVATE bcrypt ws2_32) - set_tests_properties(guest_ssl guest_ssl_load guest_ssl_ps5_readers guest_ssl_transport_kernel guest_ssl_transport_net PROPERTIES ENVIRONMENT_MODIFICATION + target_link_libraries(guest_ssl_context_lifetime_tests PRIVATE bcrypt ws2_32) + set_tests_properties(guest_ssl guest_ssl_load guest_ssl_ps5_readers guest_ssl_context_lifetime guest_ssl_transport_kernel guest_ssl_transport_net PROPERTIES ENVIRONMENT_MODIFICATION "PATH=path_list_prepend:$;PATH=path_list_prepend:$") endif() endif() diff --git a/core/libs/prx/libSceSsl/Export.cpp b/core/libs/prx/libSceSsl/Export.cpp index ceb7654ba3..3bb1000c90 100644 --- a/core/libs/prx/libSceSsl/Export.cpp +++ b/core/libs/prx/libSceSsl/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceSsl/include/Ssl.hpp" #ifdef _WIN32 #include #else @@ -466,8 +467,6 @@ struct Session { } }; -using SslVerifyCallback = int (APS5_VABI *)(int, unsigned int, void**, int, void*); - constexpr int SslVersionSsl30 = 2; constexpr int SslVersionTls12 = 5; @@ -657,7 +656,9 @@ int APS5_VABI sceSslInit_nid_postfix(std::uint64_t poolSize) { int APS5_VABI sceSslTerm_nid_postfix(int sslCtxId) { auto& state = State(); std::lock_guard lock(state.mutex); - if (!state.contexts.erase(sslCtxId)) return ErrorInvalidId; + if (!state.contexts.contains(sslCtxId)) return ErrorInvalidId; + std::erase_if(state.connections, [sslCtxId](const auto& entry) { return entry.second.context == sslCtxId; }); + state.contexts.erase(sslCtxId); return 0; } @@ -1354,4 +1355,9 @@ int APS5_VABI sceSslSetSslVersion() { return 0; } +int APS5_VABI sceSslSetServerName() { + NotImplemented_nid_no_patch(__func__); + return 0; +} + } diff --git a/core/libs/prx/libSceSsl/include/Ssl.hpp b/core/libs/prx/libSceSsl/include/Ssl.hpp new file mode 100644 index 0000000000..5de6ba4c60 --- /dev/null +++ b/core/libs/prx/libSceSsl/include/Ssl.hpp @@ -0,0 +1,66 @@ +#pragma once + +#include "SceTypes.hpp" +#include "prx/libSceSsl/SslTypes.hpp" + +using SslVerifyCallback = int (APS5_VABI *)(int, unsigned int, void**, int, void*); + +extern "C" { + +int APS5_VABI sceSslInit_nid_postfix(std::uint64_t poolSize); +int APS5_VABI sceSslTerm_nid_postfix(int sslCtxId); +int APS5_VABI sceSslGetMemoryPoolStats(int sslCtxId, SceSsl::MemoryPoolStats* stats); +int APS5_VABI sceSslLoadCert(int sslCtxId, int caCertNum, SceSsl::Data** caList, SceSsl::Data* cert, SceSsl::Data* privateKey); +int APS5_VABI sceSslUnloadCert(int sslCtxId); +int APS5_VABI sceSslGetCaList(int sslCtxId, SceSsl::CaList* output); +int APS5_VABI sceSslFreeCaList(int sslCtxId, SceSsl::CaList* list); +int APS5_VABI sceSslGetCaCerts(int sslCtxId, SceSsl::CaCerts* output); +int APS5_VABI sceSslFreeCaCerts(int sslCtxId, SceSsl::CaCerts* certificates); +int APS5_VABI sceSslCreateConnection(int sslCtxId, int sockId, const char* host); +int APS5_VABI sceSslDeleteConnection(int sslConnectionId); +int APS5_VABI sceSslSetVerifyCallback(int sslConnectionId, SslVerifyCallback cbfunc, void* userArg); +int APS5_VABI sceSslConnect(int sslConnectionId); +int APS5_VABI sceSslRead(int sslConnectionId, void* buf, size_t len, int flags); +int APS5_VABI sceSslWrite(int sslConnectionId, void* buf, size_t len, int flags); +int APS5_VABI sceSslClose(int sslConnectionId); +int APS5_VABI sceSslGetSerialNumber(int sslCtxId, void* sslCert, unsigned char* sboData, std::size_t* sboLen); +int APS5_VABI sceSslFreeSslCertName(int sslCtxId, void* certName); +int APS5_VABI sceSslEnableVerifyOption(int sslConnectionId, std::uint32_t option); +int APS5_VABI sceSslDisableVerifyOption(int sslConnectionId, std::uint32_t option); +const char* APS5_VABI sceSslGetAlpnSelected(int sslConnectionId); +int APS5_VABI sceSslSetAlpn(int sslConnectionId, const char* proto); +int APS5_VABI sceSslSetMinSslVersion(int sslConnectionId, int version); +void* APS5_VABI sceSslGetIssuerName(int sslCtxId, void* sslCert); +int APS5_VABI sceSslGetNameEntryCount(int sslCtxId, void* certName); +int APS5_VABI sceSslGetNameEntryInfo(int sslCtxId, void* certName, int entryNum, char* oidname, std::size_t maxOidnameLen, char* value, std::size_t maxValueLen, std::size_t* valueLen); +int APS5_VABI sceSslGetNotBefore(int sslCtxId, void* sslCert, SceSsl::RtcTick* begin); +int APS5_VABI sceSslGetNotAfter(int sslCtxId, void* sslCert, SceSsl::RtcTick* limit); +int APS5_VABI sceSslGetFingerprint(int sslCtxId, void* sslCert, int hashType, unsigned char* fingerprint); +int APS5_VABI sceSslGetPem(int sslCtxId, void* sslCert, char* buf, std::size_t* bufLen); +void* APS5_VABI sceSslGetSubjectName(int sslCtxId, void* sslCert); +int APS5_VABI CA_MGMT_extractKeyBlobEx(); +int APS5_VABI CA_MGMT_extractPublicKeyInfo(); +int APS5_VABI CA_MGMT_freeKeyBlob(); +int APS5_VABI CRYPTO_initAsymmetricKey(); +int APS5_VABI CRYPTO_uninitAsymmetricKey(); +int APS5_VABI RSA_verifySignature(); +int APS5_VABI VLONG_freeVlongQueue(); +int APS5_VABI sceSslCheckRecvPending(); +int APS5_VABI sceSslCreateSslConnection(); +int APS5_VABI sceSslDeleteSslConnection(); +int APS5_VABI sceSslDisableOption(); +int APS5_VABI sceSslDisableOptionInternal(); +int APS5_VABI sceSslDisableOptionInternalInsecure(); +int APS5_VABI sceSslEnableOption(); +int APS5_VABI sceSslEnableOptionInternal(); +int APS5_VABI sceSslGetNanoSSLModuleId(); +int APS5_VABI sceSslGetPeerCert(); +int APS5_VABI sceSslGetSslError(); +int APS5_VABI sceSslLoadRootCACert(); +int APS5_VABI sceSslRecv(int sslConnectionId, void* buf, std::size_t fulllen); +int APS5_VABI sceSslReuseConnection(int sslConnectionId, int sockId); +int APS5_VABI sceSslSend(int sslConnectionId, void* msg, std::size_t fulllen); +int APS5_VABI sceSslSetSslVersion(); +int APS5_VABI sceSslSetServerName(); + +} diff --git a/core/libs/prx/libSceSsl/libSceSsl.hpp b/core/libs/prx/libSceSsl/libSceSsl.hpp new file mode 100644 index 0000000000..731f181cb2 --- /dev/null +++ b/core/libs/prx/libSceSsl/libSceSsl.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceSsl/include/Ssl.hpp" diff --git a/core/libs/prx/libSceSulphaDrv/CMakeLists.txt b/core/libs/prx/libSceSulphaDrv/CMakeLists.txt new file mode 100644 index 0000000000..649d75c4d0 --- /dev/null +++ b/core/libs/prx/libSceSulphaDrv/CMakeLists.txt @@ -0,0 +1,15 @@ +add_library(libSceSulphaDrv SHARED EXCLUDE_FROM_ALL Export.cpp) +target_include_directories(libSceSulphaDrv PRIVATE ${LIBS_INCLUDE_DIR}) +configure_windows_unwind(libSceSulphaDrv) + +if(BUILD_TESTING) + add_test_executable(guest_sulpha_config_tests ${LIBS_INCLUDE_DIR}/tests/GuestSulphaConfig.cpp) + target_include_directories(guest_sulpha_config_tests PRIVATE ${LIBS_INCLUDE_DIR}) + target_link_libraries(guest_sulpha_config_tests PRIVATE libSceSulphaDrv libc) + configure_windows_unwind(guest_sulpha_config_tests) + add_test(NAME guest_sulpha_config COMMAND guest_sulpha_config_tests) + if(WIN32) + set_tests_properties(guest_sulpha_config PROPERTIES ENVIRONMENT_MODIFICATION + "PATH=path_list_prepend:$;PATH=path_list_prepend:$") + endif() +endif() diff --git a/core/libs/prx/libSceSulphaDrv/Export.cpp b/core/libs/prx/libSceSulphaDrv/Export.cpp index b956051655..a40021ac2d 100644 --- a/core/libs/prx/libSceSulphaDrv/Export.cpp +++ b/core/libs/prx/libSceSulphaDrv/Export.cpp @@ -1,5 +1,7 @@ +#include "prx/libSceSulphaDrv/include/Api.hpp" #include #include +#include #include "SceTypes.hpp" #include "prx/libc/include/General.hpp" @@ -16,8 +18,10 @@ int APS5_VABI sceSulphaGetConnectedClientCount(void) { return 0; } -int APS5_VABI sceSulphaGetDefaultConfig(void) { - NotImplemented_nid_no_patch(__func__); +int APS5_VABI sceSulphaGetDefaultConfig(void* config) { + if (config == nullptr) return static_cast(0x804D0003u); + static constexpr std::uint64_t defaults[]{24, 0x400000, 0xFA100000003}; + std::memcpy(config, defaults, sizeof(defaults)); return 0; } diff --git a/core/libs/prx/libSceSulphaDrv/include/Api.hpp b/core/libs/prx/libSceSulphaDrv/include/Api.hpp new file mode 100644 index 0000000000..86b1f74a4a --- /dev/null +++ b/core/libs/prx/libSceSulphaDrv/include/Api.hpp @@ -0,0 +1,16 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceSulphaGetClientInfo(void); +int APS5_VABI sceSulphaGetConnectedClientCount(void); +int APS5_VABI sceSulphaGetDefaultConfig(void* config); +int APS5_VABI sceSulphaGetNeededMemory(void); +int APS5_VABI sceSulphaInit(void); +int APS5_VABI sceSulphaMessage(void); +int APS5_VABI sceSulphaSetBookmark(void); +int APS5_VABI sceSulphaShutdown(void); + +} diff --git a/core/libs/prx/libSceSulphaDrv/libSceSulphaDrv.hpp b/core/libs/prx/libSceSulphaDrv/libSceSulphaDrv.hpp new file mode 100644 index 0000000000..1f85062b91 --- /dev/null +++ b/core/libs/prx/libSceSulphaDrv/libSceSulphaDrv.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceSulphaDrv/include/Api.hpp" diff --git a/core/libs/prx/libSceSysBridge/libSceSysBridge.hpp b/core/libs/prx/libSceSysBridge/libSceSysBridge.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceSysBridge/libSceSysBridge.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceSysCore/Export.cpp b/core/libs/prx/libSceSysCore/Export.cpp index de8a605acc..7758a11ed7 100644 --- a/core/libs/prx/libSceSysCore/Export.cpp +++ b/core/libs/prx/libSceSysCore/Export.cpp @@ -1,12 +1,9 @@ +#include "prx/libSceSysCore/include/Api.hpp" #include #include #include "SceTypes.hpp" #include "prx/libc/include/General.hpp" -struct ApplicationInfo { - std::byte data[152]; -}; - static_assert(sizeof(ApplicationInfo) == 152); extern "C" { diff --git a/core/libs/prx/libSceSysCore/include/Api.hpp b/core/libs/prx/libSceSysCore/include/Api.hpp new file mode 100644 index 0000000000..8f3529042c --- /dev/null +++ b/core/libs/prx/libSceSysCore/include/Api.hpp @@ -0,0 +1,85 @@ +#pragma once + +#include "SceTypes.hpp" + +struct ApplicationInfo { + std::byte data[152]; +}; + +extern "C" { + +int APS5_VABI sceApplicationGetAppInfoByAppId(std::uint32_t applicationId, ApplicationInfo* info); + +int APS5_VABI _sceApplicationGetAppId(); +int APS5_VABI sceApplicationAddProcess2(); +int APS5_VABI sceApplicationBeginSclkChange(); +int APS5_VABI sceApplicationBlockingKill2(); +int APS5_VABI sceApplicationBlockingKill3(); +int APS5_VABI sceApplicationContinue(); +int APS5_VABI sceApplicationCrashSyscore(); +int APS5_VABI sceApplicationCrashSystemProcess(); +int APS5_VABI sceApplicationEndSclkChange(); +int APS5_VABI sceApplicationExitSpawn(); +int APS5_VABI sceApplicationExitSpawn2(); +int APS5_VABI sceApplicationFinalize(); +int APS5_VABI sceApplicationGetAppPackageInfoForCoredump(); +int APS5_VABI sceApplicationGetCompiledSdkVersionByAppId(); +int APS5_VABI sceApplicationGetCoredumpDirAndFileName(); +int APS5_VABI sceApplicationGetCoredumpState(); +int APS5_VABI sceApplicationGetCpuUsage(); +int APS5_VABI sceApplicationGetCpuUsage2(); +int APS5_VABI sceApplicationGetDbgExecutablePath(); +int APS5_VABI sceApplicationGetMode(); +int APS5_VABI sceApplicationGetProcs(); +int APS5_VABI sceApplicationGetShellCoreAppId(); +int APS5_VABI sceApplicationGetStateForDebugger(); +int APS5_VABI sceApplicationInitialize(); +int APS5_VABI sceApplicationInitializeForShellCore(); +int APS5_VABI sceApplicationIsCrashReportBeingProcessed(); +int APS5_VABI sceApplicationIsPrimaryProcess(); +int APS5_VABI sceApplicationIsResumable(); +int APS5_VABI sceApplicationIsSuspendable(); +int APS5_VABI sceApplicationKickCoredump(); +int APS5_VABI sceApplicationKickCoredump2(); +int APS5_VABI sceApplicationKill(); +int APS5_VABI sceApplicationLocalProcessKill(); +int APS5_VABI sceApplicationLocalProcessKill2(); +int APS5_VABI sceApplicationLocalProcessResume(); +int APS5_VABI sceApplicationLocalProcessSuspend(); +int APS5_VABI sceApplicationNotifyCoredumpRequestEnd(); +int APS5_VABI sceApplicationNotifyCoredumpRequestProgress(); +int APS5_VABI sceApplicationNotifyVshMainOnStandby(); +int APS5_VABI sceApplicationNotifyVshReady(); +int APS5_VABI sceApplicationOnAllResourceReleased(); +int APS5_VABI sceApplicationRaiseException(); +int APS5_VABI sceApplicationRaiseExceptionToLocalPid(); +int APS5_VABI sceApplicationRaiseExceptionToPid(); +int APS5_VABI sceApplicationRequestToChangeRenderingMode(); +int APS5_VABI sceApplicationRestore(); +int APS5_VABI sceApplicationResume(); +int APS5_VABI sceApplicationSave(); +int APS5_VABI sceApplicationSendDebugSpawnResult2(); +int APS5_VABI sceApplicationSendResultOfDebuggerKillRequest(); +int APS5_VABI sceApplicationSendResultOfDebuggerResumeRequest(); +int APS5_VABI sceApplicationSendResultOfDebuggerSuspendRequest(); +int APS5_VABI sceApplicationSendResultOfDebuggerTitleIdLaunchRequest(); +int APS5_VABI sceApplicationSetApplicationFocus(); +int APS5_VABI sceApplicationSetControllerFocus(); +int APS5_VABI sceApplicationSetControllerFocusPermissionToSubProcess(); +int APS5_VABI sceApplicationSetMemoryPstate(); +int APS5_VABI sceApplicationSignalShellCoreHeartBeat(); +int APS5_VABI sceApplicationSpawn2(); +int APS5_VABI sceApplicationSuspend(); +int APS5_VABI sceApplicationSuspendSystemForDebugger(); +int APS5_VABI sceApplicationSwitchToBaseMode(); +int APS5_VABI sceApplicationSwitchToNeoMode(); +int APS5_VABI sceApplicationSwitchToNeoMode2(); +int APS5_VABI sceApplicationSystemReboot(); +int APS5_VABI sceApplicationSystemShutdown2(); +int APS5_VABI sceApplicationSystemSuspend(); +int APS5_VABI sceApplicationSystemSuspend2(); +int APS5_VABI sceApplictionGetStateForDebugger(); +int APS5_VABI sceSysCoreGetEventCount(); +int APS5_VABI sceSysCoreReceiveEvent(); + +} diff --git a/core/libs/prx/libSceSysCore/libSceSysCore.hpp b/core/libs/prx/libSceSysCore/libSceSysCore.hpp new file mode 100644 index 0000000000..c0d6d0db48 --- /dev/null +++ b/core/libs/prx/libSceSysCore/libSceSysCore.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceSysCore/include/Api.hpp" diff --git a/core/libs/prx/libSceSysUtil/Export.cpp b/core/libs/prx/libSceSysUtil/Export.cpp index 6ff461210b..a6f707cd6e 100644 --- a/core/libs/prx/libSceSysUtil/Export.cpp +++ b/core/libs/prx/libSceSysUtil/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceSysUtil/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceSysUtil/include/Api.hpp b/core/libs/prx/libSceSysUtil/include/Api.hpp new file mode 100644 index 0000000000..f07cd4a9b9 --- /dev/null +++ b/core/libs/prx/libSceSysUtil/include/Api.hpp @@ -0,0 +1,32 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceSysUtilSendSystemNotificationWithText(int32_t type, const char* message); +int APS5_VABI sceSysUtilSendAddressingSystemNotification(); +int APS5_VABI sceSysUtilSendAddressingSystemNotificationWithDeviceId(); +int APS5_VABI sceSysUtilSendAddressingSystemNotificationWithUserId(); +int APS5_VABI sceSysUtilSendAddressingSystemNotificationWithUserName(); +int APS5_VABI sceSysUtilSendNotificationRequest(); +int APS5_VABI sceSysUtilSendNpDebugNotificationRequest(); +int APS5_VABI sceSysUtilSendSystemNotification(); +int APS5_VABI sceSysUtilSendSystemNotification2(); +int APS5_VABI sceSysUtilSendSystemNotificationParamInit(); +int APS5_VABI sceSysUtilSendSystemNotificationWithAppId(); +int APS5_VABI sceSysUtilSendSystemNotificationWithAppInfo(); +int APS5_VABI sceSysUtilSendSystemNotificationWithAppName(); +int APS5_VABI sceSysUtilSendSystemNotificationWithAppNameRelatedToUser(); +int APS5_VABI sceSysUtilSendSystemNotificationWithDeviceId(); +int APS5_VABI sceSysUtilSendSystemNotificationWithDeviceIdRelatedToUser(); +int APS5_VABI sceSysUtilSendSystemNotificationWithErrorCode(); +int APS5_VABI sceSysUtilSendSystemNotificationWithParams(); +int APS5_VABI sceSysUtilSendSystemNotificationWithTextRelatedToUser(); +int APS5_VABI sceSysUtilSendSystemNotificationWithUserId(); +int APS5_VABI sceSysUtilSendSystemNotificationWithUserName(); +int APS5_VABI sceSysUtilSendSystemNotificationWithUserNameInfo(); +int APS5_VABI sceSysUtilSendTrcCheckNotificationRequest(); +int APS5_VABI sceSysUtilSendWebDebugNotificationRequest(); + +} diff --git a/core/libs/prx/libSceSysUtil/libSceSysUtil.hpp b/core/libs/prx/libSceSysUtil/libSceSysUtil.hpp new file mode 100644 index 0000000000..15c98b717c --- /dev/null +++ b/core/libs/prx/libSceSysUtil/libSceSysUtil.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceSysUtil/include/Api.hpp" diff --git a/core/libs/prx/libSceSysmodule/Export.cpp b/core/libs/prx/libSceSysmodule/Export.cpp index 78b4774cfa..272768fe00 100644 --- a/core/libs/prx/libSceSysmodule/Export.cpp +++ b/core/libs/prx/libSceSysmodule/Export.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libSceSysmodule/include/Api.hpp" #include #include #include @@ -17,8 +19,6 @@ #include "ModuleTable.hpp" #include "prx/libc/include/General.hpp" -extern "C" void* APS5_VABI dlopen_nid_postfix(const char* path, int flags); - namespace { constexpr int SCE_SYSMODULE_ERROR_INVALID_VALUE = static_cast(0x805A1000); diff --git a/core/libs/prx/libSceSysmodule/include/Api.hpp b/core/libs/prx/libSceSysmodule/include/Api.hpp new file mode 100644 index 0000000000..db439f37b3 --- /dev/null +++ b/core/libs/prx/libSceSysmodule/include/Api.hpp @@ -0,0 +1,24 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceSysmoduleGetModuleInfoForUnwind(std::uint64_t addr, int flags, ModuleInfoForUnwind* info); +int APS5_VABI sceSysmoduleGetModuleHandleInternal(std::uint32_t id, std::int32_t* handle); +int APS5_VABI sceSysmoduleIsLoaded(std::uint16_t id); +int APS5_VABI sceSysmoduleLoadModule(std::uint16_t id); +int APS5_VABI sceSysmoduleLoadModuleInternalWithArg(std::uint32_t id, int argc, void* argv, std::uint64_t unk, int* ret); +int APS5_VABI sceSysmoduleUnloadModule(std::uint16_t id); +int APS5_VABI sceSysmoduleLoadModuleInternal(std::uint32_t id); +int APS5_VABI sceSysmoduleUnloadModuleInternal(std::uint32_t id); +int APS5_VABI sceSysmoduleUnloadModuleInternalWithArg(std::uint32_t id, int argc, void* argv, std::uint64_t unk, int* ret); +int APS5_VABI sceSysmoduleIsLoadedInternal(std::uint32_t id); +int APS5_VABI sceSysmoduleIsCalledFromSysModule(); +int APS5_VABI sceSysmoduleIsCameraPreloaded(); +int APS5_VABI sceSysmoduleLoadModuleByNameInternal(std::uint8_t* fname, std::uint64_t a1, std::uint64_t a2, std::uint64_t a3, std::uint64_t a4, std::uint64_t a5); +int APS5_VABI sceSysmoduleMapLibcForLibkernel(); +int APS5_VABI sceSysmodulePreloadModuleForLibkernel(); +int APS5_VABI sceSysmoduleUnloadModuleByNameInternal(); + +} diff --git a/core/libs/prx/libSceSysmodule/libSceSysmodule.hpp b/core/libs/prx/libSceSysmodule/libSceSysmodule.hpp new file mode 100644 index 0000000000..235f65eecc --- /dev/null +++ b/core/libs/prx/libSceSysmodule/libSceSysmodule.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceSysmodule/include/Api.hpp" diff --git a/core/libs/prx/libSceSystemGesture/Export.cpp b/core/libs/prx/libSceSystemGesture/Export.cpp index 5e1fb249e6..056318a3a4 100644 --- a/core/libs/prx/libSceSystemGesture/Export.cpp +++ b/core/libs/prx/libSceSystemGesture/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceSystemGesture/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceSystemGesture/include/Api.hpp b/core/libs/prx/libSceSystemGesture/include/Api.hpp new file mode 100644 index 0000000000..ef1667c91e --- /dev/null +++ b/core/libs/prx/libSceSystemGesture/include/Api.hpp @@ -0,0 +1,31 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceSystemGestureAppendTouchRecognizer(int32_t gestureHandle, SystemGestureTouchRecognizer* recognizer); +int APS5_VABI sceSystemGestureClose(int32_t gestureHandle); +int APS5_VABI sceSystemGestureCreateTouchRecognizer(int32_t gestureHandle, SystemGestureTouchRecognizer* recognizer, int32_t type, const SystemGestureRectangle* rectangle, const void* param); +int APS5_VABI sceSystemGestureFinalizePrimitiveTouchRecognizer(void); +int APS5_VABI sceSystemGestureGetPrimitiveTouchEventByIndex(int32_t gestureHandle, uint32_t index, SystemGesturePrimitiveTouchEvent* event); +int APS5_VABI sceSystemGestureGetPrimitiveTouchEventByPrimitiveID(int32_t gestureHandle, uint16_t primitiveId, SystemGesturePrimitiveTouchEvent* event); +int APS5_VABI sceSystemGestureGetPrimitiveTouchEvents(int32_t gestureHandle, SystemGesturePrimitiveTouchEvent* eventBuffer, uint32_t capacityOfBuffer, uint32_t* numberOfEvent); +int APS5_VABI sceSystemGestureGetPrimitiveTouchEventsCount(int32_t gestureHandle); +int APS5_VABI sceSystemGestureGetTouchEventByEventID(int32_t gestureHandle, const SystemGestureTouchRecognizer* recognizer, uint32_t eventId, SystemGestureTouchEvent* event); +int APS5_VABI sceSystemGestureGetTouchEventByIndex(int32_t gestureHandle, const SystemGestureTouchRecognizer* recognizer, uint32_t index, SystemGestureTouchEvent* event); +int APS5_VABI sceSystemGestureGetTouchEvents(int32_t gestureHandle, const SystemGestureTouchRecognizer* recognizer, SystemGestureTouchEvent* eventBuffer, uint32_t capacityOfBuffer, uint32_t* numberOfEvent); +int APS5_VABI sceSystemGestureGetTouchEventsCount(int32_t gestureHandle, const SystemGestureTouchRecognizer* recognizer); +int APS5_VABI sceSystemGestureGetTouchRecognizerInformation(int32_t gestureHandle, const SystemGestureTouchRecognizer* recognizer, SystemGestureTouchRecognizerInformation* information); +int APS5_VABI sceSystemGestureInitializePrimitiveTouchRecognizer(); +int32_t APS5_VABI sceSystemGestureOpen(int32_t inputType, const void* param); +int APS5_VABI sceSystemGestureRemoveTouchRecognizer(int32_t gestureHandle, SystemGestureTouchRecognizer* recognizer); +int APS5_VABI sceSystemGestureResetPrimitiveTouchRecognizer(int32_t gestureHandle); +int APS5_VABI sceSystemGestureResetTouchRecognizer(int32_t gestureHandle, SystemGestureTouchRecognizer* recognizer); +int APS5_VABI sceSystemGestureUpdateAllTouchRecognizer(int32_t gestureHandle); +int APS5_VABI sceSystemGestureUpdatePrimitiveTouchRecognizer(int32_t gestureHandle, const SystemGestureTouchPadData* input); +int APS5_VABI sceSystemGestureUpdateTouchRecognizer(int32_t gestureHandle, SystemGestureTouchRecognizer* recognizer); +int APS5_VABI sceSystemGestureUpdateTouchRecognizerRectangle(int32_t gestureHandle, SystemGestureTouchRecognizer* recognizer, const SystemGestureRectangle* rectangle); +int APS5_VABI sceSystemGestureDebugGetVersion(); + +} diff --git a/core/libs/prx/libSceSystemGesture/libSceSystemGesture.hpp b/core/libs/prx/libSceSystemGesture/libSceSystemGesture.hpp new file mode 100644 index 0000000000..1e6ac94f6a --- /dev/null +++ b/core/libs/prx/libSceSystemGesture/libSceSystemGesture.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceSystemGesture/include/Api.hpp" diff --git a/core/libs/prx/libSceSystemLogger/Export.cpp b/core/libs/prx/libSceSystemLogger/Export.cpp index 0b82cdf1e0..ebad08c6b3 100644 --- a/core/libs/prx/libSceSystemLogger/Export.cpp +++ b/core/libs/prx/libSceSystemLogger/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceSystemLogger/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceSystemLogger/include/Api.hpp b/core/libs/prx/libSceSystemLogger/include/Api.hpp new file mode 100644 index 0000000000..d5e47a68e5 --- /dev/null +++ b/core/libs/prx/libSceSystemLogger/include/Api.hpp @@ -0,0 +1,11 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceSystemLoggerInitialize(); +int APS5_VABI sceSystemLoggerSetLogData(); +int APS5_VABI sceSystemLoggerTerminate(); + +} diff --git a/core/libs/prx/libSceSystemLogger/libSceSystemLogger.hpp b/core/libs/prx/libSceSystemLogger/libSceSystemLogger.hpp new file mode 100644 index 0000000000..e47ab854c6 --- /dev/null +++ b/core/libs/prx/libSceSystemLogger/libSceSystemLogger.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceSystemLogger/include/Api.hpp" diff --git a/core/libs/prx/libSceSystemLogger2/Export.cpp b/core/libs/prx/libSceSystemLogger2/Export.cpp index 82a408b187..860ef63046 100644 --- a/core/libs/prx/libSceSystemLogger2/Export.cpp +++ b/core/libs/prx/libSceSystemLogger2/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceSystemLogger2/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceSystemLogger2/include/Api.hpp b/core/libs/prx/libSceSystemLogger2/include/Api.hpp new file mode 100644 index 0000000000..4b8e19eaf0 --- /dev/null +++ b/core/libs/prx/libSceSystemLogger2/include/Api.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceSystemLogger2GetTimestamp(); +int APS5_VABI sceSystemLogger2Initialize(); +int APS5_VABI sceSystemLogger2SetEventAsync(); +int APS5_VABI sceSystemLogger2SetEventAsyncEx(); +int APS5_VABI sceSystemLogger2Terminate(); + +} diff --git a/core/libs/prx/libSceSystemLogger2/libSceSystemLogger2.hpp b/core/libs/prx/libSceSystemLogger2/libSceSystemLogger2.hpp new file mode 100644 index 0000000000..931a124f24 --- /dev/null +++ b/core/libs/prx/libSceSystemLogger2/libSceSystemLogger2.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceSystemLogger2/include/Api.hpp" diff --git a/core/libs/prx/libSceSystemLogger2Delivery/Export.cpp b/core/libs/prx/libSceSystemLogger2Delivery/Export.cpp index a071ef1bed..c01af333e1 100644 --- a/core/libs/prx/libSceSystemLogger2Delivery/Export.cpp +++ b/core/libs/prx/libSceSystemLogger2Delivery/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceSystemLogger2Delivery/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceSystemLogger2Delivery/include/Api.hpp b/core/libs/prx/libSceSystemLogger2Delivery/include/Api.hpp new file mode 100644 index 0000000000..c0263701f7 --- /dev/null +++ b/core/libs/prx/libSceSystemLogger2Delivery/include/Api.hpp @@ -0,0 +1,12 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceSystemLogger2DeliveryGetBatchResult(); +int APS5_VABI sceSystemLogger2DeliveryGetResult(); +int APS5_VABI sceSystemLogger2DeliverySetBatchDeliveryEvent(); +int APS5_VABI sceSystemLogger2DeliveryTerminate(); + +} diff --git a/core/libs/prx/libSceSystemLogger2Delivery/libSceSystemLogger2Delivery.hpp b/core/libs/prx/libSceSystemLogger2Delivery/libSceSystemLogger2Delivery.hpp new file mode 100644 index 0000000000..e91f676c51 --- /dev/null +++ b/core/libs/prx/libSceSystemLogger2Delivery/libSceSystemLogger2Delivery.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceSystemLogger2Delivery/include/Api.hpp" diff --git a/core/libs/prx/libSceSystemLogger2Game/libSceSystemLogger2Game.hpp b/core/libs/prx/libSceSystemLogger2Game/libSceSystemLogger2Game.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceSystemLogger2Game/libSceSystemLogger2Game.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceSystemLogger2NativeQueueClient/Export.cpp b/core/libs/prx/libSceSystemLogger2NativeQueueClient/Export.cpp index 1087fa235d..ae54608dbe 100644 --- a/core/libs/prx/libSceSystemLogger2NativeQueueClient/Export.cpp +++ b/core/libs/prx/libSceSystemLogger2NativeQueueClient/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceSystemLogger2NativeQueueClient/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceSystemLogger2NativeQueueClient/include/Api.hpp b/core/libs/prx/libSceSystemLogger2NativeQueueClient/include/Api.hpp new file mode 100644 index 0000000000..3631a92feb --- /dev/null +++ b/core/libs/prx/libSceSystemLogger2NativeQueueClient/include/Api.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceSystemLogger2NativeQueueClientCheckAndMaskData(); +int APS5_VABI sceSystemLogger2NativeQueueClientGetEvent(); +int APS5_VABI sceSystemLogger2NativeQueueClientSetDeliveryEnable(); +int APS5_VABI sceSystemLogger2NativeQueueClientSetDeliveryResult(); +int APS5_VABI sceSystemLogger2NativeQueueClientSetNativeQueueConfig(); + +} diff --git a/core/libs/prx/libSceSystemLogger2NativeQueueClient/libSceSystemLogger2NativeQueueClient.hpp b/core/libs/prx/libSceSystemLogger2NativeQueueClient/libSceSystemLogger2NativeQueueClient.hpp new file mode 100644 index 0000000000..50e859ed9d --- /dev/null +++ b/core/libs/prx/libSceSystemLogger2NativeQueueClient/libSceSystemLogger2NativeQueueClient.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceSystemLogger2NativeQueueClient/include/Api.hpp" diff --git a/core/libs/prx/libSceSystemService/Export.cpp b/core/libs/prx/libSceSystemService/Export.cpp index 64d0bf5dc1..0b9e30b645 100644 --- a/core/libs/prx/libSceSystemService/Export.cpp +++ b/core/libs/prx/libSceSystemService/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceSystemService/include/SystemService.hpp" #include #include #include @@ -422,14 +423,6 @@ int APS5_VABI sceSystemServiceOpenChallengeActivity(void) { return SYSTEM_SERVICE_OK; } -struct SystemServiceTournamentOccurrenceParam { - std::uint64_t size; - const char* occurrenceId; - std::int32_t userId; - std::uint32_t padding; - const char* context; -}; - static_assert(sizeof(SystemServiceTournamentOccurrenceParam) == 32); static_assert(offsetof(SystemServiceTournamentOccurrenceParam, occurrenceId) == 8); static_assert(offsetof(SystemServiceTournamentOccurrenceParam, userId) == 16); diff --git a/core/libs/prx/libSceSystemService/PendingExports.cpp b/core/libs/prx/libSceSystemService/PendingExports.cpp index 85bb9527ea..d2b7fca08e 100644 --- a/core/libs/prx/libSceSystemService/PendingExports.cpp +++ b/core/libs/prx/libSceSystemService/PendingExports.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceSystemService/include/SystemService.hpp" #include "prx/libc/include/General.hpp" namespace { @@ -7,72 +8,22 @@ constexpr int SystemServiceRejected = static_cast(0x80A10005); } -struct ShellCoreErrorDialogParam { - const char* message; - const char* const* formatArgs; - std::uint8_t flag; -}; - static_assert(sizeof(ShellCoreErrorDialogParam) == 24); static_assert(offsetof(ShellCoreErrorDialogParam, message) == 0); static_assert(offsetof(ShellCoreErrorDialogParam, formatArgs) == 8); static_assert(offsetof(ShellCoreErrorDialogParam, flag) == 16); -struct SystemServiceDaemonEvent; -struct SystemServiceLocalProcessStatus; struct SystemServiceEvent; -struct SystemServicePSButtonEvent; -struct SystemServicePrivacyDefinitionData; -struct SystemServicePrivacyDefinitionVersion; -struct SystemServiceTitleWorkaroundInfo; -struct SystemServiceStoreParam { - std::uint32_t size; -}; static_assert(sizeof(SystemServiceStoreParam) == 4); -struct SystemServiceCpuPstateParam; -struct SystemServiceLocalProcessParam; -struct SystemServiceJvmProcessParam; -struct SystemServicePs2ProcessParam; -struct SystemServiceAppInstallStatus; -struct SystemServiceAppStatus; -struct ShellCoreLaunchByUriParam { - std::uint32_t option; - std::int32_t userId; -}; - static_assert(sizeof(ShellCoreLaunchByUriParam) == 8); static_assert(offsetof(ShellCoreLaunchByUriParam, option) == 0); static_assert(offsetof(ShellCoreLaunchByUriParam, userId) == 4); -struct ShellCoreTelemetryToken; -struct ShellCoreUmmStatus { - std::int32_t state; - std::int32_t inDeviceMuteState; -}; static_assert(sizeof(ShellCoreUmmStatus) == 8); static_assert(offsetof(ShellCoreUmmStatus, state) == 0); static_assert(offsetof(ShellCoreUmmStatus, inDeviceMuteState) == 4); -struct ShellCorePbtcUserInfoList; -struct ShellCorePrivacyEventData; -struct ShellCorePsnAccountInfoFirst; -struct ShellCorePsnAccountInfoSecond; -struct ShellCorePsnAccountInfoThird; -struct ShellCorePsnAccountInfoFourth; -struct ShellCorePsnAccountInfoFifth; -struct ShellCoreAppLaunchTypeInfo; -struct LncGpuCrashAppStatus { - char titleId[16]; - std::int32_t appId; - std::int32_t appLocalPid; - char path[1024]; - std::int32_t appType; - std::int32_t coredumpReason; - char corefileName[256]; - std::uint32_t exceptionCode; - std::uint32_t appCategoryType; -}; static_assert(sizeof(LncGpuCrashAppStatus) == 1320); static_assert(offsetof(LncGpuCrashAppStatus, titleId) == 0); @@ -84,15 +35,6 @@ static_assert(offsetof(LncGpuCrashAppStatus, coredumpReason) == 1052); static_assert(offsetof(LncGpuCrashAppStatus, corefileName) == 1056); static_assert(offsetof(LncGpuCrashAppStatus, exceptionCode) == 1312); static_assert(offsetof(LncGpuCrashAppStatus, appCategoryType) == 1316); -struct LncLaunchParam { - std::uint32_t size; - std::int32_t userId; - std::int32_t appAttr; - std::int32_t enableCrashReport; - std::uint64_t checkFlag; - std::uint64_t contextId; - bool isSpeculativeLaunch; -}; static_assert(sizeof(LncLaunchParam) == 40); static_assert(offsetof(LncLaunchParam, size) == 0); @@ -102,49 +44,19 @@ static_assert(offsetof(LncLaunchParam, enableCrashReport) == 12); static_assert(offsetof(LncLaunchParam, checkFlag) == 16); static_assert(offsetof(LncLaunchParam, contextId) == 24); static_assert(offsetof(LncLaunchParam, isSpeculativeLaunch) == 32); -struct LncDaemonEvent; -struct LncShellUiEvent; -struct LncLocalProcessStatus { - std::int32_t appLocalPid; - std::uint8_t reserved[32]; -}; static_assert(sizeof(LncLocalProcessStatus) == 36); static_assert(offsetof(LncLocalProcessStatus, appLocalPid) == 0); static_assert(offsetof(LncLocalProcessStatus, reserved) == 4); -struct LncCoredumpState { - std::uint32_t progress; - std::uint32_t isFinished; - std::int32_t result; -}; static_assert(sizeof(LncCoredumpState) == 12); static_assert(offsetof(LncCoredumpState, progress) == 0); static_assert(offsetof(LncCoredumpState, isFinished) == 4); static_assert(offsetof(LncCoredumpState, result) == 8); -struct LncVideoFinalizeState { - std::uint32_t progress; - std::int32_t result; -}; static_assert(sizeof(LncVideoFinalizeState) == 8); static_assert(offsetof(LncVideoFinalizeState, progress) == 0); static_assert(offsetof(LncVideoFinalizeState, result) == 4); -struct LncLocalProcessParam; -struct LncAppStatus { - std::int32_t appId; - std::int32_t launchRequestAppId; - std::int32_t appType; - std::int32_t appAttr; - char titleId[16]; - std::uint32_t appCategoryType; - std::int32_t appBootMode; - std::int32_t appBootSubMode; - char appVer[6]; - char contentVersion[11]; - bool isSystemExApp; - bool isCdlgInitialized; -}; static_assert(sizeof(LncAppStatus) == 64); static_assert(offsetof(LncAppStatus, appId) == 0); @@ -159,24 +71,6 @@ static_assert(offsetof(LncAppStatus, appVer) == 44); static_assert(offsetof(LncAppStatus, contentVersion) == 50); static_assert(offsetof(LncAppStatus, isSystemExApp) == 61); static_assert(offsetof(LncAppStatus, isCdlgInitialized) == 62); -struct LncShellUiAppStatus { - std::int32_t appId; - std::int32_t appType; - std::int32_t appAttr; - std::int32_t launchRequestAppId; - std::int32_t userId; - std::int32_t isActiveCdlg; - char path[1024]; - char sceSysDir[256]; - std::int32_t isCoredumped; - std::int32_t isPrxModuleLoadFailed; - std::int32_t appLocalPid; - std::int32_t crashReportMode; - char category[4]; - std::uint32_t appCategoryType; - std::int32_t appBootMode; - std::int32_t appBootSubMode; -}; static_assert(sizeof(LncShellUiAppStatus) == 1336); static_assert(offsetof(LncShellUiAppStatus, appId) == 0); @@ -195,13 +89,6 @@ static_assert(offsetof(LncShellUiAppStatus, category) == 1320); static_assert(offsetof(LncShellUiAppStatus, appCategoryType) == 1324); static_assert(offsetof(LncShellUiAppStatus, appBootMode) == 1328); static_assert(offsetof(LncShellUiAppStatus, appBootSubMode) == 1332); -struct AppMessagingMessage { - std::int32_t sender; - std::uint32_t messageType; - std::uint8_t payload[8192]; - std::uint32_t payloadSize; - std::uint64_t timestamp; -}; static_assert(sizeof(AppMessagingMessage) == 8216); static_assert(offsetof(AppMessagingMessage, sender) == 0); @@ -210,10 +97,6 @@ static_assert(offsetof(AppMessagingMessage, payload) == 8); static_assert(offsetof(AppMessagingMessage, payloadSize) == 8200); static_assert(offsetof(AppMessagingMessage, timestamp) == 8208); -struct UsbStorageEvent; -struct UsbStorageDeviceInfo; -using UsbStorageCallback = void (APS5_VABI *)(const UsbStorageEvent* event, void* userData); - extern "C" { int APS5_VABI sceAppMessagingClearEventFlag(std::int32_t appId, std::uint64_t flags) { diff --git a/core/libs/prx/libSceSystemService/include/SystemService.hpp b/core/libs/prx/libSceSystemService/include/SystemService.hpp new file mode 100644 index 0000000000..6c0120e66b --- /dev/null +++ b/core/libs/prx/libSceSystemService/include/SystemService.hpp @@ -0,0 +1,732 @@ +#pragma once + +#include "prx/libSceUsbStorage/UsbStorage.hpp" + +#include "SceTypes.hpp" + +struct SystemServiceTournamentOccurrenceParam { + std::uint64_t size; + const char* occurrenceId; + std::int32_t userId; + std::uint32_t padding; + const char* context; +}; + +struct ShellCoreErrorDialogParam { + const char* message; + const char* const* formatArgs; + std::uint8_t flag; +}; + +struct SystemServiceDaemonEvent; +struct SystemServiceLocalProcessStatus; +struct SystemServicePSButtonEvent; +struct SystemServicePrivacyDefinitionData; +struct SystemServicePrivacyDefinitionVersion; +struct SystemServiceTitleWorkaroundInfo; + +struct SystemServiceStoreParam { + std::uint32_t size; +}; + +struct SystemServiceCpuPstateParam; +struct SystemServiceLocalProcessParam; +struct SystemServiceJvmProcessParam; +struct SystemServicePs2ProcessParam; +struct SystemServiceAppInstallStatus; +struct SystemServiceAppStatus; + +struct ShellCoreLaunchByUriParam { + std::uint32_t option; + std::int32_t userId; +}; + +struct ShellCoreTelemetryToken; + +struct ShellCoreUmmStatus { + std::int32_t state; + std::int32_t inDeviceMuteState; +}; + +struct ShellCorePbtcUserInfoList; +struct ShellCorePrivacyEventData; +struct ShellCorePsnAccountInfoFirst; +struct ShellCorePsnAccountInfoSecond; +struct ShellCorePsnAccountInfoThird; +struct ShellCorePsnAccountInfoFourth; +struct ShellCorePsnAccountInfoFifth; +struct ShellCoreAppLaunchTypeInfo; + +struct LncGpuCrashAppStatus { + char titleId[16]; + std::int32_t appId; + std::int32_t appLocalPid; + char path[1024]; + std::int32_t appType; + std::int32_t coredumpReason; + char corefileName[256]; + std::uint32_t exceptionCode; + std::uint32_t appCategoryType; +}; + +struct LncLaunchParam { + std::uint32_t size; + std::int32_t userId; + std::int32_t appAttr; + std::int32_t enableCrashReport; + std::uint64_t checkFlag; + std::uint64_t contextId; + bool isSpeculativeLaunch; +}; + +struct LncDaemonEvent; +struct LncShellUiEvent; + +struct LncLocalProcessStatus { + std::int32_t appLocalPid; + std::uint8_t reserved[32]; +}; + +struct LncCoredumpState { + std::uint32_t progress; + std::uint32_t isFinished; + std::int32_t result; +}; + +struct LncVideoFinalizeState { + std::uint32_t progress; + std::int32_t result; +}; + +struct LncLocalProcessParam; + +struct LncAppStatus { + std::int32_t appId; + std::int32_t launchRequestAppId; + std::int32_t appType; + std::int32_t appAttr; + char titleId[16]; + std::uint32_t appCategoryType; + std::int32_t appBootMode; + std::int32_t appBootSubMode; + char appVer[6]; + char contentVersion[11]; + bool isSystemExApp; + bool isCdlgInitialized; +}; + +struct LncShellUiAppStatus { + std::int32_t appId; + std::int32_t appType; + std::int32_t appAttr; + std::int32_t launchRequestAppId; + std::int32_t userId; + std::int32_t isActiveCdlg; + char path[1024]; + char sceSysDir[256]; + std::int32_t isCoredumped; + std::int32_t isPrxModuleLoadFailed; + std::int32_t appLocalPid; + std::int32_t crashReportMode; + char category[4]; + std::uint32_t appCategoryType; + std::int32_t appBootMode; + std::int32_t appBootSubMode; +}; + +struct AppMessagingMessage { + std::int32_t sender; + std::uint32_t messageType; + std::uint8_t payload[8192]; + std::uint32_t payloadSize; + std::uint64_t timestamp; +}; + +extern "C" { + +int APS5_VABI sceSystemServiceLoadExec(const char* path, const char* const* arguments); +int APS5_VABI sceSystemServiceDisableNoticeScreenSkipFlagAutoSet(void); +int APS5_VABI sceSystemServiceGetDisplaySafeAreaInfo(SystemServiceDisplaySafeAreaInfo* info); +int APS5_VABI sceSystemServiceShowDisplaySafeAreaSettings(void); +int APS5_VABI sceSystemServiceGetHdrToneMapLuminance(SystemServiceHdrToneMapLuminance* luminance); +int APS5_VABI sceSystemServiceGetNoticeScreenSkipFlag(bool* value); +int APS5_VABI sceSystemServiceGetStatus(SystemServiceStatus* status); +int APS5_VABI sceSystemServiceHideSplashScreen(void); +int APS5_VABI sceSystemServiceParamGetInt(int paramId, int* value); +int APS5_VABI sceSystemServiceParamGetString(int paramId, char* buf, size_t bufSize); +int APS5_VABI sceSystemServicePowerTick(void); +int APS5_VABI sceSystemServiceReceiveEvent(SystemServiceEvent* event); +int APS5_VABI sceSystemServiceReportAbnormalTermination(const void* info); +int APS5_VABI sceSystemServiceSetNoticeScreenSkipFlag(void); +void APS5_VABI sceSystemServiceInitializePlayerDialogParam(SystemServicePlayerDialogParam* param); +int APS5_VABI sceSystemServiceDisableMediaPlay(); +int APS5_VABI sceSystemServiceReenableMediaPlay(); +int APS5_VABI sceSystemServiceLaunchPlayerDialog(const void* param); +int APS5_VABI sceSystemServiceLaunchWebBrowser(const char* uri); +int APS5_VABI sceSystemServiceLaunchApp(const char* titleId, const char* const* arguments, const void* param); +int APS5_VABI sceSystemServiceDisableMusicPlayer(void); +int APS5_VABI sceSystemServiceOpenChallengeActivity(void); +int APS5_VABI sceSystemServiceOpenTournamentOccurrence(const SystemServiceTournamentOccurrenceParam* param); +int APS5_VABI sceSystemServiceAddLocalProcessForPsmKit(const char*, const char* const*, const void*); +int APS5_VABI sceSystemServiceKillLocalProcessForPsmKit(int); +int APS5_VABI sceSystemServiceReenableMusicPlayer(void); +int APS5_VABI sceSystemServiceShowControllerSettings(void); +int APS5_VABI sceSystemServiceGetAppIdOfRunningBigApp(void); +int APS5_VABI sceSystemServiceKillApp(int appId, int how, int reason, int coreDump); +int APS5_VABI sceLncUtilKillApp(uint32_t appId); +int APS5_VABI sceLncUtilKillAppWithReason(uint32_t appId, int reason); +int APS5_VABI sceSystemServiceLaunchSystemDeeplink(void); +int APS5_VABI sceShellCoreUtilLaunchByUriParamInit(void); +int APS5_VABI sceSystemStateMgrTickVideoPlayback(void); +int APS5_VABI sceSystemServiceTelemetrySetData2WithUserId(void); +int APS5_VABI sceShellCoreUtilStartUmmDictation(void); +int APS5_VABI sceSystemServiceGetSpotifyTitleId(void); +int APS5_VABI sceSystemServiceGetAppStatusListContainsDaemon(void); +int APS5_VABI sceSystemServiceSwitchToVRApp(void); +int APS5_VABI sceSystemServiceSwitchToNonVRApp(void); +int APS5_VABI sceLncUtilGetSpmemAllocatorConfigValue(void); +int APS5_VABI sceCsbMgrInitialize(void); +int APS5_VABI sceCsbMgrTerminate(void); +int APS5_VABI sceCsbMgrCreateLocalSandbox(void); +int APS5_VABI sceCsbMgrDestroyLocalSandbox(void); +int APS5_VABI sceCsbMgrSwitchLocalSandbox(void); +int APS5_VABI sceCsbMgrGetCurrentLocalSandboxId(void); +int APS5_VABI sceCsbMgrGetLocalSandboxIdList(void); +int APS5_VABI sceCsbMgrGetLocalSandboxInfo(void); +int APS5_VABI sceCsbMgrSetLocalSandboxInfo(void); +int APS5_VABI sceCsbMgrIssueStreamingSandboxInfo(void); +int APS5_VABI sceReportSequenceHandlerRequestReport(void); +int APS5_VABI sceReportSequenceHandlerCancelReport(void); +int APS5_VABI sceReportSequenceHandlerExistsEvent(void); +int APS5_VABI sceReportSequenceHandlerUpdateEventCache(void); +int APS5_VABI sceReportSequenceHandlerGetEventCache(void); +int APS5_VABI sceLncUtilRegisterCallEntries(void); +int APS5_VABI sceLncUtilGetSpmemConfigJson(void); +int APS5_VABI sceLncUtilExportSpmemConfigJson(void); +int APS5_VABI sceLncUtilImportSpmemConfigJson(void); +int APS5_VABI sceShellCoreUtilExitAppWithValue(void); +int APS5_VABI sceShellCoreUtilNpDebugSpecialNotification(void); +int APS5_VABI sceShellCoreUtilIsDddTemperatureDanger(void); +int APS5_VABI sceShellCoreUtilIsM2StorageTemperatureDanger(void); +int APS5_VABI sceShellCoreUtilGetAvailableSizeM2(void); +int APS5_VABI sceShellCoreUtilNotifyConnectAccountStatusChanged(void); +int APS5_VABI sceShellCoreUtilIsInternalCronosUser(void); +int APS5_VABI sceShellCoreUtilChangePbtcMode(void); +int APS5_VABI sceShellCoreUtilTelemetryCacheData(void); +int APS5_VABI sceShellCoreUtilMicMuteKeyPressed(void); +int APS5_VABI sceShellCoreUtilSwitchMicMute(void); +int APS5_VABI sceShellCoreUtilNotifyStartEventToUniversalMicMute(void); +int APS5_VABI sceShellCoreUtilIsLotusMicActivated(void); +int APS5_VABI sceShellCoreUtilResetAllNoticeScreenSkipFlag(void); +int APS5_VABI sceShellCoreUtilResetNoticeScreenSkipFlag(void); +int APS5_VABI sceShellCoreUtilGetNoticeScreenSkipFlagByAppId(void); +int APS5_VABI sceShellCoreUtilGetPasscodeInputType(void); +int APS5_VABI sceShellCoreUtilGetPasscodeDisplayInfo(void); +int APS5_VABI sceShellCoreUtilNotifySystemResumeTelemetryInfo(void); +int APS5_VABI sceShellCoreUtilUpdateTelemetryToken(void); +int APS5_VABI sceShellCoreUtilGetVRBaseMatRectangles(void); +int APS5_VABI sceShellCoreUtilSetVRBaseMatRectangles(void); +int APS5_VABI sceShellCoreUtilIsLaunchBlockDialog(void); +int APS5_VABI sceShellCoreUtilGetConsoleToken(void); +int APS5_VABI sceShellCoreUtilGetDeviceIdByDeviceUniqueId(void); +int APS5_VABI sceShellCoreUtilGetDeviceUniqueIdByDeviceId(void); +int APS5_VABI sceShellCoreUtilGetStreamingClientInfo(void); +int APS5_VABI sceShellCoreUtilRequestCffUpdate(void); +int APS5_VABI sceShellCoreUtilGetCffConfig(void); +int APS5_VABI sceShellCoreUtilRemoveCffConfigFile(void); +int APS5_VABI sceShellCoreUtilDebugGetNumberOfCffItems(void); +int APS5_VABI sceShellCoreUtilDebugGetCffInfo(void); +int APS5_VABI sceShellCoreUtilDebugSetCffStatus(void); +int APS5_VABI sceShellCoreUtilGetPeripheralConnectionSessionId(void); +int APS5_VABI sceShellCoreUtilGetCdlgEnabledFreezeRendering(void); +int APS5_VABI sceShellCoreUtilGetNpTitleId(void); +int APS5_VABI sceShellCoreUtilIsCronosInGameCommerceEnabled(void); +int APS5_VABI sceShellCoreUtilLemSettingGet(void); +int APS5_VABI sceShellCoreUtilLemSettingSet(void); +int APS5_VABI sceShellCoreUtilLemSettingGetList(void); +int APS5_VABI sceShellCoreUtilLemSettingReset(void); +int APS5_VABI sceShellCoreUtilIsEChassisVariant(void); +int APS5_VABI sceSystemStateMgrGetRebootCause(void); +int APS5_VABI sceCoredumpSequenceHandlerUpdateEventCache(void); +int APS5_VABI sceCoredumpSequenceHandlerGetEventCache(void); +int APS5_VABI sceCoredumpSequenceHandlerGetWorkingEventSummary(void); +int APS5_VABI sceCoredumpSequenceHandlerGetCoredumpStatus(void); +int APS5_VABI sceCoredumpSequenceHandlerGetCoredumpStatusByAppId(void); +int APS5_VABI sceCoredumpSequenceHandlerCancelCoredump(void); +int APS5_VABI sceSystemServiceIsBgmPlaying(void); +int APS5_VABI sceShellCoreUtilIsBgmPlaying(void); +int APS5_VABI sceAppMessagingClearEventFlag(std::int32_t appId, std::uint64_t flags); +int APS5_VABI sceAppMessagingReceiveMsg(AppMessagingMessage* message); +int APS5_VABI sceAppMessagingSendMsg(std::uint32_t appId, std::uint32_t messageId, const void* data, std::size_t size, std::uint32_t flags); +int APS5_VABI sceAppMessagingSendMsgToShellCore(std::uint32_t messageId, const void* data, std::size_t size, std::uint32_t flags); +int APS5_VABI sceAppMessagingSendMsgToShellUI(std::uint32_t messageId, const void* data, std::size_t size, std::uint32_t flags); +int APS5_VABI sceAppMessagingSetEventFlag(std::int32_t appId, std::uint64_t flags); +int APS5_VABI sceAppMessagingTryGetEventFlag(std::uint64_t mask, std::uint64_t* flags, std::uint8_t clear); +int APS5_VABI sceAppMessagingTryReceiveMsg(AppMessagingMessage* message); +int APS5_VABI sceLncUtilAcquireCpuBudgetOfExtraAudioDevices(); +int APS5_VABI sceLncUtilAcquireCpuBudgetOfImeForBigApp(); +int APS5_VABI sceLncUtilAcquireCpuBudgetOfInGameStore(); +int APS5_VABI sceLncUtilActivateCdlg(); +int APS5_VABI sceLncUtilAddLocalProcess(std::int32_t appId, const char* path, const char* const* argv, const LncLocalProcessParam* param); +int APS5_VABI sceLncUtilBlockAppSuspend(const char* reason); +int APS5_VABI sceLncUtilBlockingGetEventForDaemon(LncDaemonEvent* event, std::uint64_t receiveArgument); +int APS5_VABI sceLncUtilContinueApp(std::int32_t appId); +int APS5_VABI sceLncUtilCrashSyscore(); +int APS5_VABI sceLncUtilDeactivateCdlg(); +int APS5_VABI sceLncUtilDeclareReadyForSuspend(); +int APS5_VABI sceLncUtilDisableSuspendNotification(); +int APS5_VABI sceLncUtilEnableSuspendNotification(); +int APS5_VABI sceLncUtilFinishSpecialResume(); +int APS5_VABI sceLncUtilForceKillApp(std::int32_t appId); +int APS5_VABI sceLncUtilForceKillLocalProcess(std::int32_t appId, std::int32_t processId); +int APS5_VABI sceLncUtilGetAppCategory(std::int32_t appId, char* category); +int APS5_VABI sceLncUtilGetAppCategoryType(std::int32_t appId, std::uint32_t* categoryType); +int APS5_VABI sceLncUtilGetAppFocusedAppStatus(LncAppStatus* status); +int APS5_VABI sceLncUtilGetAppId(const char* titleId); +int APS5_VABI sceLncUtilGetAppIdListOfBigApp(std::int32_t* appIds, std::uint32_t capacity, std::uint32_t* count); +int APS5_VABI sceLncUtilGetAppIdOfRunningBigApp(); +int APS5_VABI sceLncUtilGetAppLaunchedUser(std::int32_t appId, std::int32_t* userId); +int APS5_VABI sceLncUtilGetAppStatus(LncAppStatus* status); +int APS5_VABI sceLncUtilGetAppStatusList(LncAppStatus* statuses, std::uint32_t capacity, std::uint32_t* count); +int APS5_VABI sceLncUtilGetAppStatusListForShellUIReboot(LncShellUiAppStatus* statuses, std::uint32_t capacity, std::uint32_t* count); +int APS5_VABI sceLncUtilGetAppTitleId(std::int32_t appId, char* titleId); +int APS5_VABI sceLncUtilGetAppType(std::int32_t appId, std::uint32_t* type); +int APS5_VABI sceLncUtilGetCdlgExec(std::int32_t appId, bool* executing); +int APS5_VABI sceLncUtilGetCdlgType(std::int32_t appId, std::uint32_t* type); +int APS5_VABI sceLncUtilGetCoredumpState(std::int32_t appId, std::int32_t processId, LncCoredumpState* state); +int APS5_VABI sceLncUtilGetDbgExecutablePath(char* path, std::uint64_t selector); +int APS5_VABI sceLncUtilGetEventForDaemon(LncDaemonEvent* event); +int APS5_VABI sceLncUtilGetEventForShellUI(LncShellUiEvent* event); +int APS5_VABI sceLncUtilGetGpuCrashFullDumpAppStatus(LncGpuCrashAppStatus* status); +int APS5_VABI sceLncUtilGetLocalProcessStatusList(LncLocalProcessStatus* statuses, std::uint32_t capacity, std::uint32_t* count); +int APS5_VABI sceLncUtilGetParentSocket(); +int APS5_VABI sceLncUtilGetResultKillApp(std::uint32_t requestId); +int APS5_VABI sceLncUtilGetResultLaunchAppByTitleId(std::uint32_t requestId); +int APS5_VABI sceLncUtilGetVideoFinalizeState(std::int32_t appId, std::int32_t processId, LncVideoFinalizeState* state); +int APS5_VABI sceLncUtilInitialize(); +int APS5_VABI sceLncUtilIsActiveCdlg(bool* active); +int APS5_VABI sceLncUtilIsAppLaunched(const char* titleId, bool* launched); +int APS5_VABI sceLncUtilIsAppSuspended(std::int32_t appId, bool* suspended); +int APS5_VABI sceLncUtilIsCdlgActivated(std::uint8_t* activated); +bool APS5_VABI sceLncUtilIsCpuBudgetOfExtraAudioDevicesAvailable(); +int APS5_VABI sceLncUtilIsHostBoot(std::int32_t appId, bool* hostBoot); +int APS5_VABI sceLncUtilIsPs2Emu(bool* emulated); +bool APS5_VABI sceLncUtilIsShellUiFgAndGameBgCpuMode(); +int APS5_VABI sceLncUtilIsSpeculativeLaunch(std::int32_t appId, bool* speculative); +int APS5_VABI sceLncUtilKickCoredumpOnlyProcMem(std::int32_t appId, std::int32_t processId, const char* first, const char* second); +int APS5_VABI sceLncUtilKillLocalProcess(std::int32_t appId, std::int32_t processId); +int APS5_VABI sceLncUtilLaunchApp(const char* titleId, const char* const* argv, const LncLaunchParam* param); +int APS5_VABI sceLncUtilLoadExec(const char* path, const char* const* argv); +int APS5_VABI sceLncUtilNotifyCoredumpRequestEnd(std::int32_t appId, std::int32_t processId, std::int32_t result); +int APS5_VABI sceLncUtilNotifyCoredumpRequestProgress(std::int32_t appId, std::int32_t processId, std::int32_t progress); +int APS5_VABI sceLncUtilNotifyVshReady(std::uint32_t errorCode); +int APS5_VABI sceLncUtilRaiseException(std::int32_t appId, std::uint64_t exception); +int APS5_VABI sceLncUtilRaiseExceptionLocalProcess(std::int32_t appId, std::int32_t processId, std::uint64_t exception); +int APS5_VABI sceLncUtilRegisterCdlgSharedMemoryName(const char* name); +int APS5_VABI sceLncUtilRegisterDaemon(); +int APS5_VABI sceLncUtilRegisterShellUI(); +int APS5_VABI sceLncUtilReleaseCpuBudgetOfExtraAudioDevices(); +int APS5_VABI sceLncUtilReleaseCpuBudgetOfImeForBigApp(); +int APS5_VABI sceLncUtilReleaseCpuBudgetOfInGameStore(); +int APS5_VABI sceLncUtilResumeApp(std::int32_t appId, std::uint64_t flags); +int APS5_VABI sceLncUtilResumeLocalProcess(std::int32_t processId); +int APS5_VABI sceLncUtilSetAppFocus(std::int32_t appId, std::uint64_t flags, std::uint64_t contextId); +int APS5_VABI sceLncUtilSetCdlgExec(std::int32_t appId, std::uint8_t executing); +int APS5_VABI sceLncUtilSetControllerFocus(std::int32_t appId); +int APS5_VABI sceLncUtilSetControllerFocusPermission(std::uint8_t permission); +int APS5_VABI sceLncUtilStartKillApp(std::int32_t appId, std::uint32_t* requestId); +int APS5_VABI sceLncUtilStartLaunchAppByTitleId(const char* titleId, const char* const* argv, const LncLaunchParam* param, std::uint32_t* requestId); +int APS5_VABI sceLncUtilSuspendApp(std::int32_t appId, std::uint64_t flags, std::int32_t reason); +int APS5_VABI sceLncUtilSuspendBackgroundApp(std::int32_t first, std::int32_t second); +int APS5_VABI sceLncUtilSuspendLocalProcess(std::int32_t processId); +int APS5_VABI sceLncUtilTerminate(); +int APS5_VABI sceLncUtilTryBlockAppSuspend(const char* reason); +int APS5_VABI sceLncUtilUnblockAppSuspend(const char* reason); +int APS5_VABI sceLncUtilUnregisterCdlgSharedMemoryName(const char* name); +int APS5_VABI sceLncUtilUnregisterDaemon(); +int APS5_VABI sceLncUtilUnregisterShellUI(); +int APS5_VABI sceShellCoreUtilAccessibilityZoomLock(); +int APS5_VABI sceShellCoreUtilAccessibilityZoomUnlock(); +int APS5_VABI sceShellCoreUtilAcquireBgmCpuBudget(); +int APS5_VABI sceShellCoreUtilAcquireRemotePlayCpuBudget(); +int APS5_VABI sceShellCoreUtilAcquireSharePlayCpuBudget(); +int APS5_VABI sceShellCoreUtilActivateAbort(std::intptr_t handle); +int APS5_VABI sceShellCoreUtilActivateGetStatus(std::intptr_t handle, std::int32_t* status, std::int32_t* result); +int APS5_VABI sceShellCoreUtilActivateInit(std::int32_t type, std::intptr_t* handle); +int APS5_VABI sceShellCoreUtilActivateIsActivated(std::intptr_t handle, bool* activated); +int APS5_VABI sceShellCoreUtilActivateRecordActivation(); +int APS5_VABI sceShellCoreUtilActivateStart(std::intptr_t handle); +int APS5_VABI sceShellCoreUtilActivateStartAsync(std::intptr_t handle); +int APS5_VABI sceShellCoreUtilActivateTerm(std::intptr_t handle); +int APS5_VABI sceShellCoreUtilChangeRunLevel(std::int32_t runLevel); +int APS5_VABI sceShellCoreUtilChangeToStaffModeForIDU(); +int APS5_VABI sceShellCoreUtilCheckerAbort(); +int APS5_VABI sceShellCoreUtilCleanupCrashReport(); +int APS5_VABI sceShellCoreUtilClearAppData(); +int APS5_VABI sceShellCoreUtilClearPs4AppCategoryDefaultsListUpdate(); +int APS5_VABI sceShellCoreUtilClearPsnAccountInfo(); +int APS5_VABI sceShellCoreUtilCrashReportRequestCancel(); +int APS5_VABI sceShellCoreUtilDeclareBeginOfExternalStorageAppMove(); +int APS5_VABI sceShellCoreUtilDeclareEndOfExternalStorageAppMove(); +int APS5_VABI sceShellCoreUtilDeleteDiscInstalledTitleWorkaroundFile(); +int APS5_VABI sceShellCoreUtilDeleteDownloadedHidConfigFile(std::int32_t configIndex); +int APS5_VABI sceShellCoreUtilDeleteDownloadedNetEvConfigFile(); +int APS5_VABI sceShellCoreUtilDeleteDownloadedTitleWorkaroundFile(); +int APS5_VABI sceShellCoreUtilDoFsck(const char* path); +int APS5_VABI sceShellCoreUtilDownloadHidConfigFileFromServer(std::int32_t configIndex); +int APS5_VABI sceShellCoreUtilDownloadNetEvConfigFileFromServer(); +int APS5_VABI sceShellCoreUtilDownloadTitleWorkaroundFileFromServer(); +int APS5_VABI sceShellCoreUtilEndUmmDictation(); +int APS5_VABI sceShellCoreUtilEnterPowerLockSection(); +int APS5_VABI sceShellCoreUtilExecuteCrashReport(); +int APS5_VABI sceShellCoreUtilExfatFormatExternalHdd(const char* path); +int APS5_VABI sceShellCoreUtilExitApp(); +int APS5_VABI sceShellCoreUtilExitMiniApp(); +int APS5_VABI sceShellCoreUtilExitMiniAppWithValue(const char* value); +int APS5_VABI sceShellCoreUtilFormatExternalHdd(const char* path); +int APS5_VABI sceShellCoreUtilFormatHddForRestore(); +int APS5_VABI sceShellCoreUtilGetAppData(const char* key, void* data, std::int32_t capacity, std::int32_t* size); +int APS5_VABI sceShellCoreUtilGetAppEnableTTS(std::int32_t appId, bool* enabled); +int APS5_VABI sceShellCoreUtilGetAppEnterButtonAssign(std::int32_t appId, std::int32_t* assignment); +int APS5_VABI sceShellCoreUtilGetAppLaunchTypeInfo(std::int32_t appId, ShellCoreAppLaunchTypeInfo* info); +int APS5_VABI sceShellCoreUtilGetAppLaunchedParamInt(std::int32_t appId, const char* key, std::int32_t* value); +int APS5_VABI sceShellCoreUtilGetAppLaunchedParamIntByBudgetType(std::int32_t budgetType, const char* key, std::int32_t* value); +int APS5_VABI sceShellCoreUtilGetAppLaunchedParamString(std::int32_t appId, const char* key, char* value, std::int32_t capacity); +int APS5_VABI sceShellCoreUtilGetAppLaunchedParamStringByBudgetType(std::int32_t budgetType, const char* key, char* value, std::int32_t capacity); +int APS5_VABI sceShellCoreUtilGetAutoPowerDownRemainingSeconds(); +int APS5_VABI sceShellCoreUtilGetBasicProductShape(); +int APS5_VABI sceShellCoreUtilGetCheckerString(const char* key, char* value, std::size_t capacity); +int APS5_VABI sceShellCoreUtilGetCheckerStringEx(const char* firstKey, const char* secondKey, char* value, std::size_t capacity); +int APS5_VABI sceShellCoreUtilGetCloudClientStatus(std::uint32_t* status); +int APS5_VABI sceShellCoreUtilGetCrashReportCoreFileSetSize(); +int APS5_VABI sceShellCoreUtilGetCrashReportFilterInfoStart(); +int APS5_VABI sceShellCoreUtilGetCrashReportInfoForBoot(); +int APS5_VABI sceShellCoreUtilGetCrashReportInfoForBootStart(); +int APS5_VABI sceShellCoreUtilGetCrashReportInfoStart(); +int APS5_VABI sceShellCoreUtilGetCrashReportResult(); +int APS5_VABI sceShellCoreUtilGetCrashReportStatus(); +int APS5_VABI sceShellCoreUtilGetCrashReportUploadStatus(); +int APS5_VABI sceShellCoreUtilGetDeviceIndexBehavior(std::uint32_t* behavior, std::int32_t* userId, std::uint32_t* scene); +int APS5_VABI sceShellCoreUtilGetDeviceIndexBehaviorWithTimeout(std::uint32_t* behavior, std::int32_t* userId, std::uint32_t* scene, std::uint8_t timeout); +int APS5_VABI sceShellCoreUtilGetEffectiveTotalSizeOfUserPartition(std::uint64_t* size); +std::uint64_t APS5_VABI sceShellCoreUtilGetFreeSizeOfAvContentsTmp(); +int APS5_VABI sceShellCoreUtilGetFreeSizeOfUserPartition(std::uint64_t* freeSize, std::uint64_t* totalSize); +int APS5_VABI sceShellCoreUtilGetFsckProgress(const char* titleId, std::uint32_t* progress); +int APS5_VABI sceShellCoreUtilGetGameLiveStreamingStatus(bool* active); +bool APS5_VABI sceShellCoreUtilGetGnmCompositorOnScreenProfilerFlag(); +int APS5_VABI sceShellCoreUtilGetGpuLoadEmulationMode(); +int APS5_VABI sceShellCoreUtilGetGpuLoadEmulationModeByAppId(std::int32_t appId); +int APS5_VABI sceShellCoreUtilGetHidConfigFileInfoString(char* value, std::size_t capacity, std::int32_t configIndex); +int APS5_VABI sceShellCoreUtilGetHidConfigFileString(char* value, std::size_t capacity, std::int32_t configIndex); +int APS5_VABI sceShellCoreUtilGetHidConfigName(char* value, std::size_t capacity, std::int32_t configIndex); +int APS5_VABI sceShellCoreUtilGetHidConfigNum(std::int32_t* configNum); +int APS5_VABI sceShellCoreUtilGetIDUMode(std::uint8_t* mode); +bool APS5_VABI sceShellCoreUtilGetImposeMenuFlagForPs2Emu(std::int32_t appId); +int APS5_VABI sceShellCoreUtilGetManifestFileStatus(); +int APS5_VABI sceShellCoreUtilGetNeedSizeOfAppContent(std::uint64_t* size); +int APS5_VABI sceShellCoreUtilGetNetEvConfigFileInfoString(char* value, std::size_t capacity); +int APS5_VABI sceShellCoreUtilGetOutOfVrPlayZoneWarning(); +int APS5_VABI sceShellCoreUtilGetPapcGamePcl(); +int APS5_VABI sceShellCoreUtilGetPbtcUserInfoList(ShellCorePbtcUserInfoList* info); +int APS5_VABI sceShellCoreUtilGetPlatformPrivacyDefinitionEventData(const char* firstKey, const char* secondKey, ShellCorePrivacyEventData* data); +float APS5_VABI sceShellCoreUtilGetProgressOfFormatExternalHdd(); +float APS5_VABI sceShellCoreUtilGetProgressOfFsck(); +int APS5_VABI sceShellCoreUtilGetPs4AppCategoryDefaultsListId(void* data, std::size_t capacity); +int APS5_VABI sceShellCoreUtilGetPs4AppCategoryForTitleId(const char* titleId); +int APS5_VABI sceShellCoreUtilGetPsStoreIconLayout(std::int32_t appId); +int APS5_VABI sceShellCoreUtilGetPsStoreIconState(std::int32_t appId); +int APS5_VABI sceShellCoreUtilGetPsnAccountInfo(ShellCorePsnAccountInfoFirst* first, ShellCorePsnAccountInfoSecond* second, ShellCorePsnAccountInfoThird* third, ShellCorePsnAccountInfoFourth* fourth, ShellCorePsnAccountInfoFifth* fifth); +int APS5_VABI sceShellCoreUtilGetRemotePlayStatus(bool* active); +int APS5_VABI sceShellCoreUtilGetRunLevel(); +int APS5_VABI sceShellCoreUtilGetSharePlayStatus(bool* active); +int APS5_VABI sceShellCoreUtilGetSocialScreenStatus(bool* active); +int APS5_VABI sceShellCoreUtilGetSplashScreenState(std::int32_t appId); +int APS5_VABI sceShellCoreUtilGetSupportSiteURL(std::uint32_t first, std::uint32_t second, char* value, std::size_t capacity); +bool APS5_VABI sceShellCoreUtilGetSuspendConfirmationDialogFlag(std::int32_t appId); +int APS5_VABI sceShellCoreUtilGetSystemBGState(std::int32_t appId, std::uint32_t* state); +int APS5_VABI sceShellCoreUtilGetSystemBGWaveColor(std::int32_t appId, std::uint32_t* color); +int APS5_VABI sceShellCoreUtilGetSystemBGWaveState(std::int32_t appId, std::uint32_t* state); +int APS5_VABI sceShellCoreUtilGetTelemetryToken(ShellCoreTelemetryToken* token); +int APS5_VABI sceShellCoreUtilGetTitleWorkaroundFileInfoString(char* value, std::size_t capacity); +int APS5_VABI sceShellCoreUtilGetTitleWorkaroundFileString(char* value, std::size_t capacity); +int APS5_VABI sceShellCoreUtilGetUIStatus(std::uint64_t* status); +int APS5_VABI sceShellCoreUtilGetUmmStatus(std::int32_t userId, ShellCoreUmmStatus* status); +int APS5_VABI sceShellCoreUtilGetUserFocus(std::int32_t appId, std::int32_t* userId); +int APS5_VABI sceShellCoreUtilGetUserIdOfMorpheusUser(); +int APS5_VABI sceShellCoreUtilGetVMStatsForTelemetry(char* value, std::size_t capacity); +int APS5_VABI sceShellCoreUtilGetVersionNumberOfCameraCalibrationData(); +int APS5_VABI sceShellCoreUtilGoBackToKratosCurrentSessionGame(); +int APS5_VABI sceShellCoreUtilHideBlocksFromUser(std::int64_t bytes, std::int32_t flags); +int APS5_VABI sceShellCoreUtilIncrementVersionNumberOfCameraCalibrationData(); +bool APS5_VABI sceShellCoreUtilIsAccessibilityZoomLocked(std::int32_t appId); +bool APS5_VABI sceShellCoreUtilIsBgmCpuBudgetAcquired(); +bool APS5_VABI sceShellCoreUtilIsBgmCpuBudgetAvailable(); +bool APS5_VABI sceShellCoreUtilIsExternalStorageAppMoveInProgress(); +int APS5_VABI sceShellCoreUtilIsEyeToEyeDistanceAdjusted(std::uint32_t userId, std::uint8_t* adjusted); +bool APS5_VABI sceShellCoreUtilIsGameLiveStreamingOnAir(); +int APS5_VABI sceShellCoreUtilIsIDUState(); +bool APS5_VABI sceShellCoreUtilIsImposeScreenOverlaid(); +bool APS5_VABI sceShellCoreUtilIsInSystemSuspendBlackList(std::uint32_t appId); +int APS5_VABI sceShellCoreUtilIsInternalKratosUser(); +int APS5_VABI sceShellCoreUtilIsKilledOrSuspendedByLogout(std::int32_t first, std::int32_t second, std::uint8_t* result); +int APS5_VABI sceShellCoreUtilIsNeededCrashReport(); +bool APS5_VABI sceShellCoreUtilIsPowerSaveAlertRequested(); +bool APS5_VABI sceShellCoreUtilIsRemotePlayCpuBudgetAcquired(); +bool APS5_VABI sceShellCoreUtilIsScreenSaverOn(); +bool APS5_VABI sceShellCoreUtilIsSharePlayCpuBudgetAcquired(); +int APS5_VABI sceShellCoreUtilIsShowCrashReport(); +int APS5_VABI sceShellCoreUtilIsTemperatureDanger(); +int APS5_VABI sceShellCoreUtilIsTitleWorkaroundEnabled(std::int32_t selector, const char* key); +bool APS5_VABI sceShellCoreUtilIsUsbMassStorageMounted(std::uint32_t deviceIndex); +int APS5_VABI sceShellCoreUtilLaunchByUri(const char* uri, const ShellCoreLaunchByUriParam* param); +int APS5_VABI sceShellCoreUtilLeavePowerLockSection(); +int APS5_VABI sceShellCoreUtilMakeManifestFile(); +int APS5_VABI sceShellCoreUtilMountAppRight(const char* key); +int APS5_VABI sceShellCoreUtilMountDownloadDataForShellUI(const char* key); +int APS5_VABI sceShellCoreUtilMountHddForBackup(); +int APS5_VABI sceShellCoreUtilMountHddForRestore(); +int APS5_VABI sceShellCoreUtilNavigateToAnotherApp(std::uint32_t target); +int APS5_VABI sceShellCoreUtilNavigateToGoHome(std::uint32_t target); +int APS5_VABI sceShellCoreUtilNavigateToLaunchedApp(std::uint32_t target); +int APS5_VABI sceShellCoreUtilNotificationCancelForIDU(std::int64_t notificationId); +int APS5_VABI sceShellCoreUtilNotificationRequestedForIDU(std::int64_t notificationId, const char* text, std::uint32_t type); +int APS5_VABI sceShellCoreUtilNotifyBgmCoreTermination(); +int APS5_VABI sceShellCoreUtilNotifyFsReadError(std::int32_t first, std::int32_t second, std::int32_t third, const char* detail); +int APS5_VABI sceShellCoreUtilNotifyImeStatusChanged(std::int32_t imeStatus, std::uint8_t isCalledFromGame); +int APS5_VABI sceShellCoreUtilNotifyPsnAccountInfoReceived(); +int APS5_VABI sceShellCoreUtilNotifySystemSuspendTelemetryInfo(std::uint32_t info); +int APS5_VABI sceShellCoreUtilPfAuthClientConsoleTokenClearCache(); +int APS5_VABI sceShellCoreUtilPostActivityForPsNow(std::int32_t type, const char* activity); +int APS5_VABI sceShellCoreUtilPostErrorLog(const char* titleId, std::int32_t internalErrorCode, const char* shortError, const char* messageBuffer, std::int32_t suggestionType, const char* logReport); +int APS5_VABI sceShellCoreUtilPostLaunchConfirmResult(std::uint32_t first, std::uint32_t second); +int APS5_VABI sceShellCoreUtilPostPsmEventToShellUI(std::int32_t eventId, const char* data); +int APS5_VABI sceShellCoreUtilPreNotifyOfGameLiveStreaming(); +int APS5_VABI sceShellCoreUtilPreNotifyOfRemotePlay(); +int APS5_VABI sceShellCoreUtilPreNotifyOfSharePlay(); +int APS5_VABI sceShellCoreUtilReleaseBgmCpuBudget(); +int APS5_VABI sceShellCoreUtilReleaseRemotePlayCpuBudget(); +int APS5_VABI sceShellCoreUtilReleaseSharePlayCpuBudget(); +int APS5_VABI sceShellCoreUtilReportSessionErrorToGaikaiController(std::int32_t error, const char* detail); +int APS5_VABI sceShellCoreUtilReportUnexpectedFatalErrorToSystemTelemetry(std::int32_t error, const char* detail); +int APS5_VABI sceShellCoreUtilRequestCameraCalibration(); +int APS5_VABI sceShellCoreUtilRequestEjectDevice(const char* path); +int APS5_VABI sceShellCoreUtilRequestRebootApp(std::int32_t appId); +int APS5_VABI sceShellCoreUtilRequestShutdown(std::int32_t reason); +int APS5_VABI sceShellCoreUtilResetAutoPowerDownTimer(); +int APS5_VABI sceShellCoreUtilResetBgdcConfig(); +int APS5_VABI sceShellCoreUtilSetAppData(const char* key, const char* value); +int APS5_VABI sceShellCoreUtilSetBgmProhibition(std::uint32_t value); +int APS5_VABI sceShellCoreUtilSetDeviceIndexBehavior(std::uint32_t behavior, std::int32_t userId, std::uint8_t scene); +int APS5_VABI sceShellCoreUtilSetGameLiveStreamingOnAirFlag(std::int32_t enabled); +int APS5_VABI sceShellCoreUtilSetGameLiveStreamingStatus(std::int32_t active); +int APS5_VABI sceShellCoreUtilSetGnmCompositorOnScreenProfilerFlag(std::int32_t enabled); +int APS5_VABI sceShellCoreUtilSetGpuLoadEmulationMode(std::uint32_t mode); +int APS5_VABI sceShellCoreUtilSetGpuLoadEmulationModeByAppId(std::int32_t appId, std::uint32_t mode); +int APS5_VABI sceShellCoreUtilSetIDUMode(std::uint8_t mode); +int APS5_VABI sceShellCoreUtilSetImposeStatusFlag(std::int32_t enabled); +int APS5_VABI sceShellCoreUtilSetPsStoreIconLayout(std::uint32_t layout); +int APS5_VABI sceShellCoreUtilSetPsStoreIconState(std::uint32_t state); +int APS5_VABI sceShellCoreUtilSetRemotePlayStatus(std::int32_t active); +int APS5_VABI sceShellCoreUtilSetSharePlayStatus(std::int32_t active); +int APS5_VABI sceShellCoreUtilSetSkipUpdateCheck(std::uint8_t skip); +int APS5_VABI sceShellCoreUtilSetSocialScreenStatus(std::int32_t active); +int APS5_VABI sceShellCoreUtilSetSplashScreenState(std::uint32_t state); +int APS5_VABI sceShellCoreUtilSetSystemBGState(std::uint32_t state); +int APS5_VABI sceShellCoreUtilSetSystemBGWaveColor(std::uint32_t color); +int APS5_VABI sceShellCoreUtilSetSystemBGWaveState(std::uint32_t state); +int APS5_VABI sceShellCoreUtilSetUIStatus(std::uint64_t status, std::uint64_t mask); +int APS5_VABI sceShellCoreUtilSetUserFocus(std::int32_t userId); +int APS5_VABI sceShellCoreUtilShowCriticalErrorDialog(std::uint32_t error, const char* message); +int APS5_VABI sceShellCoreUtilShowErrorDialog(std::uint32_t error, const char* message); +int APS5_VABI sceShellCoreUtilShowErrorDialogWithFormatArgs(std::uint32_t error, const char* message, const char* const* formatArgs); +int APS5_VABI sceShellCoreUtilShowErrorDialogWithParam(std::uint32_t error, const ShellCoreErrorDialogParam* param); +int APS5_VABI sceShellCoreUtilShowPsUnderLockIndicator(); +int APS5_VABI sceShellCoreUtilSignalUserInput(); +int APS5_VABI sceShellCoreUtilStartPsNowGame(const char* data); +int APS5_VABI sceShellCoreUtilStopPsNowGame(const char* data); +int APS5_VABI sceShellCoreUtilTalkKeyEventReceived(std::int64_t deviceId, std::int32_t userId, std::int32_t keyEventType); +int APS5_VABI sceShellCoreUtilTestBusTransferSpeed(const char* path, std::uint8_t* result); +int APS5_VABI sceShellCoreUtilTickHeartBeat(); +int APS5_VABI sceShellCoreUtilTriggerPapcUpdate(std::uint32_t value); +int APS5_VABI sceShellCoreUtilTurnOffScreenSaver(); +int APS5_VABI sceShellCoreUtilUnmountAppRight(const char* key); +int APS5_VABI sceShellCoreUtilUnmountDownloadDataForShellUI(const char* key); +int APS5_VABI sceShellCoreUtilUnmountHddForBackup(); +int APS5_VABI sceShellCoreUtilUnmountHddForRestore(); +int APS5_VABI sceShellCoreutilGetCrashReportProcessInformation(); +int APS5_VABI sceSystemModalDialogClose(std::uint32_t dialogId); +int APS5_VABI sceSystemModalDialogOpen(const char* message); +int APS5_VABI sceSystemServiceAcquireBgmCpuBudget(); +int APS5_VABI sceSystemServiceAcquireFb0(); +int APS5_VABI sceSystemServiceActivateHevc(); +int APS5_VABI sceSystemServiceActivateHevcAbort(std::uintptr_t handle); +int APS5_VABI sceSystemServiceActivateHevcGetStatus(std::uintptr_t handle, std::uint32_t* status, std::int32_t* result); +int APS5_VABI sceSystemServiceActivateHevcInit(std::uintptr_t* handle); +int APS5_VABI sceSystemServiceActivateHevcIsActivated(std::uint8_t* activated); +int APS5_VABI sceSystemServiceActivateHevcSoft(); +int APS5_VABI sceSystemServiceActivateHevcSoftAbort(std::uintptr_t handle); +int APS5_VABI sceSystemServiceActivateHevcSoftGetStatus(std::uintptr_t handle, std::uint32_t* status, std::int32_t* result); +int APS5_VABI sceSystemServiceActivateHevcSoftInit(std::uintptr_t* handle); +int APS5_VABI sceSystemServiceActivateHevcSoftIsActivated(std::uint8_t* activated); +int APS5_VABI sceSystemServiceActivateHevcSoftStart(std::uintptr_t handle); +int APS5_VABI sceSystemServiceActivateHevcSoftTerm(std::uintptr_t handle); +int APS5_VABI sceSystemServiceActivateHevcStart(std::uintptr_t handle); +int APS5_VABI sceSystemServiceActivateHevcTerm(std::uintptr_t handle); +int APS5_VABI sceSystemServiceActivateMpeg2Abort(std::uintptr_t handle); +int APS5_VABI sceSystemServiceActivateMpeg2GetStatus(std::uintptr_t handle, std::uint32_t* status, std::int32_t* result); +int APS5_VABI sceSystemServiceActivateMpeg2Init(std::uintptr_t* handle); +int APS5_VABI sceSystemServiceActivateMpeg2IsActivated(std::uint8_t* activated); +int APS5_VABI sceSystemServiceActivateMpeg2Start(std::uintptr_t handle); +int APS5_VABI sceSystemServiceActivateMpeg2Term(std::uintptr_t handle); +int APS5_VABI sceSystemServiceAddLocalProcess(std::int32_t appId, const char* path, const char* const* argv, const SystemServiceLocalProcessParam* param); +int APS5_VABI sceSystemServiceAddLocalProcessForJvm(const char* path, const char* const* argv, const SystemServiceJvmProcessParam* param); +int APS5_VABI sceSystemServiceAddLocalProcessForPs2Emu(const char* path, const char* const* argv, const SystemServicePs2ProcessParam* param); +int APS5_VABI sceSystemServiceAppGetAppInstallStatus(const char* titleId, SystemServiceAppInstallStatus* status); +int APS5_VABI sceSystemServiceChangeAcpClock(); +int APS5_VABI sceSystemServiceChangeClock(const char* clock, std::uint32_t value); +int APS5_VABI sceSystemServiceChangeCpuClock(); +int APS5_VABI sceSystemServiceChangeCpuPstate(const SystemServiceCpuPstateParam* param); +int APS5_VABI sceSystemServiceChangeGpuClock(); +int APS5_VABI sceSystemServiceChangeMemPstate(std::uint32_t state); +int APS5_VABI sceSystemServiceChangeMemoryClock(); +int APS5_VABI sceSystemServiceChangeMemoryClockToBaseMode(); +int APS5_VABI sceSystemServiceChangeMemoryClockToDefault(); +int APS5_VABI sceSystemServiceChangeMemoryClockToMultiMediaMode(); +int APS5_VABI sceSystemServiceChangeNumberOfGpuCu(); +int APS5_VABI sceSystemServiceChangeSamuClock(); +int APS5_VABI sceSystemServiceChangeUvdClock(); +int APS5_VABI sceSystemServiceChangeVceClock(); +int APS5_VABI sceSystemServiceDeclareReadyForSuspend(); +int APS5_VABI sceSystemServiceDisablePartyVoice(); +int APS5_VABI sceSystemServiceDisablePersonalEyeToEyeDistanceSetting(); +int APS5_VABI sceSystemServiceDisableSuspendConfirmationDialog(); +int APS5_VABI sceSystemServiceDisableSuspendNotification(); +int APS5_VABI sceSystemServiceDisableVoiceRecognition(); +int APS5_VABI sceSystemServiceEnablePersonalEyeToEyeDistanceSetting(); +int APS5_VABI sceSystemServiceEnableSuspendConfirmationDialog(); +int APS5_VABI sceSystemServiceEnableSuspendNotification(); +int APS5_VABI sceSystemServiceGetAppCategoryType(std::int32_t appId, std::uint32_t* categoryType); +int APS5_VABI sceSystemServiceGetAppFocusedAppStatus(SystemServiceAppStatus* status); +int APS5_VABI sceSystemServiceGetAppId(const char* titleId); +int APS5_VABI sceSystemServiceGetAppIdListOfBigApp(std::int32_t* appIds, std::uint32_t capacity, std::uint32_t* count); +int APS5_VABI sceSystemServiceGetAppLaunchedUser(std::int32_t appId, std::int32_t* userId); +int APS5_VABI sceSystemServiceGetAppStatus(SystemServiceAppStatus* status); +int APS5_VABI sceSystemServiceGetAppTitleId(std::int32_t appId, char* titleId); +int APS5_VABI sceSystemServiceGetAppType(std::int32_t appId, std::int32_t* type); +int APS5_VABI sceSystemServiceGetDbgExecutablePath(char* path, std::uint64_t selector); +int APS5_VABI sceSystemServiceGetEventForDaemon(SystemServiceDaemonEvent* event); +int APS5_VABI sceSystemServiceGetGpuLoadEmulationMode(); +int APS5_VABI sceSystemServiceGetLocalProcessStatusList(SystemServiceLocalProcessStatus* statuses, std::uint32_t capacity, std::uint32_t* count); +int APS5_VABI sceSystemServiceGetMainAppTitleId(); +int APS5_VABI sceSystemServiceGetPSButtonEvent(const SystemServiceEvent* event, SystemServicePSButtonEvent* buttonEvent); +int APS5_VABI sceSystemServiceGetParentSocket(); +int APS5_VABI sceSystemServiceGetParentSocketForJvm(); +int APS5_VABI sceSystemServiceGetParentSocketForPs2Emu(); +int APS5_VABI sceSystemServiceGetParentSocketForPsmKit(); +int APS5_VABI sceSystemServiceGetPlatformPrivacyDefinitionData(const char* key, SystemServicePrivacyDefinitionData* data); +int APS5_VABI sceSystemServiceGetPlatformPrivacyDefinitionVersion(const char* key, SystemServicePrivacyDefinitionVersion* version); +int APS5_VABI sceSystemServiceGetPlatformPrivacySetting(std::uint32_t* setting); +int APS5_VABI sceSystemServiceGetRecentLotusPushedButton(std::uint32_t timeout, std::int32_t* deviceId, std::uint32_t* buttons); +int APS5_VABI sceSystemServiceGetRemoteplayStatus(bool* active); +int APS5_VABI sceSystemServiceGetRenderingMode(); +int APS5_VABI sceSystemServiceGetSubAppTitleId(); +int APS5_VABI sceSystemServiceGetSubAppTitleIdForSP(); +int APS5_VABI sceSystemServiceGetTitleWorkaroundInfo(SystemServiceTitleWorkaroundInfo* info); +int APS5_VABI sceSystemServiceGetUIStatus(std::uint64_t* status); +int APS5_VABI sceSystemServiceGetVersionNumberOfCameraCalibrationData(); +int APS5_VABI sceSystemServiceInitializeForShellCore(); +int APS5_VABI sceSystemServiceInvokeAppLaunchLink(const char* uri); +int APS5_VABI sceSystemServiceIsAppSuspended(std::int32_t appId, bool* suspended); +bool APS5_VABI sceSystemServiceIsBgmCpuBudgetAvailable(); +int APS5_VABI sceSystemServiceIsEyeToEyeDistanceAdjusted(std::uint32_t userId, std::uint8_t* adjusted); +bool APS5_VABI sceSystemServiceIsGameLiveStreamingOnAir(); +bool APS5_VABI sceSystemServiceIsScreenSaverOn(); +bool APS5_VABI sceSystemServiceIsShellUiFgAndGameBgCpuMode(); +int APS5_VABI sceSystemServiceKillLocalProcess(std::int32_t appId, std::int32_t processId); +int APS5_VABI sceSystemServiceKillLocalProcessForJvm(std::int32_t processId); +int APS5_VABI sceSystemServiceKillLocalProcessForPs2Emu(std::int32_t processId); +int APS5_VABI sceSystemServiceLaunchEventDetails(std::uint64_t unusedSlot, const char* eventId); +int APS5_VABI sceSystemServiceLaunchStore(const char* uri, const SystemServiceStoreParam* param); +int APS5_VABI sceSystemServiceLaunchTournamentList(); +int APS5_VABI sceSystemServiceLaunchTournamentsTeamProfile(std::uint64_t unusedSlot, const char* profile, const char* tournament, const char* context); +int APS5_VABI sceSystemServiceLaunchUdsApp(); +int APS5_VABI sceSystemServiceLaunchWebApp(const char* argument); +int APS5_VABI sceSystemServiceLoadExecVideoServiceWebApp(); +int APS5_VABI sceSystemServiceNavigateToAnotherApp(std::uint32_t target); +int APS5_VABI sceSystemServiceNavigateToGoBack(); +int APS5_VABI sceSystemServiceNavigateToGoBackWithValue(const char* value); +int APS5_VABI sceSystemServiceNavigateToGoHome(std::uint32_t target); +int APS5_VABI sceSystemServiceNotifyBgmCoreTermination(); +int APS5_VABI sceSystemServiceRaiseExceptionLocalProcess(std::int32_t appId, std::int32_t processId, std::uint64_t exception); +int APS5_VABI sceSystemServiceReenablePartyVoice(); +int APS5_VABI sceSystemServiceReenableVoiceRecognition(); +int APS5_VABI sceSystemServiceRegisterDaemon(); +int APS5_VABI sceSystemServiceReleaseBgmCpuBudget(); +int APS5_VABI sceSystemServiceReleaseFb0(); +int APS5_VABI sceSystemServiceRequestCameraCalibration(); +int APS5_VABI sceSystemServiceRequestPowerOff(); +int APS5_VABI sceSystemServiceRequestReboot(); +int APS5_VABI sceSystemServiceRequestToChangeRenderingMode(); +int APS5_VABI sceSystemServiceResumeLocalProcess(std::int32_t processId); +int APS5_VABI sceSystemServiceSaveVideoToken(std::int32_t userId, const char* token); +int APS5_VABI sceSystemServiceSetControllerFocusPermission(std::uint8_t permission); +int APS5_VABI sceSystemServiceSetGpuLoadEmulationMode(std::uint32_t mode); +int APS5_VABI sceSystemServiceSetOutOfVrPlayAreaFlag(std::uint8_t flag); +int APS5_VABI sceSystemServiceSetOutOfVrPlayZoneWarning(); +int APS5_VABI sceSystemServiceSetPowerSaveLevel(std::uint32_t level); +int APS5_VABI sceSystemServiceShowClosedCaptionAdvancedSettings(); +int APS5_VABI sceSystemServiceShowClosedCaptionSettings(); +int APS5_VABI sceSystemServiceShowErrorDialog(std::uint32_t error, const char* message); +int APS5_VABI sceSystemServiceShowEyeToEyeDistanceSetting(); +int APS5_VABI sceSystemServiceShowImposeMenuForPs2Emu(std::uint8_t enabled, std::uint64_t reserved); +int APS5_VABI sceSystemServiceSuspendBackgroundApp(std::int32_t first, std::int32_t second); +int APS5_VABI sceSystemServiceSuspendLocalProcess(std::int32_t processId); +int APS5_VABI sceSystemServiceTelemetrySetData(const char* key, const void* data, std::size_t size); +int APS5_VABI sceSystemServiceTelemetrySetData2(const char* key, const char* data); +int APS5_VABI sceSystemServiceTickVideoPlayback(); +int APS5_VABI sceSystemServiceTurnOffScreenSaver(); +int APS5_VABI sceSystemServiceUsbStorageGetDeviceInfo(std::uint32_t device, UsbStorageDeviceInfo* info); +int APS5_VABI sceSystemServiceUsbStorageGetDeviceList(std::uint32_t* devices, std::int32_t* count); +int APS5_VABI sceSystemServiceUsbStorageGetdentsClose(std::int32_t fd); +int APS5_VABI sceSystemServiceUsbStorageGetdentsOpen(std::uint32_t device, std::int32_t* fd, std::uint64_t* bufferSize); +int APS5_VABI sceSystemServiceUsbStorageGetdentsRead(std::int32_t fd, void* buffer, std::uint64_t bufferSize, std::uint64_t* bytesRead); +int APS5_VABI sceSystemServiceUsbStorageInit(void* attr); +bool APS5_VABI sceSystemServiceUsbStorageIsExist(std::uint32_t device, const char* directory, std::uint8_t* exists); +int APS5_VABI sceSystemServiceUsbStorageRegisterCallback(std::int32_t eventType, UsbStorageCallback callback, void* arg); +int APS5_VABI sceSystemServiceUsbStorageRegisterCallbackForMapAvailable(std::uint32_t device, const char* directory, UsbStorageCallback callback, void* arg); +int APS5_VABI sceSystemServiceUsbStorageRegisterCallbackForMapUnavailable(std::uint32_t device, const char* directory, UsbStorageCallback callback, void* arg); +int APS5_VABI sceSystemServiceUsbStorageRequestMap(std::uint32_t device, const char* directory, std::int32_t flags, std::uint64_t volumeSize, char* mountPoint, std::uint64_t* mountId); +int APS5_VABI sceSystemServiceUsbStorageRequestMapWSB(std::uint32_t device, const char* directory, std::int32_t flags, std::uint64_t volumeSize, char* mountPoint, std::uint64_t* mountId); +int APS5_VABI sceSystemServiceUsbStorageRequestUnmap(std::uint32_t device, const char* directory); +int APS5_VABI sceSystemServiceUsbStorageTerm(); +int APS5_VABI sceSystemServiceUsbStorageUnregisterCallback(std::int32_t eventType, UsbStorageCallback callback); +int APS5_VABI sceSystemServiceUsbStorageUnregisterCallbackForMapAvailable(std::uint32_t device, const char* directory, UsbStorageCallback callback); +int APS5_VABI sceSystemServiceUsbStorageUnregisterCallbackForMapUnavailable(std::uint32_t device, const char* directory, UsbStorageCallback callback); +int APS5_VABI sceSystemStateMgrCancelShutdownTimer(); +int APS5_VABI sceSystemStateMgrEnterMediaPlaybackMode(); +int APS5_VABI sceSystemStateMgrEnterStandby(); +int APS5_VABI sceSystemStateMgrExtendShutdownTimer(); +int APS5_VABI sceSystemStateMgrExtendShutdownTimerForPostAutoUpdateProcess(); +int APS5_VABI sceSystemStateMgrGetCurrentState(); +int APS5_VABI sceSystemStateMgrGetTriggerCode(); +bool APS5_VABI sceSystemStateMgrIsBdDriveReady(); +int APS5_VABI sceSystemStateMgrIsGpuPerformanceNormal(); +bool APS5_VABI sceSystemStateMgrIsShellUIShutdownInProgress(); +bool APS5_VABI sceSystemStateMgrIsStandbyModeEnabled(); +int APS5_VABI sceSystemStateMgrLeaveMediaPlaybackMode(); +int APS5_VABI sceSystemStateMgrNotifySystemSuspendResumeProgress(const char* progress); +int APS5_VABI sceSystemStateMgrReboot(); +int APS5_VABI sceSystemStateMgrRequestToKeepMainOnStandby(const char* reason); +int APS5_VABI sceSystemStateMgrSendCecOneTouchPlayCommand(); +int APS5_VABI sceSystemStateMgrStartRebootTimer(std::int32_t mode); +int APS5_VABI sceSystemStateMgrStartShutdownTimer(); +int APS5_VABI sceSystemStateMgrStartStadbyTimer(); +int APS5_VABI sceSystemStateMgrStartVshAutoUpdateTimer(); +int APS5_VABI sceSystemStateMgrTickMusicPlayback(); +int APS5_VABI sceSystemStateMgrTickPartyChat(); +int APS5_VABI sceSystemStateMgrTurnOff(); +int APS5_VABI sceSystemStateMgrVshAutoUpdate(); +int APS5_VABI sceSystemStateMgrWaitVshAutoUpdateVerifyDone(); +int APS5_VABI sceSystemStateMgrWakeUp(std::uint16_t trigger); + +} diff --git a/core/libs/prx/libSceSystemService/libSceSystemService.hpp b/core/libs/prx/libSceSystemService/libSceSystemService.hpp new file mode 100644 index 0000000000..e3ff176277 --- /dev/null +++ b/core/libs/prx/libSceSystemService/libSceSystemService.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceSystemService/include/SystemService.hpp" diff --git a/core/libs/prx/libSceSystemTts/Export.cpp b/core/libs/prx/libSceSystemTts/Export.cpp index d895b270e8..dc975b9b4a 100644 --- a/core/libs/prx/libSceSystemTts/Export.cpp +++ b/core/libs/prx/libSceSystemTts/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceSystemTts/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceSystemTts/include/Api.hpp b/core/libs/prx/libSceSystemTts/include/Api.hpp new file mode 100644 index 0000000000..d0942cfe30 --- /dev/null +++ b/core/libs/prx/libSceSystemTts/include/Api.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceSystemTtsCancel(); +int APS5_VABI sceSystemTtsIsAccessibilityAvailable(); +int APS5_VABI sceSystemTtsRegisterCallback(); +int APS5_VABI sceSystemTtsSpeakRequest(); +int APS5_VABI sceSystemTtsUnregisterCallback(); + +} diff --git a/core/libs/prx/libSceSystemTts/libSceSystemTts.hpp b/core/libs/prx/libSceSystemTts/libSceSystemTts.hpp new file mode 100644 index 0000000000..f2c384d4c4 --- /dev/null +++ b/core/libs/prx/libSceSystemTts/libSceSystemTts.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceSystemTts/include/Api.hpp" diff --git a/core/libs/prx/libSceTEEClient/Export.cpp b/core/libs/prx/libSceTEEClient/Export.cpp index 58c703695b..71faf0cb5f 100644 --- a/core/libs/prx/libSceTEEClient/Export.cpp +++ b/core/libs/prx/libSceTEEClient/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceTEEClient/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceTEEClient/include/Api.hpp b/core/libs/prx/libSceTEEClient/include/Api.hpp new file mode 100644 index 0000000000..2c38c96684 --- /dev/null +++ b/core/libs/prx/libSceTEEClient/include/Api.hpp @@ -0,0 +1,18 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI AMDTEE_DLM_FetchDebugStrings_nid_postfix(void); +int APS5_VABI AMDTEE_DLM_GetDebugToken_nid_postfix(void); +int APS5_VABI AMDTEE_DLM_StopTADebug_nid_postfix(void); +int APS5_VABI TEECI_InitASD_nid_postfix(void); +int APS5_VABI TEECI_SetTimeout_nid_postfix(void); +int APS5_VABI TEEC_CloseSession_nid_postfix(void); +int APS5_VABI TEEC_InvokeCommand_nid_postfix(void); +int APS5_VABI TEEC_OpenSession_nid_postfix(void); +int APS5_VABI TEEC_ReleaseSharedMemory_nid_postfix(void); +int APS5_VABI TEEC_RequestCancellation_nid_postfix(void); + +} diff --git a/core/libs/prx/libSceTEEClient/libSceTEEClient.hpp b/core/libs/prx/libSceTEEClient/libSceTEEClient.hpp new file mode 100644 index 0000000000..7b3b5682b7 --- /dev/null +++ b/core/libs/prx/libSceTEEClient/libSceTEEClient.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceTEEClient/include/Api.hpp" diff --git a/core/libs/prx/libSceTextToSpeech/Export.cpp b/core/libs/prx/libSceTextToSpeech/Export.cpp index 05c84e9df9..cd4a31d3f6 100644 --- a/core/libs/prx/libSceTextToSpeech/Export.cpp +++ b/core/libs/prx/libSceTextToSpeech/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceTextToSpeech/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceTextToSpeech/include/Api.hpp b/core/libs/prx/libSceTextToSpeech/include/Api.hpp new file mode 100644 index 0000000000..6f8845b245 --- /dev/null +++ b/core/libs/prx/libSceTextToSpeech/include/Api.hpp @@ -0,0 +1,18 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceTextToSpeechCancelImpl(); +int APS5_VABI sceTextToSpeechCloseImpl(); +int APS5_VABI sceTextToSpeechGetStatusImpl(); +int APS5_VABI sceTextToSpeechInitImpl(); +int APS5_VABI sceTextToSpeechOpenImpl(); +int APS5_VABI sceTextToSpeechPauseImpl(); +int APS5_VABI sceTextToSpeechResumeImpl(); +int APS5_VABI sceTextToSpeechSpeakContinuousImpl(); +int APS5_VABI sceTextToSpeechSpeakImpl(); +int APS5_VABI sceTextToSpeechTermImpl(); + +} diff --git a/core/libs/prx/libSceTextToSpeech/libSceTextToSpeech.hpp b/core/libs/prx/libSceTextToSpeech/libSceTextToSpeech.hpp new file mode 100644 index 0000000000..0238da246a --- /dev/null +++ b/core/libs/prx/libSceTextToSpeech/libSceTextToSpeech.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceTextToSpeech/include/Api.hpp" diff --git a/core/libs/prx/libSceTextToSpeech2/Export.cpp b/core/libs/prx/libSceTextToSpeech2/Export.cpp index 375bf561f4..02aaefeadf 100644 --- a/core/libs/prx/libSceTextToSpeech2/Export.cpp +++ b/core/libs/prx/libSceTextToSpeech2/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceTextToSpeech2/include/Api.hpp" #include #include #include "SceTypes.hpp" @@ -9,28 +10,6 @@ constexpr std::int32_t SCE_KERNEL_ERROR_EOPNOTSUPP = static_cast(0 } -struct TextToSpeechInitParameter { - std::uint32_t version; - std::int32_t threadPriority; - std::uint64_t cpuAffinity; - std::uint8_t reserved[48]; -}; - -struct TextToSpeechOpenParameter { - std::uint32_t language; - std::uint32_t voiceType; - std::uint8_t reserved[56]; -}; - -struct TextToSpeechSpeakParameter { - const char16_t* text; - std::uint32_t length; - std::uint32_t mode; - std::uint32_t volume; - std::int32_t speed; - std::uint8_t reserved[40]; -}; - static_assert(sizeof(TextToSpeechInitParameter) == 64); static_assert(sizeof(TextToSpeechOpenParameter) == 64); static_assert(sizeof(TextToSpeechSpeakParameter) == 64); diff --git a/core/libs/prx/libSceTextToSpeech2/include/Api.hpp b/core/libs/prx/libSceTextToSpeech2/include/Api.hpp new file mode 100644 index 0000000000..23340118f7 --- /dev/null +++ b/core/libs/prx/libSceTextToSpeech2/include/Api.hpp @@ -0,0 +1,38 @@ +#pragma once + +#include "SceTypes.hpp" + +struct TextToSpeechInitParameter { + std::uint32_t version; + std::int32_t threadPriority; + std::uint64_t cpuAffinity; + std::uint8_t reserved[48]; +}; + +struct TextToSpeechOpenParameter { + std::uint32_t language; + std::uint32_t voiceType; + std::uint8_t reserved[56]; +}; + +struct TextToSpeechSpeakParameter { + const char16_t* text; + std::uint32_t length; + std::uint32_t mode; + std::uint32_t volume; + std::int32_t speed; + std::uint8_t reserved[40]; +}; + +extern "C" { + +int APS5_VABI sceTextToSpeech2GetSystemStatus(std::int32_t* status); +std::int32_t APS5_VABI sceTextToSpeech2Initialize(const TextToSpeechInitParameter* param); +int APS5_VABI sceTextToSpeech2Cancel(); +int APS5_VABI sceTextToSpeech2Close(); +int APS5_VABI sceTextToSpeech2GetSpeechStatus(std::int32_t* status); +int APS5_VABI sceTextToSpeech2Open(const TextToSpeechOpenParameter* parameter); +int APS5_VABI sceTextToSpeech2Speak(const TextToSpeechSpeakParameter* parameter); +int APS5_VABI sceTextToSpeech2Terminate(); + +} diff --git a/core/libs/prx/libSceTextToSpeech2/libSceTextToSpeech2.hpp b/core/libs/prx/libSceTextToSpeech2/libSceTextToSpeech2.hpp new file mode 100644 index 0000000000..998b2dca7a --- /dev/null +++ b/core/libs/prx/libSceTextToSpeech2/libSceTextToSpeech2.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceTextToSpeech2/include/Api.hpp" diff --git a/core/libs/prx/libSceTtsCoreG3Bc/libSceTtsCoreG3Bc.hpp b/core/libs/prx/libSceTtsCoreG3Bc/libSceTtsCoreG3Bc.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceTtsCoreG3Bc/libSceTtsCoreG3Bc.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceUlt/Export.cpp b/core/libs/prx/libSceUlt/Export.cpp index cc3c25c60a..88ac5556cc 100644 --- a/core/libs/prx/libSceUlt/Export.cpp +++ b/core/libs/prx/libSceUlt/Export.cpp @@ -1,3 +1,6 @@ +#include "prx/libkernel/Pthread/include/ThreadLifecycle.hpp" +#include "prx/libkernel/include/Api.hpp" +#include "prx/libSceUlt/include/Api.hpp" #include #include #include @@ -19,14 +22,8 @@ #include "SceUltTypes.hpp" #include "prx/libSceUlt/src/ReaderWriterLock.hpp" -extern "C" int APS5_VABI scePthreadCreate(Pthread* thread, const PthreadAttr* attr, PthreadEntry entry, void* arg, const char* name); -extern "C" int APS5_VABI scePthreadJoin(Pthread thread, void** retval); -extern "C" void APS5_VABI scePthreadExit(void* retval); -extern "C" void APS5_VABI scePthreadYield(); - namespace { - std::mutex gMutex; std::unordered_map> gMutexes; std::unordered_map> gConditions; @@ -37,7 +34,6 @@ std::unordered_map> gQueues; std::unordered_map gRuntimes; std::unordered_map> gUlthreads; - int validateCommonOptParam(const void* optParam) { if (optParam == nullptr) return ULT_OK; if ((reinterpret_cast(optParam) & 7u) != 0) return ULT_ERROR_ALIGNMENT; @@ -887,6 +883,7 @@ int APS5_VABI sceUltUlthreadYield() { return ULT_ERROR_STATE; } scePthreadYield(); + return ULT_OK; } @@ -896,6 +893,7 @@ int APS5_VABI sceUltUlthreadExit(std::int32_t status) { } gCurrentUlthread->_exited.store(true, std::memory_order_release); scePthreadExit(reinterpret_cast(static_cast(status))); + return ULT_OK; } @@ -1098,5 +1096,4 @@ int APS5_VABI sceUltUlthreadFactoryInitialize() { return 0; } - } diff --git a/core/libs/prx/libSceUlt/include/Api.hpp b/core/libs/prx/libSceUlt/include/Api.hpp new file mode 100644 index 0000000000..c4c3213f0a --- /dev/null +++ b/core/libs/prx/libSceUlt/include/Api.hpp @@ -0,0 +1,96 @@ +#pragma once + +#include "prx/libSceUlt/SceUltTypes.hpp" +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceUltInitialize(); +int APS5_VABI sceUltFinalize(); +int APS5_VABI sceUltMutexOptParamInitialize(UltMutexOptParam* optParam, std::uint32_t buildVersion); +int APS5_VABI sceUltSemaphoreOptParamInitialize(UltOptParam* optParam, std::uint32_t buildVersion); +int APS5_VABI sceUltQueueOptParamInitialize(UltOptParam* optParam, std::uint32_t buildVersion); +int APS5_VABI sceUltQueueDataResourcePoolOptParamInitialize(UltOptParam* optParam, std::uint32_t buildVersion); +int APS5_VABI sceUltWaitingQueueResourcePoolOptParamInitialize(UltOptParam* optParam, std::uint32_t buildVersion); +int APS5_VABI sceUltUlthreadOptParamInitialize(UltOptParam* optParam, std::uint32_t buildVersion); +int APS5_VABI sceUltConditionVariableOptParamInitialize(UltOptParam* optParam, std::uint32_t buildVersion); +int APS5_VABI _sceUltConditionVariableOptParamInitialize(UltOptParam* optParam, std::uint32_t buildVersion); +int APS5_VABI sceUltMutexCreate(void* mutex, const char* name, void* waitingQueueResourcePool, const UltMutexOptParam* optParam, std::uint32_t buildVersion); +int APS5_VABI sceUltMutexDestroy(void* mutex); +int APS5_VABI sceUltMutexLock(void* mutex); +int APS5_VABI sceUltMutexTryLock(void* mutex); +int APS5_VABI sceUltMutexUnlock(void* mutex); +int APS5_VABI sceUltConditionVariableCreate(void* condition, const char* name, void* mutex, const void* optParam, std::uint32_t buildVersion); +int APS5_VABI _sceUltConditionVariableCreate(void* condition, const char* name, void* mutex, const void* optParam, std::uint32_t buildVersion); +int APS5_VABI sceUltConditionVariableDestroy(void* condition); +int APS5_VABI sceUltConditionVariableSignal(void* condition); +int APS5_VABI sceUltConditionVariableWait(void* condition); +std::uint64_t APS5_VABI sceUltWaitingQueueResourcePoolGetWorkAreaSize(std::uint32_t numThreads, std::uint32_t numSyncObjects); +int APS5_VABI sceUltWaitingQueueResourcePoolCreate(void* pool, const char* name, std::uint32_t numThreads, std::uint32_t numSyncObjects, void* workArea, const void* optParam, std::uint32_t buildVersion); +int APS5_VABI sceUltWaitingQueueResourcePoolDestroy(void* pool); +std::uint64_t APS5_VABI sceUltQueueDataResourcePoolGetWorkAreaSize(std::uint32_t numData, std::uint64_t dataSize, std::uint32_t numQueueObject); +int APS5_VABI sceUltQueueDataResourcePoolCreate(void* pool, const char* name, std::uint32_t numData, std::uint64_t dataSize, std::uint32_t numQueueObject, void* waitingQueueResourcePool, void* workArea, const void* optParam, std::uint32_t buildVersion); +int APS5_VABI sceUltQueueDataResourcePoolDestroy(void* pool); +int APS5_VABI sceUltQueueCreate(void* queue, const char* name, std::uint64_t dataSize, void* waitingQueueResourcePool, void* queueDataResourcePool, const void* optParam, std::uint32_t buildVersion); +int APS5_VABI sceUltQueuePush(void* queue, const void* data); +int APS5_VABI sceUltQueueTryPush(void* queue, const void* data); +int APS5_VABI sceUltQueuePop(void* queue, void* data); +int APS5_VABI sceUltQueueTryPop(void* queue, void* data); +int APS5_VABI sceUltQueueDestroy(void* queue); +int APS5_VABI sceUltSemaphoreCreate(void* semaphore, const char* name, std::uint32_t numInitialResource, void* waitingQueueResourcePool, const void* optParam, std::uint32_t buildVersion); +int APS5_VABI sceUltSemaphoreAcquire(void* semaphore, std::int32_t numResource); +int APS5_VABI sceUltSemaphoreTryAcquire(void* semaphore, std::int32_t numResource); +int APS5_VABI sceUltSemaphoreRelease(void* semaphore, std::int32_t numResource); +int APS5_VABI sceUltSemaphoreDestroy(void* semaphore); +int APS5_VABI sceUltUlthreadRuntimeOptParamInitialize(UltUlthreadRuntimeOptParam* optParam, std::uint32_t buildVersion); +std::uint64_t APS5_VABI sceUltUlthreadRuntimeGetWorkAreaSize(std::uint32_t maxNumUlthread, std::uint32_t numWorkerThread); +int APS5_VABI sceUltUlthreadRuntimeCreate(void* runtime, const char* name, std::uint32_t maxNumUlthread, std::uint32_t numWorkerThread, void* workArea, const void* optParam, std::uint32_t buildVersion); +int APS5_VABI sceUltUlthreadCreate(void* ulthread, const char* name, UltUlthreadEntry entry, std::uint64_t arg, void* context, std::uint64_t sizeContext, void* runtime, const void* optParam, std::uint32_t buildVersion); +int APS5_VABI sceUltUlthreadJoin(void* ulthread, std::int32_t* status); +int APS5_VABI sceUltUlthreadTryJoin(void* ulthread, std::int32_t* status); +int APS5_VABI sceUltUlthreadGetSelf(void** ulthread); +int APS5_VABI sceUltUlthreadYield(); +int APS5_VABI sceUltUlthreadExit(std::int32_t status); +int APS5_VABI sceUltUlthreadRuntimeDestroy(void* runtime); +int APS5_VABI _sceUltWaitingQueueResourcePoolCreate(void* pool, const char* name, std::uint32_t numThreads, std::uint32_t numSyncObjects, void* workArea, const void* optParam); +int APS5_VABI _sceUltSemaphoreCreate(void* semaphore, const char* name, std::uint32_t numInitialResource, void* waitingQueueResourcePool, const void* optParam); +int APS5_VABI _sceUltMutexOptParamInitialize(UltMutexOptParam* optParam, std::uint32_t buildVersion); +int APS5_VABI _sceUltMutexCreate(void* mutex, const char* name, void* waitingQueueResourcePool, const UltMutexOptParam* optParam); +int APS5_VABI _sceUltQueueDataResourcePoolCreate(void* pool, const char* name, std::uint32_t numData, std::uint64_t dataSize, std::uint32_t numQueueObject, void* waitingQueueResourcePool, void* workArea, const void* optParam); +int APS5_VABI _sceUltQueueCreate(void* queue, const char* name, std::uint64_t dataSize, void* waitingQueueResourcePool, void* queueDataResourcePool, const void* optParam); +int APS5_VABI _sceUltUlthreadRuntimeOptParamInitialize(UltUlthreadRuntimeOptParam* optParam, std::uint32_t buildVersion); +int APS5_VABI _sceUltUlthreadRuntimeCreate(void* runtime, const char* name, std::uint32_t maxNumUlthread, std::uint32_t numWorkerThread, void* workArea, const void* optParam); +int APS5_VABI _sceUltUlthreadCreate(void* ulthread, const char* name, UltUlthreadEntry entry, std::uint64_t arg, void* context, std::uint64_t sizeContext, void* runtime, const void* optParam); +int APS5_VABI sceUltConditionVariableSignalAll(void* conditionVariable); +int APS5_VABI sceUltGetConditionVariableInfo(void* object, UltConditionVariableInfo* info, UltWaitingThreadInfo* waitingThreads, std::uint32_t capacity); +int APS5_VABI sceUltGetMutexInfo(void* object, UltMutexInfo* info, UltWaitingThreadInfo* waitingThreads, std::uint32_t capacity); +int APS5_VABI sceUltGetQueueDataResourcePoolInfo(void* object, UltQueueDataResourcePoolInfo* info); +int APS5_VABI sceUltGetQueueInfo(void* object, UltQueueInfo* info, UltWaitingThreadInfo* waitingThreads, std::uint32_t capacity); +int APS5_VABI sceUltGetReaderWriterLockInfo(void* object, UltReaderWriterLockInfo* info, UltWaitingThreadInfo* waitingThreads, std::uint32_t capacity); +int APS5_VABI sceUltGetSemaphoreInfo(void* object, UltSemaphoreInfo* info, UltWaitingThreadInfo* waitingThreads, std::uint32_t capacity); +int APS5_VABI sceUltGetUlthreadInfo(void* object, UltUlthreadInfo* info); +int APS5_VABI sceUltGetUlthreadRuntimeInfo(void* runtime, UltUlthreadRuntimeInfo* info, void** ulthreads, std::uint32_t ulthreadCapacity, Pthread* workerThreads, std::uint32_t workerCapacity); +int APS5_VABI sceUltGetWaitingQueueResourcePoolInfo(void* object, UltWaitingQueueResourcePoolInfo* info); +int APS5_VABI sceUltAbstractThreadFactoryCreateThread(); +int APS5_VABI sceUltAbstractThreadFactoryGetNumMaxThreads(); +int APS5_VABI sceUltAbstractThreadFactoryJoinThread(); +int APS5_VABI sceUltKernelThreadFactoryFinalize(); +int APS5_VABI sceUltKernelThreadFactoryGetFactoryPointer(); +int APS5_VABI sceUltKernelThreadFactoryInitialize(); +int APS5_VABI sceUltModuleFinalize(); +int APS5_VABI sceUltModuleInitialize(); +int APS5_VABI sceUltUlthreadFactoryFinalize(); +int APS5_VABI sceUltUlthreadFactoryGetFactoryPointer(); +int APS5_VABI sceUltUlthreadFactoryGetWorkAreaSize(); +int APS5_VABI sceUltUlthreadFactoryInitialize(); +int APS5_VABI sceUltReaderWriterLockOptParamInitialize(UltOptParam* optParam, std::uint32_t buildVersion); +int APS5_VABI sceUltReaderWriterLockCreate(void* rwlock, const char* name, void* waitingQueueResourcePool, const UltOptParam* optParam, std::uint32_t buildVersion); +int APS5_VABI sceUltReaderWriterLockDestroy(void* rwlock); +int APS5_VABI sceUltReaderWriterLockLockRead(void* rwlock); +int APS5_VABI sceUltReaderWriterLockTryLockRead(void* rwlock); +int APS5_VABI sceUltReaderWriterLockUnlockRead(void* rwlock); +int APS5_VABI sceUltReaderWriterLockLockWrite(void* rwlock); +int APS5_VABI sceUltReaderWriterLockTryLockWrite(void* rwlock); +int APS5_VABI sceUltReaderWriterLockUnlockWrite(void* rwlock); + +} diff --git a/core/libs/prx/libSceUlt/libSceUlt.hpp b/core/libs/prx/libSceUlt/libSceUlt.hpp new file mode 100644 index 0000000000..260a68efda --- /dev/null +++ b/core/libs/prx/libSceUlt/libSceUlt.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceUlt/include/Api.hpp" diff --git a/core/libs/prx/libSceUlt/src/ReaderWriterLock.cpp b/core/libs/prx/libSceUlt/src/ReaderWriterLock.cpp index c947260041..ba86691ca6 100644 --- a/core/libs/prx/libSceUlt/src/ReaderWriterLock.cpp +++ b/core/libs/prx/libSceUlt/src/ReaderWriterLock.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceUlt/include/Api.hpp" #include "prx/libSceUlt/src/ReaderWriterLock.hpp" #include "prx/libSceUlt/SceUltTypes.hpp" #include diff --git a/core/libs/prx/libSceUpdateService/Export.cpp b/core/libs/prx/libSceUpdateService/Export.cpp index 7fc0488786..d434762726 100644 --- a/core/libs/prx/libSceUpdateService/Export.cpp +++ b/core/libs/prx/libSceUpdateService/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceUpdateService/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceUpdateService/include/Api.hpp b/core/libs/prx/libSceUpdateService/include/Api.hpp new file mode 100644 index 0000000000..9dce013b86 --- /dev/null +++ b/core/libs/prx/libSceUpdateService/include/Api.hpp @@ -0,0 +1,48 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceUpsrvGetCompletedTaskId(); +int APS5_VABI sceUpsrvGetRebootFlag(); +int APS5_VABI sceUpsrvGetSystemExUpdateTaskState(); +int APS5_VABI sceUpsrvInitialize(); +int APS5_VABI sceUpsrvPostErrorLog(); +int APS5_VABI sceUpsrvResumePausedTask(); +int APS5_VABI sceUpsrvSetFakeVersion(); +int APS5_VABI sceUpsrvStartUpdateSession(); +int APS5_VABI sceUpsrvSwitchSystemExBank(); +int APS5_VABI sceUpsrvSwitchSystemExBankWithoutVerify(); +int APS5_VABI sceUpsrvTerminate(); +int APS5_VABI sceUpsrvUpdateCancelBDUpdate(); +int APS5_VABI sceUpsrvUpdateCheckCancel(); +int APS5_VABI sceUpsrvUpdateCheckCreateHandler(); +int APS5_VABI sceUpsrvUpdateCheckDestroyHandler(); +int APS5_VABI sceUpsrvUpdateCheckDoCheckSystem(); +int APS5_VABI sceUpsrvUpdateCheckDoCheckSystemForDevKit(); +int APS5_VABI sceUpsrvUpdateCheckDoCheckSystemForSettings(); +int APS5_VABI sceUpsrvUpdateCheckDoCheckSystemWithPupInfo(); +int APS5_VABI sceUpsrvUpdateCreateUpdateTask(); +int APS5_VABI sceUpsrvUpdateDestroyUpdateTask(); +int APS5_VABI sceUpsrvUpdateDoCheckBootUpdate(); +int APS5_VABI sceUpsrvUpdateDoUpdateSystemEx(); +int APS5_VABI sceUpsrvUpdateDoUpdateWithEntitlement(); +int APS5_VABI sceUpsrvUpdateDoUpdateWithPupInfo(); +int APS5_VABI sceUpsrvUpdateDoUpdateWithPupPath2(); +int APS5_VABI sceUpsrvUpdateGetBetaAgreementUrl(); +int APS5_VABI sceUpsrvUpdateGetEulaDisplay(); +int APS5_VABI sceUpsrvUpdateGetEulaStr(); +int APS5_VABI sceUpsrvUpdateGetEulaStrLen(); +int APS5_VABI sceUpsrvUpdateGetFeatureListUrl(); +int APS5_VABI sceUpsrvUpdateGetFeatureListUrlForSystemExUpdate(); +int APS5_VABI sceUpsrvUpdateGetFeatureListUrlForUpdate(); +int APS5_VABI sceUpsrvUpdateGetImageWritingProgress(); +int APS5_VABI sceUpsrvUpdateGetProgress(); +int APS5_VABI sceUpsrvUpdateGetUpdateTaskInfo(); +int APS5_VABI sceUpsrvUpdateGetUpdateTaskMgrInfo(); +int APS5_VABI sceUpsrvUpdateSetEulaAccept(); +int APS5_VABI sceUpsrvUpdateStartUpdateTask(); +int APS5_VABI sceUpsrvVerifySystemExBank(); + +} diff --git a/core/libs/prx/libSceUpdateService/libSceUpdateService.hpp b/core/libs/prx/libSceUpdateService/libSceUpdateService.hpp new file mode 100644 index 0000000000..87a15733f7 --- /dev/null +++ b/core/libs/prx/libSceUpdateService/libSceUpdateService.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceUpdateService/include/Api.hpp" diff --git a/core/libs/prx/libSceUrlConfigResolver/Export.cpp b/core/libs/prx/libSceUrlConfigResolver/Export.cpp index 60d243d931..85b45cd6ad 100644 --- a/core/libs/prx/libSceUrlConfigResolver/Export.cpp +++ b/core/libs/prx/libSceUrlConfigResolver/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceUrlConfigResolver/include/Api.hpp" #include #include #include "SceTypes.hpp" @@ -25,7 +26,6 @@ int APS5_VABI sceUrlConfigResolverGetJscHeapSizeSoftLimit() { return 0; } - int APS5_VABI sceUrlConfigResolverGetReleaseVersion() { NotImplemented_nid_no_patch(__func__); return 0; diff --git a/core/libs/prx/libSceUrlConfigResolver/include/Api.hpp b/core/libs/prx/libSceUrlConfigResolver/include/Api.hpp new file mode 100644 index 0000000000..e5eb270f75 --- /dev/null +++ b/core/libs/prx/libSceUrlConfigResolver/include/Api.hpp @@ -0,0 +1,16 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceUrlConfigResolverGetAppConfig(); +int APS5_VABI sceUrlConfigResolverGetDefaultQueryParameter(); +int APS5_VABI sceUrlConfigResolverGetDeviceId(); +int APS5_VABI sceUrlConfigResolverGetJscHeapSizeSoftLimit(); +int APS5_VABI sceUrlConfigResolverGetReleaseVersion(); +int APS5_VABI sceUrlConfigResolverGetSysVer(); +int APS5_VABI sceUrlConfigResolverIsUpdated(); +int APS5_VABI sceUrlConfigResolverUpdate(); + +} diff --git a/core/libs/prx/libSceUrlConfigResolver/libSceUrlConfigResolver.hpp b/core/libs/prx/libSceUrlConfigResolver/libSceUrlConfigResolver.hpp new file mode 100644 index 0000000000..cd604928ca --- /dev/null +++ b/core/libs/prx/libSceUrlConfigResolver/libSceUrlConfigResolver.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceUrlConfigResolver/include/Api.hpp" diff --git a/core/libs/prx/libSceUsbStorage/Export.cpp b/core/libs/prx/libSceUsbStorage/Export.cpp index 0a837a06f4..978a9dc386 100644 --- a/core/libs/prx/libSceUsbStorage/Export.cpp +++ b/core/libs/prx/libSceUsbStorage/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceSystemService/include/SystemService.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceUsbStorage/libSceUsbStorage.hpp b/core/libs/prx/libSceUsbStorage/libSceUsbStorage.hpp new file mode 100644 index 0000000000..bf34865160 --- /dev/null +++ b/core/libs/prx/libSceUsbStorage/libSceUsbStorage.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceUsbStorage/UsbStorage.hpp" diff --git a/core/libs/prx/libSceUsbStorageDialog/Export.cpp b/core/libs/prx/libSceUsbStorageDialog/Export.cpp index 612ac95a57..290ab47eca 100644 --- a/core/libs/prx/libSceUsbStorageDialog/Export.cpp +++ b/core/libs/prx/libSceUsbStorageDialog/Export.cpp @@ -1,3 +1,5 @@ +#include "prx/libSceUsbStorageDialog/include/Api.hpp" +#include "prx/libSceUserService/UserService.hpp" #include #include #include @@ -7,8 +9,6 @@ #include "prx/libc/include/ApplicationHeap.hpp" #include "prx/libc/include/General.hpp" -extern "C" int APS5_VABI sceUserServiceGetLoginUserIdList(UserServiceLoginUserIdList* users); - namespace { constexpr int COMMON_DIALOG_STATUS_NONE = 0; diff --git a/core/libs/prx/libSceUsbStorageDialog/include/Api.hpp b/core/libs/prx/libSceUsbStorageDialog/include/Api.hpp new file mode 100644 index 0000000000..636ddf50f5 --- /dev/null +++ b/core/libs/prx/libSceUsbStorageDialog/include/Api.hpp @@ -0,0 +1,16 @@ +#pragma once + +#include "prx/libSceCommonDialog/CommonDialog.hpp" +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceUsbStorageDialogInitialize(void); +int APS5_VABI sceUsbStorageDialogOpen(const UsbStorageDialogParam* param); +int APS5_VABI sceUsbStorageDialogGetStatus(void); +int APS5_VABI sceUsbStorageDialogUpdateStatus(void); +int APS5_VABI sceUsbStorageDialogGetResult(UsbStorageDialogResult* result); +int APS5_VABI sceUsbStorageDialogClose(void); +int APS5_VABI sceUsbStorageDialogTerminate(void); + +} diff --git a/core/libs/prx/libSceUsbStorageDialog/libSceUsbStorageDialog.hpp b/core/libs/prx/libSceUsbStorageDialog/libSceUsbStorageDialog.hpp new file mode 100644 index 0000000000..fdc47497d7 --- /dev/null +++ b/core/libs/prx/libSceUsbStorageDialog/libSceUsbStorageDialog.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceUsbStorageDialog/include/Api.hpp" diff --git a/core/libs/prx/libSceUsbd/Export.cpp b/core/libs/prx/libSceUsbd/Export.cpp index 2859958e57..edc6a19de0 100644 --- a/core/libs/prx/libSceUsbd/Export.cpp +++ b/core/libs/prx/libSceUsbd/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceUsbd/include/Api.hpp" #include #include #include "SceTypes.hpp" @@ -5,6 +6,7 @@ #include +#include #include #include #include @@ -31,35 +33,6 @@ constexpr std::uint8_t SUPPORTED_TRANSFER_FLAGS = LIBUSB_TRANSFER_SHORT_NOT_OK | constexpr std::uint16_t STRING_DESCRIPTOR_SIZE = 255; constexpr std::uint32_t STRING_DESCRIPTOR_TIMEOUT = 1000; -struct UsbdTimeval { - std::int64_t seconds; - std::int64_t microseconds; -}; - -struct UsbdIsoPacketDescriptor { - std::uint32_t length; - std::uint32_t actualLength; - std::int32_t status; -}; - -using UsbdTransferCallback = void (APS5_VABI*)(struct UsbdTransfer*); - -struct UsbdTransfer { - void* deviceHandle; - std::uint8_t flags; - std::uint8_t endpoint; - std::uint8_t type; - std::uint32_t timeout; - std::int32_t status; - std::int32_t length; - std::int32_t actualLength; - UsbdTransferCallback callback; - void* userData; - std::uint8_t* buffer; - std::int32_t numIsoPackets; - UsbdIsoPacketDescriptor isoPacketDescriptors[1]; -}; - static_assert(offsetof(UsbdTransfer, timeout) == 12 && offsetof(UsbdTransfer, callback) == 32 && offsetof(UsbdTransfer, numIsoPackets) == 56 && offsetof(UsbdTransfer, isoPacketDescriptors) == 60); static_assert(sizeof(libusb_device_descriptor) == 18); static_assert(sizeof(libusb_config_descriptor) == 40 && offsetof(libusb_config_descriptor, interface) == 16 && offsetof(libusb_config_descriptor, extra) == 24 && offsetof(libusb_config_descriptor, extra_length) == 32); @@ -75,6 +48,7 @@ struct UsbdState { std::unordered_map devices; std::unordered_set lists; std::unordered_set handles; + std::unordered_map claimed; std::unordered_set configs; std::unordered_map inFlight; }; @@ -100,11 +74,15 @@ std::int32_t ToGuestError(int result) { return static_cast(0x80240000u - static_cast(result)); } +bool IsKnownDevice(const UsbdState& state, libusb_device* device) { + return state.devices.contains(device) || std::any_of(state.handles.begin(), state.handles.end(), [device](libusb_device_handle* handle) { return libusb_get_device(handle) == device; }); +} + libusb_device* KnownDevice(void* device, const char* function) { auto& state = State(); std::lock_guard lock(state.mutex); auto* host = static_cast(device); - if (!state.devices.contains(host)) throw std::runtime_error(AbsentDevice(function)); + if (!IsKnownDevice(state, host)) throw std::runtime_error(AbsentDevice(function)); return host; } @@ -143,6 +121,27 @@ void LIBUSB_CALL CompleteTransfer(libusb_transfer* host) { if (guest->callback != nullptr) guest->callback(guest); } +int MaxPacketSize(libusb_device* device, std::uint8_t endpoint) { + libusb_config_descriptor* config = nullptr; + const int result = libusb_get_active_config_descriptor(device, &config); + if (result < 0) return result; + int size = LIBUSB_ERROR_NOT_FOUND; + for (int index = 0; index < config->bNumInterfaces && size == LIBUSB_ERROR_NOT_FOUND; ++index) { + const auto& entry = config->interface[index]; + for (int alternate = 0; alternate < entry.num_altsetting && size == LIBUSB_ERROR_NOT_FOUND; ++alternate) { + const auto& setting = entry.altsetting[alternate]; + for (int item = 0; item < setting.bNumEndpoints; ++item) { + if (setting.endpoint[item].bEndpointAddress == endpoint) { + size = setting.endpoint[item].wMaxPacketSize; + break; + } + } + } + } + libusb_free_config_descriptor(config); + return size; +} + bool RequestStringDescriptor(libusb_device_handle* handle, std::uint8_t descriptorIndex, std::uint16_t languageId, std::uint8_t* descriptor) { std::memset(descriptor, 0, STRING_DESCRIPTOR_SIZE); const auto value = static_cast(LIBUSB_DT_STRING << 8 | descriptorIndex); @@ -171,6 +170,7 @@ void APS5_VABI sceUsbdExit() { if (state.initCount == 0 || --state.initCount != 0) return; if (!state.inFlight.empty()) throw std::runtime_error(std::string(__func__) + ": transfers are still in flight"); for (auto* handle : state.handles) libusb_close(handle); + state.claimed.clear(); for (auto* config : state.configs) libusb_free_config_descriptor(config); for (auto* list : state.lists) libusb_free_device_list(list, 0); for (const auto& [device, references] : state.devices) { @@ -386,7 +386,14 @@ std::int32_t APS5_VABI sceUsbdCheckConnected(void* deviceHandle) { std::int32_t APS5_VABI sceUsbdClaimInterface(void* deviceHandle, std::int32_t interfaceNumber) { if (deviceHandle == nullptr) return SCE_USBD_ERROR_INVALID_ARG; - return ToGuestError(libusb_claim_interface(KnownHandle(deviceHandle, __func__), interfaceNumber)); + auto* handle = KnownHandle(deviceHandle, __func__); + const int result = libusb_claim_interface(handle, interfaceNumber); + if (result == 0) { + auto& state = State(); + std::lock_guard lock(state.mutex); + state.claimed[handle] |= 1u << interfaceNumber; + } + return ToGuestError(result); } void APS5_VABI sceUsbdClose(void* deviceHandle) { @@ -395,6 +402,7 @@ void APS5_VABI sceUsbdClose(void* deviceHandle) { std::lock_guard lock(state.mutex); auto* host = static_cast(deviceHandle); if (state.handles.erase(host) == 0) throw std::runtime_error(UnopenedHandle(__func__)); + state.claimed.erase(host); libusb_close(host); } @@ -477,14 +485,21 @@ void* APS5_VABI sceUsbdRefDevice(void* device) { auto& state = State(); std::lock_guard lock(state.mutex); auto* host = static_cast(device); - if (!state.devices.contains(host)) throw std::runtime_error(AbsentDevice(__func__)); + if (!IsKnownDevice(state, host)) throw std::runtime_error(AbsentDevice(__func__)); AddDeviceReference(state, host); return libusb_ref_device(host); } std::int32_t APS5_VABI sceUsbdReleaseInterface(void* deviceHandle, std::int32_t interfaceNumber) { if (deviceHandle == nullptr) return SCE_USBD_ERROR_INVALID_ARG; - return ToGuestError(libusb_release_interface(KnownHandle(deviceHandle, __func__), interfaceNumber)); + auto* handle = KnownHandle(deviceHandle, __func__); + const int result = libusb_release_interface(handle, interfaceNumber); + if (result == 0) { + auto& state = State(); + std::lock_guard lock(state.mutex); + state.claimed[handle] &= ~(1u << interfaceNumber); + } + return ToGuestError(result); } std::int32_t APS5_VABI sceUsbdResetDevice(void* deviceHandle) { @@ -544,13 +559,16 @@ void APS5_VABI sceUsbdUnrefDevice(void* device) { } std::int32_t APS5_VABI sceUsbdClearHalt(void* deviceHandle, std::uint8_t endpoint) { - NotImplemented_nid_no_patch(__func__); - return 0; + if (deviceHandle == nullptr) throw std::runtime_error(std::string(__func__) + ": null handle"); + const int result = libusb_clear_halt(KnownHandle(deviceHandle, __func__), endpoint); + if (result == 0) return 0; + if (result == LIBUSB_ERROR_NOT_FOUND) return SCE_USBD_ERROR_OTHER; + throw std::runtime_error(std::string(__func__) + ": libusb error " + std::to_string(result) + " has no known console result"); } std::int32_t APS5_VABI sceUsbdDetachKernelDriver(void* deviceHandle, int interfaceNumber) { - NotImplemented_nid_no_patch(__func__); - return 0; + if (deviceHandle == nullptr) return SCE_USBD_ERROR_INVALID_ARG; + return libusb_detach_kernel_driver(KnownHandle(deviceHandle, __func__), static_cast(interfaceNumber)) == 0 ? 0 : SCE_USBD_ERROR_OTHER; } std::int32_t APS5_VABI sceUsbdEventHandlerActive() { @@ -587,23 +605,27 @@ std::int32_t APS5_VABI sceUsbdGetDescriptor(void* deviceHandle, std::uint8_t des } void* APS5_VABI sceUsbdGetDevice(void* deviceHandle) { - NotImplemented_nid_no_patch(__func__); - return 0; + if (deviceHandle == nullptr) return nullptr; + return libusb_get_device(KnownHandle(deviceHandle, __func__)); } int APS5_VABI sceUsbdGetDeviceSpeed(void* device) { - NotImplemented_nid_no_patch(__func__); - return 0; + if (device == nullptr) return LIBUSB_SPEED_UNKNOWN; + return std::min(libusb_get_device_speed(KnownDevice(device, __func__)), static_cast(LIBUSB_SPEED_SUPER)); } std::int32_t APS5_VABI sceUsbdGetMaxIsoPacketSize(void* device, std::uint8_t endpoint) { - NotImplemented_nid_no_patch(__func__); - return 0; + if (device == nullptr) throw std::runtime_error(std::string(__func__) + ": null device"); + auto* host = KnownDevice(device, __func__); + int size = MaxPacketSize(host, endpoint); + const int speed = libusb_get_device_speed(host); + if (speed != LIBUSB_SPEED_LOW && speed != LIBUSB_SPEED_FULL && size >= 0) size = (size & 0x7FF) * std::min(1 + ((size >> 11) & 3), 3); + return ToGuestError(size); } std::int32_t APS5_VABI sceUsbdGetMaxPacketSize(void* device, std::uint8_t endpoint) { - NotImplemented_nid_no_patch(__func__); - return 0; + if (device == nullptr) return ToGuestError(LIBUSB_ERROR_NO_DEVICE); + return ToGuestError(MaxPacketSize(KnownDevice(device, __func__), endpoint)); } std::int32_t APS5_VABI sceUsbdGetStringDescriptorAscii(void* deviceHandle, std::uint8_t descriptorIndex, std::uint8_t* data, std::int32_t length) { @@ -657,13 +679,39 @@ void APS5_VABI sceUsbdLockEvents() { } void* APS5_VABI sceUsbdOpenDeviceWithVidPid(std::uint16_t vendorId, std::uint16_t productId) { - NotImplemented_nid_no_patch(__func__); - return 0; + auto& state = State(); + std::lock_guard lock(state.mutex); + if (state.context == nullptr) return nullptr; + libusb_device** devices = nullptr; + const ssize_t count = libusb_get_device_list(state.context, &devices); + if (count < 0) return nullptr; + libusb_device_handle* handle = nullptr; + for (ssize_t index = 0; index < count; ++index) { + libusb_device_descriptor descriptor{}; + if (libusb_get_device_descriptor(devices[index], &descriptor) == 0 && descriptor.idVendor == vendorId && descriptor.idProduct == productId) { + if (libusb_open(devices[index], &handle) != 0) handle = nullptr; + break; + } + } + libusb_free_device_list(devices, 1); + if (handle != nullptr) state.handles.insert(handle); + return handle; } std::int32_t APS5_VABI sceUsbdSetInterfaceAltSetting(void* deviceHandle, int interfaceNumber, int alternateSetting) { - NotImplemented_nid_no_patch(__func__); - return 0; + if (deviceHandle == nullptr) return SCE_USBD_ERROR_INVALID_ARG; + auto* handle = KnownHandle(deviceHandle, __func__); + if (interfaceNumber < 0 || interfaceNumber > 31) return SCE_USBD_ERROR_INVALID_ARG; + { + auto& state = State(); + std::lock_guard lock(state.mutex); + const auto claimed = state.claimed.find(handle); + if (claimed == state.claimed.end() || (claimed->second & (1u << interfaceNumber)) == 0) return ToGuestError(LIBUSB_ERROR_NOT_FOUND); + for (const auto& [guest, host] : state.inFlight) { + if (host->dev_handle == handle) throw std::runtime_error(std::string(__func__) + ": the device has transfers in flight, which FreeBSD libusb cancels first"); + } + } + return libusb_set_interface_alt_setting(handle, interfaceNumber, static_cast(alternateSetting)) == 0 ? 0 : SCE_USBD_ERROR_OTHER; } std::int32_t APS5_VABI sceUsbdTryLockEvents() { diff --git a/core/libs/prx/libSceUsbd/include/Api.hpp b/core/libs/prx/libSceUsbd/include/Api.hpp new file mode 100644 index 0000000000..5b5aa49a05 --- /dev/null +++ b/core/libs/prx/libSceUsbd/include/Api.hpp @@ -0,0 +1,111 @@ +#pragma once + +#include "SceTypes.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct UsbdTimeval { + std::int64_t seconds; + std::int64_t microseconds; +}; + +struct UsbdIsoPacketDescriptor { + std::uint32_t length; + std::uint32_t actualLength; + std::int32_t status; +}; + +using UsbdTransferCallback = void (APS5_VABI*)(struct UsbdTransfer*); + +struct UsbdTransfer { + void* deviceHandle; + std::uint8_t flags; + std::uint8_t endpoint; + std::uint8_t type; + std::uint32_t timeout; + std::int32_t status; + std::int32_t length; + std::int32_t actualLength; + UsbdTransferCallback callback; + void* userData; + std::uint8_t* buffer; + std::int32_t numIsoPackets; + UsbdIsoPacketDescriptor isoPacketDescriptors[1]; +}; + +extern "C" { + +std::int32_t APS5_VABI sceUsbdInit(); +void APS5_VABI sceUsbdExit(); +std::int64_t APS5_VABI sceUsbdGetDeviceList(void*** list); +void APS5_VABI sceUsbdFreeDeviceList(void** list, std::int32_t unrefDevices); +std::int32_t APS5_VABI sceUsbdHandleEventsTimeout(const UsbdTimeval* timeout); +UsbdTransfer* APS5_VABI sceUsbdAllocTransfer(std::int32_t isoPackets); +void APS5_VABI sceUsbdFreeTransfer(UsbdTransfer* transfer); +void APS5_VABI sceUsbdFillInterruptTransfer(UsbdTransfer* transfer, void* deviceHandle, std::uint8_t endpoint, std::uint8_t* buffer, std::int32_t length, UsbdTransferCallback callback, void* userData, std::uint32_t timeout); +void APS5_VABI sceUsbdFillBulkTransfer(UsbdTransfer* transfer, void* deviceHandle, std::uint8_t endpoint, std::uint8_t* buffer, std::int32_t length, UsbdTransferCallback callback, void* userData, std::uint32_t timeout); +void APS5_VABI sceUsbdFillIsoTransfer(UsbdTransfer* transfer, void* deviceHandle, std::uint8_t endpoint, std::uint8_t* buffer, std::int32_t length, std::int32_t numIsoPackets, UsbdTransferCallback callback, void* userData, std::uint32_t timeout); +void APS5_VABI sceUsbdFillControlSetup(std::uint8_t* buffer, std::uint8_t requestType, std::uint8_t request, std::uint16_t value, std::uint16_t index, std::uint16_t length); +void APS5_VABI sceUsbdFillControlTransfer(UsbdTransfer* transfer, void* deviceHandle, std::uint8_t* buffer, UsbdTransferCallback callback, void* userData, std::uint32_t timeout); +std::uint8_t* APS5_VABI sceUsbdControlTransferGetData(UsbdTransfer* transfer); +std::uint8_t* APS5_VABI sceUsbdControlTransferGetSetup(UsbdTransfer* transfer); +void APS5_VABI sceUsbdSetIsoPacketLengths(UsbdTransfer* transfer, std::uint32_t length); +std::uint8_t* APS5_VABI sceUsbdGetIsoPacketBuffer(UsbdTransfer* transfer, std::uint32_t packet); +std::int32_t APS5_VABI sceUsbdBulkTransfer(void* deviceHandle, std::uint8_t endpoint, std::uint8_t* data, std::int32_t length, std::int32_t* transferred, std::uint32_t timeout); +std::int32_t APS5_VABI sceUsbdInterruptTransfer(void* deviceHandle, std::uint8_t endpoint, std::uint8_t* data, std::int32_t length, std::int32_t* transferred, std::uint32_t timeout); +std::int32_t APS5_VABI sceUsbdCancelTransfer(UsbdTransfer* transfer); +std::int32_t APS5_VABI sceUsbdEventHandlingOk(); +void APS5_VABI sceUsbdFreeConfigDescriptor(void* config); +std::int32_t APS5_VABI sceUsbdAttachKernelDriver(void* deviceHandle, std::int32_t interfaceNumber); +std::int32_t APS5_VABI sceUsbdCheckConnected(void* deviceHandle); +std::int32_t APS5_VABI sceUsbdClaimInterface(void* deviceHandle, std::int32_t interfaceNumber); +void APS5_VABI sceUsbdClose(void* deviceHandle); +std::int32_t APS5_VABI sceUsbdControlTransfer(void* deviceHandle, std::uint8_t requestType, std::uint8_t request, std::uint16_t value, std::uint16_t index, std::uint8_t* data, std::uint16_t length, std::uint32_t timeout); +std::int32_t APS5_VABI sceUsbdGetActiveConfigDescriptor(void* device, void** config); +std::uint8_t APS5_VABI sceUsbdGetBusNumber(void* device); +std::int32_t APS5_VABI sceUsbdGetConfigDescriptor(void* device, std::uint8_t configIndex, void** config); +std::uint8_t APS5_VABI sceUsbdGetDeviceAddress(void* device); +std::int32_t APS5_VABI sceUsbdGetDeviceDescriptor(void* device, void* descriptor); +std::int32_t APS5_VABI sceUsbdGetStringDescriptor(void* deviceHandle, std::uint8_t descriptorIndex, std::uint16_t languageId, std::uint8_t* data, std::int32_t length); +std::int32_t APS5_VABI sceUsbdKernelDriverActive(void* deviceHandle, std::int32_t interfaceNumber); +std::int32_t APS5_VABI sceUsbdOpen(void* device, void** deviceHandle); +void* APS5_VABI sceUsbdRefDevice(void* device); +std::int32_t APS5_VABI sceUsbdReleaseInterface(void* deviceHandle, std::int32_t interfaceNumber); +std::int32_t APS5_VABI sceUsbdResetDevice(void* deviceHandle); +std::int32_t APS5_VABI sceUsbdSetConfiguration(void* deviceHandle, std::int32_t configuration); +std::int32_t APS5_VABI sceUsbdSubmitTransfer(UsbdTransfer* transfer); +void APS5_VABI sceUsbdUnrefDevice(void* device); +std::int32_t APS5_VABI sceUsbdClearHalt(void* deviceHandle, std::uint8_t endpoint); +std::int32_t APS5_VABI sceUsbdDetachKernelDriver(void* deviceHandle, int interfaceNumber); +std::int32_t APS5_VABI sceUsbdEventHandlerActive(); +std::int32_t APS5_VABI sceUsbdGetConfigDescriptorByValue(void* device, std::uint8_t configurationValue, void** config); +std::int32_t APS5_VABI sceUsbdGetConfiguration(void* deviceHandle, std::int32_t* configuration); +std::int32_t APS5_VABI sceUsbdGetDescriptor(void* deviceHandle, std::uint8_t descriptorType, std::uint8_t descriptorIndex, std::uint8_t* data, std::int32_t length); +void* APS5_VABI sceUsbdGetDevice(void* deviceHandle); +int APS5_VABI sceUsbdGetDeviceSpeed(void* device); +std::int32_t APS5_VABI sceUsbdGetMaxIsoPacketSize(void* device, std::uint8_t endpoint); +std::int32_t APS5_VABI sceUsbdGetMaxPacketSize(void* device, std::uint8_t endpoint); +std::int32_t APS5_VABI sceUsbdGetStringDescriptorAscii(void* deviceHandle, std::uint8_t descriptorIndex, std::uint8_t* data, std::int32_t length); +std::int32_t APS5_VABI sceUsbdHandleEvents(); +std::int32_t APS5_VABI sceUsbdHandleEventsLocked(UsbdTimeval* timeout); +void APS5_VABI sceUsbdLockEventWaiters(); +void APS5_VABI sceUsbdLockEvents(); +void* APS5_VABI sceUsbdOpenDeviceWithVidPid(std::uint16_t vendorId, std::uint16_t productId); +std::int32_t APS5_VABI sceUsbdSetInterfaceAltSetting(void* deviceHandle, int interfaceNumber, int alternateSetting); +std::int32_t APS5_VABI sceUsbdTryLockEvents(); +void APS5_VABI sceUsbdUnlockEventWaiters(); +void APS5_VABI sceUsbdUnlockEvents(); +std::int32_t APS5_VABI sceUsbdWaitForEvent(UsbdTimeval* timeout); + +} diff --git a/core/libs/prx/libSceUsbd/libSceUsbd.hpp b/core/libs/prx/libSceUsbd/libSceUsbd.hpp new file mode 100644 index 0000000000..6e1c2333f9 --- /dev/null +++ b/core/libs/prx/libSceUsbd/libSceUsbd.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceUsbd/include/Api.hpp" diff --git a/core/libs/prx/libSceUserService/Export.cpp b/core/libs/prx/libSceUserService/Export.cpp index e96a561ddf..fa8edb8b62 100644 --- a/core/libs/prx/libSceUserService/Export.cpp +++ b/core/libs/prx/libSceUserService/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceSystemService/include/SystemService.hpp" #include #include #include "SceTypes.hpp" @@ -29,9 +30,17 @@ int UserIndex(int userId) { return -1; } -int ReportAccessibilitySetting(int user_id, int32_t* setting, int32_t value) { - const int index = UserIndex(user_id); +bool IsUserLoggedIn(int userId) { + const int index = UserIndex(userId); if (index < 0) { + return false; + } + std::lock_guard lock(userMutex); + return userConnected[index]; +} + +int ReportAccessibilitySetting(int user_id, int32_t* setting, int32_t value) { + if (!IsUserLoggedIn(user_id)) { return USER_SERVICE_ERROR_NOT_LOGGED_IN; } if (setting == nullptr) { @@ -53,7 +62,6 @@ void PopulateInitialLoginEvents() { } } -extern "C" int APS5_VABI sceSystemServiceParamGetInt(int param_id, int* value); // Per-user keyboard settings. Nothing in AnyPS5 stores a keyboard type or input variant, so every known user reports // the keyboard type of the configured system language and 0 for the input variants (see @@ -151,8 +159,7 @@ int APS5_VABI sceUserServiceGetAccessibilityZoomFollowFocus(int user_id, int32_t } int APS5_VABI sceUserServiceGetAgeLevel(int user_id, uint32_t* age_level) { - const int index = UserIndex(user_id); - if (index < 0) { + if (!IsUserLoggedIn(user_id)) { return USER_SERVICE_ERROR_NOT_LOGGED_IN; } if (age_level == nullptr) { diff --git a/core/libs/prx/libSceUserService/UserService.hpp b/core/libs/prx/libSceUserService/UserService.hpp index 2ef3478df9..3169ed503c 100644 --- a/core/libs/prx/libSceUserService/UserService.hpp +++ b/core/libs/prx/libSceUserService/UserService.hpp @@ -3,6 +3,7 @@ #include #include +#include "SceTypes.hpp" struct UserServiceInitParam { std::int32_t priority; @@ -31,4 +32,35 @@ constexpr const char* USER_SERVICE_USER_NAMES[USER_SERVICE_MAX_USERS] = { extern "C" void UserServiceSetUserConnected_nid_postfix(int userIndex, bool connected); +extern "C" { + +int APS5_VABI sceUserServiceGetAccessibilityChatTranscription(int userId, int32_t* chatTranscription); +int APS5_VABI sceUserServiceGetAccessibilityKeyremapEnable(std::int32_t userId, std::int32_t* enabled); +int APS5_VABI sceUserServiceGetAccessibilityPressAndHoldDelay(int userId, int32_t* pressAndHoldDelay); +int APS5_VABI sceUserServiceGetAccessibilityTriggerEffect(int userId, int32_t* triggerEffect); +int APS5_VABI sceUserServiceGetAccessibilityVibration(int userId, int32_t* vibration); +int APS5_VABI sceUserServiceGetAccessibilityZoom(std::int32_t userId, std::int32_t* zoom); +int APS5_VABI sceUserServiceGetAccessibilityZoomEnabled(int userId, int32_t* zoomEnabled); +int APS5_VABI sceUserServiceGetAccessibilityZoomFollowFocus(int userId, int32_t* zoomFollowFocus); +int APS5_VABI sceUserServiceGetAgeLevel(int userId, uint32_t* ageLevel); +int APS5_VABI sceUserServiceGetEvent(SceUserServiceEvent* event); +int APS5_VABI sceUserServiceGetGamePresets(int userId, UserServiceGamePresets* presets); +int APS5_VABI sceUserServiceGetInitialUser(int* userId); +int APS5_VABI sceUserServiceGetLoginUserIdList(UserServiceLoginUserIdList* userIdList); +int APS5_VABI sceUserServiceGetUserName(int userId, char* name, size_t size); +int APS5_VABI sceUserServiceGetUserNumber(int userId, int32_t* number); +int APS5_VABI sceUserServiceInitialize(const UserServiceInitParam* params); +int APS5_VABI sceUserServiceInitialize2(std::int32_t priority, KernelCpumask affinityMask); +int APS5_VABI sceUserServiceTerminate(void); +int APS5_VABI sceUserServiceGetPlatformPrivacyWs1(int32_t userId, int32_t* value); +int APS5_VABI sceUserServiceGetForegroundUser(int* userId); +int APS5_VABI sceUserServiceGetRegisteredUserIdList(UserServiceRegisteredUserIdList* userIdList); +int APS5_VABI sceUserServiceGetUserColor(int userId, int* color); +int APS5_VABI sceUserServiceGetKeyboardType(int userId, int32_t* type); +int APS5_VABI sceUserServiceGetJapaneseInputType(int userId, int32_t* type); +int APS5_VABI sceUserServiceGetTraditionalChineseInputType(int userId, int32_t* type); +int APS5_VABI sceUserServiceGetNpAccountId(int userId, uint64_t* accountId); + +} + #endif diff --git a/core/libs/prx/libSceUserService/libSceUserService.hpp b/core/libs/prx/libSceUserService/libSceUserService.hpp new file mode 100644 index 0000000000..32a9d2d7ae --- /dev/null +++ b/core/libs/prx/libSceUserService/libSceUserService.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceUserService/UserService.hpp" diff --git a/core/libs/prx/libSceVcodec/libSceVcodec.hpp b/core/libs/prx/libSceVcodec/libSceVcodec.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceVcodec/libSceVcodec.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceVdecCore.native/Export.cpp b/core/libs/prx/libSceVdecCore.native/Export.cpp index f619cb820b..3ee8802672 100644 --- a/core/libs/prx/libSceVdecCore.native/Export.cpp +++ b/core/libs/prx/libSceVdecCore.native/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceVdecCore.native/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceVdecCore.native/include/Api.hpp b/core/libs/prx/libSceVdecCore.native/include/Api.hpp new file mode 100644 index 0000000000..e7166aa853 --- /dev/null +++ b/core/libs/prx/libSceVdecCore.native/include/Api.hpp @@ -0,0 +1,12 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceVdecCoreCreateDecoderBid(); +int APS5_VABI sceVdecCoreCreateDecoderSvp(); +int APS5_VABI sceVdecCoreMapMemory(); +int APS5_VABI sceVdecCoreSetDecodeInputSvp(); + +} diff --git a/core/libs/prx/libSceVdecCore.native/libSceVdecCore.native.hpp b/core/libs/prx/libSceVdecCore.native/libSceVdecCore.native.hpp new file mode 100644 index 0000000000..ad02da52c4 --- /dev/null +++ b/core/libs/prx/libSceVdecCore.native/libSceVdecCore.native.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceVdecCore.native/include/Api.hpp" diff --git a/core/libs/prx/libSceVdecCore/Export.cpp b/core/libs/prx/libSceVdecCore/Export.cpp index 343d1ec6a6..0c25b209ec 100644 --- a/core/libs/prx/libSceVdecCore/Export.cpp +++ b/core/libs/prx/libSceVdecCore/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceVdecCore/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceVdecCore/include/Api.hpp b/core/libs/prx/libSceVdecCore/include/Api.hpp new file mode 100644 index 0000000000..9b1aaeed6c --- /dev/null +++ b/core/libs/prx/libSceVdecCore/include/Api.hpp @@ -0,0 +1,28 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceVdecCoreAnalyzeStream(); +int APS5_VABI sceVdecCoreCreateDecoder(); +int APS5_VABI sceVdecCoreDeleteDecoder(); +int APS5_VABI sceVdecCoreFinalizeComputeResource(); +int APS5_VABI sceVdecCoreFlushDecodeOutput(); +int APS5_VABI sceVdecCoreGetDecodeOutput(); +int APS5_VABI sceVdecCoreInitializeComputeResource(); +int APS5_VABI sceVdecCoreMapMemoryBlock(); +int APS5_VABI sceVdecCoreQueryComputeResourceInfo(); +int APS5_VABI sceVdecCoreQueryFrameBufferInfo(); +int APS5_VABI sceVdecCoreQueryInstanceSize(); +int APS5_VABI sceVdecCoreResetDecoder(); +int APS5_VABI sceVdecCoreSetDecodeInput(); +int APS5_VABI sceVdecCoreSetDecodeOutputSw(); +int APS5_VABI sceVdecCoreSyncDecode(); +int APS5_VABI sceVdecCoreSyncDecodeOutputSw(); +int APS5_VABI sceVdecCoreSyncDecodeWptr(); +int APS5_VABI sceVdecCoreTrySyncDecode(); +int APS5_VABI sceVdecCoreTrySyncDecodeOutputSw(); +int APS5_VABI sceVdecCoreTrySyncDecodeWptr(); + +} diff --git a/core/libs/prx/libSceVdecCore/libSceVdecCore.hpp b/core/libs/prx/libSceVdecCore/libSceVdecCore.hpp new file mode 100644 index 0000000000..347e124988 --- /dev/null +++ b/core/libs/prx/libSceVdecCore/libSceVdecCore.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceVdecCore/include/Api.hpp" diff --git a/core/libs/prx/libSceVdecSavc/Export.cpp b/core/libs/prx/libSceVdecSavc/Export.cpp index c30e4f9c37..72330582cd 100644 --- a/core/libs/prx/libSceVdecSavc/Export.cpp +++ b/core/libs/prx/libSceVdecSavc/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceVdecSavc/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceVdecSavc/include/Api.hpp b/core/libs/prx/libSceVdecSavc/include/Api.hpp new file mode 100644 index 0000000000..cd352d8c30 --- /dev/null +++ b/core/libs/prx/libSceVdecSavc/include/Api.hpp @@ -0,0 +1,12 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceSdecCreateSw(); +int APS5_VABI sceSdecDestroySw(); +int APS5_VABI sceSdecGetVersionSw(); +int APS5_VABI sceSdecQueryMemorySw(); + +} diff --git a/core/libs/prx/libSceVdecSavc/libSceVdecSavc.hpp b/core/libs/prx/libSceVdecSavc/libSceVdecSavc.hpp new file mode 100644 index 0000000000..658d88c565 --- /dev/null +++ b/core/libs/prx/libSceVdecSavc/libSceVdecSavc.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceVdecSavc/include/Api.hpp" diff --git a/core/libs/prx/libSceVdecSavc2.native/libSceVdecSavc2.native.hpp b/core/libs/prx/libSceVdecSavc2.native/libSceVdecSavc2.native.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceVdecSavc2.native/libSceVdecSavc2.native.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceVdecSavc2/Export.cpp b/core/libs/prx/libSceVdecSavc2/Export.cpp index 6f217fc959..6ca11f6ef7 100644 --- a/core/libs/prx/libSceVdecSavc2/Export.cpp +++ b/core/libs/prx/libSceVdecSavc2/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceVdecSavc2/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceVdecSavc2/include/Api.hpp b/core/libs/prx/libSceVdecSavc2/include/Api.hpp new file mode 100644 index 0000000000..985cdcd141 --- /dev/null +++ b/core/libs/prx/libSceVdecSavc2/include/Api.hpp @@ -0,0 +1,12 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceSdecCreateSw2(); +int APS5_VABI sceSdecDestroySw2(); +int APS5_VABI sceSdecGetVersionSw2(); +int APS5_VABI sceSdecQueryMemorySw2(); + +} diff --git a/core/libs/prx/libSceVdecSavc2/libSceVdecSavc2.hpp b/core/libs/prx/libSceVdecSavc2/libSceVdecSavc2.hpp new file mode 100644 index 0000000000..10fff4393c --- /dev/null +++ b/core/libs/prx/libSceVdecSavc2/libSceVdecSavc2.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceVdecSavc2/include/Api.hpp" diff --git a/core/libs/prx/libSceVdecShevc.native/libSceVdecShevc.native.hpp b/core/libs/prx/libSceVdecShevc.native/libSceVdecShevc.native.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceVdecShevc.native/libSceVdecShevc.native.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceVdecShevc/Export.cpp b/core/libs/prx/libSceVdecShevc/Export.cpp index 8f63aa61a9..43e4936066 100644 --- a/core/libs/prx/libSceVdecShevc/Export.cpp +++ b/core/libs/prx/libSceVdecShevc/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceVdecShevc/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceVdecShevc/include/Api.hpp b/core/libs/prx/libSceVdecShevc/include/Api.hpp new file mode 100644 index 0000000000..f6685c6a64 --- /dev/null +++ b/core/libs/prx/libSceVdecShevc/include/Api.hpp @@ -0,0 +1,15 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceSdecCreateSwHevc(); +int APS5_VABI sceSdecDestroySwHevc(); +int APS5_VABI sceSdecExecuteSwHevc(); +int APS5_VABI sceSdecGetFrameSwHevc(); +int APS5_VABI sceSdecGetVersionSwHevc(); +int APS5_VABI sceSdecQueryMemorySwHevc(); +int APS5_VABI sceSdecResetSwHevc(); + +} diff --git a/core/libs/prx/libSceVdecShevc/libSceVdecShevc.hpp b/core/libs/prx/libSceVdecShevc/libSceVdecShevc.hpp new file mode 100644 index 0000000000..e6f868789a --- /dev/null +++ b/core/libs/prx/libSceVdecShevc/libSceVdecShevc.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceVdecShevc/include/Api.hpp" diff --git a/core/libs/prx/libSceVdecSvp9.native/libSceVdecSvp9.native.hpp b/core/libs/prx/libSceVdecSvp9.native/libSceVdecSvp9.native.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceVdecSvp9.native/libSceVdecSvp9.native.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceVdecsw/Export.cpp b/core/libs/prx/libSceVdecsw/Export.cpp index d6fa384070..b39ea9bc46 100644 --- a/core/libs/prx/libSceVdecsw/Export.cpp +++ b/core/libs/prx/libSceVdecsw/Export.cpp @@ -1,3 +1,5 @@ +#include "prx/libSceVideodec2/include/Api.hpp" +#include "prx/libSceVdecsw/include/Api.hpp" #include #include #include @@ -15,6 +17,8 @@ namespace { +using namespace SceVdecsw; + constexpr int VdecswErrorOutputPending = static_cast(0x81510115u); constexpr int VdecswErrorInputQueueEmpty = static_cast(0x81510116u); constexpr int VdecswErrorDecodePending = static_cast(0x81510117u); @@ -23,157 +27,12 @@ constexpr std::size_t MaxQueuedPictures = 4; constexpr std::uint32_t CodecAvc = 1; constexpr std::uint32_t CodecHevc = 974921; -struct InputData { - std::uint64_t thisSize; - const std::uint8_t* auData; - std::uint64_t auSize; - std::uint64_t ptsData; - std::uint64_t dtsData; - std::uint64_t attachedData; -}; - -struct InputResult { - std::uint64_t thisSize; - const void* decodedAu; - std::uint32_t outputFrameCount; - std::uint32_t reserved; -}; - -struct FrameBuffer { - std::uint64_t thisSize; - void* frameBuffer; - std::uint64_t frameBufferSize; -}; - -struct OutputInfo { - std::uint64_t thisSize; - bool isValid; - bool isLastFrame; - bool isErrorFrame; - std::uint8_t pictureCount; - std::uint32_t codecType; - std::uint32_t frameWidth; - std::uint32_t framePitch; - std::uint32_t frameHeight; - bool isDiscardedFrame; - void* frameBuffer; - std::uint64_t frameBufferSize; - std::uint32_t frameFormat; - std::uint32_t framePitchInBytes; -}; - -struct Vp9PictureInfo { - std::uint64_t thisSize; - bool isValid; - std::uint64_t ptsData; - std::uint64_t dtsData; - std::uint64_t attachedData; - std::uint32_t profile; - std::uint32_t level; - std::uint32_t keyFrameFlag; - std::uint32_t intraOnly; - std::uint8_t bitDepth; - std::uint8_t colorRange; - std::uint32_t colorSpace; - std::uint32_t numFrames; - std::uint32_t frameWidth; - std::uint32_t frameHeight; - std::uint32_t renderWidth; - std::uint32_t renderHeight; -}; - -struct AvcPictureInfo { - std::uint64_t thisSize; - bool isValid; - std::uint64_t ptsData; - std::uint64_t dtsData; - std::uint64_t attachedData; - std::uint8_t idrPictureFlag; - std::uint8_t profileIdc; - std::uint8_t levelIdc; - std::uint32_t picWidthInMbsMinus1; - std::uint32_t picHeightInMapUnitsMinus1; - std::uint8_t frameMbsOnlyFlag; - std::uint8_t frameCroppingFlag; - std::uint32_t frameCropLeftOffset; - std::uint32_t frameCropRightOffset; - std::uint32_t frameCropTopOffset; - std::uint32_t frameCropBottomOffset; - std::uint8_t vui[44]; -}; - -struct HevcPictureInfo { - std::uint64_t thisSize; - bool isValid; - std::uint64_t ptsData; - std::uint64_t dtsData; - std::uint64_t attachedData; - std::uint32_t picWidthInLumaSamples; - std::uint32_t picHeightInLumaSamples; - std::uint8_t bitDepthLumaMinus8; - std::uint8_t bitDepthChromaMinus8; - std::uint8_t timingInfoPresentFlag; - std::uint32_t numUnitsInTick; - std::uint32_t timeScale; - std::uint32_t aspectRatioInfoPresentFlag; - std::uint8_t aspectRatioIdc; - std::uint16_t sarWidth; - std::uint16_t sarHeight; - std::uint8_t videoSignal[8]; - std::uint32_t picStruct; - std::uint32_t sourceScanType; - std::uint32_t duplicateFlag; - std::uint32_t conformanceWindowFlag; - std::uint32_t confWinLeftOffset; - std::uint32_t confWinRightOffset; - std::uint32_t confWinTopOffset; - std::uint32_t confWinBottomOffset; - std::uint32_t defaultDisplayWindow[5]; - std::uint8_t chromaLocation[4]; - std::uint8_t presentFlags[11]; - std::uint8_t idrPictureFlag; - std::uint8_t irapPictureFlag; - std::uint8_t generalProfileSpace; - std::uint8_t generalTierFlag; - std::uint8_t generalProfileIdc; - std::uint8_t generalSourceFlags[3]; - std::uint8_t generalLevelIdc; - std::uint8_t subLayer[9]; - std::uint8_t frameCroppingFlag; - std::uint32_t frameCropLeftOffset; - std::uint32_t frameCropRightOffset; - std::uint32_t frameCropTopOffset; - std::uint32_t frameCropBottomOffset; -}; - -static_assert(sizeof(InputData) == 0x30 && sizeof(InputResult) == 0x18 && sizeof(FrameBuffer) == 0x18); -static_assert(sizeof(Vp9PictureInfo) == 0x58 && offsetof(Vp9PictureInfo, ptsData) == 0x10 && offsetof(Vp9PictureInfo, profile) == 0x28 && offsetof(Vp9PictureInfo, bitDepth) == 0x38 && offsetof(Vp9PictureInfo, colorSpace) == 0x3c && offsetof(Vp9PictureInfo, renderHeight) == 0x50); +static_assert(sizeof(SceVideodec2::InputData) == 0x30 && sizeof(InputResult) == 0x18 && sizeof(FrameBuffer) == 0x18); +static_assert(sizeof(SceVideodec2::Vp9PictureInfo) == 0x58 && offsetof(SceVideodec2::Vp9PictureInfo, ptsData) == 0x10 && offsetof(SceVideodec2::Vp9PictureInfo, profile) == 0x28 && offsetof(SceVideodec2::Vp9PictureInfo, bitDepth) == 0x38 && offsetof(SceVideodec2::Vp9PictureInfo, colorSpace) == 0x3c && offsetof(SceVideodec2::Vp9PictureInfo, renderHeight) == 0x50); static_assert(sizeof(OutputInfo) == 0x38 && offsetof(OutputInfo, isLastFrame) == 9 && offsetof(OutputInfo, pictureCount) == 0xb && offsetof(OutputInfo, isDiscardedFrame) == 0x1c); static_assert(sizeof(AvcPictureInfo) == 0x78 && offsetof(AvcPictureInfo, picWidthInMbsMinus1) == 0x2c && offsetof(AvcPictureInfo, frameCropBottomOffset) == 0x44); static_assert(sizeof(HevcPictureInfo) == 0xb8 && offsetof(HevcPictureInfo, picWidthInLumaSamples) == 0x28 && offsetof(HevcPictureInfo, sarWidth) == 0x42 && offsetof(HevcPictureInfo, picStruct) == 0x50 && offsetof(HevcPictureInfo, conformanceWindowFlag) == 0x5c && offsetof(HevcPictureInfo, idrPictureFlag) == 0x93 && offsetof(HevcPictureInfo, generalProfileIdc) == 0x97 && offsetof(HevcPictureInfo, generalLevelIdc) == 0x9b && offsetof(HevcPictureInfo, frameCroppingFlag) == 0xa5 && offsetof(HevcPictureInfo, frameCropBottomOffset) == 0xb4); -struct Videodec2FrameBuffer { - std::uint64_t thisSize; - void* frameBuffer; - std::uint64_t frameBufferSize; - bool isAccepted; -}; - -struct Videodec2OutputInfo { - std::uint64_t thisSize; - bool isValid; - bool isErrorFrame; - std::uint8_t pictureCount; - std::uint32_t codecType; - std::uint32_t frameWidth; - std::uint32_t framePitch; - std::uint32_t frameHeight; - void* frameBuffer; - std::uint64_t frameBufferSize; - std::uint32_t frameFormat; - std::uint32_t framePitchInBytes; -}; - struct Videodec2Crop { std::uint32_t left; std::uint32_t right; @@ -193,38 +52,17 @@ struct Videodec2PictureHeader { std::uint8_t bitDepthMinus8; }; -struct DecoderMemoryInfo { - std::uint64_t thisSize; - std::uint64_t cpuMemorySize; - void* cpuMemory; - std::uint64_t gpuMemorySize; - void* gpuMemory; - std::uint64_t cpuGpuMemorySize; - void* cpuGpuMemory; - std::uint64_t maxFrameBufferSize; - std::uint32_t frameBufferAlignment; -}; - } extern "C" { -int APS5_VABI sceVideodec2QueryComputeMemoryInfo_nid_postfix(void* info); -int APS5_VABI sceVideodec2AllocateComputeQueue_nid_postfix(const void* config, const void* memory, std::uint64_t* queue); -int APS5_VABI sceVideodec2ReleaseComputeQueue_nid_postfix(std::uint64_t queue); -int APS5_VABI sceVideodec2QueryDecoderMemoryInfo_nid_postfix(const void* config, void* memory); -int APS5_VABI sceVideodec2CreateDecoder_nid_postfix(const void* config, const void* memory, std::uint64_t* handle); -int APS5_VABI sceVideodec2DeleteDecoder_nid_postfix(std::uint64_t handle); -int APS5_VABI sceVideodec2Decode_nid_postfix(std::uint64_t handle, const InputData* input, Videodec2FrameBuffer* frame, Videodec2OutputInfo* output); -int APS5_VABI sceVideodec2Flush_nid_postfix(std::uint64_t handle, Videodec2FrameBuffer* frame, Videodec2OutputInfo* output); -int APS5_VABI sceVideodec2GetVp9PictureInfo_nid_postfix(const Videodec2OutputInfo* output, Vp9PictureInfo* info); -int APS5_VABI sceVideodec2Reset_nid_postfix(std::uint64_t handle); + void Videodec2PictureHeader_nid_no_patch(std::uint64_t handle, const void* frameBuffer, Videodec2PictureHeader* header); } namespace { struct PendingInput { - InputData input; + SceVideodec2::InputData input; std::vector data; }; @@ -237,7 +75,7 @@ using PictureInfo = std::variant; struct Picture { std::vector pixels; - Videodec2OutputInfo output; + SceVideodec2::OutputInfo output; PictureInfo info; }; @@ -251,7 +89,7 @@ struct Decoder { std::map delivered; bool finalized = false; bool drained = false; - std::map deliveredVp9; + std::map deliveredVp9; }; std::mutex decodersMutex; @@ -264,7 +102,7 @@ std::shared_ptr findDecoder(std::uint64_t handle) { return found->second; } -PictureInfo pictureInfo(std::uint64_t handle, const Videodec2OutputInfo& output) { +PictureInfo pictureInfo(std::uint64_t handle, const SceVideodec2::OutputInfo& output) { Videodec2PictureHeader header{}; Videodec2PictureHeader_nid_no_patch(handle, output.frameBuffer, &header); const auto& crop = header.crop; @@ -319,9 +157,10 @@ PictureInfo pictureInfo(std::uint64_t handle, const Videodec2OutputInfo& output) return info; } -Vp9PictureInfo vp9PictureInfo(const Videodec2OutputInfo& output) { - Vp9PictureInfo info{sizeof(Vp9PictureInfo)}; +SceVideodec2::Vp9PictureInfo vp9PictureInfo(const SceVideodec2::OutputInfo& output) { + SceVideodec2::Vp9PictureInfo info{sizeof(SceVideodec2::Vp9PictureInfo)}; sceVideodec2GetVp9PictureInfo_nid_postfix(&output, &info); + if (!info.isValid) throw std::runtime_error("Vdecsw: decoded picture has no VP9 picture info"); return info; } @@ -352,17 +191,19 @@ int deliveredPictureInfo(const OutputInfo* output, TInfo* info) { void advance(std::uint64_t handle, Decoder& decoder) { while (decoder.pictures.size() < MaxQueuedPictures) { std::vector pixels(decoder.frameBytes); - Videodec2FrameBuffer frame{sizeof(Videodec2FrameBuffer), pixels.data(), pixels.size(), false}; - Videodec2OutputInfo output{sizeof(Videodec2OutputInfo)}; + SceVideodec2::FrameBuffer frame{sizeof(SceVideodec2::FrameBuffer), pixels.data(), pixels.size(), false}; + SceVideodec2::OutputInfo output{sizeof(SceVideodec2::OutputInfo)}; if (!decoder.inputs.empty()) { const auto* au = static_cast(decoder.inputs.front().input.auData); auto input = decoder.inputs.front().input; input.auData = decoder.inputs.front().data.data(); sceVideodec2Decode_nid_postfix(handle, &input, &frame, &output); + decoder.inputs.pop_front(); decoder.consumed.push_back({au, output.isValid ? 1u : 0u}); } else if (decoder.finalized && !decoder.drained) { sceVideodec2Flush_nid_postfix(handle, &frame, &output); + decoder.drained = !output.isValid; } else { return; @@ -378,11 +219,11 @@ void advance(std::uint64_t handle, Decoder& decoder) { extern "C" { -int APS5_VABI sceVdecswQueryComputeMemoryInfo(void* info) { +int APS5_VABI sceVdecswQueryComputeMemoryInfo(SceVideodec2::ComputeMemoryInfo* info) { return sceVideodec2QueryComputeMemoryInfo_nid_postfix(info); } -int APS5_VABI sceVdecswAllocateComputeQueue(const void* config, const void* memory, std::uint64_t* queue) { +int APS5_VABI sceVdecswAllocateComputeQueue(const SceVideodec2::ComputeConfigInfo* config, const SceVideodec2::ComputeMemoryInfo* memory, std::uint64_t* queue) { return sceVideodec2AllocateComputeQueue_nid_postfix(config, memory, queue); } @@ -390,13 +231,13 @@ int APS5_VABI sceVdecswReleaseComputeQueue(std::uint64_t queue) { return sceVideodec2ReleaseComputeQueue_nid_postfix(queue); } -int APS5_VABI sceVdecswQueryDecoderMemoryInfo(const void* config, void* memory) { - return sceVideodec2QueryDecoderMemoryInfo_nid_postfix(config, memory); +int APS5_VABI sceVdecswQueryDecoderMemoryInfo(const void* config, SceVideodec2::DecoderMemoryInfo* memory) { + return sceVideodec2QueryDecoderMemoryInfo_nid_postfix(static_cast(config), memory); } -int APS5_VABI sceVdecswCreateDecoder(const void* config, const DecoderMemoryInfo* memory, std::uint64_t* handle) { - if (handle == nullptr || memory == nullptr || memory->thisSize < sizeof(DecoderMemoryInfo) || memory->maxFrameBufferSize == 0) throw std::runtime_error("Vdecsw: invalid decoder creation arguments"); - const auto result = sceVideodec2CreateDecoder_nid_postfix(config, memory, handle); +int APS5_VABI sceVdecswCreateDecoder(const void* config, const SceVideodec2::DecoderMemoryInfo* memory, std::uint64_t* handle) { + if (handle == nullptr || memory == nullptr || memory->thisSize < sizeof(SceVideodec2::DecoderMemoryInfo) || memory->maxFrameBufferSize == 0) throw std::runtime_error("Vdecsw: invalid decoder creation arguments"); + const auto result = sceVideodec2CreateDecoder_nid_postfix(static_cast(config), memory, handle); if (result != 0) return result; auto decoder = std::make_shared(); decoder->frameBytes = memory->maxFrameBufferSize; @@ -413,8 +254,8 @@ int APS5_VABI sceVdecswDeleteDecoder(std::uint64_t handle) { return sceVideodec2DeleteDecoder_nid_postfix(handle); } -int APS5_VABI sceVdecswSetDecodeInput(std::uint64_t handle, const InputData* input) { - if (input == nullptr || input->thisSize < sizeof(InputData)) throw std::runtime_error("Vdecsw: invalid decode input"); +int APS5_VABI sceVdecswSetDecodeInput(std::uint64_t handle, const SceVideodec2::InputData* input) { + if (input == nullptr || input->thisSize < sizeof(SceVideodec2::InputData)) throw std::runtime_error("Vdecsw: invalid decode input"); const auto decoder = findDecoder(handle); std::lock_guard lock(decoder->mutex); if (decoder->finalized) throw std::runtime_error("Vdecsw: decode input after the sequence was finalized"); @@ -520,7 +361,7 @@ int APS5_VABI sceVdecswGetHevcPictureInfo(const OutputInfo* output, HevcPictureI return deliveredPictureInfo(output, picture); } -int APS5_VABI sceVdecswGetVp9PictureInfo(const OutputInfo* output, Vp9PictureInfo* picture) { +int APS5_VABI sceVdecswGetVp9PictureInfo(const OutputInfo* output, SceVideodec2::Vp9PictureInfo* picture) { if (output == nullptr || picture == nullptr || picture->thisSize < sizeof(std::uint64_t)) throw std::runtime_error("Vdecsw: invalid argument pointer"); if (output->pictureCount > 1) throw std::runtime_error("Vdecsw: more than one VP9 picture info is not implemented"); if (output->pictureCount == 0) return 0; @@ -533,7 +374,7 @@ int APS5_VABI sceVdecswGetVp9PictureInfo(const OutputInfo* output, Vp9PictureInf std::lock_guard lock(decoder->mutex); const auto found = decoder->deliveredVp9.find(output->frameBuffer); if (found == decoder->deliveredVp9.end()) continue; - const auto bytes = std::min(picture->thisSize, sizeof(Vp9PictureInfo)) - sizeof(std::uint64_t); + const auto bytes = std::min(picture->thisSize, sizeof(SceVideodec2::Vp9PictureInfo)) - sizeof(std::uint64_t); std::memcpy(reinterpret_cast(picture) + sizeof(std::uint64_t), reinterpret_cast(&found->second) + sizeof(std::uint64_t), bytes); return 0; } diff --git a/core/libs/prx/libSceVdecsw/include/Api.hpp b/core/libs/prx/libSceVdecsw/include/Api.hpp new file mode 100644 index 0000000000..7b5fdf595a --- /dev/null +++ b/core/libs/prx/libSceVdecsw/include/Api.hpp @@ -0,0 +1,162 @@ +#include "prx/libSceVideodec2/include/Api.hpp" +#pragma once + +#include "SceTypes.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace SceVdecsw { + +struct DecoderConfigInfo { + SceVideodec2::DecoderConfigInfo decoder; + std::uint64_t computeQueue; + std::uint64_t cpuAffinityMask; + std::int32_t cpuThreadPriority; + bool optimizeProgressiveVideo; + std::uint8_t reserved[19]; +}; + +struct InputResult { + std::uint64_t thisSize; + const void* decodedAu; + std::uint32_t outputFrameCount; + std::uint32_t reserved; +}; + +} + +namespace SceVdecsw { + +struct FrameBuffer { + std::uint64_t thisSize; + void* frameBuffer; + std::uint64_t frameBufferSize; +}; + +} + +namespace SceVdecsw { + +struct OutputInfo { + std::uint64_t thisSize; + bool isValid; + bool isLastFrame; + bool isErrorFrame; + std::uint8_t pictureCount; + std::uint32_t codecType; + std::uint32_t frameWidth; + std::uint32_t framePitch; + std::uint32_t frameHeight; + bool isDiscardedFrame; + void* frameBuffer; + std::uint64_t frameBufferSize; + std::uint32_t frameFormat; + std::uint32_t framePitchInBytes; +}; + +} + +namespace SceVdecsw { + +struct AvcPictureInfo { + std::uint64_t thisSize; + bool isValid; + std::uint64_t ptsData; + std::uint64_t dtsData; + std::uint64_t attachedData; + std::uint8_t idrPictureFlag; + std::uint8_t profileIdc; + std::uint8_t levelIdc; + std::uint32_t picWidthInMbsMinus1; + std::uint32_t picHeightInMapUnitsMinus1; + std::uint8_t frameMbsOnlyFlag; + std::uint8_t frameCroppingFlag; + std::uint32_t frameCropLeftOffset; + std::uint32_t frameCropRightOffset; + std::uint32_t frameCropTopOffset; + std::uint32_t frameCropBottomOffset; + std::uint8_t vui[44]; +}; + +} + +namespace SceVdecsw { + +struct HevcPictureInfo { + std::uint64_t thisSize; + bool isValid; + std::uint64_t ptsData; + std::uint64_t dtsData; + std::uint64_t attachedData; + std::uint32_t picWidthInLumaSamples; + std::uint32_t picHeightInLumaSamples; + std::uint8_t bitDepthLumaMinus8; + std::uint8_t bitDepthChromaMinus8; + std::uint8_t timingInfoPresentFlag; + std::uint32_t numUnitsInTick; + std::uint32_t timeScale; + std::uint32_t aspectRatioInfoPresentFlag; + std::uint8_t aspectRatioIdc; + std::uint16_t sarWidth; + std::uint16_t sarHeight; + std::uint8_t videoSignal[8]; + std::uint32_t picStruct; + std::uint32_t sourceScanType; + std::uint32_t duplicateFlag; + std::uint32_t conformanceWindowFlag; + std::uint32_t confWinLeftOffset; + std::uint32_t confWinRightOffset; + std::uint32_t confWinTopOffset; + std::uint32_t confWinBottomOffset; + std::uint32_t defaultDisplayWindow[5]; + std::uint8_t chromaLocation[4]; + std::uint8_t presentFlags[11]; + std::uint8_t idrPictureFlag; + std::uint8_t irapPictureFlag; + std::uint8_t generalProfileSpace; + std::uint8_t generalTierFlag; + std::uint8_t generalProfileIdc; + std::uint8_t generalSourceFlags[3]; + std::uint8_t generalLevelIdc; + std::uint8_t subLayer[9]; + std::uint8_t frameCroppingFlag; + std::uint32_t frameCropLeftOffset; + std::uint32_t frameCropRightOffset; + std::uint32_t frameCropTopOffset; + std::uint32_t frameCropBottomOffset; +}; + +} + +extern "C" { + +int APS5_VABI sceVdecswQueryComputeMemoryInfo(SceVideodec2::ComputeMemoryInfo* info); +int APS5_VABI sceVdecswAllocateComputeQueue(const SceVideodec2::ComputeConfigInfo* config, const SceVideodec2::ComputeMemoryInfo* memory, std::uint64_t* queue); +int APS5_VABI sceVdecswReleaseComputeQueue(std::uint64_t queue); +int APS5_VABI sceVdecswQueryDecoderMemoryInfo(const void* config, SceVideodec2::DecoderMemoryInfo* memory); +int APS5_VABI sceVdecswCreateDecoder(const void* config, const SceVideodec2::DecoderMemoryInfo* memory, std::uint64_t* handle); +int APS5_VABI sceVdecswDeleteDecoder(std::uint64_t handle); +int APS5_VABI sceVdecswSetDecodeInput(std::uint64_t handle, const SceVideodec2::InputData* input); +int APS5_VABI sceVdecswTrySyncDecodeInput(std::uint64_t handle, SceVdecsw::InputResult* result); +int APS5_VABI sceVdecswSyncDecodeInput(std::uint64_t handle, SceVdecsw::InputResult* result); +int APS5_VABI sceVdecswSetDecodeOutput(std::uint64_t handle, const SceVdecsw::FrameBuffer* frame); +int APS5_VABI sceVdecswTrySyncDecodeOutput(std::uint64_t handle, SceVdecsw::OutputInfo* output); +int APS5_VABI sceVdecswSyncDecodeOutput(std::uint64_t handle, SceVdecsw::OutputInfo* output); +int APS5_VABI sceVdecswGetPictureInfo(const SceVdecsw::OutputInfo* output, void* first, void* second); +int APS5_VABI sceVdecswGetAvcPictureInfo(const SceVdecsw::OutputInfo* output, SceVdecsw::AvcPictureInfo* first, SceVdecsw::AvcPictureInfo* second); +int APS5_VABI sceVdecswGetHevcPictureInfo(const SceVdecsw::OutputInfo* output, SceVdecsw::HevcPictureInfo* picture); +int APS5_VABI sceVdecswGetVp9PictureInfo(const SceVdecsw::OutputInfo* output, SceVideodec2::Vp9PictureInfo* picture); +int APS5_VABI sceVdecswFinalizeDecodeSequence(std::uint64_t handle); +int APS5_VABI sceVdecswResetDecoder(std::uint64_t handle); + +} diff --git a/core/libs/prx/libSceVdecsw/libSceVdecsw.hpp b/core/libs/prx/libSceVdecsw/libSceVdecsw.hpp new file mode 100644 index 0000000000..c080ab901a --- /dev/null +++ b/core/libs/prx/libSceVdecsw/libSceVdecsw.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceVdecsw/include/Api.hpp" diff --git a/core/libs/prx/libSceVdecwrap/Export.cpp b/core/libs/prx/libSceVdecwrap/Export.cpp index ae14644219..923c85002b 100644 --- a/core/libs/prx/libSceVdecwrap/Export.cpp +++ b/core/libs/prx/libSceVdecwrap/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceVdecwrap/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceVdecwrap/include/Api.hpp b/core/libs/prx/libSceVdecwrap/include/Api.hpp new file mode 100644 index 0000000000..44f275d760 --- /dev/null +++ b/core/libs/prx/libSceVdecwrap/include/Api.hpp @@ -0,0 +1,19 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceVdecwrapCreateDecoder(); +int APS5_VABI sceVdecwrapDeleteDecoder(); +int APS5_VABI sceVdecwrapFlushDecodeOutput(); +int APS5_VABI sceVdecwrapGetDecodeOutput(); +int APS5_VABI sceVdecwrapMapDirectMemory(); +int APS5_VABI sceVdecwrapMapMemory(); +int APS5_VABI sceVdecwrapQueryDecoderMemoryInfo(); +int APS5_VABI sceVdecwrapQueryFrameBufferInfo(); +int APS5_VABI sceVdecwrapResetDecoder(); +int APS5_VABI sceVdecwrapSetDecodeInput(); +int APS5_VABI sceVdecwrapSyncDecode(); + +} diff --git a/core/libs/prx/libSceVdecwrap/libSceVdecwrap.hpp b/core/libs/prx/libSceVdecwrap/libSceVdecwrap.hpp new file mode 100644 index 0000000000..65c7e47394 --- /dev/null +++ b/core/libs/prx/libSceVdecwrap/libSceVdecwrap.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceVdecwrap/include/Api.hpp" diff --git a/core/libs/prx/libSceVenc/Export.cpp b/core/libs/prx/libSceVenc/Export.cpp index 8d8de5aa65..c423ca85fb 100644 --- a/core/libs/prx/libSceVenc/Export.cpp +++ b/core/libs/prx/libSceVenc/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceVenc/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceVenc/include/Api.hpp b/core/libs/prx/libSceVenc/include/Api.hpp new file mode 100644 index 0000000000..26d25b4a07 --- /dev/null +++ b/core/libs/prx/libSceVenc/include/Api.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceVencCreateEncoder(); +int APS5_VABI sceVencDeleteEncoder(); +int APS5_VABI sceVencGetConfig(); +int APS5_VABI sceVencMapMemory(); +int APS5_VABI sceVencQueryHeader(); +int APS5_VABI sceVencQueryMemorySize(); +int APS5_VABI sceVencQueryPreset(); +int APS5_VABI sceVencSetConfig(); +int APS5_VABI sceVencSetDecodedFrame(); +int APS5_VABI sceVencSetPictureConfig(); +int APS5_VABI sceVencSetRateControlConfig(); +int APS5_VABI sceVencSetReferenceFrameInvalidationConfig(); +int APS5_VABI sceVencStartEncode(); +int APS5_VABI sceVencStopEncode(); + +} diff --git a/core/libs/prx/libSceVenc/libSceVenc.hpp b/core/libs/prx/libSceVenc/libSceVenc.hpp new file mode 100644 index 0000000000..cae676b0b2 --- /dev/null +++ b/core/libs/prx/libSceVenc/libSceVenc.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceVenc/include/Api.hpp" diff --git a/core/libs/prx/libSceVideoArbitration/Export.cpp b/core/libs/prx/libSceVideoArbitration/Export.cpp index 2825147db8..23b1eaa853 100644 --- a/core/libs/prx/libSceVideoArbitration/Export.cpp +++ b/core/libs/prx/libSceVideoArbitration/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceVideoArbitration/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceVideoArbitration/include/Api.hpp b/core/libs/prx/libSceVideoArbitration/include/Api.hpp new file mode 100644 index 0000000000..126dfd0696 --- /dev/null +++ b/core/libs/prx/libSceVideoArbitration/include/Api.hpp @@ -0,0 +1,11 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceVideoArbitrationAcceptEvent(); +int APS5_VABI sceVideoArbitrationEnable(); +int APS5_VABI sceVideoArbitrationInitialize(); + +} diff --git a/core/libs/prx/libSceVideoArbitration/libSceVideoArbitration.hpp b/core/libs/prx/libSceVideoArbitration/libSceVideoArbitration.hpp new file mode 100644 index 0000000000..46377c3aca --- /dev/null +++ b/core/libs/prx/libSceVideoArbitration/libSceVideoArbitration.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceVideoArbitration/include/Api.hpp" diff --git a/core/libs/prx/libSceVideoCoreInterface/Export.cpp b/core/libs/prx/libSceVideoCoreInterface/Export.cpp index 69f5eb3f02..d81f5a18e0 100644 --- a/core/libs/prx/libSceVideoCoreInterface/Export.cpp +++ b/core/libs/prx/libSceVideoCoreInterface/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceVideoCoreInterface/include/Api.hpp" #include #include #include "SceTypes.hpp" @@ -10,7 +11,6 @@ int APS5_VABI sceVideoCoreIfSetFunctionTableUnlimited() { return 0; } - int APS5_VABI sceVideoCoreIfInitializeInterface() { NotImplemented_nid_no_patch(__func__); return 0; diff --git a/core/libs/prx/libSceVideoCoreInterface/include/Api.hpp b/core/libs/prx/libSceVideoCoreInterface/include/Api.hpp new file mode 100644 index 0000000000..7b01f1539c --- /dev/null +++ b/core/libs/prx/libSceVideoCoreInterface/include/Api.hpp @@ -0,0 +1,12 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceVideoCoreIfSetFunctionTableUnlimited(); +int APS5_VABI sceVideoCoreIfInitializeInterface(); +int APS5_VABI sceVideoCoreIfMainLoop(); +int APS5_VABI sceVideoCoreIfSetFunctionTable(); + +} diff --git a/core/libs/prx/libSceVideoCoreInterface/libSceVideoCoreInterface.hpp b/core/libs/prx/libSceVideoCoreInterface/libSceVideoCoreInterface.hpp new file mode 100644 index 0000000000..0a1d280f24 --- /dev/null +++ b/core/libs/prx/libSceVideoCoreInterface/libSceVideoCoreInterface.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceVideoCoreInterface/include/Api.hpp" diff --git a/core/libs/prx/libSceVideoCoreServerInterface/Export.cpp b/core/libs/prx/libSceVideoCoreServerInterface/Export.cpp index 37c16803eb..0c92606c7e 100644 --- a/core/libs/prx/libSceVideoCoreServerInterface/Export.cpp +++ b/core/libs/prx/libSceVideoCoreServerInterface/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceVideoCoreServerInterface/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceVideoCoreServerInterface/include/Api.hpp b/core/libs/prx/libSceVideoCoreServerInterface/include/Api.hpp new file mode 100644 index 0000000000..1b44bc62ac --- /dev/null +++ b/core/libs/prx/libSceVideoCoreServerInterface/include/Api.hpp @@ -0,0 +1,55 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceVideoCoreAbortRequest(); +int APS5_VABI sceVideoCoreAcquireDecoderResource(); +int APS5_VABI sceVideoCoreAcquireDecoderResourceForBeWrapper(); +int APS5_VABI sceVideoCoreAddStream(); +int APS5_VABI sceVideoCoreAsyncAddStream(); +int APS5_VABI sceVideoCoreAsyncSendRequest(); +int APS5_VABI sceVideoCoreCancelThumbnail(); +int APS5_VABI sceVideoCoreChangeActiveStatus(); +int APS5_VABI sceVideoCoreChangeAudioStream(); +int APS5_VABI sceVideoCoreChangeDisplaySize(); +int APS5_VABI sceVideoCoreChangeHdcpSetting(); +int APS5_VABI sceVideoCoreChangeSubtitle(); +int APS5_VABI sceVideoCoreDeleteStream(); +int APS5_VABI sceVideoCoreGenerateThumbnail(); +int APS5_VABI sceVideoCoreGenerateThumbnail2(); +int APS5_VABI sceVideoCoreGetCanvasHandle(); +int APS5_VABI sceVideoCoreGetPlayStatus(); +int APS5_VABI sceVideoCoreGetPlayStatus2(); +int APS5_VABI sceVideoCoreGetStreamUid(); +int APS5_VABI sceVideoCoreGetThumbnail(); +int APS5_VABI sceVideoCoreGetThumbnail2(); +int APS5_VABI sceVideoCoreLaunchVideoCore(); +int APS5_VABI sceVideoCoreMediaSourceAbortSourceBuffer(); +int APS5_VABI sceVideoCoreMediaSourceAddSourceBuffer(); +int APS5_VABI sceVideoCoreMediaSourceAppendData(); +int APS5_VABI sceVideoCoreMediaSourceEndOfStream(); +int APS5_VABI sceVideoCoreMediaSourceGetBufferedTimeRanges(); +int APS5_VABI sceVideoCoreMediaSourceGetInputBufferEmptySize(); +int APS5_VABI sceVideoCoreMediaSourceGetPlaybackQuality(); +int APS5_VABI sceVideoCoreMediaSourceGetSourceBufferEvent(); +int APS5_VABI sceVideoCoreMediaSourceRemoveSourceBuffer(); +int APS5_VABI sceVideoCoreMediaSourceSetDuration(); +int APS5_VABI sceVideoCoreMediaSourceSetTimestampOffset(); +int APS5_VABI sceVideoCorePlayControl(); +int APS5_VABI sceVideoCoreRegistEventCallback(); +int APS5_VABI sceVideoCoreReleaseDecoderResource(); +int APS5_VABI sceVideoCoreReleaseDecoderResourceForBeWrapper(); +int APS5_VABI sceVideoCoreSetAudioMute(); +int APS5_VABI sceVideoCoreSetAudioVolume(); +int APS5_VABI sceVideoCoreSetFullScreen(); +int APS5_VABI sceVideoCoreSetInitialInfo(); +int APS5_VABI sceVideoCoreSetInitializeInfo(); +int APS5_VABI sceVideoCoreSetPlaybackRange(); +int APS5_VABI sceVideoCoreSetThumbnailInfo(); +int APS5_VABI sceVideoCoreSyncAddStream(); +int APS5_VABI sceVideoCoreSyncSendRequest(); +int APS5_VABI sceVideoCoreUnregistEventCallback(); + +} diff --git a/core/libs/prx/libSceVideoCoreServerInterface/libSceVideoCoreServerInterface.hpp b/core/libs/prx/libSceVideoCoreServerInterface/libSceVideoCoreServerInterface.hpp new file mode 100644 index 0000000000..5a97dc597f --- /dev/null +++ b/core/libs/prx/libSceVideoCoreServerInterface/libSceVideoCoreServerInterface.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceVideoCoreServerInterface/include/Api.hpp" diff --git a/core/libs/prx/libSceVideoDecoderArbitration/Export.cpp b/core/libs/prx/libSceVideoDecoderArbitration/Export.cpp index 4e2ab88329..3dc080db54 100644 --- a/core/libs/prx/libSceVideoDecoderArbitration/Export.cpp +++ b/core/libs/prx/libSceVideoDecoderArbitration/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceVideoDecoderArbitration/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceVideoDecoderArbitration/include/Api.hpp b/core/libs/prx/libSceVideoDecoderArbitration/include/Api.hpp new file mode 100644 index 0000000000..0029460ffa --- /dev/null +++ b/core/libs/prx/libSceVideoDecoderArbitration/include/Api.hpp @@ -0,0 +1,12 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceVideoDecoderArbitrationAcceptEvent(); +int APS5_VABI sceVideoDecoderArbitrationEnable(); +int APS5_VABI sceVideoDecoderArbitrationEnableSuspendMode(); +int APS5_VABI sceVideoDecoderArbitrationInitialize(); + +} diff --git a/core/libs/prx/libSceVideoDecoderArbitration/libSceVideoDecoderArbitration.hpp b/core/libs/prx/libSceVideoDecoderArbitration/libSceVideoDecoderArbitration.hpp new file mode 100644 index 0000000000..93ab58e19f --- /dev/null +++ b/core/libs/prx/libSceVideoDecoderArbitration/libSceVideoDecoderArbitration.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceVideoDecoderArbitration/include/Api.hpp" diff --git a/core/libs/prx/libSceVideoNativeExtEssential/Export.cpp b/core/libs/prx/libSceVideoNativeExtEssential/Export.cpp index 2c3047328f..83c4dda32a 100644 --- a/core/libs/prx/libSceVideoNativeExtEssential/Export.cpp +++ b/core/libs/prx/libSceVideoNativeExtEssential/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceVideoNativeExtEssential/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceVideoNativeExtEssential/include/Api.hpp b/core/libs/prx/libSceVideoNativeExtEssential/include/Api.hpp new file mode 100644 index 0000000000..0801f28d5d --- /dev/null +++ b/core/libs/prx/libSceVideoNativeExtEssential/include/Api.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceVideoNativeExtEssential_CreateDecInstance(); +int APS5_VABI sceVideoNativeExtEssential_DestroyDecInstance(); +int APS5_VABI sceVideoNativeExtEssential_Finalize(); +int APS5_VABI sceVideoNativeExtEssential_Initialize(); +int APS5_VABI sceVideoNativeExtEssential_IsInit(); + +} diff --git a/core/libs/prx/libSceVideoNativeExtEssential/libSceVideoNativeExtEssential.hpp b/core/libs/prx/libSceVideoNativeExtEssential/libSceVideoNativeExtEssential.hpp new file mode 100644 index 0000000000..07fbad2f88 --- /dev/null +++ b/core/libs/prx/libSceVideoNativeExtEssential/libSceVideoNativeExtEssential.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceVideoNativeExtEssential/include/Api.hpp" diff --git a/core/libs/prx/libSceVideoOut/Unimplemented.cpp b/core/libs/prx/libSceVideoOut/Unimplemented.cpp index 91b75fbb31..35751e05fd 100644 --- a/core/libs/prx/libSceVideoOut/Unimplemented.cpp +++ b/core/libs/prx/libSceVideoOut/Unimplemented.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceVideoOut/include/VideoOut.hpp" #include #include #include "SceTypes.hpp" @@ -62,7 +63,6 @@ int APS5_VABI sceVideoOutAdjustColorSpaceConversion_(int handle, const VideoOutC return sceVideoOutAdjustColorSpaceConversion(handle, settings); } - int APS5_VABI sceDbgVideoOutAddOutputModeVr60Privilege() { NotImplemented_nid_no_patch(__func__); return 0; diff --git a/core/libs/prx/libSceVideoOut/include/Buffer.hpp b/core/libs/prx/libSceVideoOut/include/Buffer.hpp index 5ae8013ae6..112e9cc682 100644 --- a/core/libs/prx/libSceVideoOut/include/Buffer.hpp +++ b/core/libs/prx/libSceVideoOut/include/Buffer.hpp @@ -3,23 +3,22 @@ #include -#include "prx/libc/include/General.hpp" #include "SceTypes.hpp" extern "C" { -int APS5_VABI sceVideoOutRegisterBuffers(int handle, int buffer_index_start, void* const* addresses, int buffer_num, const VideoOutBufferAttribute* attribute); -void APS5_VABI sceVideoOutSetBufferAttribute(VideoOutBufferAttribute* attribute, uint32_t pixel_format, uint32_t tiling_mode, uint32_t aspect_ratio, uint32_t width, uint32_t height, uint32_t pitch_in_pixel); -int APS5_VABI sceVideoOutRegisterBuffers2(int handle, int set_index, int buffer_index_start, const VideoOutBuffers* buffers, int buffer_num, const VideoOutBufferAttribute2* attribute, int category, void* option); -void APS5_VABI sceVideoOutSetBufferAttribute2(VideoOutBufferAttribute2* attribute, uint64_t pixel_format, uint32_t tiling_mode, uint32_t width, uint32_t height, uint64_t option, uint32_t dcc_control, uint64_t dcc_cb_register_clear_color); +int APS5_VABI sceVideoOutRegisterBuffers(int handle, int bufferIndexStart, void* const* addresses, int bufferNum, const VideoOutBufferAttribute* attribute); +void APS5_VABI sceVideoOutSetBufferAttribute(VideoOutBufferAttribute* attribute, uint32_t pixelFormat, uint32_t tilingMode, uint32_t aspectRatio, uint32_t width, uint32_t height, uint32_t pitchInPixel); +int APS5_VABI sceVideoOutRegisterBuffers2(int handle, int setIndex, int bufferIndexStart, const VideoOutBuffers* buffers, int bufferNum, const VideoOutBufferAttribute2* attribute, int category, void* option); +void APS5_VABI sceVideoOutSetBufferAttribute2(VideoOutBufferAttribute2* attribute, uint64_t pixelFormat, uint32_t tilingMode, uint32_t width, uint32_t height, uint64_t option, uint32_t dccControl, uint64_t dccCbRegisterClearColor); void APS5_VABI sceVideoOutAddBufferAttributeOption(VideoOutBufferAttribute2* attribute, uint64_t option); void APS5_VABI sceVideoOutRemoveBufferAttributeOption(VideoOutBufferAttribute2* attribute, uint64_t option); -int APS5_VABI sceVideoOutSubmitChangeBufferAttribute2(int handle, int set_index, const VideoOutBufferAttribute2* attribute, void* option); -int APS5_VABI sceVideoOutSubmitEopFlip(int handle, int index, int flip_mode, int64_t flip_arg, std::uint32_t* token); -int APS5_VABI sceVideoOutSubmitFlip(int handle, int index, int flip_mode, int64_t flip_arg); -int APS5_VABI sceVideoOutUnregisterBuffers(int handle, int set_index); +int APS5_VABI sceVideoOutSubmitChangeBufferAttribute2(int handle, int setIndex, const VideoOutBufferAttribute2* attribute, void* option); +int APS5_VABI sceVideoOutSubmitEopFlip(int handle, int index, int flipMode, int64_t flipArg, std::uint32_t* token); +int APS5_VABI sceVideoOutSubmitFlip(int handle, int index, int flipMode, int64_t flipArg); +int APS5_VABI sceVideoOutUnregisterBuffers(int handle, int setIndex); int APS5_VABI sceVideoOutGetBufferLabelAddress(int handle, uintptr_t* address); -#endif - } + +#endif diff --git a/core/libs/prx/libSceVideoOut/include/Event.hpp b/core/libs/prx/libSceVideoOut/include/Event.hpp index ca5e4f09f7..aea9cf2186 100644 --- a/core/libs/prx/libSceVideoOut/include/Event.hpp +++ b/core/libs/prx/libSceVideoOut/include/Event.hpp @@ -3,7 +3,6 @@ #include -#include "prx/libc/include/General.hpp" #include "SceTypes.hpp" extern "C" { @@ -24,6 +23,6 @@ int APS5_VABI sceVideoOutGetEventCount(const KernelEvent* ev); int APS5_VABI sceVideoOutGetEventData(const KernelEvent* ev, int64_t* data); int APS5_VABI sceVideoOutGetEventId(const KernelEvent* ev); -#endif - } + +#endif diff --git a/core/libs/prx/libSceVideoOut/include/Output.hpp b/core/libs/prx/libSceVideoOut/include/Output.hpp index 569e97ee77..caebc2514a 100644 --- a/core/libs/prx/libSceVideoOut/include/Output.hpp +++ b/core/libs/prx/libSceVideoOut/include/Output.hpp @@ -2,17 +2,16 @@ #define CORE_LIBS_PRX_LIBSCEVIDEOUOUT_INCLUDE_OUTPUT_HPP #include -#include "prx/libc/include/General.hpp" #include "SceTypes.hpp" int ValidateVideoOutOutputMode_nid_no_patch(uint64_t mode, const VideoOutOutputOptions* options, int displayRefreshRate); extern "C" { -int APS5_VABI sceVideoOutOpen(int user_id, int bus_type, int index, const void* param); +int APS5_VABI sceVideoOutOpen(int userId, int busType, int index, const void* param); int APS5_VABI sceVideoOutClose(int handle); -int APS5_VABI sceVideoOutConfigureOutput(int handle, uint64_t mode, const VideoOutOutputOptions* options, void* reserved_ptr, uint64_t reserved); -int APS5_VABI sceVideoOutIsOutputSupported(int handle, uint64_t mode, const VideoOutOutputOptions* options, void* reserved_ptr, uint64_t reserved); +int APS5_VABI sceVideoOutConfigureOutput(int handle, uint64_t mode, const VideoOutOutputOptions* options, void* reservedPtr, uint64_t reserved); +int APS5_VABI sceVideoOutIsOutputSupported(int handle, uint64_t mode, const VideoOutOutputOptions* options, void* reservedPtr, uint64_t reserved); int APS5_VABI sceVideoOutInitializeOutputOptions(VideoOutOutputOptions* options); int APS5_VABI sceVideoOutAllowOutputResolutionWqhdDetection(int handle); int APS5_VABI sceVideoOutSetFlipRate(int handle, int rate); @@ -31,9 +30,9 @@ int APS5_VABI sceVideoOutAdjustColor(int handle, const VideoOutColorSettings* se int APS5_VABI sceVideoOutColorSpaceConversionSettingsSetDefaultSdrToHdrConversion(VideoOutColorSpaceConversionSettings* settings); int APS5_VABI sceVideoOutColorSpaceConversionSettingsSetSdrToHdrConversion(VideoOutColorSpaceConversionSettings* settings, float lumaScale, uint32_t option); int APS5_VABI sceVideoOutAdjustColorSpaceConversion(int handle, const VideoOutColorSpaceConversionSettings* settings); -int APS5_VABI sceVideoOutColorSpaceConversionSettingsSetDefaultSdrToHdrConversion_(VideoOutColorSpaceConversionSettings* settings, uint32_t settings_size); -int APS5_VABI sceVideoOutColorSpaceConversionSettingsSetSdrToHdrConversion_(VideoOutColorSpaceConversionSettings* settings, float lumaScale, uint32_t option, uint32_t settings_size); -int APS5_VABI sceVideoOutAdjustColorSpaceConversion_(int handle, const VideoOutColorSpaceConversionSettings* settings, uint32_t settings_size); +int APS5_VABI sceVideoOutColorSpaceConversionSettingsSetDefaultSdrToHdrConversion_(VideoOutColorSpaceConversionSettings* settings, uint32_t settingsSize); +int APS5_VABI sceVideoOutColorSpaceConversionSettingsSetSdrToHdrConversion_(VideoOutColorSpaceConversionSettings* settings, float lumaScale, uint32_t option, uint32_t settingsSize); +int APS5_VABI sceVideoOutAdjustColorSpaceConversion_(int handle, const VideoOutColorSpaceConversionSettings* settings, uint32_t settingsSize); int APS5_VABI sceVideoOutSetGlobalBlendSpace(int handle, uint32_t space, uint32_t option); int APS5_VABI sceVideoOutVrrPegToFixedRate(int handle, uint64_t arg1, uint64_t arg2); int APS5_VABI sceVideoOutVrrUnpegFromFixedRate(int handle); diff --git a/core/libs/prx/libSceVideoOut/include/VideoOut.hpp b/core/libs/prx/libSceVideoOut/include/VideoOut.hpp new file mode 100644 index 0000000000..8f86fea2b9 --- /dev/null +++ b/core/libs/prx/libSceVideoOut/include/VideoOut.hpp @@ -0,0 +1,18 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceVideoOutSetFlipMaster(std::int32_t handle, std::int32_t masterHandle); +int APS5_VABI sceVideoOutClearFlipMaster(std::int32_t handle); +int APS5_VABI sceVideoOutCursorEnable(int32_t, int32_t, const void*); +int APS5_VABI sceVideoOutCursorDisable(int32_t, int32_t); +int APS5_VABI sceVideoOutCursorSetImageAddress(int32_t, int32_t, const void*); +int APS5_VABI sceVideoOutCursorSetPosition(int32_t, int32_t, uint32_t, uint32_t); +int APS5_VABI sceVideoOutAdjustColor_(int handle, const VideoOutColorSettings* settings, uint32_t settingsSize); +int APS5_VABI sceVideoOutColorSettingsSetGamma_(VideoOutColorSettings* settings, float gamma, uint32_t settingsSize); +int APS5_VABI sceDbgVideoOutAddOutputModeVr60Privilege(); +int APS5_VABI sceVideoOutAddVrrStatusFlagsPrivilege(); + +} diff --git a/core/libs/prx/libSceVideoOut/libSceVideoOut.hpp b/core/libs/prx/libSceVideoOut/libSceVideoOut.hpp new file mode 100644 index 0000000000..d3328b1410 --- /dev/null +++ b/core/libs/prx/libSceVideoOut/libSceVideoOut.hpp @@ -0,0 +1,6 @@ +#pragma once + +#include "prx/libSceVideoOut/include/Buffer.hpp" +#include "prx/libSceVideoOut/include/Event.hpp" +#include "prx/libSceVideoOut/include/Output.hpp" +#include "prx/libSceVideoOut/include/VideoOut.hpp" diff --git a/core/libs/prx/libSceVideoOut/src/Buffer.cpp b/core/libs/prx/libSceVideoOut/src/Buffer.cpp index 7197986ca7..75c4e8a067 100644 --- a/core/libs/prx/libSceVideoOut/src/Buffer.cpp +++ b/core/libs/prx/libSceVideoOut/src/Buffer.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceVideoOut/include/Buffer.hpp" #include #include #include diff --git a/core/libs/prx/libSceVideoOut/src/Event.cpp b/core/libs/prx/libSceVideoOut/src/Event.cpp index d13e6494fb..dde7b34821 100644 --- a/core/libs/prx/libSceVideoOut/src/Event.cpp +++ b/core/libs/prx/libSceVideoOut/src/Event.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceVideoOut/include/Event.hpp" #include #include #include diff --git a/core/libs/prx/libSceVideoOut/src/Output.cpp b/core/libs/prx/libSceVideoOut/src/Output.cpp index 20fb05c756..f1d49072fb 100644 --- a/core/libs/prx/libSceVideoOut/src/Output.cpp +++ b/core/libs/prx/libSceVideoOut/src/Output.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceVideoOut/include/VideoOut.hpp" #include #include #include diff --git a/core/libs/prx/libSceVideoOut/tests/Flip.cpp b/core/libs/prx/libSceVideoOut/tests/Flip.cpp index 75870fadad..877e19e1fa 100644 --- a/core/libs/prx/libSceVideoOut/tests/Flip.cpp +++ b/core/libs/prx/libSceVideoOut/tests/Flip.cpp @@ -1,3 +1,4 @@ +#include "prx/libkernel/include/Api.hpp" #include "prx/libSceVideoOut/include/VideoOutDriver.hpp" #include "prx/libSceVideoOut/include/Buffer.hpp" #include "prx/libSceVideoOut/include/Output.hpp" @@ -25,11 +26,6 @@ #undef main -extern "C" int APS5_VABI sceKernelCreateEqueue(KernelEqueue* eq, const char* name); -extern "C" int APS5_VABI sceKernelDeleteEqueue(KernelEqueue eq); -extern "C" int APS5_VABI sceKernelAllocateDirectMemory(std::int64_t, std::int64_t, std::size_t, std::size_t, int, std::int64_t*); -extern "C" int APS5_VABI sceKernelMapDirectMemory(void**, std::size_t, int, int, std::int64_t, std::size_t); - namespace { void check(bool condition, const char* reason) { diff --git a/core/libs/prx/libSceVideoOut/tests/MouseInput.cpp b/core/libs/prx/libSceVideoOut/tests/MouseInput.cpp index 759c9708e7..12c9119998 100644 --- a/core/libs/prx/libSceVideoOut/tests/MouseInput.cpp +++ b/core/libs/prx/libSceVideoOut/tests/MouseInput.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceMouse/include/Api.hpp" #include "prx/libSceVideoOut/include/MouseInput.hpp" #include "prx/libSceMouse/include/mouse_structs.h" #include "prx/libc/include/general/VabiMacros.hpp" @@ -9,13 +10,6 @@ #include #undef main -extern "C" { -int APS5_VABI sceMouseInit(); -int APS5_VABI sceMouseOpen(int userId, std::int32_t type, std::int32_t index, const void* param); -int APS5_VABI sceMouseRead(std::int32_t handle, MouseData* data, std::int32_t num); -int APS5_VABI sceMouseClose(std::int32_t handle); -} - namespace { void Require(bool condition, const char* reason) { diff --git a/core/libs/prx/libSceVideoOut/tests/OutputModePolicy.cpp b/core/libs/prx/libSceVideoOut/tests/OutputModePolicy.cpp index 5a4a600944..59fafc5235 100644 --- a/core/libs/prx/libSceVideoOut/tests/OutputModePolicy.cpp +++ b/core/libs/prx/libSceVideoOut/tests/OutputModePolicy.cpp @@ -1,6 +1,7 @@ #include "prx/libSceVideoOut/include/Output.hpp" #include #include +#include #include static void Require(bool value, const char* reason) { diff --git a/core/libs/prx/libSceVideoOutSecondary/libSceVideoOutSecondary.hpp b/core/libs/prx/libSceVideoOutSecondary/libSceVideoOutSecondary.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceVideoOutSecondary/libSceVideoOutSecondary.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceVideoRecording.native/libSceVideoRecording.native.hpp b/core/libs/prx/libSceVideoRecording.native/libSceVideoRecording.native.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceVideoRecording.native/libSceVideoRecording.native.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceVideoRecording/libSceVideoRecording.hpp b/core/libs/prx/libSceVideoRecording/libSceVideoRecording.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceVideoRecording/libSceVideoRecording.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceVideoRecordingP/Export.cpp b/core/libs/prx/libSceVideoRecordingP/Export.cpp index c3b67583f6..6166139756 100644 --- a/core/libs/prx/libSceVideoRecordingP/Export.cpp +++ b/core/libs/prx/libSceVideoRecordingP/Export.cpp @@ -1,51 +1,15 @@ +#include "prx/libSceVideoRecordingP/include/Api.hpp" #include #include #include "SceTypes.hpp" #include "prx/libc/include/General.hpp" -struct VideoRecordingContext; - -struct VideoRecordingQueryParam { - std::uint64_t size; - std::uint32_t reserved8; - std::int32_t mode; - std::uint8_t reserved16[12]; - std::uint32_t option; - std::uint8_t reserved32[32]; -}; - static_assert(sizeof(VideoRecordingQueryParam) == 64); static_assert(offsetof(VideoRecordingQueryParam, mode) == 12); static_assert(offsetof(VideoRecordingQueryParam, option) == 28); - -struct VideoRecordingSupportInfo { - std::uint8_t data[18]; -}; - static_assert(sizeof(VideoRecordingSupportInfo) == 18); -struct VideoRecordingParam { - std::uint64_t size; - std::int32_t threadPriority; - std::uint32_t duration; - std::uint32_t mode; - std::int32_t outputMode; - std::uint32_t option; - std::uint32_t format; -}; - -struct VideoRecordingParam2 { - std::uint64_t size; - std::uint64_t affinityMask; - std::int32_t threadPriority; - std::uint32_t duration; - std::uint32_t mode; - std::int32_t outputMode; - std::uint32_t option; - std::uint32_t format; -}; - static_assert(sizeof(VideoRecordingParam) == 32); static_assert(offsetof(VideoRecordingParam, duration) == 12); static_assert(offsetof(VideoRecordingParam, format) == 28); diff --git a/core/libs/prx/libSceVideoRecordingP/include/Api.hpp b/core/libs/prx/libSceVideoRecordingP/include/Api.hpp new file mode 100644 index 0000000000..2f831a0c7e --- /dev/null +++ b/core/libs/prx/libSceVideoRecordingP/include/Api.hpp @@ -0,0 +1,68 @@ +#pragma once + +#include "SceTypes.hpp" + +struct VideoRecordingContext; + +struct VideoRecordingParam { + std::uint64_t size; + std::int32_t threadPriority; + std::uint32_t duration; + std::uint32_t mode; + std::int32_t outputMode; + std::uint32_t option; + std::uint32_t format; +}; + +struct VideoRecordingParam2 { + std::uint64_t size; + std::uint64_t affinityMask; + std::int32_t threadPriority; + std::uint32_t duration; + std::uint32_t mode; + std::int32_t outputMode; + std::uint32_t option; + std::uint32_t format; +}; + +struct VideoRecordingQueryParam { + std::uint64_t size; + std::uint32_t reserved8; + std::int32_t mode; + std::uint8_t reserved16[12]; + std::uint32_t option; + std::uint8_t reserved32[32]; +}; + +struct VideoRecordingSupportInfo { + std::uint8_t data[18]; +}; + +extern "C" { + +void APS5_VABI _sceVideoRecordingQueryParam_nid_postfix(VideoRecordingQueryParam* param); +int APS5_VABI sceVideoRecordingClose(int discard); +int APS5_VABI sceVideoRecordingCloseByHandle(VideoRecordingContext* handle, int discard); +int APS5_VABI sceVideoRecordingCopyBGRAtoNV12(void* dst, const void* src, uint32_t width, uint32_t height); +int APS5_VABI sceVideoRecordingGetInfo(std::int32_t info, void*, std::size_t); +int APS5_VABI sceVideoRecordingGetInfoByHandle(VideoRecordingContext* handle, int32_t info, void* data, size_t size); +int APS5_VABI sceVideoRecordingGetStatus(void); +int APS5_VABI sceVideoRecordingGetSupportInfo(VideoRecordingSupportInfo* info); +int APS5_VABI sceVideoRecordingGetVideoOutMode(std::uint32_t* mode); +int APS5_VABI sceVideoRecordingInit(void); +int APS5_VABI sceVideoRecordingInitialize(void* param); +int APS5_VABI sceVideoRecordingOpen(const char* path, const VideoRecordingParam* param, void* heap, int heapSize); +int APS5_VABI sceVideoRecordingOpen2(const char* path, const VideoRecordingParam2* param, void* heap, int heapSize); +std::int64_t APS5_VABI sceVideoRecordingQueryHddSize2(const VideoRecordingParam2* param); +int APS5_VABI sceVideoRecordingQueryMemSize(const VideoRecordingParam* param); +int APS5_VABI sceVideoRecordingQueryMemSize2(const VideoRecordingParam2* param); +int APS5_VABI sceVideoRecordingRestModeProcessGetStatus(void* status); +int APS5_VABI sceVideoRecordingRestModeProcessStart(void* param); +int APS5_VABI sceVideoRecordingSendCommand(int cmd, const void* param); +int APS5_VABI sceVideoRecordingSetInfo(std::int32_t info, const void* data, std::size_t size); +int APS5_VABI sceVideoRecordingStart(void); +int APS5_VABI sceVideoRecordingStop(void); +int APS5_VABI sceVideoRecordingTerm(void); +int APS5_VABI videoRecordingUnknown_iQS6DUtLybE(void); + +} diff --git a/core/libs/prx/libSceVideoRecordingP/libSceVideoRecordingP.hpp b/core/libs/prx/libSceVideoRecordingP/libSceVideoRecordingP.hpp new file mode 100644 index 0000000000..33ebd6f0fc --- /dev/null +++ b/core/libs/prx/libSceVideoRecordingP/libSceVideoRecordingP.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceVideoRecordingP/include/Api.hpp" diff --git a/core/libs/prx/libSceVideoStreamingEngine/Export.cpp b/core/libs/prx/libSceVideoStreamingEngine/Export.cpp index 1a09e3b9df..f773806a45 100644 --- a/core/libs/prx/libSceVideoStreamingEngine/Export.cpp +++ b/core/libs/prx/libSceVideoStreamingEngine/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceVideoStreamingEngine/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceVideoStreamingEngine/include/Api.hpp b/core/libs/prx/libSceVideoStreamingEngine/include/Api.hpp new file mode 100644 index 0000000000..2b807d7c25 --- /dev/null +++ b/core/libs/prx/libSceVideoStreamingEngine/include/Api.hpp @@ -0,0 +1,20 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceVideoStreamingEngineDestroyMediaKeySystemAccess(); +int APS5_VABI sceVideoStreamingEngineMediaKeySessionGenerateRequest(); +int APS5_VABI sceVideoStreamingEngineMediaKeySessionGetExpiration(); +int APS5_VABI sceVideoStreamingEngineMediaKeySessionGetKeyStatuses(); +int APS5_VABI sceVideoStreamingEngineMediaKeySessionGetSessionId(); +int APS5_VABI sceVideoStreamingEngineMediaKeySessionLoad(); +int APS5_VABI sceVideoStreamingEngineMediaKeySessionSetEventHandler(); +int APS5_VABI sceVideoStreamingEngineMediaKeySystemAccessCreateMediaKeys(); +int APS5_VABI sceVideoStreamingEngineMediaKeySystemAccessDestroyMediaKeys(); +int APS5_VABI sceVideoStreamingEngineMediaKeySystemAccessGetKeySystem(); +int APS5_VABI sceVideoStreamingEngineMediaKeySystemAccessSetCdmStorageConfig(); +int APS5_VABI sceVideoStreamingEngineMediaKeysCreateSession(); + +} diff --git a/core/libs/prx/libSceVideoStreamingEngine/libSceVideoStreamingEngine.hpp b/core/libs/prx/libSceVideoStreamingEngine/libSceVideoStreamingEngine.hpp new file mode 100644 index 0000000000..f0f435d15e --- /dev/null +++ b/core/libs/prx/libSceVideoStreamingEngine/libSceVideoStreamingEngine.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceVideoStreamingEngine/include/Api.hpp" diff --git a/core/libs/prx/libSceVideoStreamingEngine_sys/libSceVideoStreamingEngine_sys.hpp b/core/libs/prx/libSceVideoStreamingEngine_sys/libSceVideoStreamingEngine_sys.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceVideoStreamingEngine_sys/libSceVideoStreamingEngine_sys.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceVideodec/Export.cpp b/core/libs/prx/libSceVideodec/Export.cpp index 56ae352fcf..efb762dbfe 100644 --- a/core/libs/prx/libSceVideodec/Export.cpp +++ b/core/libs/prx/libSceVideodec/Export.cpp @@ -1,3 +1,5 @@ +#include "prx/libSceVideodec2/include/Api.hpp" +#include "prx/libSceVideodec/include/Api.hpp" #include #include #include @@ -10,6 +12,8 @@ namespace { +using namespace SceVideodec; + constexpr int VideodecErrorApiFail = static_cast(0x80C10000); constexpr int VideodecErrorStructSize = static_cast(0x80C10002); constexpr int VideodecErrorHandle = static_cast(0x80C10003); @@ -24,142 +28,6 @@ constexpr int VideodecErrorDecodeAu = static_cast(0x80C10011); constexpr std::uint32_t CodecAvc = 1; constexpr std::uint32_t PitchAlignment = 64; -struct ConfigInfo { - std::uint64_t thisSize; - std::uint32_t codecType; - std::uint32_t profile; - std::uint32_t maxLevel; - std::int32_t maxFrameWidth; - std::int32_t maxFrameHeight; - std::int32_t maxDpbFrameCount; - std::uint64_t videodecFlags; -}; - -struct ResourceInfo { - std::uint64_t thisSize; - std::uint64_t cpuMemorySize; - void* cpuMemory; - std::uint64_t cpuGpuMemorySize; - void* cpuGpuMemory; - std::uint64_t maxFrameBufferSize; - std::uint32_t frameBufferAlignment; -}; - -struct Ctrl { - std::uint64_t thisSize; - void* handle; - std::uint64_t version; -}; - -struct FrameBuffer { - std::uint64_t thisSize; - void* frameBuffer; - std::uint64_t frameBufferSize; -}; - -struct AvcInfo { - std::uint32_t numUnitsInTick; - std::uint32_t timeScale; - std::uint8_t fixedFrameRateFlag; - std::uint8_t aspectRatioIdc; - std::uint16_t sarWidth; - std::uint16_t sarHeight; - std::uint8_t colourPrimaries; - std::uint8_t transferCharacteristics; - std::uint8_t matrixCoefficients; - std::uint8_t videoFullRangeFlag; - std::uint32_t frameCropLeftOffset; - std::uint32_t frameCropRightOffset; - std::uint32_t frameCropTopOffset; - std::uint32_t frameCropBottomOffset; -}; - -union CodecInfo { - std::uint8_t reserved[64]; - AvcInfo avc; -}; - -struct PictureInfo { - std::uint64_t thisSize; - std::uint32_t isValid; - std::uint32_t codecType; - std::uint32_t frameWidth; - std::uint32_t framePitch; - std::uint32_t frameHeight; - std::uint32_t isErrorPic; - std::uint64_t ptsData; - std::uint64_t attachedData; - CodecInfo codec; -}; - -struct InputData { - std::uint64_t thisSize; - const std::uint8_t* auData; - std::uint64_t auSize; - std::uint64_t ptsData; - std::uint64_t dtsData; - std::uint64_t attachedData; -}; - -struct Decoder2ConfigInfo { - std::uint64_t thisSize; - std::uint32_t resourceType; - std::uint32_t codecType; - std::uint32_t profile; - std::uint32_t maxLevel; - std::int32_t maxFrameWidth; - std::int32_t maxFrameHeight; - std::int32_t maxDpbFrameCount; - std::uint32_t decodePipelineDepth; -}; - -struct Decoder2MemoryInfo { - std::uint64_t thisSize; - std::uint64_t cpuMemorySize; - void* cpuMemory; - std::uint64_t gpuMemorySize; - void* gpuMemory; - std::uint64_t cpuGpuMemorySize; - void* cpuGpuMemory; - std::uint64_t maxFrameBufferSize; - std::uint32_t frameBufferAlignment; -}; - -struct Decoder2FrameBuffer { - std::uint64_t thisSize; - void* frameBuffer; - std::uint64_t frameBufferSize; - bool isAccepted; -}; - -struct Decoder2OutputInfo { - std::uint64_t thisSize; - bool isValid; - bool isErrorFrame; - std::uint8_t pictureCount; - std::uint32_t codecType; - std::uint32_t frameWidth; - std::uint32_t framePitch; - std::uint32_t frameHeight; - void* frameBuffer; - std::uint64_t frameBufferSize; - std::uint32_t frameFormat; - std::uint32_t framePitchInBytes; -}; - -struct Decoder2AvcPictureInfo { - std::uint64_t thisSize; - bool isValid; - std::uint64_t ptsData; - std::uint64_t dtsData; - std::uint64_t attachedData; - std::uint8_t idrPictureFlag; - std::uint8_t profileIdc; - std::uint8_t levelIdc; - std::uint32_t picWidthInLumaSamples; - std::uint32_t picHeightInLumaSamples; -}; - struct Decoder2Crop { std::uint32_t left; std::uint32_t right; @@ -171,8 +39,8 @@ static_assert(sizeof(ConfigInfo) == 40 && sizeof(ResourceInfo) == 56 && sizeof(C static_assert(offsetof(ConfigInfo, maxFrameWidth) == 20 && offsetof(ConfigInfo, videodecFlags) == 32); static_assert(offsetof(ResourceInfo, cpuGpuMemorySize) == 24 && offsetof(ResourceInfo, maxFrameBufferSize) == 40); static_assert(offsetof(ResourceInfo, frameBufferAlignment) == 48); -static_assert(sizeof(Decoder2ConfigInfo) == 40 && sizeof(Decoder2MemoryInfo) == 72); -static_assert(sizeof(FrameBuffer) == 24 && sizeof(InputData) == 48 && sizeof(PictureInfo) == 112); +static_assert(sizeof(SceVideodec2::DecoderConfigInfo) == 40 && sizeof(SceVideodec2::DecoderMemoryInfo) == 72); +static_assert(sizeof(FrameBuffer) == 24 && sizeof(SceVideodec2::InputData) == 48 && sizeof(PictureInfo) == 112); static_assert(sizeof(CodecInfo) == 64 && offsetof(PictureInfo, codec) == 48); struct Decoder { @@ -197,13 +65,7 @@ std::uint32_t AlignUp(std::uint32_t value, std::uint32_t alignment) { } extern "C" { -int APS5_VABI sceVideodec2QueryDecoderMemoryInfo_nid_postfix(const Decoder2ConfigInfo*, Decoder2MemoryInfo*); -int APS5_VABI sceVideodec2CreateDecoder_nid_postfix(const Decoder2ConfigInfo*, const Decoder2MemoryInfo*, std::uint64_t*); -int APS5_VABI sceVideodec2DeleteDecoder_nid_postfix(std::uint64_t); -int APS5_VABI sceVideodec2Decode_nid_postfix(std::uint64_t, const InputData*, Decoder2FrameBuffer*, Decoder2OutputInfo*); -int APS5_VABI sceVideodec2Flush_nid_postfix(std::uint64_t, Decoder2FrameBuffer*, Decoder2OutputInfo*); -int APS5_VABI sceVideodec2Reset_nid_postfix(std::uint64_t); -int APS5_VABI sceVideodec2GetAvcPictureInfo_nid_postfix(const Decoder2OutputInfo*, Decoder2AvcPictureInfo*, Decoder2AvcPictureInfo*); + void Videodec2PictureCrop_nid_no_patch(std::uint64_t, const void*, Decoder2Crop*); } @@ -216,9 +78,9 @@ struct Geometry { Decoder2Crop crop{}; }; -Decoder2ConfigInfo MapConfig(const ConfigInfo& config) { - Decoder2ConfigInfo decoderConfig{}; - decoderConfig.thisSize = sizeof(Decoder2ConfigInfo); +SceVideodec2::DecoderConfigInfo MapConfig(const ConfigInfo& config) { + SceVideodec2::DecoderConfigInfo decoderConfig{}; + decoderConfig.thisSize = sizeof(SceVideodec2::DecoderConfigInfo); decoderConfig.resourceType = 1; decoderConfig.codecType = CodecAvc; decoderConfig.profile = config.profile; @@ -230,7 +92,7 @@ Decoder2ConfigInfo MapConfig(const ConfigInfo& config) { return decoderConfig; } -Geometry Measure(const Decoder2OutputInfo& output, const Decoder2Crop& crop) { +Geometry Measure(const SceVideodec2::OutputInfo& output, const Decoder2Crop& crop) { Geometry geometry; geometry.width = output.frameWidth; geometry.height = output.frameHeight; @@ -239,7 +101,7 @@ Geometry Measure(const Decoder2OutputInfo& output, const Decoder2Crop& crop) { return geometry; } -void FillPictureInfo(const Geometry& geometry, const Decoder2OutputInfo& output, PictureInfo* picture) { +void FillPictureInfo(const Geometry& geometry, const SceVideodec2::OutputInfo& output, PictureInfo* picture) { picture->isValid = 0; picture->codecType = 0; picture->frameWidth = 0; @@ -261,7 +123,7 @@ void FillPictureInfo(const Geometry& geometry, const Decoder2OutputInfo& output, picture->codec.avc.frameCropBottomOffset = geometry.crop.bottom / 2; } -int CopyPicture(const Decoder2OutputInfo& output, const Geometry& geometry, const FrameBuffer* frameBuffer) { +int CopyPicture(const SceVideodec2::OutputInfo& output, const Geometry& geometry, const FrameBuffer* frameBuffer) { const auto bytes = static_cast(geometry.pitch) * geometry.height * 3 / 2; if (frameBuffer->frameBuffer == nullptr) return VideodecErrorFrameBufferPointer; if (frameBuffer->frameBufferSize < bytes) return VideodecErrorFrameBufferSize; @@ -285,8 +147,8 @@ int APS5_VABI sceVideodecCreateDecoder(const ConfigInfo* config, const ResourceI if (config == nullptr || resource == nullptr || ctrl == nullptr) return VideodecErrorArgumentPointer; if (config->thisSize < sizeof(ConfigInfo) || resource->thisSize < sizeof(ResourceInfo)) return VideodecErrorStructSize; const auto decoderConfig = MapConfig(*config); - Decoder2MemoryInfo decoderMemory{}; - decoderMemory.thisSize = sizeof(Decoder2MemoryInfo); + SceVideodec2::DecoderMemoryInfo decoderMemory{}; + decoderMemory.thisSize = sizeof(SceVideodec2::DecoderMemoryInfo); decoderMemory.cpuMemorySize = resource->cpuMemorySize; decoderMemory.cpuMemory = resource->cpuMemory; decoderMemory.cpuGpuMemorySize = resource->cpuGpuMemorySize; @@ -295,6 +157,7 @@ int APS5_VABI sceVideodecCreateDecoder(const ConfigInfo* config, const ResourceI decoderMemory.frameBufferAlignment = resource->frameBufferAlignment; try { sceVideodec2QueryDecoderMemoryInfo_nid_postfix(&decoderConfig, &decoderMemory); + } catch (const std::exception&) { return VideodecErrorConfigInfo; } @@ -313,11 +176,11 @@ int APS5_VABI sceVideodecCreateDecoder(const ConfigInfo* config, const ResourceI return 0; } -int APS5_VABI sceVideodecDecode(Ctrl* ctrl, const InputData* input, FrameBuffer* frameBuffer, PictureInfo* picture) { +int APS5_VABI sceVideodecDecode(Ctrl* ctrl, const SceVideodec2::InputData* input, FrameBuffer* frameBuffer, PictureInfo* picture) { if (ctrl == nullptr || input == nullptr || picture == nullptr) return VideodecErrorArgumentPointer; if (frameBuffer == nullptr) return VideodecErrorFrameBufferPointer; if (ctrl->thisSize < sizeof(Ctrl)) return VideodecErrorStructSize; - if (input->thisSize < sizeof(InputData)) return VideodecErrorStructSize; + if (input->thisSize < sizeof(SceVideodec2::InputData)) return VideodecErrorStructSize; if (picture->thisSize < sizeof(PictureInfo)) return VideodecErrorStructSize; if (frameBuffer->thisSize < sizeof(FrameBuffer)) return VideodecErrorStructSize; auto* decoder = FindDecoder(ctrl->handle); @@ -325,20 +188,21 @@ int APS5_VABI sceVideodecDecode(Ctrl* ctrl, const InputData* input, FrameBuffer* if (input->auData == nullptr) return VideodecErrorAuPointer; if (input->auSize == 0) return VideodecErrorAuSize; if (frameBuffer->frameBuffer == nullptr) return VideodecErrorFrameBufferPointer; - Decoder2FrameBuffer target{}; - target.thisSize = sizeof(Decoder2FrameBuffer); + SceVideodec2::FrameBuffer target{}; + target.thisSize = sizeof(SceVideodec2::FrameBuffer); target.frameBuffer = decoder->picture.data(); target.frameBufferSize = decoder->picture.size(); - Decoder2OutputInfo output{sizeof(Decoder2OutputInfo)}; + SceVideodec2::OutputInfo output{sizeof(SceVideodec2::OutputInfo)}; try { sceVideodec2Decode_nid_postfix(decoder->handle, input, &target, &output); + } catch (const std::exception&) { return VideodecErrorDecodeAu; } Decoder2Crop crop{}; if (output.isValid) Videodec2PictureCrop_nid_no_patch(decoder->handle, output.frameBuffer, &crop); const auto geometry = Measure(output, crop); - Decoder2AvcPictureInfo avc{sizeof(Decoder2AvcPictureInfo)}; + SceVideodec2::AvcPictureInfo avc{sizeof(SceVideodec2::AvcPictureInfo)}; if (output.isValid) sceVideodec2GetAvcPictureInfo_nid_postfix(&output, &avc, nullptr); FillPictureInfo(geometry, output, picture); picture->ptsData = avc.ptsData; @@ -362,6 +226,7 @@ int APS5_VABI sceVideodecDeleteDecoder(Ctrl* ctrl) { delete decoder; try { sceVideodec2DeleteDecoder_nid_postfix(handle); + } catch (const std::exception&) { return VideodecErrorApiFail; } @@ -377,20 +242,21 @@ int APS5_VABI sceVideodecFlush(Ctrl* ctrl, FrameBuffer* frameBuffer, PictureInfo auto* decoder = FindDecoder(ctrl->handle); if (decoder == nullptr) return VideodecErrorHandle; if (frameBuffer->frameBuffer == nullptr) return VideodecErrorFrameBufferPointer; - Decoder2FrameBuffer target{}; - target.thisSize = sizeof(Decoder2FrameBuffer); + SceVideodec2::FrameBuffer target{}; + target.thisSize = sizeof(SceVideodec2::FrameBuffer); target.frameBuffer = decoder->picture.data(); target.frameBufferSize = decoder->picture.size(); - Decoder2OutputInfo output{sizeof(Decoder2OutputInfo)}; + SceVideodec2::OutputInfo output{sizeof(SceVideodec2::OutputInfo)}; try { sceVideodec2Flush_nid_postfix(decoder->handle, &target, &output); + } catch (const std::exception&) { return VideodecErrorDecodeAu; } Decoder2Crop crop{}; if (output.isValid) Videodec2PictureCrop_nid_no_patch(decoder->handle, output.frameBuffer, &crop); const auto geometry = Measure(output, crop); - Decoder2AvcPictureInfo avc{sizeof(Decoder2AvcPictureInfo)}; + SceVideodec2::AvcPictureInfo avc{sizeof(SceVideodec2::AvcPictureInfo)}; if (output.isValid) sceVideodec2GetAvcPictureInfo_nid_postfix(&output, &avc, nullptr); FillPictureInfo(geometry, output, picture); picture->ptsData = avc.ptsData; @@ -406,6 +272,7 @@ int APS5_VABI sceVideodecReset(Ctrl* ctrl) { if (decoder == nullptr) return VideodecErrorHandle; try { sceVideodec2Reset_nid_postfix(decoder->handle); + } catch (const std::exception&) { return VideodecErrorApiFail; } @@ -420,10 +287,11 @@ int APS5_VABI sceVideodecQueryResourceInfo(const ConfigInfo* config, ResourceInf if (config == nullptr || resource == nullptr) return VideodecErrorArgumentPointer; if (config->thisSize < sizeof(ConfigInfo) || resource->thisSize < sizeof(ResourceInfo)) return VideodecErrorStructSize; const auto decoderConfig = MapConfig(*config); - Decoder2MemoryInfo decoderMemory{}; - decoderMemory.thisSize = sizeof(Decoder2MemoryInfo); + SceVideodec2::DecoderMemoryInfo decoderMemory{}; + decoderMemory.thisSize = sizeof(SceVideodec2::DecoderMemoryInfo); try { sceVideodec2QueryDecoderMemoryInfo_nid_postfix(&decoderConfig, &decoderMemory); + } catch (const std::exception&) { return VideodecErrorConfigInfo; } diff --git a/core/libs/prx/libSceVideodec/include/Api.hpp b/core/libs/prx/libSceVideodec/include/Api.hpp new file mode 100644 index 0000000000..46fd7ef835 --- /dev/null +++ b/core/libs/prx/libSceVideodec/include/Api.hpp @@ -0,0 +1,119 @@ +#include "prx/libSceVideodec2/include/Api.hpp" +#pragma once + +#include "SceTypes.hpp" +#include +#include +#include +#include +#include +#include +#include + +namespace SceVideodec { + +struct ConfigInfo { + std::uint64_t thisSize; + std::uint32_t codecType; + std::uint32_t profile; + std::uint32_t maxLevel; + std::int32_t maxFrameWidth; + std::int32_t maxFrameHeight; + std::int32_t maxDpbFrameCount; + std::uint64_t videodecFlags; +}; + +} + +namespace SceVideodec { + +struct ResourceInfo { + std::uint64_t thisSize; + std::uint64_t cpuMemorySize; + void* cpuMemory; + std::uint64_t cpuGpuMemorySize; + void* cpuGpuMemory; + std::uint64_t maxFrameBufferSize; + std::uint32_t frameBufferAlignment; +}; + +} + +namespace SceVideodec { + +struct Ctrl { + std::uint64_t thisSize; + void* handle; + std::uint64_t version; +}; + +} + +namespace SceVideodec { + +struct FrameBuffer { + std::uint64_t thisSize; + void* frameBuffer; + std::uint64_t frameBufferSize; +}; + +} + +namespace SceVideodec { + +struct AvcInfo { + std::uint32_t numUnitsInTick; + std::uint32_t timeScale; + std::uint8_t fixedFrameRateFlag; + std::uint8_t aspectRatioIdc; + std::uint16_t sarWidth; + std::uint16_t sarHeight; + std::uint8_t colourPrimaries; + std::uint8_t transferCharacteristics; + std::uint8_t matrixCoefficients; + std::uint8_t videoFullRangeFlag; + std::uint32_t frameCropLeftOffset; + std::uint32_t frameCropRightOffset; + std::uint32_t frameCropTopOffset; + std::uint32_t frameCropBottomOffset; +}; + +} + +namespace SceVideodec { + +union CodecInfo { + std::uint8_t reserved[64]; + AvcInfo avc; +}; + +} + +namespace SceVideodec { + +struct PictureInfo { + std::uint64_t thisSize; + std::uint32_t isValid; + std::uint32_t codecType; + std::uint32_t frameWidth; + std::uint32_t framePitch; + std::uint32_t frameHeight; + std::uint32_t isErrorPic; + std::uint64_t ptsData; + std::uint64_t attachedData; + CodecInfo codec; +}; + +} + +extern "C" { + +int APS5_VABI sceVideodecCreateDecoder(const SceVideodec::ConfigInfo* config, const SceVideodec::ResourceInfo* resource, SceVideodec::Ctrl* ctrl); +int APS5_VABI sceVideodecDecode(SceVideodec::Ctrl* ctrl, const SceVideodec2::InputData* input, SceVideodec::FrameBuffer* frameBuffer, SceVideodec::PictureInfo* picture); +int APS5_VABI sceVideodecDeleteDecoder(SceVideodec::Ctrl* ctrl); +int APS5_VABI sceVideodecFlush(SceVideodec::Ctrl* ctrl, SceVideodec::FrameBuffer* frameBuffer, SceVideodec::PictureInfo* picture); +int APS5_VABI sceVideodecReset(SceVideodec::Ctrl* ctrl); +int APS5_VABI sceVideodecMapMemory(void); +int APS5_VABI sceVideodecQueryResourceInfo(const SceVideodec::ConfigInfo* config, SceVideodec::ResourceInfo* resource); + +} diff --git a/core/libs/prx/libSceVideodec/libSceVideodec.hpp b/core/libs/prx/libSceVideodec/libSceVideodec.hpp new file mode 100644 index 0000000000..8fa57dc2dd --- /dev/null +++ b/core/libs/prx/libSceVideodec/libSceVideodec.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceVideodec/include/Api.hpp" diff --git a/core/libs/prx/libSceVideodec2/Export.cpp b/core/libs/prx/libSceVideodec2/Export.cpp index 583b18c0ff..de23de7b72 100644 --- a/core/libs/prx/libSceVideodec2/Export.cpp +++ b/core/libs/prx/libSceVideodec2/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceVideodec2/include/Api.hpp" #include #include #include @@ -24,6 +25,8 @@ extern "C" { namespace { +using namespace SceVideodec2; + constexpr std::uint64_t WorkMemoryBytes = 1u << 20u; constexpr std::uint32_t PitchAlignment = 256; constexpr std::uint32_t HeightAlignment = 32; @@ -33,107 +36,6 @@ constexpr std::uint32_t CodecVp9 = 2382845; constexpr int Videodec2ErrorAccessUnitSize = static_cast(0x811D010Du); constexpr int Videodec2ErrorAccessUnitPointer = static_cast(0x811D010Eu); -struct ComputeMemoryInfo { - std::uint64_t thisSize; - std::uint64_t cpuGpuMemorySize; - void* cpuGpuMemory; -}; - -struct ComputeConfigInfo { - std::uint64_t thisSize; - std::uint16_t computePipeId; - std::uint16_t computeQueueId; - bool checkMemoryType; -}; - -struct DecoderConfigInfo { - std::uint64_t thisSize; - std::uint32_t resourceType; - std::uint32_t codecType; - std::uint32_t profile; - std::uint32_t maxLevel; - std::int32_t maxFrameWidth; - std::int32_t maxFrameHeight; - std::int32_t maxDpbFrameCount; - std::uint32_t decodePipelineDepth; -}; - -struct DecoderMemoryInfo { - std::uint64_t thisSize; - std::uint64_t cpuMemorySize; - void* cpuMemory; - std::uint64_t gpuMemorySize; - void* gpuMemory; - std::uint64_t cpuGpuMemorySize; - void* cpuGpuMemory; - std::uint64_t maxFrameBufferSize; - std::uint32_t frameBufferAlignment; -}; - -struct InputData { - std::uint64_t thisSize; - const std::uint8_t* auData; - std::uint64_t auSize; - std::uint64_t ptsData; - std::uint64_t dtsData; - std::uint64_t attachedData; -}; - -struct FrameBuffer { - std::uint64_t thisSize; - void* frameBuffer; - std::uint64_t frameBufferSize; - bool isAccepted; -}; - -struct OutputInfo { - std::uint64_t thisSize; - bool isValid; - bool isErrorFrame; - std::uint8_t pictureCount; - std::uint32_t codecType; - std::uint32_t frameWidth; - std::uint32_t framePitch; - std::uint32_t frameHeight; - void* frameBuffer; - std::uint64_t frameBufferSize; - std::uint32_t frameFormat; - std::uint32_t framePitchInBytes; -}; - -struct AvcPictureInfo { - std::uint64_t thisSize; - bool isValid; - std::uint64_t ptsData; - std::uint64_t dtsData; - std::uint64_t attachedData; - std::uint8_t idrPictureFlag; - std::uint8_t profileIdc; - std::uint8_t levelIdc; - std::uint32_t picWidthInLumaSamples; - std::uint32_t picHeightInLumaSamples; -}; - -struct Vp9PictureInfo { - std::uint64_t thisSize; - bool isValid; - std::uint64_t ptsData; - std::uint64_t dtsData; - std::uint64_t attachedData; - std::uint32_t profile; - std::uint32_t level; - std::uint32_t keyFrameFlag; - std::uint32_t intraOnly; - std::uint8_t bitDepth; - std::uint8_t colorRange; - std::uint32_t colorSpace; - std::uint32_t numFrames; - std::uint32_t frameWidth; - std::uint32_t frameHeight; - std::uint32_t renderWidth; - std::uint32_t renderHeight; -}; - static_assert(sizeof(Vp9PictureInfo) == 88); static_assert(offsetof(Vp9PictureInfo, colorSpace) == 60); diff --git a/core/libs/prx/libSceVideodec2/Unimplemented.cpp b/core/libs/prx/libSceVideodec2/Unimplemented.cpp index b427d652ac..62a9691332 100644 --- a/core/libs/prx/libSceVideodec2/Unimplemented.cpp +++ b/core/libs/prx/libSceVideodec2/Unimplemented.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceVideodec2/include/Api.hpp" #include "SceTypes.hpp" #include "prx/libc/include/General.hpp" diff --git a/core/libs/prx/libSceVideodec2/include/Api.hpp b/core/libs/prx/libSceVideodec2/include/Api.hpp new file mode 100644 index 0000000000..ff71178c8c --- /dev/null +++ b/core/libs/prx/libSceVideodec2/include/Api.hpp @@ -0,0 +1,186 @@ +#pragma once + +#include "SceTypes.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace SceVideodec2 { + +struct ComputeMemoryInfo { + std::uint64_t thisSize; + std::uint64_t cpuGpuMemorySize; + void* cpuGpuMemory; +}; + +} + +namespace SceVideodec2 { + +struct ComputeConfigInfo { + std::uint64_t thisSize; + std::uint16_t computePipeId; + std::uint16_t computeQueueId; + bool checkMemoryType; +}; + +} + +namespace SceVideodec2 { + +struct DecoderConfigInfo { + std::uint64_t thisSize; + std::uint32_t resourceType; + std::uint32_t codecType; + std::uint32_t profile; + std::uint32_t maxLevel; + std::int32_t maxFrameWidth; + std::int32_t maxFrameHeight; + std::int32_t maxDpbFrameCount; + std::uint32_t decodePipelineDepth; +}; + +} + +namespace SceVideodec2 { + +struct DecoderMemoryInfo { + std::uint64_t thisSize; + std::uint64_t cpuMemorySize; + void* cpuMemory; + std::uint64_t gpuMemorySize; + void* gpuMemory; + std::uint64_t cpuGpuMemorySize; + void* cpuGpuMemory; + std::uint64_t maxFrameBufferSize; + std::uint32_t frameBufferAlignment; +}; + +} + +namespace SceVideodec2 { + +struct InputData { + std::uint64_t thisSize; + const std::uint8_t* auData; + std::uint64_t auSize; + std::uint64_t ptsData; + std::uint64_t dtsData; + std::uint64_t attachedData; +}; + +} + +namespace SceVideodec2 { + +struct FrameBuffer { + std::uint64_t thisSize; + void* frameBuffer; + std::uint64_t frameBufferSize; + bool isAccepted; +}; + +} + +namespace SceVideodec2 { + +struct OutputInfo { + std::uint64_t thisSize; + bool isValid; + bool isErrorFrame; + std::uint8_t pictureCount; + std::uint32_t codecType; + std::uint32_t frameWidth; + std::uint32_t framePitch; + std::uint32_t frameHeight; + void* frameBuffer; + std::uint64_t frameBufferSize; + std::uint32_t frameFormat; + std::uint32_t framePitchInBytes; +}; + +} + +namespace SceVideodec2 { + +struct AvcPictureInfo { + std::uint64_t thisSize; + bool isValid; + std::uint64_t ptsData; + std::uint64_t dtsData; + std::uint64_t attachedData; + std::uint8_t idrPictureFlag; + std::uint8_t profileIdc; + std::uint8_t levelIdc; + std::uint32_t picWidthInLumaSamples; + std::uint32_t picHeightInLumaSamples; +}; + +} + +namespace SceVideodec2 { + +struct Vp9PictureInfo { + std::uint64_t thisSize; + bool isValid; + std::uint64_t ptsData; + std::uint64_t dtsData; + std::uint64_t attachedData; + std::uint32_t profile; + std::uint32_t level; + std::uint32_t keyFrameFlag; + std::uint32_t intraOnly; + std::uint8_t bitDepth; + std::uint8_t colorRange; + std::uint32_t colorSpace; + std::uint32_t numFrames; + std::uint32_t frameWidth; + std::uint32_t frameHeight; + std::uint32_t renderWidth; + std::uint32_t renderHeight; +}; + +} + +extern "C" { + +int APS5_VABI sceVideodec2QueryComputeMemoryInfo_nid_postfix(SceVideodec2::ComputeMemoryInfo* info); +int APS5_VABI sceVideodec2AllocateComputeQueue_nid_postfix(const SceVideodec2::ComputeConfigInfo* config, const SceVideodec2::ComputeMemoryInfo* memory, std::uint64_t* queue); +int APS5_VABI sceVideodec2ReleaseComputeQueue_nid_postfix(std::uint64_t queue); +int APS5_VABI sceVideodec2QueryDecoderMemoryInfo_nid_postfix(const SceVideodec2::DecoderConfigInfo* config, SceVideodec2::DecoderMemoryInfo* memory); +int APS5_VABI sceVideodec2CreateDecoder_nid_postfix(const SceVideodec2::DecoderConfigInfo* config, const SceVideodec2::DecoderMemoryInfo* memory, std::uint64_t* handle); +int APS5_VABI sceVideodec2DeleteDecoder_nid_postfix(std::uint64_t handle); +int APS5_VABI sceVideodec2Decode_nid_postfix(std::uint64_t handle, const SceVideodec2::InputData* input, SceVideodec2::FrameBuffer* frame, SceVideodec2::OutputInfo* output); +int APS5_VABI sceVideodec2Flush_nid_postfix(std::uint64_t handle, SceVideodec2::FrameBuffer* frame, SceVideodec2::OutputInfo* output); +int APS5_VABI sceVideodec2Reset_nid_postfix(std::uint64_t handle); +int APS5_VABI sceVideodec2GetPictureInfo_nid_postfix(const SceVideodec2::OutputInfo* output, SceVideodec2::AvcPictureInfo* first, void* second); +int APS5_VABI sceVideodec2GetAvcPictureInfo_nid_postfix(const SceVideodec2::OutputInfo* output, SceVideodec2::AvcPictureInfo* first, SceVideodec2::AvcPictureInfo* second); +int APS5_VABI sceVideodec2GetVp9PictureInfo_nid_postfix(const SceVideodec2::OutputInfo* output, SceVideodec2::Vp9PictureInfo* info); +int APS5_VABI sceVideodec2TermLibrary(); +int APS5_VABI sceVideodec2QueryLibraryInfo(); +int APS5_VABI sceVideodec2QueryDecoderInfo(); +int APS5_VABI sceVideodec2MapMemory(); +int APS5_VABI sceVideodec2MapDirectMemory(void*, const void*); +int APS5_VABI sceVideodec2PresetDecoderConfigInfo(); +int APS5_VABI sceVideodec2PresetDecoderConfigInfoAvc(); +int APS5_VABI sceVideodec2PresetDecoderConfigInfoHevc(); +int APS5_VABI sceVideodec2PresetDecoderConfigInfoVp9(); +int APS5_VABI sceVideodec2CreateDecoderBid(); +int APS5_VABI sceVideodec2CreateHevcDecoder(); +int APS5_VABI sceVideodec2QueryHevcDecoderMemoryInfo(); +int APS5_VABI sceVideodec2GetHevcPictureInfo(); +int APS5_VABI sceVideodec2InitLibrary(); + +} diff --git a/core/libs/prx/libSceVideodec2/libSceVideodec2.hpp b/core/libs/prx/libSceVideodec2/libSceVideodec2.hpp new file mode 100644 index 0000000000..85a17c3882 --- /dev/null +++ b/core/libs/prx/libSceVideodec2/libSceVideodec2.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceVideodec2/include/Api.hpp" diff --git a/core/libs/prx/libSceVisionManager/Export.cpp b/core/libs/prx/libSceVisionManager/Export.cpp index 91dd5c2463..de5e1986f2 100644 --- a/core/libs/prx/libSceVisionManager/Export.cpp +++ b/core/libs/prx/libSceVisionManager/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceVisionManager/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceVisionManager/include/Api.hpp b/core/libs/prx/libSceVisionManager/include/Api.hpp new file mode 100644 index 0000000000..95c8fb3a85 --- /dev/null +++ b/core/libs/prx/libSceVisionManager/include/Api.hpp @@ -0,0 +1,64 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceVisionManagerApplyCalibrateHmdResult(); +int APS5_VABI sceVisionManagerCancelRequest(); +int APS5_VABI sceVisionManagerClose(); +int APS5_VABI sceVisionManagerFinalize(); +int APS5_VABI sceVisionManagerGenerateRegisterUserData(); +int APS5_VABI sceVisionManagerGenerateRegisterUserDataFinalize(); +int APS5_VABI sceVisionManagerGenerateRegisterUserDataInitialize(); +int APS5_VABI sceVisionManagerGetCalibrateTrackingLedInfo(); +int APS5_VABI sceVisionManagerGetCalibrateTrackingLedNecessity(); +int APS5_VABI sceVisionManagerGetHitCountOfRegisterUserData(); +int APS5_VABI sceVisionManagerGetLibraryVersion(); +int APS5_VABI sceVisionManagerGetNumOfRegisterUserDataSlot(); +int APS5_VABI sceVisionManagerGetRegisterUserDataSize(); +int APS5_VABI sceVisionManagerGetRegisterUserDataVersion(); +int APS5_VABI sceVisionManagerGetResultOfCalibrateHmd(); +int APS5_VABI sceVisionManagerGetResultOfCalibrateStereoCamera(); +int APS5_VABI sceVisionManagerGetResultOfCalibrateTrackingLed(); +int APS5_VABI sceVisionManagerGetResultOfFindFace(); +int APS5_VABI sceVisionManagerGetResultOfFindPad(); +int APS5_VABI sceVisionManagerGetResultOfFindPadCorrespondRegion(); +int APS5_VABI sceVisionManagerGetResultOfFindUser(); +int APS5_VABI sceVisionManagerGetResultOfFindUserInRegion(); +int APS5_VABI sceVisionManagerGetResultOfFindUserWithoutIdentify(); +int APS5_VABI sceVisionManagerGetResultOfRegisterUserInRegion(); +int APS5_VABI sceVisionManagerGetStoreCameraImgYPtr(); +int APS5_VABI sceVisionManagerGetWorkingMemorySize(); +int APS5_VABI sceVisionManagerInitialize(); +int APS5_VABI sceVisionManagerLoadSettings(); +int APS5_VABI sceVisionManagerOpen(); +int APS5_VABI sceVisionManagerRegistryClear(); +int APS5_VABI sceVisionManagerRequestCalibrateHmd(); +int APS5_VABI sceVisionManagerRequestCalibrateStereoCamera(); +int APS5_VABI sceVisionManagerRequestCalibrateTrackingLed(); +int APS5_VABI sceVisionManagerRequestClose(); +int APS5_VABI sceVisionManagerRequestFindFace(); +int APS5_VABI sceVisionManagerRequestFindPad(); +int APS5_VABI sceVisionManagerRequestFindPadCorrespondRegion(); +int APS5_VABI sceVisionManagerRequestFindUser(); +int APS5_VABI sceVisionManagerRequestFindUserInRegion(); +int APS5_VABI sceVisionManagerRequestFindUserWithoutIdentify(); +int APS5_VABI sceVisionManagerRequestHeadDetection(); +int APS5_VABI sceVisionManagerRequestInitializeRegisterUserData(); +int APS5_VABI sceVisionManagerRequestOpen(); +int APS5_VABI sceVisionManagerRequestPadTracking(); +int APS5_VABI sceVisionManagerRequestRecogUtility(); +int APS5_VABI sceVisionManagerRequestRegisterUserInRegion(); +int APS5_VABI sceVisionManagerRequestStoreCameraImgY(); +int APS5_VABI sceVisionManagerSetCallbackForUpdateCalibrateHmdResult(); +int APS5_VABI sceVisionManagerSetCallbackForUpdateCalibrateStereoCameraResult(); +int APS5_VABI sceVisionManagerSetCallbackForUpdateCalibrateTrackingLedResult(); +int APS5_VABI sceVisionManagerSetCallbackForUpdateCameraFrame(); +int APS5_VABI sceVisionManagerSetCallbackForUpdateCtrlCore(); +int APS5_VABI sceVisionManagerSetCallbackForUpdateRecog(); +int APS5_VABI sceVisionManagerSetCallbackForUpdateRunningStatus(); +int APS5_VABI sceVisionManagerSetCallbackForUpdateStoreFrame(); +int APS5_VABI sceVisionManagerWaitResponse(); + +} diff --git a/core/libs/prx/libSceVisionManager/libSceVisionManager.hpp b/core/libs/prx/libSceVisionManager/libSceVisionManager.hpp new file mode 100644 index 0000000000..e2529647b8 --- /dev/null +++ b/core/libs/prx/libSceVisionManager/libSceVisionManager.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceVisionManager/include/Api.hpp" diff --git a/core/libs/prx/libSceVnaInternal/libSceVnaInternal.hpp b/core/libs/prx/libSceVnaInternal/libSceVnaInternal.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceVnaInternal/libSceVnaInternal.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceVnaWebsocket/libSceVnaWebsocket.hpp b/core/libs/prx/libSceVnaWebsocket/libSceVnaWebsocket.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceVnaWebsocket/libSceVnaWebsocket.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceVoice/Export.cpp b/core/libs/prx/libSceVoice/Export.cpp index 3357ee67ea..a7dfe71792 100644 --- a/core/libs/prx/libSceVoice/Export.cpp +++ b/core/libs/prx/libSceVoice/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceVoice/include/Api.hpp" #include #include #include diff --git a/core/libs/prx/libSceVoice/include/Api.hpp b/core/libs/prx/libSceVoice/include/Api.hpp new file mode 100644 index 0000000000..cdaf1823b6 --- /dev/null +++ b/core/libs/prx/libSceVoice/include/Api.hpp @@ -0,0 +1,44 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceVoiceInit(const VoiceInitParam* param, std::int32_t version); +int APS5_VABI sceVoiceSetThreadsParams(const VoiceThreadsParams* params); +int APS5_VABI sceVoiceStart(const VoiceStartParam* param); +int APS5_VABI sceVoiceStop(void); +int APS5_VABI sceVoiceEnd_nid_postfix(void); +int APS5_VABI sceVoiceCreatePort(std::uint32_t* portId, const VoicePortParam* param); +int APS5_VABI sceVoiceDeletePort(uint32_t portId); +int APS5_VABI sceVoiceConnectIPortToOPort(uint32_t inputPortId, uint32_t outputPortId); +int APS5_VABI sceVoiceDisconnectIPortFromOPort(uint32_t inputPortId, uint32_t outputPortId); +int APS5_VABI sceVoiceGetBitRate(std::uint32_t portId, std::uint32_t* bitrate); +int APS5_VABI sceVoiceSetVolume(std::uint32_t portId, float volume); +int APS5_VABI sceVoiceGetVolume(std::uint32_t portId, float* volume); +int APS5_VABI sceVoiceGetPortInfo(uint32_t portId, VoicePortInfo* info); +int APS5_VABI sceVoiceGetPortAttr(std::uint32_t portId, std::int32_t attr, void* value, std::int32_t size); +int APS5_VABI sceVoiceReadFromOPort(uint32_t outputPortId, void* data, uint32_t* size); +int APS5_VABI sceVoiceWriteToIPort(uint32_t inputPortId, const void* data, uint32_t* size, int16_t frameGaps); +int APS5_VABI sceVoiceSetMuteFlag(std::uint32_t portId, std::uint8_t muted); +int APS5_VABI sceVoiceGetMuteFlag(std::uint32_t portId, bool* muted); +int APS5_VABI sceVoiceGetResourceInfo(VoiceResourceInfo* info); +int APS5_VABI sceVoiceEnableChat(void); +int APS5_VABI sceVoiceResetPort(std::uint32_t portId); +int APS5_VABI sceVoicePausePort(std::uint32_t portId); +int APS5_VABI sceVoiceResumePort(std::uint32_t portId); +int APS5_VABI sceVoiceDisableChat(void); +int APS5_VABI sceVoiceInitHQ(const VoiceInitParam* param, std::int32_t version); +int APS5_VABI sceVoiceGetMemorySize(void); +int APS5_VABI sceVoiceDeviceInCustomerData(void); +int APS5_VABI sceVoiceQAEnableRecording(void); +int APS5_VABI sceVoiceVADAdjustment(void); +int APS5_VABI sceVoiceVADPVTAdjustment(void); +int APS5_VABI sceVoiceVADSetVersion(std::int32_t version); +int APS5_VABI sceVoiceSetMuteFlagAll(bool muted); +int APS5_VABI sceVoiceSetBitRate(std::uint32_t portId, std::uint32_t bitrate); +int APS5_VABI sceVoiceUpdatePort(std::uint32_t portId, const VoicePortParam* param); +int APS5_VABI sceVoicePausePortAll(void); +int APS5_VABI sceVoiceResumePortAll(void); + +} diff --git a/core/libs/prx/libSceVoice/libSceVoice.hpp b/core/libs/prx/libSceVoice/libSceVoice.hpp new file mode 100644 index 0000000000..5892fc763a --- /dev/null +++ b/core/libs/prx/libSceVoice/libSceVoice.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceVoice/include/Api.hpp" diff --git a/core/libs/prx/libSceVoiceChat/Export.cpp b/core/libs/prx/libSceVoiceChat/Export.cpp index 49e582df5f..b1fde4c767 100644 --- a/core/libs/prx/libSceVoiceChat/Export.cpp +++ b/core/libs/prx/libSceVoiceChat/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceVoiceChat/include/Api.hpp" #include #include #include diff --git a/core/libs/prx/libSceVoiceChat/include/Api.hpp b/core/libs/prx/libSceVoiceChat/include/Api.hpp new file mode 100644 index 0000000000..5d5676dff3 --- /dev/null +++ b/core/libs/prx/libSceVoiceChat/include/Api.hpp @@ -0,0 +1,50 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceVoiceChatInitialize(void* param); +int APS5_VABI sceVoiceChatTerminate(void); +int APS5_VABI sceVoiceChatRegisterHandlers(void* a); +int APS5_VABI sceVoiceChatRegisterMicEventHandler(void* a, void* b); +int APS5_VABI sceVoiceChatProcessEvent(void); +int APS5_VABI sceVoiceChatDeleteRequest(int requestId); +int APS5_VABI sceVoiceChatCreateRequest(void* a, void* b); +int APS5_VABI NAME(int requestId, void* a, void* b); +int APS5_VABI sceVoiceChatAbortRequest(int requestId); +int APS5_VABI sceVoiceChatGetActiveChannel(void* channel); +int APS5_VABI sceVoiceChatGetChannelMemberActiveChannelMatchingState(void* a, void* b); +int APS5_VABI sceVoiceChatGetChannelMemberVoiceConnectionState(void* a, void* b); +int APS5_VABI sceVoiceChatGetChatChannelMemberInfoList(void* a, void* b); +int APS5_VABI sceVoiceChatGetChatGroupMemberInfoList(void* a, void* b); +int APS5_VABI sceVoiceChatGetMicState(void* state); +int APS5_VABI sceVoiceChatGetUserVoiceVolumeGain(void* a, void* gain); +int APS5_VABI sceVoiceChatSetUserVoiceVolumeGain(void* a, int32_t gain); +int APS5_VABI sceVoiceChatRegisterChannelEventHandler(void* a, void* b); +int APS5_VABI sceVoiceChatRegisterDaemonEventHandler(void* a, void* b); +int APS5_VABI sceVoiceChatRegisterMemberEventHandler(void* a, void* b); +int APS5_VABI sceVoiceChatRegisterPartyUserStateChangedHandler(void* a, void* b); +int APS5_VABI sceVoiceChatRegisterVoiceEventHandler(void* a, void* b); +int APS5_VABI sceVoiceChatStartAccessibilityEvent(void* a); +int APS5_VABI sceVoiceChatStartChannelEvent(void* a); +int APS5_VABI sceVoiceChatStartDaemonEvent(void* a); +int APS5_VABI sceVoiceChatStartMemberEvent(void* a); +int APS5_VABI sceVoiceChatStartRangedMemberEvent(void* a); +int APS5_VABI sceVoiceChatStartVoiceEvent(void* a); +int APS5_VABI sceVoiceChatStopAccessibilityEvent(void* a); +int APS5_VABI sceVoiceChatStopChannelEvent(void* a); +int APS5_VABI sceVoiceChatStopDaemonEvent(void* a); +int APS5_VABI sceVoiceChatStopMemberEvent(void* a); +int APS5_VABI sceVoiceChatStopRangedMemberEvent(void* a); +int APS5_VABI sceVoiceChatStopVoiceEvent(void* a); +int APS5_VABI sceVoiceChatUnregisterAccessibilityEventHandler(void* a); +int APS5_VABI sceVoiceChatUnregisterChannelEventHandler(void* a); +int APS5_VABI sceVoiceChatUnregisterDaemonEventHandler(void* a); +int APS5_VABI sceVoiceChatUnregisterMemberEventHandler(void* a); +int APS5_VABI sceVoiceChatUnregisterMicEventHandler(void* a); +int APS5_VABI sceVoiceChatUnregisterPartyUserStateChangedHandler(void* a); +int APS5_VABI sceVoiceChatUnregisterRangedMemberEventHandler(void* a); +int APS5_VABI sceVoiceChatUnregisterVoiceEventHandler(void* a); + +} diff --git a/core/libs/prx/libSceVoiceChat/libSceVoiceChat.hpp b/core/libs/prx/libSceVoiceChat/libSceVoiceChat.hpp new file mode 100644 index 0000000000..81d8245cc3 --- /dev/null +++ b/core/libs/prx/libSceVoiceChat/libSceVoiceChat.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceVoiceChat/include/Api.hpp" diff --git a/core/libs/prx/libSceVoiceCommand/libSceVoiceCommand.hpp b/core/libs/prx/libSceVoiceCommand/libSceVoiceCommand.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceVoiceCommand/libSceVoiceCommand.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceVoiceQoS/Export.cpp b/core/libs/prx/libSceVoiceQoS/Export.cpp index 6c52605b5e..7781cd7ec8 100644 --- a/core/libs/prx/libSceVoiceQoS/Export.cpp +++ b/core/libs/prx/libSceVoiceQoS/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceVoiceQoS/include/Api.hpp" #include #include #include diff --git a/core/libs/prx/libSceVoiceQoS/include/Api.hpp b/core/libs/prx/libSceVoiceQoS/include/Api.hpp new file mode 100644 index 0000000000..a37b2d9239 --- /dev/null +++ b/core/libs/prx/libSceVoiceQoS/include/Api.hpp @@ -0,0 +1,33 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceVoiceQoSInit(void* memBlock, uint32_t memSize, int32_t appType); +int APS5_VABI sceVoiceQoSEnd(); +int APS5_VABI sceVoiceQoSCreateLocalEndpoint(int32_t* localId, int32_t userId, int32_t deviceInId, int32_t deviceOutId); +int APS5_VABI sceVoiceQoSDeleteLocalEndpoint(int32_t localId); +int APS5_VABI sceVoiceQoSCreateRemoteEndpoint(int32_t* remoteId); +int APS5_VABI sceVoiceQoSDeleteRemoteEndpoint(int32_t remoteId); +int APS5_VABI sceVoiceQoSConnect(int32_t* connectionId, int32_t localId, int32_t remoteId); +int APS5_VABI sceVoiceQoSDisconnect(int32_t connectionId); +int APS5_VABI sceVoiceQoSSetConnectionAttribute(std::int32_t connectionId, std::int32_t attributeId, const void* value, std::int32_t size); +int APS5_VABI sceVoiceQoSSetLocalEndpointAttribute(int32_t localId, int32_t attributeId, const void* value, int32_t size); +int APS5_VABI sceVoiceQoSSetRemoteEndpointAttribute(int32_t remoteId, int32_t attributeId, const void* value, int32_t size); +int APS5_VABI sceVoiceQoSReadPacket(int32_t connectionId, void* buffer, uint32_t* size); +int APS5_VABI sceVoiceQoSWritePacket(int32_t connectionId, const void* buffer, uint32_t* size); +int APS5_VABI sceVoiceQoSGetLocalEndpointAttribute(int32_t localId, int32_t attributeId, void* value, int32_t size); +int APS5_VABI sceVoiceQoSGetRemoteEndpointAttribute(int32_t remoteId, int32_t attributeId, void* value, int32_t size); +int APS5_VABI sceVoiceQoSGetConnectionAttribute(int32_t connectionId, int32_t attributeId, void* value, int32_t size); +int APS5_VABI sceVoiceQoSGetLocalEndpoint(int32_t connectionId, int32_t* localId); +int APS5_VABI sceVoiceQoSGetRemoteEndpoint(int32_t connectionId, int32_t* remoteId); +int APS5_VABI sceVoiceQoSEnableChat(); +int APS5_VABI sceVoiceQoSDisableChat(); +int APS5_VABI sceVoiceQoSGetStatus(int32_t connectionId, int32_t statusId, void* value, int32_t size); +int APS5_VABI sceVoiceQoSDebugGetStatus(std::int32_t connectionId, std::int32_t statusId, void* value, std::int32_t size); +int APS5_VABI sceVoiceQoSInitHQ(void* memory, std::uint32_t memorySize, std::int32_t appType); +int APS5_VABI sceVoiceQoSSetMode(); +int APS5_VABI sceVoiceQoSTerminate(); + +} diff --git a/core/libs/prx/libSceVoiceQoS/libSceVoiceQoS.hpp b/core/libs/prx/libSceVoiceQoS/libSceVoiceQoS.hpp new file mode 100644 index 0000000000..e6e7967b46 --- /dev/null +++ b/core/libs/prx/libSceVoiceQoS/libSceVoiceQoS.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceVoiceQoS/include/Api.hpp" diff --git a/core/libs/prx/libSceVorbisDec/Export.cpp b/core/libs/prx/libSceVorbisDec/Export.cpp index b6b60cadf5..44b39a6c58 100644 --- a/core/libs/prx/libSceVorbisDec/Export.cpp +++ b/core/libs/prx/libSceVorbisDec/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceVorbisDec/include/Api.hpp" #include "prx/libSceVorbisDec/include/GuestVorbisFile.hpp" #include "prx/libc/include/General.hpp" diff --git a/core/libs/prx/libSceVorbisDec/include/Api.hpp b/core/libs/prx/libSceVorbisDec/include/Api.hpp new file mode 100644 index 0000000000..7f0e484c62 --- /dev/null +++ b/core/libs/prx/libSceVorbisDec/include/Api.hpp @@ -0,0 +1,53 @@ +#pragma once + +#include "prx/libSceVorbisDec/include/GuestVorbisFile.hpp" +#include "SceTypes.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern "C" { + +int APS5_VABI sceVorbisDecOpenCallbacks(void* datasource, void* vf, const char* initial, std::int64_t ibytes, VorbisDec::GuestCallbacks callbacks); +int APS5_VABI sceVorbisDecClear(void* vf); +std::int64_t APS5_VABI sceVorbisDecBitrate(void* vf, int link); +std::int64_t APS5_VABI sceVorbisDecBitrateInstant(void* vf); +VorbisDec::GuestComment* APS5_VABI sceVorbisDecComment(void* vf, int link); +int APS5_VABI sceVorbisDecCrossLap(void* first, void* second); +int APS5_VABI sceVorbisDecGetDecodePriority(void); +int APS5_VABI sceVorbisDecGetLastDecodeError(void); +int APS5_VABI sceVorbisDecHalfrate(void* vf, int flag); +int APS5_VABI sceVorbisDecHalfrateP(void* vf); +VorbisDec::GuestInfo* APS5_VABI sceVorbisDecInfo(void* vf, int link); +int APS5_VABI sceVorbisDecPcmSeek(void* vf, std::int64_t position); +int APS5_VABI sceVorbisDecPcmSeekLap(void* vf, std::int64_t position); +int APS5_VABI sceVorbisDecPcmSeekPage(void* vf, std::int64_t position); +int APS5_VABI sceVorbisDecPcmSeekPageLap(void* vf, std::int64_t position); +std::int64_t APS5_VABI sceVorbisDecPcmTell(void* vf); +std::int64_t APS5_VABI sceVorbisDecPcmTotal(void* vf, int link); +int APS5_VABI sceVorbisDecRawSeek(void* vf, std::int64_t position); +int APS5_VABI sceVorbisDecRawSeekLap(void* vf, std::int64_t position); +std::int64_t APS5_VABI sceVorbisDecRawTell(void* vf); +std::int64_t APS5_VABI sceVorbisDecRawTotal(void* vf, int link); +std::int64_t APS5_VABI sceVorbisDecRead(void* vf, char* buffer, int length, int bigEndian, int word, int isSigned, int* bitstream); +std::int64_t APS5_VABI sceVorbisDecReadFilter(void* vf, char* buffer, int length, int bigEndian, int word, int isSigned, int* bitstream, VorbisDec::GuestFilter filter, void* filterParam); +std::int64_t APS5_VABI sceVorbisDecReadFloat(void* vf, float*** pcmChannels, int samples, int* bitstream); +std::int64_t APS5_VABI sceVorbisDecSeekable(void* vf); +std::int64_t APS5_VABI sceVorbisDecSerialNumber(void* vf, int link); +int APS5_VABI sceVorbisDecSetDecodePriority(void); +std::int64_t APS5_VABI sceVorbisDecStreams(void* vf); +int APS5_VABI sceVorbisDecTimeSeek(void* vf, double position); +int APS5_VABI sceVorbisDecTimeSeekLap(void* vf, double position); +int APS5_VABI sceVorbisDecTimeSeekPage(void* vf, double position); +int APS5_VABI sceVorbisDecTimeSeekPageLap(void* vf, double position); +double APS5_VABI sceVorbisDecTimeTell(void* vf); +double APS5_VABI sceVorbisDecTimeTotal(void* vf, int link); + +} diff --git a/core/libs/prx/libSceVorbisDec/libSceVorbisDec.hpp b/core/libs/prx/libSceVorbisDec/libSceVorbisDec.hpp new file mode 100644 index 0000000000..4e737bab8b --- /dev/null +++ b/core/libs/prx/libSceVorbisDec/libSceVorbisDec.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceVorbisDec/include/Api.hpp" diff --git a/core/libs/prx/libSceVrServiceDialog/Export.cpp b/core/libs/prx/libSceVrServiceDialog/Export.cpp index a4c1d1f62e..961e74e397 100644 --- a/core/libs/prx/libSceVrServiceDialog/Export.cpp +++ b/core/libs/prx/libSceVrServiceDialog/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceVrServiceDialog/include/Api.hpp" #include #include #include diff --git a/core/libs/prx/libSceVrServiceDialog/include/Api.hpp b/core/libs/prx/libSceVrServiceDialog/include/Api.hpp new file mode 100644 index 0000000000..a68e4b7059 --- /dev/null +++ b/core/libs/prx/libSceVrServiceDialog/include/Api.hpp @@ -0,0 +1,15 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceVrServiceDialogInitialize(void); +int APS5_VABI sceVrServiceDialogOpen(const void* param); +int APS5_VABI sceVrServiceDialogUpdateStatus(void); +int APS5_VABI sceVrServiceDialogGetStatus(void); +int APS5_VABI sceVrServiceDialogGetResult(void* result); +int APS5_VABI sceVrServiceDialogClose(void); +int APS5_VABI sceVrServiceDialogTerminate(void); + +} diff --git a/core/libs/prx/libSceVrServiceDialog/libSceVrServiceDialog.hpp b/core/libs/prx/libSceVrServiceDialog/libSceVrServiceDialog.hpp new file mode 100644 index 0000000000..b0f8e5c411 --- /dev/null +++ b/core/libs/prx/libSceVrServiceDialog/libSceVrServiceDialog.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceVrServiceDialog/include/Api.hpp" diff --git a/core/libs/prx/libSceVrSetupDialog/Export.cpp b/core/libs/prx/libSceVrSetupDialog/Export.cpp index 2aa6aad360..f9196d0109 100644 --- a/core/libs/prx/libSceVrSetupDialog/Export.cpp +++ b/core/libs/prx/libSceVrSetupDialog/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceVrSetupDialog/include/Api.hpp" #include #include #include diff --git a/core/libs/prx/libSceVrSetupDialog/include/Api.hpp b/core/libs/prx/libSceVrSetupDialog/include/Api.hpp new file mode 100644 index 0000000000..0ee132a7e1 --- /dev/null +++ b/core/libs/prx/libSceVrSetupDialog/include/Api.hpp @@ -0,0 +1,16 @@ +#pragma once + +#include "prx/libSceCommonDialog/CommonDialog.hpp" +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceVrSetupDialogInitialize(void); +int APS5_VABI sceVrSetupDialogOpen(const VrSetupDialogParam* param); +int APS5_VABI sceVrSetupDialogUpdateStatus(void); +int APS5_VABI sceVrSetupDialogGetStatus(void); +int APS5_VABI sceVrSetupDialogGetResult(std::int32_t* result); +int APS5_VABI sceVrSetupDialogClose(void); +int APS5_VABI sceVrSetupDialogTerminate(void); + +} diff --git a/core/libs/prx/libSceVrSetupDialog/libSceVrSetupDialog.hpp b/core/libs/prx/libSceVrSetupDialog/libSceVrSetupDialog.hpp new file mode 100644 index 0000000000..85cdf54080 --- /dev/null +++ b/core/libs/prx/libSceVrSetupDialog/libSceVrSetupDialog.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceVrSetupDialog/include/Api.hpp" diff --git a/core/libs/prx/libSceVrTracker/Export.cpp b/core/libs/prx/libSceVrTracker/Export.cpp index cc4a5d1778..7e66fd197e 100644 --- a/core/libs/prx/libSceVrTracker/Export.cpp +++ b/core/libs/prx/libSceVrTracker/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceVrTracker/include/Api.hpp" #include #include #include @@ -5,66 +6,12 @@ #include "SceTypes.hpp" #include "prx/libc/include/General.hpp" -struct VrTrackerMemoryBlock { - void* address; - std::uint32_t size; - std::uint32_t alignment; -}; - -struct VrTrackerInitConfig { - std::uint32_t type; - std::uint32_t option; - std::uint32_t mode; - std::uint32_t parameter; - std::uint32_t reserved[4]; -}; - -struct VrTrackerInitParam { - std::uint32_t size; - std::int32_t mode; - std::uint32_t reserved[6]; - VrTrackerInitConfig config; - VrTrackerMemoryBlock memory[3]; - std::uint32_t option112; - std::uint32_t option116; - std::uint32_t reservedTail[6]; -}; - static_assert(sizeof(VrTrackerMemoryBlock) == 16); static_assert(sizeof(VrTrackerInitConfig) == 32); static_assert(sizeof(VrTrackerInitParam) == 144); static_assert(offsetof(VrTrackerInitParam, config) == 32); static_assert(offsetof(VrTrackerInitParam, memory) == 64); static_assert(offsetof(VrTrackerInitParam, option112) == 112); -struct VrTrackerGpuSubmitParam; -struct VrTrackerResult; - -struct VrTrackerCpuProcessParam { - std::uint32_t size; - std::uint32_t mode; - std::uint32_t argument; - std::uint32_t reserved[5]; -}; - -struct VrTrackerGpuWaitParam { - std::uint32_t size; - std::byte payload[28]; -}; - -struct VrTrackerGetResultParam { - std::uint32_t size; - std::int32_t handle; - std::uint32_t mode; - std::uint32_t extendedResult; - std::uint64_t time; - std::uint32_t statusMode; - std::uint32_t reserved0; - std::uint32_t option32; - std::byte outputValue[4]; - std::uint32_t option40; - std::uint32_t reserved1[2]; - std::byte unused[4]; -}; static_assert(sizeof(VrTrackerCpuProcessParam) == 32); static_assert(offsetof(VrTrackerCpuProcessParam, mode) == 4); @@ -78,6 +25,8 @@ static_assert(offsetof(VrTrackerGetResultParam, reserved1) == 44); namespace { +using namespace VrTrackerLegacy; + constexpr int NotInit = static_cast(0x81260801u); constexpr int AlreadyInitialized = static_cast(0x81260802u); constexpr int DeviceNotRegistered = static_cast(0x81260803u); @@ -92,33 +41,8 @@ constexpr std::uint32_t WorkSize = 0x1000000; constexpr std::uint32_t CalibrationManual = 0; constexpr std::uint32_t CalibrationAuto = 1; -struct CalibrationSettings { - std::uint32_t hmd_position; - std::uint32_t pad_position; - std::uint32_t move_position; - std::uint32_t gun_position; - std::uint32_t reserved[4]; -}; - -struct QueryMemoryParam { - std::uint32_t size; - std::uint32_t profile; - std::uint32_t reserved[6]; - CalibrationSettings calibration_settings; -}; static_assert(sizeof(QueryMemoryParam) == 0x40); -struct QueryMemoryResult { - std::uint32_t size; - std::uint32_t direct_memory_onion_size; - std::uint32_t direct_memory_onion_alignment; - std::uint32_t direct_memory_garlic_size; - std::uint32_t direct_memory_garlic_alignment; - std::uint32_t work_memory_size; - std::uint32_t work_memory_alignment; - std::uint32_t reserved[9]; -}; - bool ValidCalibration(const CalibrationSettings& settings) { return settings.pad_position <= CalibrationAuto && settings.hmd_position <= CalibrationManual && settings.move_position <= CalibrationAuto && settings.gun_position <= CalibrationAuto; @@ -131,29 +55,6 @@ std::uint32_t OnionSize(const CalibrationSettings& settings) { constexpr std::int32_t ComputePipes = 7; constexpr std::int32_t QueuesPerPipe = 8; -struct InitParam { - std::uint32_t size; - std::uint32_t profile; - std::uint32_t execution_mode; - std::int32_t hmd_thread_priority; - std::int32_t pad_thread_priority; - std::int32_t move_thread_priority; - std::int32_t gun_thread_priority; - std::int32_t reserved; - std::uint64_t cpu_mask; - CalibrationSettings calibration_settings; - void* direct_memory_onion; - std::uint32_t direct_memory_onion_size; - std::uint32_t direct_memory_onion_alignment; - void* direct_memory_garlic; - std::uint32_t direct_memory_garlic_size; - std::uint32_t direct_memory_garlic_alignment; - void* work_memory; - std::uint32_t work_memory_size; - std::uint32_t work_memory_alignment; - std::int32_t gpu_pipe_id; - std::int32_t gpu_queue_id; -}; static_assert(sizeof(InitParam) == 0x80); std::atomic g_initialized{false}; @@ -164,19 +65,10 @@ constexpr std::uint32_t DeviceGun = 3; std::mutex g_devicesMutex; std::int32_t g_deviceHandles[DeviceGun + 1] = {-1, -1, -1, -1}; -struct RecalibrateParam { - std::uint32_t size; - std::uint32_t device_type; - std::uint32_t calibration_type; - std::uint32_t reserved[5]; -}; - } // namespace extern "C" { -int APS5_VABI sceVrTrackerRegisterDeviceInternal(int device_type, int handle, int unk0, int); - int APS5_VABI sceVrTrackerCpuProcess(const VrTrackerCpuProcessParam* param) { NotImplemented_nid_no_patch(__func__); return 0; diff --git a/core/libs/prx/libSceVrTracker/include/Api.hpp b/core/libs/prx/libSceVrTracker/include/Api.hpp new file mode 100644 index 0000000000..0481e61d60 --- /dev/null +++ b/core/libs/prx/libSceVrTracker/include/Api.hpp @@ -0,0 +1,159 @@ +#pragma once + +#include "SceTypes.hpp" +#include +#include +#include +#include + +struct VrTrackerMemoryBlock { + void* address; + std::uint32_t size; + std::uint32_t alignment; +}; + +struct VrTrackerInitConfig { + std::uint32_t type; + std::uint32_t option; + std::uint32_t mode; + std::uint32_t parameter; + std::uint32_t reserved[4]; +}; + +struct VrTrackerInitParam { + std::uint32_t size; + std::int32_t mode; + std::uint32_t reserved[6]; + VrTrackerInitConfig config; + VrTrackerMemoryBlock memory[3]; + std::uint32_t option112; + std::uint32_t option116; + std::uint32_t reservedTail[6]; +}; + +struct VrTrackerGpuSubmitParam; + +struct VrTrackerResult; + +struct VrTrackerCpuProcessParam { + std::uint32_t size; + std::uint32_t mode; + std::uint32_t argument; + std::uint32_t reserved[5]; +}; + +struct VrTrackerGpuWaitParam { + std::uint32_t size; + std::byte payload[28]; +}; + +struct VrTrackerGetResultParam { + std::uint32_t size; + std::int32_t handle; + std::uint32_t mode; + std::uint32_t extendedResult; + std::uint64_t time; + std::uint32_t statusMode; + std::uint32_t reserved0; + std::uint32_t option32; + std::byte outputValue[4]; + std::uint32_t option40; + std::uint32_t reserved1[2]; + std::byte unused[4]; +}; + +namespace VrTrackerLegacy { + +struct CalibrationSettings { + std::uint32_t hmd_position; + std::uint32_t pad_position; + std::uint32_t move_position; + std::uint32_t gun_position; + std::uint32_t reserved[4]; +}; + +struct QueryMemoryParam { + std::uint32_t size; + std::uint32_t profile; + std::uint32_t reserved[6]; + CalibrationSettings calibration_settings; +}; + +struct QueryMemoryResult { + std::uint32_t size; + std::uint32_t direct_memory_onion_size; + std::uint32_t direct_memory_onion_alignment; + std::uint32_t direct_memory_garlic_size; + std::uint32_t direct_memory_garlic_alignment; + std::uint32_t work_memory_size; + std::uint32_t work_memory_alignment; + std::uint32_t reserved[9]; +}; + +struct InitParam { + std::uint32_t size; + std::uint32_t profile; + std::uint32_t execution_mode; + std::int32_t hmd_thread_priority; + std::int32_t pad_thread_priority; + std::int32_t move_thread_priority; + std::int32_t gun_thread_priority; + std::int32_t reserved; + std::uint64_t cpu_mask; + CalibrationSettings calibration_settings; + void* direct_memory_onion; + std::uint32_t direct_memory_onion_size; + std::uint32_t direct_memory_onion_alignment; + void* direct_memory_garlic; + std::uint32_t direct_memory_garlic_size; + std::uint32_t direct_memory_garlic_alignment; + void* work_memory; + std::uint32_t work_memory_size; + std::uint32_t work_memory_alignment; + std::int32_t gpu_pipe_id; + std::int32_t gpu_queue_id; +}; + +struct RecalibrateParam { + std::uint32_t size; + std::uint32_t device_type; + std::uint32_t calibration_type; + std::uint32_t reserved[5]; +}; + +} + +extern "C" { + +int APS5_VABI sceVrTrackerCpuProcess(const VrTrackerCpuProcessParam* param); +int APS5_VABI sceVrTrackerGetResult(const VrTrackerGetResultParam* param, VrTrackerResult* result); +int APS5_VABI sceVrTrackerGetTime(std::uint64_t* time); +int APS5_VABI sceVrTrackerGpuSubmit(const VrTrackerGpuSubmitParam* param); +int APS5_VABI sceVrTrackerGpuWait(const VrTrackerGpuWaitParam* param); +int APS5_VABI sceVrTrackerInit(const VrTrackerInitParam* param); +int APS5_VABI sceVrTrackerCpuPopMarker(); +int APS5_VABI sceVrTrackerCpuPushMarker(); +int APS5_VABI sceVrTrackerGetLiveCaptureId(); +int APS5_VABI sceVrTrackerGetPlayAreaWarningInfo(void* info); +int APS5_VABI sceVrTrackerGpuWaitAndCpuProcess(); +int APS5_VABI sceVrTrackerNotifyEndOfCpuProcess(const void* param); +int APS5_VABI sceVrTrackerQueryMemory(const void* param, void* result); +int APS5_VABI sceVrTrackerRecalibrate(const void* param); +int APS5_VABI sceVrTrackerRegisterDevice(int deviceType, int handle); +int APS5_VABI sceVrTrackerRegisterDevice2(int deviceType, int handle); +int APS5_VABI sceVrTrackerRegisterDeviceInternal(int deviceType, int handle, int unk0, int); +int APS5_VABI sceVrTrackerResetAll(); +int APS5_VABI sceVrTrackerResetOrientationRelative(int deviceType, int handle); +int APS5_VABI sceVrTrackerSaveInternalBuffers(); +int APS5_VABI sceVrTrackerSetDeviceRejection(); +int APS5_VABI sceVrTrackerSetDurationUntilStatusNotTracking(int deviceType, std::uint32_t); +int APS5_VABI sceVrTrackerSetExtendedMode(); +int APS5_VABI sceVrTrackerSetLEDBrightness(); +int APS5_VABI sceVrTrackerSetRestingMode(); +int APS5_VABI sceVrTrackerStartLiveCapture(); +int APS5_VABI sceVrTrackerStopLiveCapture(); +int APS5_VABI sceVrTrackerTerm(); +int APS5_VABI sceVrTrackerUnregisterDevice(int handle); +int APS5_VABI sceVrTrackerUpdateMotionSensorData(const void* param); + +} diff --git a/core/libs/prx/libSceVrTracker/libSceVrTracker.hpp b/core/libs/prx/libSceVrTracker/libSceVrTracker.hpp new file mode 100644 index 0000000000..81621f7084 --- /dev/null +++ b/core/libs/prx/libSceVrTracker/libSceVrTracker.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceVrTracker/include/Api.hpp" diff --git a/core/libs/prx/libSceVrTracker2/CMakeLists.txt b/core/libs/prx/libSceVrTracker2/CMakeLists.txt index aaf8e867d1..cccd8e8455 100644 --- a/core/libs/prx/libSceVrTracker2/CMakeLists.txt +++ b/core/libs/prx/libSceVrTracker2/CMakeLists.txt @@ -1,12 +1,12 @@ add_library(libSceVrTracker2 SHARED EXCLUDE_FROM_ALL Export.cpp) target_include_directories(libSceVrTracker2 PRIVATE ${LIBS_INCLUDE_DIR}) -target_link_libraries(libSceVrTracker2 PRIVATE libc) +target_link_libraries(libSceVrTracker2 PRIVATE libSceHmd2 libc) configure_windows_unwind(libSceVrTracker2) if(BUILD_TESTING) add_test_executable(guest_vr_tracker2_tests ${LIBS_INCLUDE_DIR}/tests/GuestVrTracker2.cpp) target_include_directories(guest_vr_tracker2_tests PRIVATE ${LIBS_INCLUDE_DIR}) - target_link_libraries(guest_vr_tracker2_tests PRIVATE libSceVrTracker2 libc) + target_link_libraries(guest_vr_tracker2_tests PRIVATE libSceVrTracker2 libkernel libc) configure_windows_unwind(guest_vr_tracker2_tests) add_test(NAME guest_vr_tracker2 COMMAND guest_vr_tracker2_tests) if(WIN32) diff --git a/core/libs/prx/libSceVrTracker2/Export.cpp b/core/libs/prx/libSceVrTracker2/Export.cpp index 2e521f452e..f9246da310 100644 --- a/core/libs/prx/libSceVrTracker2/Export.cpp +++ b/core/libs/prx/libSceVrTracker2/Export.cpp @@ -1,3 +1,6 @@ +#include "prx/libSceVrTracker2/include/Api.hpp" +#include "prx/libSceHmd2/libSceHmd2.hpp" +#include #include #include #include @@ -6,34 +9,6 @@ #include "prx/libc/include/General.hpp" #include "prx/libc/include/ApplicationHeap.hpp" -struct VrTracker2InitializeParameter { - std::uint32_t size; - std::uint32_t mode; - std::int32_t threadPriorities[2]; - std::uint64_t threadAffinityMasks[2]; - void* workMemory; - std::uint32_t workMemorySize; - std::uint32_t workMemoryAlignment; - std::uint32_t option; - std::uint32_t coordinateSystem; - std::uint8_t disableOption; - std::int8_t optionMode; - std::uint8_t reserved[14]; -}; - -struct VrTracker2MemoryParameter { - std::uint32_t size; - std::uint32_t mode; - std::uint8_t reserved[24]; -}; - -struct VrTracker2MemoryRequirement { - std::uint32_t size; - std::uint32_t memorySize; - std::uint32_t memoryAlignment; - std::uint8_t reserved[20]; -}; - static_assert(sizeof(VrTracker2InitializeParameter) == 72); static_assert(offsetof(VrTracker2InitializeParameter, threadAffinityMasks) == 16); static_assert(offsetof(VrTracker2InitializeParameter, workMemory) == 32); @@ -41,55 +16,14 @@ static_assert(offsetof(VrTracker2InitializeParameter, coordinateSystem) == 52); static_assert(offsetof(VrTracker2InitializeParameter, reserved) == 58); static_assert(sizeof(VrTracker2MemoryParameter) == 32); static_assert(sizeof(VrTracker2MemoryRequirement) == 32); -struct VrTracker2LegacyParameter12 { - std::uint32_t size; - std::uint8_t opaque[8]; -}; - -struct VrTracker2LegacyParameter20 { - std::uint32_t size; - std::uint8_t opaque[16]; -}; - -struct VrTracker2UnsupportedCoordinateParameter; static_assert(sizeof(VrTracker2LegacyParameter12) == 12); static_assert(sizeof(VrTracker2LegacyParameter20) == 20); -struct VrTracker2CalibrationResult; -struct VrTracker2TelemetryData; -struct VrTracker2PoseParameter; -struct VrTracker2PoseResult; - -struct VrTracker2MeshRequirement { - std::uint32_t vertexCount; - std::uint32_t indexCount; - std::uint32_t vertexDataSize; - std::uint32_t indexDataSize; -}; - -struct VrTracker2Pose { - float position[3]; - std::uint8_t padding[4]; - float orientation[4]; -}; - static_assert(sizeof(VrTracker2MeshRequirement) == 16); static_assert(sizeof(VrTracker2Pose) == 32); static_assert(offsetof(VrTracker2Pose, orientation) == 16); -struct VrTracker2ResultParameter { - std::uint32_t size; - std::int32_t deviceHandle; - std::uint32_t reserved; - std::uint8_t padding[4]; - std::uint64_t timestamp; - std::uint32_t reserved2; - std::uint8_t padding2[4]; - std::uint64_t userTag; - std::uint32_t reserved3[2]; -}; - struct VrTracker2LegacyResultParameter { std::uint32_t size; std::int32_t deviceHandle; @@ -105,20 +39,6 @@ static_assert(offsetof(VrTracker2ResultParameter, timestamp) == 16); static_assert(offsetof(VrTracker2ResultParameter, userTag) == 32); static_assert(sizeof(VrTracker2LegacyResultParameter) == 32); static_assert(offsetof(VrTracker2LegacyResultParameter, userTag) == 24); -struct VrTracker2Result; -struct VrTracker2CoordinateLocation; - -struct VrTracker2BoundaryGeometry { - std::uint32_t size; - std::uint32_t pointCount; - float points[256][3]; -}; - -struct VrTracker2OrientedBoundingBox { - std::uint32_t size; - float transform[16]; - float extents[3]; -}; static_assert(sizeof(VrTracker2BoundaryGeometry) == 3080); static_assert(offsetof(VrTracker2BoundaryGeometry, points) == 8); @@ -130,8 +50,96 @@ namespace { constexpr std::int32_t SCE_OK = 0; constexpr std::int32_t VR_TRACKER2_ERROR_NOT_INITIALIZED = static_cast(0x8A740001u); +constexpr std::int32_t VR_TRACKER2_ERROR_ALREADY_INITIALIZED = static_cast(0x8A740002u); constexpr std::int32_t VR_TRACKER2_ERROR_INVALID_ARGUMENT = static_cast(0x8A740006u); +constexpr std::uint32_t TrackerMode = 0; +constexpr std::uint32_t SystemTrackingMode = 1000; +constexpr std::uint32_t SystemClientMode = 1001; +constexpr std::uint32_t MinimumWorkMemoryAlignment = 0x10000; +constexpr std::int32_t MinimumThreadPriority = 256; +constexpr std::int32_t MaximumThreadPriority = 767; +constexpr std::uint64_t TrackerAffinityLimit = 0x2000; +constexpr std::uint64_t SystemAffinityMask = 0xEA00; +constexpr std::uint32_t OptionModeSdkVersion = 0x7000000; + +std::atomic state{0}; + +std::uint32_t WorkMemorySize(std::uint32_t mode) { + if (mode == SystemTrackingMode) return 7u << 20; + if (mode == SystemClientMode) return 3u << 20; + return 32u << 20; +} + +std::uint32_t CompiledSdkVersion() { + const auto* process = static_cast(ApplicationProcessParameters_nid_no_patch()); + std::uint32_t sdkVersion; + std::memcpy(&sdkVersion, process + 0x10, sizeof(sdkVersion)); + return sdkVersion; +} + +std::int32_t ValidateMode(std::uint32_t mode) { + if (mode == SystemTrackingMode || mode == SystemClientMode) NotImplemented_nid_no_patch("sceVrTracker2Initialize: application category of a system mode"); + return mode == TrackerMode ? SCE_OK : VR_TRACKER2_ERROR_INVALID_ARGUMENT; +} + +bool PriorityAllowed(std::int32_t priority) { + return priority >= MinimumThreadPriority && priority <= MaximumThreadPriority; +} + +bool AffinityAllowed(std::uint32_t mode, std::uint64_t mask) { + if (mode == TrackerMode) return mask < TrackerAffinityLimit; + return (mask & ~SystemAffinityMask) == 0; +} + +bool OptionModeAllowed(std::int8_t optionMode) { + if (optionMode == -1 || optionMode == 0) return true; + return optionMode == 1 && CompiledSdkVersion() >= OptionModeSdkVersion; +} + +class InitializeSession { +public: + std::int32_t OpenTracking() { + return track(sceHmd2InternalTrackingOpen(), trackingOpened); + } + + std::int32_t StartTracking() { + return track(sceHmd2InternalTrackingStart(), trackingStarted); + } + + std::int32_t OpenLedDetector() { + return track(sceHmd2InternalLedDetectorOpen(), ledDetectorOpened); + } + + std::int32_t StartLedDetector() { + return track(sceHmd2InternalLedDetectorStart(), ledDetectorStarted); + } + + void Rollback() { + if (ledDetectorStarted) sceHmd2InternalLedDetectorStop(); + if (ledDetectorOpened) sceHmd2InternalLedDetectorClose(); + if (trackingStarted) sceHmd2InternalTrackingStop(); + if (trackingOpened) sceHmd2InternalTrackingClose(); + state.store(0); + } + + std::int32_t Abort(std::int32_t result) { + Rollback(); + return result; + } + +private: + static std::int32_t track(std::int32_t result, bool& done) { + done = result == SCE_OK; + return result; + } + + bool trackingOpened = false; + bool trackingStarted = false; + bool ledDetectorOpened = false; + bool ledDetectorStarted = false; +}; + std::int32_t ClearThenReportNotInitialized(void* output, std::size_t size) { if (output == nullptr) return VR_TRACKER2_ERROR_INVALID_ARGUMENT; std::memset(output, 0, size); @@ -140,130 +148,30 @@ std::int32_t ClearThenReportNotInitialized(void* output, std::size_t size) { } -struct VrTracker2RelativePoseResult { - VrTracker2Pose pose; - std::uint8_t reserved[32]; -}; - static_assert(sizeof(VrTracker2RelativePoseResult) == 64); -struct VrTracker2ScalarResult { - std::uint32_t size; - float value; -}; - -struct VrTracker2TrackingOptions { - std::int32_t options[3]; - std::uint8_t reset; - std::uint8_t reserved[3]; - float vector[3]; -}; - -struct VrTracker2TrackingOptionsResult { - VrTracker2TrackingOptions options; - float position[3]; -}; - -struct VrTracker2DiagnosticResult; -struct VrTracker2ExtendedResult; -struct VrTracker2TrackingConfiguration; - static_assert(sizeof(VrTracker2ScalarResult) == 8); static_assert(sizeof(VrTracker2TrackingOptions) == 28); static_assert(offsetof(VrTracker2TrackingOptions, vector) == 16); static_assert(sizeof(VrTracker2TrackingOptionsResult) == 40); static_assert(offsetof(VrTracker2TrackingOptionsResult, position) == 28); -struct VrTracker2ModeParameter { - std::uint32_t size; - std::uint32_t mode; - float value; -}; - -struct VrTracker2DiagnosticText { - char sections[6][512]; -}; - -struct VrTracker2CompositePoseResult; -struct VrTracker2CameraImages; -struct VrTracker2SensorFrame; -struct VrTracker2TrackingStatus; -struct VrTracker2BoundaryParameter; - static_assert(sizeof(VrTracker2ModeParameter) == 12); static_assert(sizeof(VrTracker2DiagnosticText) == 3072); -struct VrTracker2CameraFrame { - std::uint32_t selector; - std::uint32_t identifiers[2]; - std::uint32_t width; - std::uint32_t height; - std::uint32_t pitch; - const void* pixels; - std::int32_t bufferIndex; -}; - -struct VrTracker2CameraFrameMetadata; - static_assert(offsetof(VrTracker2CameraFrame, pixels) == 24); static_assert(offsetof(VrTracker2CameraFrame, bufferIndex) == 32); static_assert(sizeof(VrTracker2CameraFrame) == 40); -struct VrTracker2SpatialQueryResult { - std::uint32_t size; - std::int32_t status; - float vectors[2][3]; - float value; -}; - -struct VrTracker2DeviceCalibrationStatus; -struct VrTracker2DeviceBoundaryParameter; -struct VrTracker2ResetPoseParameter; - static_assert(sizeof(VrTracker2SpatialQueryResult) == 36); static_assert(offsetof(VrTracker2SpatialQueryResult, vectors) == 8); static_assert(offsetof(VrTracker2SpatialQueryResult, value) == 32); -struct VrTracker2MapData; -struct VrTracker2MapStatus; - -struct VrTracker2RuntimeStatus; -struct VrTracker2DiagnosticState; -struct VrTracker2ExtendedDiagnosticState; -struct VrTracker2SensorDiagnostics; -struct VrTracker2DeviceDiagnostics; -struct VrTracker2TimingDiagnostics; -struct VrTracker2MapConfiguration; -struct VrTracker2SensorSummary; - -struct VrTracker2CoordinateResultParameter { - std::uint32_t coordinateSystem; - std::uint32_t reserved; - VrTracker2ResultParameter parameter; -}; - -struct VrTracker2BoundaryFitResult { - std::uint8_t flags[4]; - float dimensions[4]; -}; - -struct VrTracker2VectorResult { - std::uint32_t size; - float value[3]; -}; - -struct VrTracker2ExtendedTrackingResult; - static_assert(sizeof(VrTracker2CoordinateResultParameter) == 56); static_assert(offsetof(VrTracker2CoordinateResultParameter, parameter) == 8); static_assert(sizeof(VrTracker2BoundaryFitResult) == 20); static_assert(sizeof(VrTracker2VectorResult) == 16); -struct VrTracker2MeshVertex; -struct VrTracker2TimedPoseResult; -struct VrTracker2ImagePoseResult; -struct VrTracker2ImageFrame; - extern "C" { std::int32_t APS5_VABI sceVrTracker2Finalize() { @@ -309,16 +217,12 @@ std::int32_t APS5_VABI sceVrTracker2UnregisterDevice(std::int32_t deviceHandle) std::int32_t APS5_VABI sceVrTracker2QueryMemory(const VrTracker2MemoryParameter* parameter, VrTracker2MemoryRequirement* requirement) { if (parameter == nullptr || requirement == nullptr) return VR_TRACKER2_ERROR_INVALID_ARGUMENT; if (parameter->size != sizeof(VrTracker2MemoryParameter)) return VR_TRACKER2_ERROR_INVALID_ARGUMENT; - std::uint32_t memorySize = 32u << 20; - if (parameter->mode == 1000 || parameter->mode == 1001) { - const auto* process = static_cast(ApplicationProcessParameters_nid_no_patch()); - std::uint32_t sdkVersion; - std::memcpy(&sdkVersion, process + 0x10, sizeof(sdkVersion)); - if (sdkVersion < 0x1000000) return VR_TRACKER2_ERROR_INVALID_ARGUMENT; - memorySize = parameter->mode == 1000 ? 7u << 20 : 3u << 20; - } else if (parameter->mode != 0) { + if (parameter->mode == SystemTrackingMode || parameter->mode == SystemClientMode) { + if (CompiledSdkVersion() < 0x1000000) return VR_TRACKER2_ERROR_INVALID_ARGUMENT; + } else if (parameter->mode != TrackerMode) { return VR_TRACKER2_ERROR_INVALID_ARGUMENT; } + const std::uint32_t memorySize = WorkMemorySize(parameter->mode); for (const auto value : parameter->reserved) if (value != 0) return VR_TRACKER2_ERROR_INVALID_ARGUMENT; *requirement = {sizeof(VrTracker2MemoryRequirement), memorySize, 64u << 10, {}}; @@ -326,6 +230,30 @@ std::int32_t APS5_VABI sceVrTracker2QueryMemory(const VrTracker2MemoryParameter* } std::int32_t APS5_VABI sceVrTracker2Initialize(const VrTracker2InitializeParameter* parameter) { + if (parameter == nullptr || parameter->size != sizeof(VrTracker2InitializeParameter)) return VR_TRACKER2_ERROR_INVALID_ARGUMENT; + const std::uint32_t mode = parameter->mode; + if (const std::int32_t result = ValidateMode(mode); result != SCE_OK) return result; + if (parameter->workMemory == nullptr) return VR_TRACKER2_ERROR_INVALID_ARGUMENT; + if (parameter->workMemorySize < WorkMemorySize(mode)) return VR_TRACKER2_ERROR_INVALID_ARGUMENT; + if (parameter->workMemoryAlignment < MinimumWorkMemoryAlignment) return VR_TRACKER2_ERROR_INVALID_ARGUMENT; + for (const auto value : parameter->reserved) + if (value != 0) return VR_TRACKER2_ERROR_INVALID_ARGUMENT; + for (const auto priority : parameter->threadPriorities) + if (!PriorityAllowed(priority)) return VR_TRACKER2_ERROR_INVALID_ARGUMENT; + for (const auto mask : parameter->threadAffinityMasks) + if (!AffinityAllowed(mode, mask)) return VR_TRACKER2_ERROR_INVALID_ARGUMENT; + std::uint32_t expected = 0; + if (!state.compare_exchange_strong(expected, 1)) return VR_TRACKER2_ERROR_ALREADY_INITIALIZED; + InitializeSession session; + if (mode == TrackerMode) std::memset(parameter->workMemory, 0, WorkMemorySize(mode)); + if (mode != SystemClientMode) { + if (!OptionModeAllowed(parameter->optionMode)) return session.Abort(VR_TRACKER2_ERROR_INVALID_ARGUMENT); + if (const std::int32_t result = session.OpenTracking(); result != SCE_OK) return session.Abort(result); + if (const std::int32_t result = session.StartTracking(); result != SCE_OK) return session.Abort(result); + if (const std::int32_t result = session.OpenLedDetector(); result != SCE_OK) return session.Abort(result); + if (const std::int32_t result = session.StartLedDetector(); result != SCE_OK) return session.Abort(result); + } + session.Rollback(); NotImplemented_nid_no_patch(__func__); return 0; } diff --git a/core/libs/prx/libSceVrTracker2/include/Api.hpp b/core/libs/prx/libSceVrTracker2/include/Api.hpp new file mode 100644 index 0000000000..871f89b821 --- /dev/null +++ b/core/libs/prx/libSceVrTracker2/include/Api.hpp @@ -0,0 +1,310 @@ +#pragma once + +#include "SceTypes.hpp" +#include +#include +#include +#include +#include + +struct VrTracker2InitializeParameter { + std::uint32_t size; + std::uint32_t mode; + std::int32_t threadPriorities[2]; + std::uint64_t threadAffinityMasks[2]; + void* workMemory; + std::uint32_t workMemorySize; + std::uint32_t workMemoryAlignment; + std::uint32_t option; + std::uint32_t coordinateSystem; + std::uint8_t disableOption; + std::int8_t optionMode; + std::uint8_t reserved[14]; +}; + +struct VrTracker2MemoryParameter { + std::uint32_t size; + std::uint32_t mode; + std::uint8_t reserved[24]; +}; + +struct VrTracker2MemoryRequirement { + std::uint32_t size; + std::uint32_t memorySize; + std::uint32_t memoryAlignment; + std::uint8_t reserved[20]; +}; + +struct VrTracker2LegacyParameter12 { + std::uint32_t size; + std::uint8_t opaque[8]; +}; + +struct VrTracker2LegacyParameter20 { + std::uint32_t size; + std::uint8_t opaque[16]; +}; + +struct VrTracker2UnsupportedCoordinateParameter; + +struct VrTracker2CalibrationResult; + +struct VrTracker2TelemetryData; + +struct VrTracker2PoseParameter; + +struct VrTracker2PoseResult; + +struct VrTracker2MeshRequirement { + std::uint32_t vertexCount; + std::uint32_t indexCount; + std::uint32_t vertexDataSize; + std::uint32_t indexDataSize; +}; + +struct VrTracker2Pose { + float position[3]; + std::uint8_t padding[4]; + float orientation[4]; +}; + +struct VrTracker2ResultParameter { + std::uint32_t size; + std::int32_t deviceHandle; + std::uint32_t reserved; + std::uint8_t padding[4]; + std::uint64_t timestamp; + std::uint32_t reserved2; + std::uint8_t padding2[4]; + std::uint64_t userTag; + std::uint32_t reserved3[2]; +}; + +struct VrTracker2Result; + +struct VrTracker2CoordinateLocation; + +struct VrTracker2BoundaryGeometry { + std::uint32_t size; + std::uint32_t pointCount; + float points[256][3]; +}; + +struct VrTracker2OrientedBoundingBox { + std::uint32_t size; + float transform[16]; + float extents[3]; +}; + +struct VrTracker2RelativePoseResult { + VrTracker2Pose pose; + std::uint8_t reserved[32]; +}; + +struct VrTracker2ScalarResult { + std::uint32_t size; + float value; +}; + +struct VrTracker2TrackingOptions { + std::int32_t options[3]; + std::uint8_t reset; + std::uint8_t reserved[3]; + float vector[3]; +}; + +struct VrTracker2TrackingOptionsResult { + VrTracker2TrackingOptions options; + float position[3]; +}; + +struct VrTracker2DiagnosticResult; + +struct VrTracker2ExtendedResult; + +struct VrTracker2TrackingConfiguration; + +struct VrTracker2ModeParameter { + std::uint32_t size; + std::uint32_t mode; + float value; +}; + +struct VrTracker2DiagnosticText { + char sections[6][512]; +}; + +struct VrTracker2CompositePoseResult; + +struct VrTracker2CameraImages; + +struct VrTracker2SensorFrame; + +struct VrTracker2TrackingStatus; + +struct VrTracker2BoundaryParameter; + +struct VrTracker2CameraFrame { + std::uint32_t selector; + std::uint32_t identifiers[2]; + std::uint32_t width; + std::uint32_t height; + std::uint32_t pitch; + const void* pixels; + std::int32_t bufferIndex; +}; + +struct VrTracker2CameraFrameMetadata; + +struct VrTracker2SpatialQueryResult { + std::uint32_t size; + std::int32_t status; + float vectors[2][3]; + float value; +}; + +struct VrTracker2DeviceCalibrationStatus; + +struct VrTracker2DeviceBoundaryParameter; + +struct VrTracker2ResetPoseParameter; + +struct VrTracker2MapData; + +struct VrTracker2MapStatus; + +struct VrTracker2RuntimeStatus; + +struct VrTracker2DiagnosticState; + +struct VrTracker2ExtendedDiagnosticState; + +struct VrTracker2SensorDiagnostics; + +struct VrTracker2DeviceDiagnostics; + +struct VrTracker2TimingDiagnostics; + +struct VrTracker2MapConfiguration; + +struct VrTracker2SensorSummary; + +struct VrTracker2CoordinateResultParameter { + std::uint32_t coordinateSystem; + std::uint32_t reserved; + VrTracker2ResultParameter parameter; +}; + +struct VrTracker2BoundaryFitResult { + std::uint8_t flags[4]; + float dimensions[4]; +}; + +struct VrTracker2VectorResult { + std::uint32_t size; + float value[3]; +}; + +struct VrTracker2ExtendedTrackingResult; + +struct VrTracker2MeshVertex; + +struct VrTracker2TimedPoseResult; + +struct VrTracker2ImagePoseResult; + +struct VrTracker2ImageFrame; + +extern "C" { + +std::int32_t APS5_VABI sceVrTracker2Finalize(); +std::int32_t APS5_VABI sceVrTracker2GetCoordinateSystem(std::uint32_t* coordinateSystem); +std::int32_t APS5_VABI sceVrTracker2GetPlayAreaBoundaryGeometry(VrTracker2BoundaryGeometry* geometry); +std::int32_t APS5_VABI sceVrTracker2GetPlayAreaOrientedBoundingBox(VrTracker2OrientedBoundingBox* box); +std::int32_t APS5_VABI sceVrTracker2GetResult(const VrTracker2ResultParameter* parameter, VrTracker2Result* result); +std::int32_t APS5_VABI sceVrTracker2LocateCoordinateSystem(std::uint32_t coordinateSystem, VrTracker2CoordinateLocation* location); +std::int32_t APS5_VABI sceVrTracker2RegisterDevice(std::uint32_t deviceType, std::int32_t deviceHandle); +std::int32_t APS5_VABI sceVrTracker2ResetLocalCoordinate(std::int32_t deviceHandle); +std::int32_t APS5_VABI sceVrTracker2SetCoordinateSystem(std::uint32_t coordinateSystem); +std::int32_t APS5_VABI sceVrTracker2UnregisterDevice(std::int32_t deviceHandle); +std::int32_t APS5_VABI sceVrTracker2QueryMemory(const VrTracker2MemoryParameter* parameter, VrTracker2MemoryRequirement* requirement); +std::int32_t APS5_VABI sceVrTracker2Initialize(const VrTracker2InitializeParameter* parameter); +std::int32_t APS5_VABI VrTracker2GetRelativePose(std::uint32_t firstCoordinateSystem, std::uint32_t secondCoordinateSystem, VrTracker2RelativePoseResult* result); +std::int32_t APS5_VABI VrTracker2GetDiagnosticResult(VrTracker2DiagnosticResult* result); +std::int32_t APS5_VABI VrTracker2SetTrackingOptions(const VrTracker2TrackingOptions* options); +std::int32_t APS5_VABI VrTracker2GetTrackingOptions(VrTracker2TrackingOptionsResult* result); +std::int32_t APS5_VABI VrTracker2GetExtendedResult(VrTracker2ExtendedResult* result); +std::int32_t APS5_VABI VrTracker2GetCompositePose(const VrTracker2ResultParameter* parameter, VrTracker2CompositePoseResult* result); +std::int32_t APS5_VABI VrTracker2GetCounter(std::uint64_t* counter, std::uint32_t selector); +std::int32_t APS5_VABI VrTracker2SetTrackingConfiguration(const VrTracker2TrackingConfiguration* configuration); +std::int32_t APS5_VABI VrTracker2GetTrackingConfiguration(VrTracker2TrackingConfiguration* configuration); +std::int32_t APS5_VABI VrTracker2GetCameraImages(VrTracker2CameraImages* images); +std::int32_t APS5_VABI VrTracker2GetCameraImage(void* image, std::uint32_t size, std::uint32_t* frameId); +std::int32_t APS5_VABI VrTracker2GetDiagnosticText(VrTracker2DiagnosticText* text); +std::int32_t APS5_VABI VrTracker2GetSensorFrame(VrTracker2SensorFrame* frame); +std::int32_t APS5_VABI VrTracker2GetTrackingStatus(VrTracker2TrackingStatus* status); +std::int32_t APS5_VABI VrTracker2GetBoundaryParameter(VrTracker2BoundaryParameter* parameter); +std::int32_t APS5_VABI VrTracker2SetBoundaryParameter(const VrTracker2BoundaryParameter* parameter); +std::int32_t APS5_VABI VrTracker2SetMode(const VrTracker2ModeParameter* parameter); +std::int32_t APS5_VABI VrTracker2GetScalarResult(VrTracker2ScalarResult* result); +std::int32_t APS5_VABI VrTracker2LegacyQuery12(const VrTracker2LegacyParameter12* parameter); +std::int32_t APS5_VABI VrTracker2LegacyQuery20(const VrTracker2LegacyParameter20* parameter); +std::int32_t APS5_VABI VrTracker2UnsupportedCoordinateOperation(const VrTracker2UnsupportedCoordinateParameter* parameter); +std::int32_t APS5_VABI VrTracker2AcquireCameraFrame(std::uint32_t selector, VrTracker2CameraFrame* frame); +std::int32_t APS5_VABI VrTracker2AcquireCameraFrameWithMetadata(std::uint32_t selector, VrTracker2CameraFrame* frame, VrTracker2CameraFrameMetadata* metadata); +std::int32_t APS5_VABI VrTracker2ReleaseCameraFrame(const VrTracker2CameraFrame* frame); +std::int32_t APS5_VABI VrTracker2SetScalarOption(float value); +std::int32_t APS5_VABI VrTracker2GetScalarOption(float* value); +std::int32_t APS5_VABI VrTracker2SelectCoordinateSystem(std::uint32_t coordinateSystem); +std::int32_t APS5_VABI VrTracker2GetSelectedCoordinateSystem(std::uint32_t* coordinateSystem); +std::int32_t APS5_VABI VrTracker2ResetDevicePose(std::int32_t deviceHandle); +std::int32_t APS5_VABI VrTracker2ResetPose(const VrTracker2ResetPoseParameter* parameter); +std::int32_t APS5_VABI VrTracker2QueryPosition(const float* position, VrTracker2SpatialQueryResult* result); +std::int32_t APS5_VABI VrTracker2QueryDevicePosition(std::int32_t deviceHandle, VrTracker2SpatialQueryResult* result); +std::int32_t APS5_VABI VrTracker2GetTrackingBounds(VrTracker2OrientedBoundingBox* bounds); +std::int32_t APS5_VABI VrTracker2GetDeviceState(std::int32_t deviceHandle, std::int32_t* state); +std::int32_t APS5_VABI VrTracker2GetDeviceCalibrationStatus(std::int32_t deviceHandle, VrTracker2DeviceCalibrationStatus* status); +std::int32_t APS5_VABI VrTracker2SetDeviceBoundary(std::int32_t deviceHandle, std::int32_t selector, const VrTracker2DeviceBoundaryParameter* parameter); +std::int32_t APS5_VABI VrTracker2GetDeviceBoundary(std::int32_t deviceHandle, std::int32_t selector, VrTracker2DeviceBoundaryParameter* parameter); +std::int32_t APS5_VABI VrTracker2ApplyDeviceBoundary(std::int32_t deviceHandle, std::int32_t selector); +std::int32_t APS5_VABI VrTracker2GetDeviceMapState(std::int32_t deviceHandle, std::int32_t* state); +std::int32_t APS5_VABI VrTracker2InitializeMap(std::int32_t deviceHandle, const float* parameter); +std::int32_t APS5_VABI VrTracker2GetCoordinateTrackingResult(const VrTracker2CoordinateResultParameter* parameter, VrTracker2ExtendedTrackingResult* result); +std::int32_t APS5_VABI VrTracker2GetExtendedTrackingResult(const VrTracker2ResultParameter* parameter, VrTracker2ExtendedTrackingResult* result); +std::int32_t APS5_VABI VrTracker2FitBoundary(const VrTracker2BoundaryGeometry* boundary, VrTracker2BoundaryFitResult* result); +std::int32_t APS5_VABI VrTracker2FitBoundaryWithBounds(const VrTracker2BoundaryGeometry* boundary, VrTracker2OrientedBoundingBox* firstBounds, VrTracker2OrientedBoundingBox* secondBounds, VrTracker2BoundaryFitResult* result); +std::int32_t APS5_VABI VrTracker2GetDeviceCenter(std::int32_t deviceHandle, VrTracker2VectorResult* result); +std::int32_t APS5_VABI VrTracker2GetRuntimeStatus(VrTracker2RuntimeStatus* status); +std::int32_t APS5_VABI VrTracker2GetTrackingFlags(bool* active, std::uint8_t* flags); +std::int32_t APS5_VABI VrTracker2GetDiagnosticState(VrTracker2DiagnosticState* state); +std::int32_t APS5_VABI VrTracker2GetExtendedDiagnosticState(VrTracker2ExtendedDiagnosticState* state); +std::int32_t APS5_VABI VrTracker2GetSensorDiagnostics(VrTracker2SensorDiagnostics* diagnostics); +std::int32_t APS5_VABI VrTracker2GetDeviceDiagnostics(VrTracker2DeviceDiagnostics* diagnostics); +std::int32_t APS5_VABI VrTracker2GetTimingDiagnostics(VrTracker2TimingDiagnostics* diagnostics); +std::int32_t APS5_VABI VrTracker2GetMapConfiguration(VrTracker2MapConfiguration* configuration); +std::int32_t APS5_VABI VrTracker2SetMapConfiguration(const VrTracker2MapConfiguration* configuration); +std::int32_t APS5_VABI VrTracker2GetMapStatus(VrTracker2MapStatus* status); +std::int32_t APS5_VABI VrTracker2BuildMesh(VrTracker2MeshVertex* vertices, std::uint16_t* indices, std::uint32_t format); +std::int32_t APS5_VABI VrTracker2GetMapScalar(float* value, const VrTracker2MapData* data); +std::int32_t APS5_VABI VrTracker2GetTimedPose(VrTracker2TimedPoseResult* result, std::uint64_t timestamp, std::uint64_t userTag); +std::int32_t APS5_VABI VrTracker2GetMapData(VrTracker2MapData* data, std::uint32_t size); +std::int32_t APS5_VABI VrTracker2GetPoseScalar(float* value); +std::int32_t APS5_VABI VrTracker2SubmitImageFrame(const VrTracker2ImageFrame* frame); +std::int32_t APS5_VABI VrTracker2GetImagePose(VrTracker2ImagePoseResult* result); +std::int32_t APS5_VABI VrTracker2GetSensorSummary(VrTracker2SensorSummary* summary); +std::int32_t APS5_VABI VrTracker2NotInitialized(); +std::int32_t APS5_VABI VrTracker2ClearWideResult(void* result); +std::int32_t APS5_VABI VrTracker2ClearNarrowResult(void* result); +std::int32_t APS5_VABI VrTracker2CheckSecondThenReportNotInitialized(const void* first, const void* second); +std::int32_t APS5_VABI VrTracker2Accept(); +std::int32_t APS5_VABI VrTracker2FillDefaults(void* output); +std::int32_t APS5_VABI VrTracker2ClearWord(void* output); +std::int32_t APS5_VABI VrTracker2Unknown01(VrTracker2CalibrationResult* result, std::uint32_t capacity); +std::int32_t APS5_VABI VrTracker2Unknown02(VrTracker2MeshRequirement* requirement, std::uint32_t format); +std::int32_t APS5_VABI VrTracker2Unknown03(std::uint32_t mode, void* output, std::size_t capacity, std::size_t* writtenSize); +std::int32_t APS5_VABI VrTracker2Unknown04(const VrTracker2ResultParameter* parameter, VrTracker2Result* result); +std::int32_t APS5_VABI VrTracker2Unknown05(VrTracker2Pose* pose, std::uint64_t coordinateId); +std::int32_t APS5_VABI VrTracker2Unknown06(const VrTracker2TelemetryData* data); +std::int32_t APS5_VABI VrTracker2Unknown07(const VrTracker2PoseParameter* parameter, VrTracker2PoseResult* result); + +} diff --git a/core/libs/prx/libSceVrTracker2/libSceVrTracker2.hpp b/core/libs/prx/libSceVrTracker2/libSceVrTracker2.hpp new file mode 100644 index 0000000000..667a8cf90f --- /dev/null +++ b/core/libs/prx/libSceVrTracker2/libSceVrTracker2.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceVrTracker2/include/Api.hpp" diff --git a/core/libs/prx/libSceWeb/libSceWeb.hpp b/core/libs/prx/libSceWeb/libSceWeb.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceWeb/libSceWeb.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceWebBrowserDialog/Export.cpp b/core/libs/prx/libSceWebBrowserDialog/Export.cpp index 3b8080508c..d5961d6211 100644 --- a/core/libs/prx/libSceWebBrowserDialog/Export.cpp +++ b/core/libs/prx/libSceWebBrowserDialog/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceWebBrowserDialog/include/Api.hpp" #include #include #include @@ -6,18 +7,6 @@ #include "prx/libSceCommonDialog/CommonDialog.hpp" #include "prx/libc/include/General.hpp" -struct WebBrowserDialogCookieParam { - std::uint64_t size; - const char* address; - const char* cookie; - std::uint8_t reserved[256]; -}; - -struct WebBrowserDialogResetCookieParam { - std::uint64_t size; - std::uint8_t reserved[256]; -}; - static_assert(sizeof(WebBrowserDialogCookieParam) == 280); static_assert(offsetof(WebBrowserDialogCookieParam, address) == 8); static_assert(offsetof(WebBrowserDialogCookieParam, cookie) == 16); @@ -120,7 +109,6 @@ int APS5_VABI sceWebBrowserDialogUpdateStatus(void) { return status; } - int APS5_VABI sceWebBrowserDialogSetCookie(const WebBrowserDialogCookieParam* param) { if (g_status.load() == COMMON_DIALOG_STATUS_NONE) return COMMON_DIALOG_ERROR_NOT_INITIALIZED; if (g_open.load()) return COMMON_DIALOG_ERROR_INVALID_STATE; diff --git a/core/libs/prx/libSceWebBrowserDialog/include/Api.hpp b/core/libs/prx/libSceWebBrowserDialog/include/Api.hpp new file mode 100644 index 0000000000..e291592e7f --- /dev/null +++ b/core/libs/prx/libSceWebBrowserDialog/include/Api.hpp @@ -0,0 +1,34 @@ +#pragma once + +#include "prx/libSceCommonDialog/CommonDialog.hpp" +#include "SceTypes.hpp" + +struct WebBrowserDialogCookieParam { + std::uint64_t size; + const char* address; + const char* cookie; + std::uint8_t reserved[256]; +}; + +struct WebBrowserDialogResetCookieParam { + std::uint64_t size; + std::uint8_t reserved[256]; +}; + +extern "C" { + +int APS5_VABI sceWebBrowserDialogInitialize(void); +int APS5_VABI sceWebBrowserDialogTerminate(void); +int APS5_VABI sceWebBrowserDialogClose(void); +int APS5_VABI sceWebBrowserDialogGetResult(WebBrowserDialogResult* result); +int APS5_VABI sceWebBrowserDialogGetStatus(void); +int APS5_VABI sceWebBrowserDialogOpen(const void* param); +int APS5_VABI sceWebBrowserDialogUpdateStatus(void); +int APS5_VABI sceWebBrowserDialogSetCookie(const WebBrowserDialogCookieParam* param); +int APS5_VABI sceWebBrowserDialogOpenForPredeterminedContent(const void* param, const WebBrowserDialogAllowList* allowList); +int APS5_VABI sceWebBrowserDialogResetCookie(const WebBrowserDialogResetCookieParam* param); +int APS5_VABI sceWebBrowserDialogGetEvent(); +int APS5_VABI sceWebBrowserDialogNavigate(); +int APS5_VABI sceWebBrowserDialogSetZoom(); + +} diff --git a/core/libs/prx/libSceWebBrowserDialog/libSceWebBrowserDialog.hpp b/core/libs/prx/libSceWebBrowserDialog/libSceWebBrowserDialog.hpp new file mode 100644 index 0000000000..d9b740e440 --- /dev/null +++ b/core/libs/prx/libSceWebBrowserDialog/libSceWebBrowserDialog.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceWebBrowserDialog/include/Api.hpp" diff --git a/core/libs/prx/libSceWebKit2/libSceWebKit2.hpp b/core/libs/prx/libSceWebKit2/libSceWebKit2.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceWebKit2/libSceWebKit2.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceWebKit2Secure/libSceWebKit2Secure.hpp b/core/libs/prx/libSceWebKit2Secure/libSceWebKit2Secure.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceWebKit2Secure/libSceWebKit2Secure.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceWebmParserMdrw/libSceWebmParserMdrw.hpp b/core/libs/prx/libSceWebmParserMdrw/libSceWebmParserMdrw.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceWebmParserMdrw/libSceWebmParserMdrw.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceWkFontConfig/Export.cpp b/core/libs/prx/libSceWkFontConfig/Export.cpp index 08ae01f5ec..7257bc7ef7 100644 --- a/core/libs/prx/libSceWkFontConfig/Export.cpp +++ b/core/libs/prx/libSceWkFontConfig/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceWkFontConfig/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libSceWkFontConfig/include/Api.hpp b/core/libs/prx/libSceWkFontConfig/include/Api.hpp new file mode 100644 index 0000000000..94402813b4 --- /dev/null +++ b/core/libs/prx/libSceWkFontConfig/include/Api.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceWkFontConfigGetAttr(void); +int APS5_VABI sceWkFontConfigGetFont(void); +int APS5_VABI sceWkFontConfigGetFontFromFontName(void); +int APS5_VABI sceWkFontConfigGetFontName(void); +int APS5_VABI sceWkFontConfigGetFontPath(void); + +} diff --git a/core/libs/prx/libSceWkFontConfig/libSceWkFontConfig.hpp b/core/libs/prx/libSceWkFontConfig/libSceWkFontConfig.hpp new file mode 100644 index 0000000000..0d45867b73 --- /dev/null +++ b/core/libs/prx/libSceWkFontConfig/libSceWkFontConfig.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceWkFontConfig/include/Api.hpp" diff --git a/core/libs/prx/libSceWorkspace/libSceWorkspace.hpp b/core/libs/prx/libSceWorkspace/libSceWorkspace.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceWorkspace/libSceWorkspace.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceXml/libSceXml.hpp b/core/libs/prx/libSceXml/libSceXml.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libSceXml/libSceXml.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libSceZlib/Export.cpp b/core/libs/prx/libSceZlib/Export.cpp index c70efa66a4..f908068b6b 100644 --- a/core/libs/prx/libSceZlib/Export.cpp +++ b/core/libs/prx/libSceZlib/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceZlib/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "zlib.h" #include @@ -21,7 +22,7 @@ constexpr std::int32_t NO_SPACE = static_cast(0x8112001C); constexpr std::int32_t INVALID_ARGUMENT = static_cast(0x81120016); constexpr std::int32_t FATAL = static_cast(0x811200FF); -struct Result { +struct InflateResult { std::uint32_t produced; std::int32_t status; }; @@ -30,7 +31,7 @@ std::mutex serviceMutex; bool initialized = false; std::uint64_t nextId = 1; std::uint64_t session = 0; -std::unordered_map results; +std::unordered_map results; std::deque completed; std::condition_variable completion; @@ -79,7 +80,7 @@ std::int32_t APS5_VABI sceZlibInflate(const void* source, std::uint32_t sourceLe const int ended = inflateEnd(&stream); if (ended != Z_OK) throw std::runtime_error("sceZlibInflate: decoder cleanup failed"); const std::uint64_t id = nextId++; - results[id] = Result{produced, status}; + results[id] = InflateResult{produced, status}; completed.push_back(id); completion.notify_one(); *requestId = id; diff --git a/core/libs/prx/libSceZlib/include/Api.hpp b/core/libs/prx/libSceZlib/include/Api.hpp new file mode 100644 index 0000000000..ec57e94915 --- /dev/null +++ b/core/libs/prx/libSceZlib/include/Api.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +std::int32_t APS5_VABI sceZlibInitialize(const void* buffer, std::uint64_t length); +std::int32_t APS5_VABI sceZlibFinalize(); +std::int32_t APS5_VABI sceZlibInflate(const void* source, std::uint32_t sourceLength, void* destination, std::uint32_t destinationLength, std::uint64_t* requestId); +std::int32_t APS5_VABI sceZlibWaitForDone(std::uint64_t* requestId, std::uint32_t* timeout); +std::int32_t APS5_VABI sceZlibGetResult(std::uint64_t requestId, std::uint32_t* destinationLength, std::int32_t* status); + +} diff --git a/core/libs/prx/libSceZlib/libSceZlib.hpp b/core/libs/prx/libSceZlib/libSceZlib.hpp new file mode 100644 index 0000000000..2740f392a8 --- /dev/null +++ b/core/libs/prx/libSceZlib/libSceZlib.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libSceZlib/include/Api.hpp" diff --git a/core/libs/prx/libc/CMakeLists.txt b/core/libs/prx/libc/CMakeLists.txt index d3e9bed678..bf8e7ab043 100644 --- a/core/libs/prx/libc/CMakeLists.txt +++ b/core/libs/prx/libc/CMakeLists.txt @@ -638,6 +638,15 @@ if(BUILD_TESTING) set_tests_properties(guest_memrchr PROPERTIES ENVIRONMENT_MODIFICATION "PATH=path_list_prepend:$") endif() + add_test_executable(guest_string_compare_tests ${LIBS_INCLUDE_DIR}/tests/GuestStringCompare.cpp) + target_include_directories(guest_string_compare_tests PRIVATE ${LIBS_INCLUDE_DIR}) + target_link_libraries(guest_string_compare_tests PRIVATE libc) + configure_windows_unwind(guest_string_compare_tests) + add_test(NAME guest_string_compare COMMAND guest_string_compare_tests) + if(WIN32) + set_tests_properties(guest_string_compare PROPERTIES ENVIRONMENT_MODIFICATION + "PATH=path_list_prepend:$") + endif() add_test_executable(guest_daemon_tests ${LIBS_INCLUDE_DIR}/tests/GuestDaemon.cpp) target_include_directories(guest_daemon_tests PRIVATE ${LIBS_INCLUDE_DIR}) target_link_libraries(guest_daemon_tests PRIVATE libc) @@ -941,6 +950,7 @@ if(BUILD_TESTING) add_test(NAME exception_runtime COMMAND exception_runtime_tests) enable_language(C) add_test_executable(exception_c_cleanup_tests ${LIBS_INCLUDE_DIR}/tests/ExceptionCCleanup.cpp ${LIBS_INCLUDE_DIR}/tests/ExceptionCCleanup.c) + target_include_directories(exception_c_cleanup_tests PRIVATE ${LIBS_INCLUDE_DIR}) set_source_files_properties(${LIBS_INCLUDE_DIR}/tests/ExceptionCCleanup.c PROPERTIES COMPILE_OPTIONS -fexceptions) target_link_libraries(exception_c_cleanup_tests PRIVATE libc) add_test(NAME exception_c_cleanup COMMAND exception_c_cleanup_tests) @@ -1187,6 +1197,7 @@ if(MINGW) set_tests_properties(windows_exceptions PROPERTIES ENVIRONMENT_MODIFICATION "PATH=path_list_prepend:$") add_test_executable(windows_backtrace_report_tests ${LIBS_INCLUDE_DIR}/tests/WindowsBacktraceReport.cpp) target_link_libraries(windows_backtrace_report_tests PRIVATE libc) + target_include_directories(windows_backtrace_report_tests PRIVATE ${LIBS_INCLUDE_DIR}) add_test(NAME windows_backtrace_report COMMAND windows_backtrace_report_tests) set_tests_properties(windows_backtrace_report PROPERTIES TIMEOUT 20 ENVIRONMENT_MODIFICATION "PATH=path_list_prepend:$" diff --git a/core/libs/prx/libc/Export.cpp b/core/libs/prx/libc/Export.cpp index 6056428c98..cb7055cfd5 100644 --- a/core/libs/prx/libc/Export.cpp +++ b/core/libs/prx/libc/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include #include #include "SceTypes.hpp" @@ -8,8 +9,6 @@ uint32_t Need_sceLibc = 1; extern "C" { - int APS5_VABI _ZSt13_Execute_onceRSt9once_flagPFiPvS1_PS1_ES1__nid_postfix(int*, int (APS5_VABI *)(void*, void*, void**), void*); - int APS5_VABI std_execute_once_nid_postfix(int* flag, int (APS5_VABI *func)(void*, void*, void**), void* arg) { return _ZSt13_Execute_onceRSt9once_flagPFiPvS1_PS1_ES1__nid_postfix(flag, func, arg); } @@ -25,7 +24,6 @@ int APS5_VABI _ZSt14_Atomic_assertPKcS0__nid_postfix() { return 0; } - APS5_EXPORT("H2e8t5ScQGc", libc___cxa_finalize); void APS5_VABI libc___cxa_finalize(void* dsoHandle) { CxaFinalize_nid_no_patch(dsoHandle); diff --git a/core/libs/prx/libc/include/Api.hpp b/core/libs/prx/libc/include/Api.hpp new file mode 100644 index 0000000000..9ce7610ed3 --- /dev/null +++ b/core/libs/prx/libc/include/Api.hpp @@ -0,0 +1,1401 @@ +#pragma once + +#include "prx/libc/include/specifics/linux/ElfTypes.hpp" +#include "prx/libc/include/specifics/itanium/UnwindAbi.hpp" +#include "prx/libc/include/MallocManagedSize.hpp" +#include "prx/libc/include/GuestTime.hpp" +#include "prx/libc/include/GuestLocale.hpp" +#include "prx/libc/include/GuestDirectory.hpp" +#include "prx/libc/include/FileStream.hpp" +#include "prx/libc/include/exceptions/Unwind.hpp" +#include "prx/libc/include/exceptions/Runtime.hpp" +#include "SceTypes.hpp" +#include +#include + +#ifdef _LIBCPP_VERSION +struct GuestExceptionPointer { + void* object {}; + explicit GuestExceptionPointer(void* primary) noexcept : object(primary) {} + GuestExceptionPointer(const GuestExceptionPointer&) = delete; + ~GuestExceptionPointer() {} +}; +using GuestExceptionPointerArgument = GuestExceptionPointer&; +#else +using GuestExceptionPointer = std::exception_ptr; +using GuestExceptionPointerArgument = GuestExceptionPointer; +#endif + +using GuestCompare = int (APS5_VABI *)(const void*, const void*); + +using GuestContextCompare = int (APS5_VABI*)(const void*, const void*, void*); + +using GuestExitCallback = void (APS5_VABI*)(); + +struct GuestFloatingPointEnvironment { + std::uint32_t control; + std::uint32_t status; + std::uint32_t tag; + unsigned char other[16]; + std::uint32_t mxcsr; +}; + +struct GuestInterfaceAddress { + GuestInterfaceAddress* next; + char* name; + std::uint32_t flags; + void* address; + void* netmask; + void* destination; + void* data; +}; + +struct GuestLocaleFacade { + GuestLocale::Implementation* implementation; +}; + +using GuestNewHandler = void (APS5_VABI*)(); + +struct GuestPad { + unsigned (APS5_VABI* const* vtable)(GuestPad*); + void* condition; + void* mutex; + bool started; +}; + +using Int128 = __int128; + +using LibcTerminateHandler = void(*)(); + +struct MinMaxPointers { + const void* minimum; + const void* maximum; +}; + +struct StreamManipulator { + GuestLocale::IosBase* (APS5_VABI* function)(GuestLocale::IosBase*, std::int32_t); + std::int32_t argument; +}; + +using Uint128 = unsigned __int128; + +struct Xtime { + std::int64_t sec; + std::int64_t nsec; +}; + +namespace LibcException { + +} + +namespace LibcException { + +struct CategoryObject { const void* vtable; }; + +struct ExceptionObject { const void* vtable; const char* message; }; + +struct ErrorCode { int reserved; int value; const CategoryObject* category; }; + +struct SystemErrorObject { ExceptionObject base; ErrorCode code; }; + +} + +extern "C" { + +int APS5_VABI std_execute_once_nid_postfix(int* flag, int (APS5_VABI *func)(void*, void*, void**), void* arg); +void APS5_VABI LibcHeapGetTraceInfo_nid_postfix(LibcHeapInfo* info); +int APS5_VABI _ZSt14_Atomic_assertPKcS0__nid_postfix(); +void APS5_VABI libc___cxa_finalize(void* dsoHandle); +char* APS5_VABI strndup_nid_postfix(const char* source, std::size_t limit); +char* APS5_VABI strdup_nid_postfix(const char* source); +int APS5_VABI asprintf_nid_postfix(char** destination, const char* format, ...); +void* APS5_VABI scriptingGetMem_nid_postfix(std::size_t alignment, std::size_t bytes); +void APS5_VABI scriptingFreeMem_nid_postfix(void* pointer); +void APS5_VABI __atomic_load_nid_postfix(std::size_t, void*, void*, int); +void APS5_VABI __atomic_store_nid_postfix(std::size_t, void*, void*, int); +void APS5_VABI __atomic_exchange_nid_postfix(std::size_t, void*, void*, void*, int); +bool APS5_VABI __atomic_compare_exchange_nid_postfix(std::size_t, void*, void*, void*, int, int); +bool APS5_VABI __atomic_is_lock_free_nid_postfix(std::size_t size, const void* pointer); +Uint128 APS5_VABI __sync_fetch_and_add_16_nid_postfix(Uint128* target, Uint128 value); +Uint128 APS5_VABI __sync_fetch_and_sub_16_nid_postfix(Uint128* target, Uint128 value); +Uint128 APS5_VABI __sync_fetch_and_and_16_nid_postfix(Uint128* target, Uint128 value); +Uint128 APS5_VABI __sync_fetch_and_or_16_nid_postfix(Uint128* target, Uint128 value); +Uint128 APS5_VABI __sync_fetch_and_xor_16_nid_postfix(Uint128* target, Uint128 value); +Uint128 APS5_VABI __sync_lock_test_and_set_16_nid_postfix(Uint128* target, Uint128 value); +int APS5_VABI sceLibcBacktraceGetBufferSize_nid_postfix(int limit, int* count, std::size_t* size); +int APS5_VABI sceLibcBacktraceSelf_nid_postfix(int limit, void* buffer, std::size_t size, int* count); +double APS5_VABI j0_nid_postfix(double x); +double APS5_VABI y0_nid_postfix(double x); +double APS5_VABI j1_nid_postfix(double x); +double APS5_VABI y1_nid_postfix(double x); +double APS5_VABI jn_nid_postfix(int order, double x); +double APS5_VABI yn_nid_postfix(int order, double x); +int APS5_VABI getw_nid_postfix(FileStream* stream); +int APS5_VABI putw_nid_postfix(int value, FileStream* stream); +void APS5_VABI abort_handler_s_nid_postfix(const char* message, void*, int); +void* APS5_VABI bsearch_s_nid_postfix(const void* key, const void* base, std::size_t count, std::size_t size, GuestContextCompare compare, void* context); +std::uint16_t* APS5_VABI wcstok_s_nid_postfix(std::uint16_t* str, std::size_t* remaining, const std::uint16_t* delimiters, std::uint16_t** context); +int APS5_VABI wctomb_s_nid_postfix(int* status, char* destination, std::size_t capacity, std::uint16_t wide); +int APS5_VABI wcrtomb_s_nid_postfix(std::size_t* result, char* destination, std::size_t capacity, std::uint16_t wide, void* state); +int APS5_VABI mbstowcs_s_nid_postfix(std::size_t* result, std::uint16_t* destination, std::size_t capacity, const char* source, std::size_t limit); +int APS5_VABI mbsrtowcs_s_nid_postfix(std::size_t* result, std::uint16_t* destination, std::size_t capacity, const char** source, std::size_t limit, void* state); +char* APS5_VABI gets_s_nid_postfix(char* buffer, std::size_t size); +void* APS5_VABI __cxa_demangle_nid_postfix(const char* mangled, char* buf, std::size_t* len, int* status); +int APS5_VABI __cxa_thread_atexit_impl_nid_postfix(void (APS5_VABI *func)(void*), void* arg, void* dso); +int APS5_VABI __cxa_thread_atexit_nid_postfix(void (APS5_VABI *func)(void*), void* arg, void* dso); +int APS5_VABI LibcInternalExtCxaThreadAtexit_nid_postfix(void (APS5_VABI *destructor)(void*), void* object, void* moduleId); +int APS5_VABI _ZSt13_Execute_onceRSt9once_flagPFiPvS1_PS1_ES1__nid_postfix( int* flag, int (APS5_VABI *callback)(void*, void*, void**), void* arg ); +void APS5_VABI _Atomic_store_1_nid_postfix(volatile std::uint8_t* target, std::uint8_t value, int); +void APS5_VABI _Atomic_store_2_nid_postfix(volatile std::uint16_t* target, std::uint16_t value, int); +void APS5_VABI _Atomic_store_4_nid_postfix(volatile std::uint32_t* target, std::uint32_t value, int); +void APS5_VABI _Atomic_store_8_nid_postfix(volatile std::uint64_t* target, std::uint64_t value, int); +std::uint8_t APS5_VABI _Atomic_load_1_nid_postfix(volatile std::uint8_t* target, int); +std::uint16_t APS5_VABI _Atomic_load_2_nid_postfix(volatile std::uint16_t* target, int); +std::uint64_t APS5_VABI _Atomic_load_8_nid_postfix(volatile std::uint64_t* target, int order); +std::uint8_t APS5_VABI _Atomic_exchange_1_nid_postfix(volatile std::uint8_t* target, std::uint8_t value, int); +std::uint16_t APS5_VABI _Atomic_exchange_2_nid_postfix(volatile std::uint16_t* target, std::uint16_t value, int); +std::uint32_t APS5_VABI _Atomic_exchange_4_nid_postfix(volatile std::uint32_t* target, std::uint32_t value, int); +std::uint64_t APS5_VABI _Atomic_exchange_8_nid_postfix(volatile std::uint64_t* target, std::uint64_t value, int order); +int APS5_VABI _Atomic_compare_exchange_strong_1_nid_postfix(volatile std::uint8_t* target, std::uint8_t* expected, std::uint8_t desired, int, int); +int APS5_VABI _Atomic_compare_exchange_strong_2_nid_postfix(volatile std::uint16_t* target, std::uint16_t* expected, std::uint16_t desired, int, int); +int APS5_VABI _Atomic_compare_exchange_strong_4_nid_postfix(volatile std::uint32_t* target, std::uint32_t* expected, std::uint32_t desired, int, int); +int APS5_VABI _Atomic_compare_exchange_strong_8_nid_postfix(volatile std::uint64_t* target, std::uint64_t* expected, std::uint64_t desired, int, int); +int APS5_VABI _Atomic_compare_exchange_weak_1_nid_postfix(volatile std::uint8_t* target, std::uint8_t* expected, std::uint8_t desired, int, int); +int APS5_VABI _Atomic_compare_exchange_weak_2_nid_postfix(volatile std::uint16_t* target, std::uint16_t* expected, std::uint16_t desired, int, int); +int APS5_VABI _Atomic_compare_exchange_weak_8_nid_postfix(volatile std::uint64_t* target, std::uint64_t* expected, std::uint64_t desired, int, int); +std::uint8_t APS5_VABI _Atomic_fetch_add_1_nid_postfix(volatile std::uint8_t* target, std::uint8_t value, int); +std::uint16_t APS5_VABI _Atomic_fetch_add_2_nid_postfix(volatile std::uint16_t* target, std::uint16_t value, int); +std::uint64_t APS5_VABI _Atomic_fetch_add_8_nid_postfix(volatile std::uint64_t* target, std::uint64_t value, int order); +std::uint8_t APS5_VABI _Atomic_fetch_sub_1_nid_postfix(volatile std::uint8_t* target, std::uint8_t value, int); +std::uint16_t APS5_VABI _Atomic_fetch_sub_2_nid_postfix(volatile std::uint16_t* target, std::uint16_t value, int); +std::uint64_t APS5_VABI _Atomic_fetch_sub_8_nid_postfix(volatile std::uint64_t* target, std::uint64_t value, int order); +std::uint8_t APS5_VABI _Atomic_fetch_and_1_nid_postfix(volatile std::uint8_t* target, std::uint8_t value, int); +std::uint16_t APS5_VABI _Atomic_fetch_and_2_nid_postfix(volatile std::uint16_t* target, std::uint16_t value, int); +std::uint32_t APS5_VABI _Atomic_fetch_and_4_nid_postfix(volatile std::uint32_t* target, std::uint32_t value, int); +std::uint64_t APS5_VABI _Atomic_fetch_and_8_nid_postfix(volatile std::uint64_t* target, std::uint64_t value, int order); +std::uint8_t APS5_VABI _Atomic_fetch_or_1_nid_postfix(volatile std::uint8_t* target, std::uint8_t value, int); +std::uint16_t APS5_VABI _Atomic_fetch_or_2_nid_postfix(volatile std::uint16_t* target, std::uint16_t value, int); +std::uint32_t APS5_VABI _Atomic_fetch_or_4_nid_postfix(volatile std::uint32_t* target, std::uint32_t value, int); +std::uint64_t APS5_VABI _Atomic_fetch_or_8_nid_postfix(volatile std::uint64_t* target, std::uint64_t value, int order); +std::uint8_t APS5_VABI _Atomic_fetch_xor_1_nid_postfix(volatile std::uint8_t* target, std::uint8_t value, int); +std::uint16_t APS5_VABI _Atomic_fetch_xor_2_nid_postfix(volatile std::uint16_t* target, std::uint16_t value, int); +std::uint32_t APS5_VABI _Atomic_fetch_xor_4_nid_postfix(volatile std::uint32_t* target, std::uint32_t value, int); +std::uint64_t APS5_VABI _Atomic_fetch_xor_8_nid_postfix(volatile std::uint64_t* target, std::uint64_t value, int order); +int APS5_VABI _Atomic_is_lock_free_1_nid_postfix(); +int APS5_VABI _Atomic_is_lock_free_2_nid_postfix(); +int APS5_VABI _Atomic_is_lock_free_4_nid_postfix(); +int APS5_VABI _Atomic_is_lock_free_8_nid_postfix(); +int APS5_VABI _Atomic_flag_test_and_set_nid_postfix(volatile unsigned char* flag, int); +void APS5_VABI _Atomic_flag_clear_nid_postfix(volatile unsigned char* flag, int); +void APS5_VABI _Atomic_thread_fence_nid_postfix(int order); +void APS5_VABI _Atomic_signal_fence_nid_postfix(int); +void APS5_VABI _Atomic_copy_nid_postfix(volatile unsigned char* flag, std::size_t size, volatile void* target, const volatile void* source, int); +void APS5_VABI _Atomic_exchange_nid_postfix(volatile unsigned char* flag, std::size_t size, volatile void* target, volatile void* value, int); +int APS5_VABI _Atomic_compare_exchange_strong_nid_postfix(volatile unsigned char* flag, std::size_t size, volatile void* target, void* expected, const void* desired, int, int); +int APS5_VABI _Atomic_compare_exchange_weak_nid_postfix(volatile unsigned char* flag, std::size_t size, volatile void* target, void* expected, const void* desired, int, int); +double APS5_VABI _Stod_nid_postfix(const char* text, char** end, std::int64_t pten); +long long APS5_VABI _Stoll_nid_postfix(const char* text, char** end, int base); +double APS5_VABI _Sin_nid_postfix(double x, unsigned int quadrant); +float APS5_VABI _FSin_nid_postfix(float x, unsigned int quadrant); +long double APS5_VABI _LSin_nid_postfix(long double x, unsigned int quadrant); +double APS5_VABI _Log_nid_postfix(double x, int base); +float APS5_VABI _FLog_nid_postfix(float x, int base); +long double APS5_VABI _LLog_nid_postfix(long double x, int base); +long double APS5_VABI _LDivide_nid_postfix(long double x, long double y); +long double APS5_VABI _LRecip_nid_postfix(long double x); +void* APS5_VABI opendir_nid_postfix(const char* path); +GuestDirectoryEntry* APS5_VABI readdir_nid_postfix(void* handle); +int APS5_VABI readdir_r_nid_postfix(void* handle, GuestDirectoryEntry* entry, GuestDirectoryEntry** result); +int APS5_VABI closedir_nid_postfix(void* handle); +void APS5_VABI rewinddir_nid_postfix(void* handle); +std::int64_t APS5_VABI telldir_nid_postfix(void* handle); +void APS5_VABI seekdir_nid_postfix(void* handle, std::int64_t location); +char* APS5_VABI getenv_nid_postfix(const char* name); +int APS5_VABI setenv_nid_postfix(const char* name, const char* value, int overwrite); +int APS5_VABI unsetenv_nid_postfix(const char* name); +int APS5_VABI putenv_nid_postfix(char* text); +char* APS5_VABI strerror_nid_postfix(int error); +int APS5_VABI strerror_r_nid_postfix(int error, char* buffer, std::size_t length); +void APS5_VABI perror_nid_postfix(const char* prefix); +FileStream* APS5_VABI fdopen_nid_postfix(int descriptor, const char* mode); +FileStream* APS5_VABI freopen_nid_postfix(const char* filename, const char* mode, FileStream* stream); +FileStream* APS5_VABI fopen_nid_postfix(const char* filename, const char* mode); +int APS5_VABI fopen_s_nid_postfix(FileStream** result, const char* filename, const char* mode); +int APS5_VABI fclose_nid_postfix(FileStream* stream); +FileStream* APS5_VABI _ZSt7_FiopenPKcNSt5_IosbIiE9_OpenmodeEi_nid_postfix(const char* filename, int mode, int protection); +size_t APS5_VABI fread_nid_postfix(void* buffer, size_t size, size_t count, FileStream* stream); +size_t APS5_VABI fwrite_nid_postfix(const void* buffer, size_t size, size_t count, FileStream* stream); +int APS5_VABI fseeko_nid_postfix(FileStream* stream, std::int64_t offset, int origin); +std::int64_t APS5_VABI ftello_nid_postfix(FileStream* stream); +int APS5_VABI fseek_nid_postfix(FileStream* stream, std::int64_t offset, int origin); +std::int64_t APS5_VABI ftell_nid_postfix(FileStream* stream); +int APS5_VABI fgetpos_nid_postfix(FileStream* stream, std::int64_t* position); +int APS5_VABI fsetpos_nid_postfix(FileStream* stream, const std::int64_t* position); +void APS5_VABI rewind_nid_postfix(FileStream* stream); +int APS5_VABI fputs_nid_postfix(const char* str, FileStream* stream); +int APS5_VABI fflush_nid_postfix(FileStream* stream); +int APS5_VABI malloc_stats_fast_nid_postfix(void* stats); +size_t APS5_VABI malloc_usable_size_nid_postfix(void* pointer); +void* APS5_VABI malloc_nid_postfix(size_t size); +void APS5_VABI free_nid_postfix(void* ptr); +void* APS5_VABI realloc_nid_postfix(void* ptr, size_t newSize); +void* APS5_VABI reallocf_nid_postfix(void* ptr, size_t newSize); +void* APS5_VABI memalign_nid_postfix(size_t alignment, size_t size); +void* APS5_VABI aligned_alloc_nid_postfix(size_t alignment, size_t size); +void* APS5_VABI reallocalign_nid_postfix(void* ptr, size_t size, size_t alignment); +void* APS5_VABI calloc_nid_postfix(size_t count, size_t size); +int APS5_VABI posix_memalign_nid_postfix(void** pointer, size_t alignment, size_t size); +void* APS5_VABI bsearch_nid_postfix(const void* key, const void* base, size_t count, size_t size, int (APS5_VABI *compare)(const void*, const void*)); +int APS5_VABI mergesort_nid_postfix(void* base, size_t count, size_t size, GuestCompare compare); +void APS5_VABI qsort_nid_postfix(void* base, size_t count, size_t size, int (APS5_VABI *compare)(const void*, const void*)); +int APS5_VABI qsort_s_nid_postfix(void* base, size_t count, size_t size, GuestContextCompare compare, void* context); +int APS5_VABI access_nid_postfix(const char* path, int mode); +int APS5_VABI remove_nid_postfix(const char* path); +double APS5_VABI __adddf3_nid_postfix(double a, double b); +float APS5_VABI __addsf3_nid_postfix(float a, float b); +double APS5_VABI __subdf3_nid_postfix(double a, double b); +float APS5_VABI __subsf3_nid_postfix(float a, float b); +double APS5_VABI __muldf3_nid_postfix(double a, double b); +float APS5_VABI __mulsf3_nid_postfix(float a, float b); +double APS5_VABI __divdf3_nid_postfix(double a, double b); +float APS5_VABI __divsf3_nid_postfix(float a, float b); +double APS5_VABI __negdf2_nid_postfix(double a); +float APS5_VABI __negsf2_nid_postfix(float a); +int APS5_VABI __eqdf2_nid_postfix(double a, double b); +int APS5_VABI __nedf2_nid_postfix(double a, double b); +int APS5_VABI __ltdf2_nid_postfix(double a, double b); +int APS5_VABI __ledf2_nid_postfix(double a, double b); +int APS5_VABI __gtdf2_nid_postfix(double a, double b); +int APS5_VABI __gedf2_nid_postfix(double a, double b); +int APS5_VABI __unorddf2_nid_postfix(double a, double b); +int APS5_VABI __eqsf2_nid_postfix(float a, float b); +int APS5_VABI __nesf2_nid_postfix(float a, float b); +int APS5_VABI __ltsf2_nid_postfix(float a, float b); +int APS5_VABI __lesf2_nid_postfix(float a, float b); +int APS5_VABI __gtsf2_nid_postfix(float a, float b); +int APS5_VABI __gesf2_nid_postfix(float a, float b); +int APS5_VABI __unordsf2_nid_postfix(float a, float b); +double APS5_VABI __extendsfdf2_nid_postfix(float a); +float APS5_VABI __truncdfsf2_nid_postfix(double a); +std::int32_t APS5_VABI __fixsfsi_nid_postfix(float a); +std::int64_t APS5_VABI __fixsfdi_nid_postfix(float a); +Int128 APS5_VABI __fixsfti_nid_postfix(float a); +std::int32_t APS5_VABI __fixdfsi_nid_postfix(double a); +std::int64_t APS5_VABI __fixdfdi_nid_postfix(double a); +Int128 APS5_VABI __fixdfti_nid_postfix(double a); +std::uint32_t APS5_VABI __fixunssfsi_nid_postfix(float a); +std::uint64_t APS5_VABI __fixunssfdi_nid_postfix(float a); +Uint128 APS5_VABI __fixunssfti_nid_postfix(float a); +std::uint32_t APS5_VABI __fixunsdfsi_nid_postfix(double a); +std::uint64_t APS5_VABI __fixunsdfdi_nid_postfix(double a); +Uint128 APS5_VABI __fixunsdfti_nid_postfix(double a); +std::int64_t APS5_VABI __fixxfdi_nid_postfix(long double a); +Int128 APS5_VABI __fixxfti_nid_postfix(long double a); +std::uint32_t APS5_VABI __fixunsxfsi_nid_postfix(long double a); +std::uint64_t APS5_VABI __fixunsxfdi_nid_postfix(long double a); +Uint128 APS5_VABI __fixunsxfti_nid_postfix(long double a); +double APS5_VABI __floatsidf_nid_postfix(std::int32_t a); +double APS5_VABI __floatunsidf_nid_postfix(std::uint32_t a); +float APS5_VABI __floatsisf_nid_postfix(std::int32_t a); +float APS5_VABI __floatunsisf_nid_postfix(std::uint32_t a); +double APS5_VABI __floatdidf_nid_postfix(std::int64_t a); +float APS5_VABI __floatdisf_nid_postfix(std::int64_t a); +long double APS5_VABI __floatdixf_nid_postfix(std::int64_t a); +double APS5_VABI __floatundidf_nid_postfix(std::uint64_t a); +float APS5_VABI __floatundisf_nid_postfix(std::uint64_t a); +long double APS5_VABI __floatundixf_nid_postfix(std::uint64_t a); +double APS5_VABI __floattidf_nid_postfix(Int128 a); +float APS5_VABI __floattisf_nid_postfix(Int128 a); +long double APS5_VABI __floattixf_nid_postfix(Int128 a); +double APS5_VABI __floatuntidf_nid_postfix(Uint128 a); +float APS5_VABI __floatuntisf_nid_postfix(Uint128 a); +long double APS5_VABI __floatuntixf_nid_postfix(Uint128 a); +__complex__ float APS5_VABI __mulsc3_nid_postfix(float a, float b, float c, float d); +__complex__ double APS5_VABI __muldc3_nid_postfix(double a, double b, double c, double d); +__complex__ long double APS5_VABI __mulxc3_nid_postfix(long double a, long double b, long double c, long double d); +__complex__ float APS5_VABI __divsc3_nid_postfix(float a, float b, float c, float d); +__complex__ double APS5_VABI __divdc3_nid_postfix(double a, double b, double c, double d); +__complex__ long double APS5_VABI __divxc3_nid_postfix(long double a, long double b, long double c, long double d); +long double APS5_VABI __powixf2_nid_postfix(long double base, int exponent); +int APS5_VABI fegetround_nid_postfix(); +int APS5_VABI fesetround_nid_postfix(int rounding); +int APS5_VABI fetestexcept_nid_postfix(int exceptions); +int APS5_VABI fegetexceptflag_nid_postfix(std::uint16_t* flags, int exceptions); +void APS5_VABI _Feraise_nid_postfix(int exceptions); +int APS5_VABI fesetexceptflag_nid_postfix(const std::uint16_t* flags, int exceptions); +int APS5_VABI feclearexcept_nid_postfix(int exceptions); +int APS5_VABI feenableexcept_nid_postfix(int exceptions); +int APS5_VABI fedisableexcept_nid_postfix(int exceptions); +int APS5_VABI __feenableexcept_nid_postfix(int exceptions); +int APS5_VABI __fedisableexcept_nid_postfix(int exceptions); +int APS5_VABI fegettrapenable_nid_postfix(); +int APS5_VABI fegetexcept_nid_postfix(); +int APS5_VABI fesettrapenable_nid_postfix(int exceptions); +int APS5_VABI vasprintf_nid_postfix(char** destination, const char* format, VaList* args); +int APS5_VABI vfprintf_nid_postfix(FileStream* stream, const char* format, VaList* args); +int APS5_VABI fprintf_nid_postfix(FileStream* stream, const char* format, ...); +int APS5_VABI fscanf_nid_postfix(FileStream* stream, const char* format, ...); +int APS5_VABI printf_nid_postfix(const char* format, ...); +int APS5_VABI libc_printf_nid_postfix(const char* format, ...); +int APS5_VABI snprintf_nid_postfix(char* buffer, size_t size, const char* format, ...); +int APS5_VABI sprintf_nid_postfix(char* buffer, const char* format, ...); +int APS5_VABI vsscanf_nid_postfix(const char* input, const char* format, VaList* args); +int APS5_VABI sscanf_nid_postfix(const char* input, const char* format, ...); +int APS5_VABI sscanf_s_nid_postfix(const char* buffer, const char* format, ...); +int APS5_VABI vprintf_nid_postfix(const char* str, VaList* c); +int APS5_VABI vsprintf_nid_postfix(char* str, const char* format, VaList* args); +int APS5_VABI vsnprintf_nid_postfix(char* str, size_t size, const char* format, VaList* c); +int APS5_VABI vsnprintf_s_nid_postfix(char* buffer, size_t size, const char* format, VaList* args); +int APS5_VABI vsscanf_s_nid_postfix(const char* buffer, const char* format, VaList* args); +int APS5_VABI snprintf_s_nid_postfix(char* buffer, size_t size, const char* format, ...); +int APS5_VABI printf_s_nid_postfix(const char* format, ...); +int APS5_VABI vsprintf_s_nid_postfix(char* buffer, size_t size, const char* format, VaList* args); +int APS5_VABI sprintf_s_nid_postfix(char* buffer, size_t size, const char* format, ...); +int APS5_VABI puts_nid_postfix(const char* s); +int APS5_VABI vfscanf_nid_postfix(FileStream* stream, const char* format, VaList* args); +int APS5_VABI vscanf_nid_postfix(const char* format, VaList* args); +int APS5_VABI scanf_nid_postfix(const char* format, ...); +int APS5_VABI vswprintf_nid_postfix(char16_t* buffer, std::size_t size, const char16_t* format, VaList* args); +int APS5_VABI swprintf_nid_postfix(char16_t* buffer, std::size_t size, const char16_t* format, ...); +int APS5_VABI snwprintf_s_nid_postfix(char16_t* buffer, std::size_t size, const char16_t* format, ...); +int APS5_VABI vswprintf_s_nid_postfix(char16_t* buffer, std::size_t size, const char16_t* format, VaList* args); +int APS5_VABI swprintf_s_nid_postfix(char16_t* buffer, std::size_t size, const char16_t* format, ...); +int APS5_VABI vsnwprintf_s_nid_postfix(char16_t* buffer, std::size_t size, const char16_t* format, VaList* args); +int APS5_VABI wprintf_nid_postfix(const char16_t* format, ...); +int APS5_VABI vfwprintf_nid_postfix(FileStream* stream, const char16_t* format, VaList* args); +int APS5_VABI fwprintf_nid_postfix(FileStream* stream, const char16_t* format, ...); +int APS5_VABI vwprintf_nid_postfix(const char16_t* format, VaList* args); +int APS5_VABI fputwc_nid_postfix(char16_t value, FileStream* stream); +int APS5_VABI fputws_nid_postfix(const char16_t* str, FileStream* stream); +int APS5_VABI putwc_nid_postfix(char16_t value, FileStream* stream); +int APS5_VABI putwchar_nid_postfix(char16_t value); +char16_t* APS5_VABI fgetws_nid_postfix(char16_t* buffer, int size, FileStream* stream); +int APS5_VABI chdir_nid_postfix(const char* path); +char* APS5_VABI getcwd_nid_postfix(char* buffer, std::size_t size); +void APS5_VABI sceLibcInternalBacktraceForGame_nid_postfix(const char* heapName); +void APS5_VABI sceLibcInternalHeapErrorReportForGame_nid_postfix(void* heap, void* block, std::uint32_t error); +int APS5_VABI gethostname_nid_postfix(char* name, std::size_t length); +std::int64_t APS5_VABI __ashldi3_nid_postfix(std::int64_t value, int shift); +std::int64_t APS5_VABI __ashrdi3_nid_postfix(std::int64_t value, int shift); +std::int64_t APS5_VABI __lshrdi3_nid_postfix(std::int64_t value, int shift); +Int128 APS5_VABI __ashlti3_nid_postfix(Int128 value, int shift); +Int128 APS5_VABI __ashrti3_nid_postfix(Int128 value, int shift); +Int128 APS5_VABI __lshrti3_nid_postfix(Int128 value, int shift); +int APS5_VABI __clzsi2_nid_postfix(std::uint32_t value); +int APS5_VABI __clzdi2_nid_postfix(std::uint64_t value); +int APS5_VABI __clzti2_nid_postfix(Uint128 value); +int APS5_VABI __ctzsi2_nid_postfix(std::uint32_t value); +int APS5_VABI __ctzdi2_nid_postfix(std::uint64_t value); +int APS5_VABI __ctzti2_nid_postfix(Uint128 value); +int APS5_VABI __ffsdi2_nid_postfix(std::uint64_t value); +int APS5_VABI __ffsti2_nid_postfix(Uint128 value); +int APS5_VABI __paritysi2_nid_postfix(std::uint32_t value); +int APS5_VABI __paritydi2_nid_postfix(std::uint64_t value); +int APS5_VABI __parityti2_nid_postfix(Uint128 value); +int APS5_VABI __popcountsi2_nid_postfix(std::uint32_t value); +int APS5_VABI __popcountdi2_nid_postfix(std::uint64_t value); +int APS5_VABI __popcountti2_nid_postfix(Uint128 value); +int APS5_VABI __cmpdi2_nid_postfix(std::int64_t a, std::int64_t b); +int APS5_VABI __cmpti2_nid_postfix(Int128 a, Int128 b); +int APS5_VABI __ucmpdi2_nid_postfix(std::uint64_t a, std::uint64_t b); +int APS5_VABI __ucmpti2_nid_postfix(Uint128 a, Uint128 b); +std::int64_t APS5_VABI __negdi2_nid_postfix(std::int64_t value); +Int128 APS5_VABI __negti2_nid_postfix(Int128 value); +std::int64_t APS5_VABI __muldi3_nid_postfix(std::int64_t a, std::int64_t b); +Int128 APS5_VABI __multi3_nid_postfix(Int128 a, Int128 b); +std::int32_t APS5_VABI __divsi3_nid_postfix(std::int32_t a, std::int32_t b); +std::int64_t APS5_VABI __divdi3_nid_postfix(std::int64_t a, std::int64_t b); +std::int32_t APS5_VABI __modsi3_nid_postfix(std::int32_t a, std::int32_t b); +std::int64_t APS5_VABI __moddi3_nid_postfix(std::int64_t a, std::int64_t b); +std::uint32_t APS5_VABI __udivsi3_nid_postfix(std::uint32_t a, std::uint32_t b); +std::uint64_t APS5_VABI __udivdi3_nid_postfix(std::uint64_t a, std::uint64_t b); +std::uint32_t APS5_VABI __umodsi3_nid_postfix(std::uint32_t a, std::uint32_t b); +std::uint64_t APS5_VABI __umoddi3_nid_postfix(std::uint64_t a, std::uint64_t b); +std::int32_t APS5_VABI __divmodsi4_nid_postfix(std::int32_t a, std::int32_t b, std::int32_t* remainder); +std::int64_t APS5_VABI __divmoddi4_nid_postfix(std::int64_t a, std::int64_t b, std::int64_t* remainder); +std::uint32_t APS5_VABI __udivmodsi4_nid_postfix(std::uint32_t a, std::uint32_t b, std::uint32_t* remainder); +std::uint64_t APS5_VABI __udivmoddi4_nid_postfix(std::uint64_t a, std::uint64_t b, std::uint64_t* remainder); +Uint128 APS5_VABI __udivmodti4_nid_postfix(Uint128 a, Uint128 b, Uint128* remainder); +std::int32_t APS5_VABI __mulosi4_nid_postfix(std::int32_t a, std::int32_t b, int* overflow); +std::int64_t APS5_VABI __mulodi4_nid_postfix(std::int64_t a, std::int64_t b, int* overflow); +Int128 APS5_VABI __muloti4_nid_postfix(Int128 a, Int128 b, int* overflow); +std::int32_t APS5_VABI __mulvsi3_nid_postfix(std::int32_t a, std::int32_t b); +std::int64_t APS5_VABI __mulvdi3_nid_postfix(std::int64_t a, std::int64_t b); +Int128 APS5_VABI __mulvti3_nid_postfix(Int128 a, Int128 b); +std::int32_t APS5_VABI __addvsi3_nid_postfix(std::int32_t a, std::int32_t b); +std::int64_t APS5_VABI __addvdi3_nid_postfix(std::int64_t a, std::int64_t b); +Int128 APS5_VABI __addvti3_nid_postfix(Int128 a, Int128 b); +std::int32_t APS5_VABI __subvsi3_nid_postfix(std::int32_t a, std::int32_t b); +std::int64_t APS5_VABI __subvdi3_nid_postfix(std::int64_t a, std::int64_t b); +Int128 APS5_VABI __subvti3_nid_postfix(Int128 a, Int128 b); +std::int32_t APS5_VABI __negvsi2_nid_postfix(std::int32_t value); +std::int64_t APS5_VABI __negvdi2_nid_postfix(std::int64_t value); +Int128 APS5_VABI __negvti2_nid_postfix(Int128 value); +std::int32_t APS5_VABI __absvsi2_nid_postfix(std::int32_t value); +std::int64_t APS5_VABI __absvdi2_nid_postfix(std::int64_t value); +Int128 APS5_VABI __absvti2_nid_postfix(Int128 value); +int APS5_VABI getifaddrs_nid_postfix(GuestInterfaceAddress** list); +void APS5_VABI freeifaddrs_nid_postfix(GuestInterfaceAddress* list); +int APS5_VABI isupper_nid_postfix(int c); +int APS5_VABI islower_nid_postfix(int c); +int APS5_VABI isalpha_nid_postfix(int c); +int APS5_VABI isdigit_nid_postfix(int c); +int APS5_VABI isalnum_nid_postfix(int c); +int APS5_VABI isspace_nid_postfix(int c); +int APS5_VABI isblank_nid_postfix(int c); +int APS5_VABI iscntrl_nid_postfix(int c); +int APS5_VABI isprint_nid_postfix(int c); +int APS5_VABI isgraph_nid_postfix(int c); +int APS5_VABI ispunct_nid_postfix(int c); +int APS5_VABI isxdigit_nid_postfix(int c); +int APS5_VABI isascii_nid_postfix(int c); +int APS5_VABI toascii_nid_postfix(int c); +int APS5_VABI toupper_nid_postfix(int c); +int APS5_VABI tolower_nid_postfix(int c); +void APS5_VABI _ZNSt8ios_baseD2Ev_nid_postfix(GuestLocale::IosBase* self); +GuestLocale::IosBase* APS5_VABI SetStreamWidth(GuestLocale::IosBase* stream, std::int32_t width); +StreamManipulator APS5_VABI _ZSt4setwi_nid_postfix(std::int32_t width); +void APS5_VABI _ZNSt8ios_base7_AddstdEPS__nid_postfix(GuestLocale::IosBase* self); +GuestLocale::Implementation* APS5_VABI _ZNSt6locale5_InitEv_nid_postfix(); +void APS5_VABI _ZNSt6locale5facet9_RegisterEv_nid_postfix(GuestLocale::Facet* self); +GuestLocale::Implementation* APS5_VABI _ZNSt6locale16_GetgloballocaleEv_nid_postfix(); +GuestLocaleFacade* APS5_VABI _ZNSt6locale7classicEv_nid_postfix(); +std::size_t APS5_VABI _ZNSt7collateIwE7_GetcatEPPKNSt6locale5facetEPKS1__nid_postfix(GuestLocale::Facet** facet, const GuestLocale::Implementation* const* locale); +std::size_t APS5_VABI _ZNSt7collateIcE7_GetcatEPPKNSt6locale5facetEPKS1__nid_postfix(GuestLocale::Facet** facet, const GuestLocale::Implementation* const* locale); +void APS5_VABI _ZNSt8_LocinfoC1EPKc_nid_postfix(GuestLocale::LocinfoStorage* self, const char* localeName); +void APS5_VABI _ZNSt8_LocinfoD1Ev_nid_postfix(GuestLocale::LocinfoStorage* self); +int APS5_VABI _Mbtowcx_nid_postfix(std::uint16_t* dst, const char* src, std::size_t count, mbstate_t* st); +int APS5_VABI _Wctombx_nid_postfix(char* dst, std::uint16_t src, mbstate_t* st); +const short* APS5_VABI _Getpctype_nid_postfix(); +const short* APS5_VABI _Getptolower_nid_postfix(); +const short* APS5_VABI _Getptoupper_nid_postfix(); +mbstate_t* APS5_VABI _Getpmbstate_nid_postfix(); +mbstate_t* APS5_VABI _Getpwcstate_nid_postfix(); +std::uint32_t APS5_VABI _Towctrans_nid_postfix(std::uint32_t c, std::uint64_t desc); +void APS5_VABI _ZNSt6locale7_LocimpC1ERKS0__nid_postfix(GuestLocale::Implementation* self, const GuestLocale::Implementation* source); +void APS5_VABI _ZNSt6locale7_Locimp7_AddfacEPNS_5facetEm_nid_postfix(GuestLocale::Implementation* self, GuestLocale::Facet* facet, std::size_t id); +void APS5_VABI _init_env_nid_postfix(); +void APS5_VABI init_env_nid_postfix(const InitEnvParams* params); +SonyLconv* APS5_VABI localeconv_nid_postfix(void); +std::lldiv_t APS5_VABI lldiv_nid_postfix(long long numerator, long long denominator); +std::lldiv_t APS5_VABI ldiv_nid_postfix(std::int64_t numerator, std::int64_t denominator); +std::lldiv_t APS5_VABI imaxdiv_nid_postfix(std::int64_t numerator, std::int64_t denominator); +std::int64_t APS5_VABI labs_nid_postfix(std::int64_t x); +std::int64_t APS5_VABI llabs_nid_postfix(std::int64_t x); +std::int64_t APS5_VABI imaxabs_nid_postfix(std::int64_t x); +float APS5_VABI fmodf_nid_postfix(float x, float y); +float APS5_VABI asinf_nid_postfix(float x); +float APS5_VABI acosf_nid_postfix(float x); +float APS5_VABI atan2f_nid_postfix(float y, float x); +float APS5_VABI hypotf_nid_postfix(float x, float y); +double APS5_VABI hypot_nid_postfix(double x, double y); +float APS5_VABI log10f_nid_postfix(float x); +float APS5_VABI logbf_nid_postfix(float x); +double APS5_VABI exp2_nid_postfix(double x); +double APS5_VABI ldexp_nid_postfix(double x, int exponent); +double APS5_VABI scalbn_nid_postfix(double x, int exponent); +float APS5_VABI scalbnf_nid_postfix(float x, int exponent); +long double APS5_VABI scalbnl_nid_postfix(long double x, int exponent); +float APS5_VABI significandf_nid_postfix(float x); +double APS5_VABI significand_nid_postfix(double x); +double APS5_VABI frexp_nid_postfix(double x, int* exponent); +float APS5_VABI frexpf_nid_postfix(float x, int* exponent); +std::int64_t APS5_VABI lround_nid_postfix(double x); +std::int64_t APS5_VABI lroundf_nid_postfix(float x); +std::int64_t APS5_VABI llround_nid_postfix(double x); +std::int64_t APS5_VABI llroundf_nid_postfix(float x); +std::int64_t APS5_VABI llroundl_nid_postfix(long double x); +int APS5_VABI __isfinitef_nid_postfix(float x); +int APS5_VABI __isnormal_nid_postfix(double x); +int APS5_VABI __isnormalf_nid_postfix(float x); +int APS5_VABI __isinff_nid_postfix(float x); +float APS5_VABI nearbyintf_nid_postfix(float x); +long double APS5_VABI nearbyintl_nid_postfix(long double x); +double APS5_VABI nearbyint_nid_postfix(double x); +double APS5_VABI cbrt_nid_postfix(double x); +double APS5_VABI asin_nid_postfix(double x); +double APS5_VABI acos_nid_postfix(double x); +double APS5_VABI sqrt_nid_postfix(double x); +float APS5_VABI sqrtf_nid_postfix(float x); +double APS5_VABI fabs_nid_postfix(double x); +float APS5_VABI fabsf_nid_postfix(float x); +long double APS5_VABI fabsl_nid_postfix(long double x); +double APS5_VABI copysign_nid_postfix(double x, double y); +float APS5_VABI copysignf_nid_postfix(float x, float y); +int APS5_VABI abs_nid_postfix(int x); +double APS5_VABI trunc_nid_postfix(double x); +double APS5_VABI ceil_nid_postfix(double x); +double APS5_VABI floor_nid_postfix(double x); +float APS5_VABI truncf_nid_postfix(float x); +float APS5_VABI ceilf_nid_postfix(float x); +float APS5_VABI floorf_nid_postfix(float x); +double APS5_VABI fma_nid_postfix(double x, double y, double z); +float APS5_VABI fmaf_nid_postfix(float x, float y, float z); +double APS5_VABI fmin_nid_postfix(double x, double y); +float APS5_VABI fminf_nid_postfix(float x, float y); +long double APS5_VABI fminl_nid_postfix(long double x, long double y); +double APS5_VABI fmax_nid_postfix(double x, double y); +float APS5_VABI fmaxf_nid_postfix(float x, float y); +long double APS5_VABI fmaxl_nid_postfix(long double x, long double y); +double APS5_VABI fdim_nid_postfix(double x, double y); +float APS5_VABI fdimf_nid_postfix(float x, float y); +long double APS5_VABI acosl_nid_postfix(long double x); +long double APS5_VABI acoshl_nid_postfix(long double x); +long double APS5_VABI asinhl_nid_postfix(long double x); +long double APS5_VABI atanhl_nid_postfix(long double x); +long double APS5_VABI atan2l_nid_postfix(long double y, long double x); +long double APS5_VABI cbrtl_nid_postfix(long double x); +long double APS5_VABI erfl_nid_postfix(long double x); +long double APS5_VABI erfcl_nid_postfix(long double x); +long double APS5_VABI expm1l_nid_postfix(long double x); +long double APS5_VABI log1pl_nid_postfix(long double x); +long double APS5_VABI log2l_nid_postfix(long double x); +long double APS5_VABI lgammal_nid_postfix(long double x); +long double APS5_VABI tgammal_nid_postfix(long double x); +float APS5_VABI tgammaf_nid_postfix(float x); +long double APS5_VABI hypotl_nid_postfix(long double x, long double y); +float APS5_VABI hypot3f_nid_postfix(float x, float y, float z); +double APS5_VABI hypot3_nid_postfix(double x, double y, double z); +long double APS5_VABI hypot3l_nid_postfix(long double x, long double y, long double z); +float APS5_VABI j0f_nid_postfix(float x); +float APS5_VABI j1f_nid_postfix(float x); +float APS5_VABI jnf_nid_postfix(int order, float x); +float APS5_VABI y0f_nid_postfix(float x); +float APS5_VABI y1f_nid_postfix(float x); +float APS5_VABI ynf_nid_postfix(int order, float x); +long double APS5_VABI asinl_nid_postfix(long double x); +long double APS5_VABI frexpl_nid_postfix(long double x, int* exponent); +double APS5_VABI exp_nid_postfix(double x); +double APS5_VABI atan_nid_postfix(double x); +double APS5_VABI tan_nid_postfix(double x); +double APS5_VABI log2_nid_postfix(double x); +double APS5_VABI log_nid_postfix(double x); +double APS5_VABI log1p_nid_postfix(double x); +float APS5_VABI log1pf_nid_postfix(float x); +double APS5_VABI expm1_nid_postfix(double x); +float APS5_VABI expm1f_nid_postfix(float x); +float APS5_VABI erff_nid_postfix(float x); +double APS5_VABI erf_nid_postfix(double x); +double APS5_VABI erfc_nid_postfix(double x); +float APS5_VABI erfcf_nid_postfix(float x); +double APS5_VABI lgamma_nid_postfix(double x); +float APS5_VABI sinf_nid_postfix(float x); +float APS5_VABI cosf_nid_postfix(float x); +float APS5_VABI tanf_nid_postfix(float x); +void APS5_VABI sincosf_nid_postfix(float x, float* sinp, float* cosp); +double APS5_VABI sin_nid_postfix(double x); +double APS5_VABI cos_nid_postfix(double x); +double APS5_VABI sinh_nid_postfix(double x); +double APS5_VABI cosh_nid_postfix(double x); +float APS5_VABI coshf_nid_postfix(float x); +float APS5_VABI sinhf_nid_postfix(float x); +double APS5_VABI asinh_nid_postfix(double x); +float APS5_VABI asinhf_nid_postfix(float x); +double APS5_VABI acosh_nid_postfix(double x); +float APS5_VABI acoshf_nid_postfix(float x); +double APS5_VABI atanh_nid_postfix(double x); +float APS5_VABI atanhf_nid_postfix(float x); +void APS5_VABI sincos_nid_postfix(double x, double* sinp, double* cosp); +float APS5_VABI atanf_nid_postfix(float x); +double APS5_VABI atan2_nid_postfix(double y, double x); +float APS5_VABI powf_nid_postfix(float base, float exp); +double APS5_VABI pow_nid_postfix(double base, double exp); +float APS5_VABI __powisf2_nid_postfix(float base, int exponent); +double APS5_VABI __powidf2_nid_postfix(double base, int exponent); +float APS5_VABI expf_nid_postfix(float x); +float APS5_VABI exp2f_nid_postfix(float x); +float APS5_VABI logf_nid_postfix(float x); +float APS5_VABI log2f_nid_postfix(float x); +double APS5_VABI log10_nid_postfix(double x); +float APS5_VABI ldexpf_nid_postfix(float x, int exp); +double APS5_VABI fmod_nid_postfix(double x, double y); +float APS5_VABI roundf_nid_postfix(float x); +double APS5_VABI round_nid_postfix(double x); +float APS5_VABI cbrtf_nid_postfix(float x); +float APS5_VABI remainderf_nid_postfix(float x, float y); +double APS5_VABI _Divide_nid_postfix(double x, double y); +float APS5_VABI _FDivide_nid_postfix(float x, float y); +double APS5_VABI _Recip_nid_postfix(double x); +float APS5_VABI _FRecip_nid_postfix(float x); +float APS5_VABI nextafterf_nid_postfix(float x, float y); +double APS5_VABI nextafter_nid_postfix(double x, double y); +int APS5_VABI __isfinite_nid_postfix(double x); +int APS5_VABI __isnan_nid_postfix(double x); +int APS5_VABI __isinf_nid_postfix(double x); +int APS5_VABI __signbit_nid_postfix(double x); +float APS5_VABI nanf_nid_postfix(const char* tagp); +double APS5_VABI nan_nid_postfix(const char* tagp); +double APS5_VABI modf_nid_postfix(double x, double* integral); +float APS5_VABI modff_nid_postfix(float x, float* integral); +double APS5_VABI tanh_nid_postfix(double x); +float APS5_VABI tanhf_nid_postfix(float x); +long double APS5_VABI atanl_nid_postfix(long double x); +long double APS5_VABI sinl_nid_postfix(long double x); +long double APS5_VABI cosl_nid_postfix(long double x); +long double APS5_VABI tanl_nid_postfix(long double x); +long double APS5_VABI sinhl_nid_postfix(long double x); +long double APS5_VABI coshl_nid_postfix(long double x); +long double APS5_VABI tanhl_nid_postfix(long double x); +long double APS5_VABI expl_nid_postfix(long double x); +long double APS5_VABI exp2l_nid_postfix(long double x); +long double APS5_VABI logl_nid_postfix(long double x); +long double APS5_VABI log10l_nid_postfix(long double x); +long double APS5_VABI powl_nid_postfix(long double base, long double exp); +long double APS5_VABI ldexpl_nid_postfix(long double x, int exp); +long double APS5_VABI truncl_nid_postfix(long double x); +long double APS5_VABI ceill_nid_postfix(long double x); +long double APS5_VABI floorl_nid_postfix(long double x); +double APS5_VABI logb_nid_postfix(double x); +int APS5_VABI ilogb_nid_postfix(double x); +int APS5_VABI ilogbf_nid_postfix(float x); +double APS5_VABI remainder_nid_postfix(double x, double y); +double APS5_VABI remquo_nid_postfix(double x, double y, int* quo); +float APS5_VABI remquof_nid_postfix(float x, float y, int* quo); +float APS5_VABI _FSinh_nid_postfix(float x, float y); +float APS5_VABI _FCosh_nid_postfix(float x, float y); +short APS5_VABI _FDtest_nid_postfix(const float* value); +short APS5_VABI _Dtest_nid_postfix(const double* value); +int APS5_VABI __isnanf_nid_postfix(float x); +int APS5_VABI isnanf_nid_postfix(float x); +int APS5_VABI isnan_nid_postfix(double x); +int APS5_VABI isinf_nid_postfix(double x); +int APS5_VABI __fpclassifyf_nid_postfix(float x); +int APS5_VABI __signbitf_nid_postfix(float x); +int APS5_VABI __signbitl_nid_postfix(long double x); +int APS5_VABI __isfinitel_nid_postfix(long double x); +int APS5_VABI rand_nid_postfix(); +int APS5_VABI rand_r_nid_postfix(unsigned int* state); +void APS5_VABI srand_nid_postfix(unsigned int seed); +int APS5_VABI __fpclassifyd_nid_postfix(double value); +double APS5_VABI _Sinh_nid_postfix(double x, double y); +double APS5_VABI _Cosh_nid_postfix(double x, double y); +int APS5_VABI _Fltrounds_nid_postfix(void); +int APS5_VABI fegetenv_nid_postfix(GuestFloatingPointEnvironment* environment); +long double APS5_VABI copysignl_nid_postfix(long double x, long double y); +long double APS5_VABI fdiml_nid_postfix(long double x, long double y); +long double APS5_VABI fmodl_nid_postfix(long double x, long double y); +long double APS5_VABI remainderl_nid_postfix(long double x, long double y); +long double APS5_VABI remquol_nid_postfix(long double x, long double y, int* quotient); +long double APS5_VABI logbl_nid_postfix(long double x); +int APS5_VABI ilogbl_nid_postfix(long double x); +long double APS5_VABI rintl_nid_postfix(long double x); +long double APS5_VABI roundl_nid_postfix(long double x); +std::int64_t APS5_VABI lroundl_nid_postfix(long double x); +std::int64_t APS5_VABI lrintl_nid_postfix(long double x); +long long APS5_VABI llrintl_nid_postfix(long double x); +long double APS5_VABI sqrtl_nid_postfix(long double x); +long double APS5_VABI modfl_nid_postfix(long double x, long double* integral); +long double APS5_VABI nanl_nid_postfix(const char*); +long double APS5_VABI scalblnl_nid_postfix(long double x, std::int64_t exponent); +long double APS5_VABI fmal_nid_postfix(long double x, long double y, long double z); +double APS5_VABI rint_nid_postfix(double x); +float APS5_VABI rintf_nid_postfix(float x); +std::int64_t APS5_VABI lrint_nid_postfix(double x); +std::int64_t APS5_VABI lrintf_nid_postfix(float x); +long long APS5_VABI llrint_nid_postfix(double x); +long long APS5_VABI llrintf_nid_postfix(float x); +double APS5_VABI drem_nid_postfix(double x, double y); +float APS5_VABI dremf_nid_postfix(float x, float y); +double APS5_VABI scalbln_nid_postfix(double x, std::int64_t exponent); +float APS5_VABI scalblnf_nid_postfix(float x, std::int64_t exponent); +double APS5_VABI scalb_nid_postfix(double x, double exponent); +float APS5_VABI scalbf_nid_postfix(float x, float exponent); +int APS5_VABI finite_nid_postfix(double x); +int APS5_VABI finitef_nid_postfix(float x); +int APS5_VABI __fpclassifyl_nid_postfix(long double x); +int APS5_VABI __isinfl_nid_postfix(long double x); +int APS5_VABI __isnanl_nid_postfix(long double x); +int APS5_VABI __isnormall_nid_postfix(long double x); +short APS5_VABI _LDtest_nid_postfix(const long double* value); +int APS5_VABI _Dclass_nid_postfix(double x); +int APS5_VABI _FDclass_nid_postfix(float x); +int APS5_VABI _LDclass_nid_postfix(long double x); +short APS5_VABI _LDsign_nid_postfix(long double x); +void* APS5_VABI sceLibcMspaceCreate_nid_postfix(const char* name, void* base, std::size_t size, unsigned flags); +int APS5_VABI sceLibcMspaceDestroy_nid_postfix(void* handle); +void* APS5_VABI sceLibcMspaceMalloc_nid_postfix(void* handle, std::size_t size); +void APS5_VABI sceLibcMspaceFree_nid_postfix(void* handle, void* pointer); +void* APS5_VABI sceLibcMspaceCalloc_nid_postfix(void* handle, std::size_t count, std::size_t size); +void* APS5_VABI sceLibcMspaceRealloc_nid_postfix(void* handle, void* pointer, std::size_t size); +int APS5_VABI sceLibcMspacePosixMemalign_nid_postfix(void* handle, void** result, std::size_t alignment, std::size_t size); +void* APS5_VABI sceLibcMspaceMemalign_nid_postfix(void* handle, std::size_t alignment, std::size_t size); +void* APS5_VABI sceLibcMspaceAlignedAlloc_nid_postfix(void* handle, std::size_t alignment, std::size_t size); +void* APS5_VABI sceLibcMspaceReallocalign_nid_postfix(void* handle, void* pointer, std::size_t alignment, std::size_t size); +int APS5_VABI sceLibcMspaceMallocStats_nid_postfix(void* handle, MallocManagedSize* stats); +int APS5_VABI sceLibcMspaceMallocStatsFast_nid_postfix(void* handle, MallocManagedSize* stats); +std::size_t APS5_VABI sceLibcMspaceMallocUsableSize_nid_postfix(const void* pointer); +void* APS5_VABI sceLibcPafMspaceCreate_nid_postfix(const char* name, void* base, std::size_t size, unsigned flags, const void* options); +int APS5_VABI sceLibcPafMspaceDestroy_nid_postfix(void* handle); +void* APS5_VABI sceLibcPafMspaceMalloc_nid_postfix(void* handle, std::size_t size, const void* owner); +void* APS5_VABI sceLibcPafMspaceMemalign_nid_postfix(void* handle, std::size_t alignment, std::size_t size, const void* owner); +void APS5_VABI sceLibcPafMspaceFree_nid_postfix(void* handle, void* pointer, const void* owner); +void* APS5_VABI sceLibcPafMspaceCalloc_nid_postfix(void* handle, std::size_t count, std::size_t size, const void* owner); +void* APS5_VABI sceLibcPafMspaceRealloc_nid_postfix(void* handle, void* pointer, std::size_t size, const void* owner); +void* APS5_VABI sceLibcPafMspaceReallocalign_nid_postfix(void* handle, void* pointer, std::size_t alignment, std::size_t size, const void* owner); +int APS5_VABI sceLibcPafMspacePosixMemalign_nid_postfix(void* handle, void** result, std::size_t alignment, std::size_t size, const void* owner); +int APS5_VABI sceLibcPafMspaceMallocStats_nid_postfix(void* handle, MallocManagedSize* stats); +int APS5_VABI sceLibcPafMspaceMallocStatsFast_nid_postfix(void* handle, MallocManagedSize* stats); +int APS5_VABI ___mb_cur_max_nid_postfix(); +int APS5_VABI _Getmbcurmax_nid_postfix(); +int APS5_VABI mbsinit_nid_postfix(const void* state); +std::size_t APS5_VABI mbrtowc_nid_postfix(std::uint16_t* destination, const char* source, std::size_t count, void* state); +std::size_t APS5_VABI mbrlen_nid_postfix(const char* source, std::size_t count, void* state); +int APS5_VABI mbtowc_nid_postfix(std::uint16_t* destination, const char* source, std::size_t count); +std::size_t APS5_VABI wcrtomb_nid_postfix(char* destination, std::uint16_t value, void*); +int APS5_VABI mblen_nid_postfix(const char* source, std::size_t count); +int APS5_VABI wctomb_nid_postfix(char* destination, std::uint16_t value); +std::size_t APS5_VABI c32rtomb_nid_postfix(char* destination, std::uint32_t value, void*); +std::size_t APS5_VABI c16rtomb_nid_postfix(char* destination, std::uint16_t unit, void* state); +std::size_t APS5_VABI mbrtoc32_nid_postfix(std::uint32_t* destination, const char* source, std::size_t count, void* state); +std::size_t APS5_VABI mbrtoc16_nid_postfix(std::uint16_t* destination, const char* source, std::size_t count, void* state); +std::size_t APS5_VABI wcsrtombs_nid_postfix(char* destination, const std::uint16_t** source, std::size_t capacity, void*); +int APS5_VABI wcsrtombs_s_nid_postfix( std::size_t* result, char* destination, std::size_t capacity, const std::uint16_t** source, std::size_t limit, void* state ); +int APS5_VABI wcstombs_s_nid_postfix( std::size_t* result, char* destination, std::size_t capacity, const std::uint16_t* source, std::size_t limit ); +std::size_t APS5_VABI mbsrtowcs_nid_postfix(std::uint16_t* destination, const char** source, std::size_t capacity, void* state); +std::size_t APS5_VABI mbstowcs_nid_postfix(std::uint16_t* dest, const char* src, std::size_t size); +void APS5_VABI exit_nid_postfix(int code); +int* APS5_VABI libc_error_nid_postfix(); +int* APS5_VABI __error_nid_postfix(); +int APS5_VABI atexit_nid_postfix(GuestExitCallback func); +int APS5_VABI at_quick_exit_nid_postfix(GuestExitCallback func); +int APS5_VABI daemon_nid_postfix(int noChdir, int noClose); +double APS5_VABI erand48_nid_postfix(std::uint16_t* seed); +std::int64_t APS5_VABI nrand48_nid_postfix(std::uint16_t* seed); +std::int64_t APS5_VABI jrand48_nid_postfix(std::uint16_t* seed); +double APS5_VABI drand48_nid_postfix(); +std::int64_t APS5_VABI lrand48_nid_postfix(); +std::int64_t APS5_VABI mrand48_nid_postfix(); +void APS5_VABI srand48_nid_postfix(std::int64_t seedval); +std::uint16_t* APS5_VABI seed48_nid_postfix(const std::uint16_t* seed); +void APS5_VABI lcong48_nid_postfix(const std::uint16_t* parameters); +std::int64_t APS5_VABI random_nid_postfix(); +void APS5_VABI srandom_nid_postfix(std::uint64_t seed); +char* APS5_VABI initstate_nid_postfix(std::uint64_t seed, char* state, std::int64_t size); +char* APS5_VABI setstate_nid_postfix(char* state); +char* APS5_VABI realpath_nid_postfix(const char* path, char* resolved); +int APS5_VABI rename_nid_postfix(const char* from, const char* to); +int APS5_VABI iswalnum_nid_postfix(std::uint32_t c); +int APS5_VABI iswalpha_nid_postfix(std::uint32_t c); +int APS5_VABI iswblank_nid_postfix(std::uint32_t c); +int APS5_VABI iswcntrl_nid_postfix(std::uint32_t c); +int APS5_VABI iswdigit_nid_postfix(std::uint32_t c); +int APS5_VABI iswgraph_nid_postfix(std::uint32_t c); +int APS5_VABI iswlower_nid_postfix(std::uint32_t c); +int APS5_VABI iswprint_nid_postfix(std::uint32_t c); +int APS5_VABI iswpunct_nid_postfix(std::uint32_t c); +int APS5_VABI iswspace_nid_postfix(std::uint32_t c); +int APS5_VABI iswupper_nid_postfix(std::uint32_t c); +int APS5_VABI iswxdigit_nid_postfix(std::uint32_t c); +int APS5_VABI iswascii_nid_postfix(std::uint32_t c); +int APS5_VABI iswctype_nid_postfix(std::uint32_t c, std::uint64_t mask); +int APS5_VABI _Iswctype_nid_postfix(std::uint32_t c, std::uint64_t type); +std::uint64_t APS5_VABI wctype_nid_postfix(const char* property); +std::uint32_t APS5_VABI towlower_nid_postfix(std::uint32_t c); +std::uint32_t APS5_VABI towupper_nid_postfix(std::uint32_t c); +std::uint32_t APS5_VABI btowc_nid_postfix(int c); +int APS5_VABI wctob_nid_postfix(std::uint32_t c); +std::uint64_t APS5_VABI wctrans_nid_postfix(const char* property); +std::uint32_t APS5_VABI towctrans_nid_postfix(std::uint32_t c, std::uint64_t desc); +std::uint32_t APS5_VABI _Towlower_nid_postfix(std::uint32_t c, const void*); +std::uint32_t APS5_VABI _Towupper_nid_postfix(std::uint32_t c, const void*); +int APS5_VABI _Tolower_nid_postfix(int c, const void*); +int APS5_VABI _Toupper_nid_postfix(int c, const void*); +int APS5_VABI __cxa_atexit_nid_postfix(void (APS5_VABI *func)(void*), void* arg, void* dsoHandle); +int APS5_VABI cxa_atexit_nid_postfix(void (APS5_VABI *func)(void*), void* arg, void* dsoHandle); +void APS5_VABI cxa_finalize_nid_postfix(void* dsoHandle); +void APS5_VABI _Vacopy_nid_postfix(unsigned char* destination, const unsigned char* source); +unsigned int APS5_VABI _Atomic_fetch_add_4_nid_postfix(volatile unsigned int* target, unsigned int value, int memoryOrder); +unsigned int APS5_VABI _Atomic_fetch_sub_4_nid_postfix(volatile unsigned int* target, unsigned int value, int memoryOrder); +int APS5_VABI _Atomic_compare_exchange_weak_4_nid_postfix(volatile unsigned int* target, unsigned int* expected, unsigned int desired, int successOrder, int failureOrder); +unsigned int APS5_VABI _Atomic_load_4_nid_postfix(volatile unsigned int* target, int memoryOrder); +std::intmax_t APS5_VABI strtoimax_nid_postfix(const char* str, char** endptr, int base); +std::uintmax_t APS5_VABI strtoumax_nid_postfix(const char* str, char** endptr, int base); +unsigned int APS5_VABI _ZSt14_Random_devicev_nid_postfix(); +void APS5_VABI _Lockfilelock_nid_postfix(FileStream* stream); +void APS5_VABI _Unlockfilelock_nid_postfix(FileStream* stream); +void APS5_VABI flockfile_nid_postfix(FileStream* stream); +void APS5_VABI funlockfile_nid_postfix(FileStream* stream); +int APS5_VABI ftrylockfile_nid_postfix(FileStream* stream); +std::uint64_t APS5_VABI _Stoul_nid_postfix(const char* str, char** endptr, int base); +void APS5_VABI _Locksyslock_nid_postfix(); +void APS5_VABI _Unlocksyslock_nid_postfix(); +__int128 APS5_VABI __divti3_nid_postfix(__int128 dividend, __int128 divisor); +unsigned __int128 APS5_VABI __udivti3_nid_postfix(unsigned __int128 dividend, unsigned __int128 divisor); +unsigned __int128 APS5_VABI __umodti3_nid_postfix(unsigned __int128 dividend, unsigned __int128 divisor); +__int128 APS5_VABI __modti3_nid_postfix(__int128 dividend, __int128 divisor); +int APS5_VABI swscanf_nid_postfix(const char16_t* buffer, const char16_t* format, ...); +int APS5_VABI swscanf_s_nid_postfix(const char16_t* buffer, const char16_t* format, ...); +int APS5_VABI vswscanf_nid_postfix(const char16_t* buffer, const char16_t* format, VaList* args); +int APS5_VABI vswscanf_s_nid_postfix(const char16_t* buffer, const char16_t* format, VaList* args); +int APS5_VABI vfwscanf_nid_postfix(FileStream* stream, const char16_t* format, VaList* args); +int APS5_VABI vfwscanf_s_nid_postfix(FileStream* stream, const char16_t* format, VaList* args); +int APS5_VABI vwscanf_nid_postfix(const char16_t* format, VaList* args); +int APS5_VABI vwscanf_s_nid_postfix(const char16_t* format, VaList* args); +int APS5_VABI fwscanf_nid_postfix(FileStream* stream, const char16_t* format, ...); +int APS5_VABI fwscanf_s_nid_postfix(FileStream* stream, const char16_t* format, ...); +int APS5_VABI wscanf_nid_postfix(const char16_t* format, ...); +int APS5_VABI wscanf_s_nid_postfix(const char16_t* format, ...); +int APS5_VABI fgetc_nid_postfix(FileStream* stream); +std::int32_t APS5_VABI fgetwc_nid_postfix(FileStream* stream); +std::int32_t APS5_VABI ungetwc_nid_postfix(std::int32_t value, FileStream* stream); +int APS5_VABI getc_nid_postfix(FileStream* stream); +int APS5_VABI getc_unlocked_nid_postfix(FileStream* stream); +int APS5_VABI __srget_nid_postfix(FileStream* stream); +int APS5_VABI getchar_nid_postfix(); +char* APS5_VABI gets_nid_postfix(char* buffer); +std::int32_t APS5_VABI getwc_nid_postfix(FileStream* stream); +std::int32_t APS5_VABI getwchar_nid_postfix(); +int APS5_VABI getchar_unlocked_nid_postfix(); +int APS5_VABI fputc_nid_postfix(int value, FileStream* stream); +int APS5_VABI putc_nid_postfix(int value, FileStream* stream); +int APS5_VABI putc_unlocked_nid_postfix(int value, FileStream* stream); +int APS5_VABI __swbuf_nid_postfix(int value, FileStream* stream); +int APS5_VABI putchar_nid_postfix(int value); +int APS5_VABI putchar_unlocked_nid_postfix(int value); +int APS5_VABI ungetc_nid_postfix(int value, FileStream* stream); +char* APS5_VABI fgets_nid_postfix(char* buffer, int size, FileStream* stream); +int APS5_VABI feof_nid_postfix(FileStream* stream); +int APS5_VABI ferror_nid_postfix(FileStream* stream); +int APS5_VABI feof_unlocked_nid_postfix(FileStream* stream); +int APS5_VABI ferror_unlocked_nid_postfix(FileStream* stream); +void APS5_VABI clearerr_nid_postfix(FileStream* stream); +int APS5_VABI fileno_nid_postfix(FileStream* stream); +void APS5_VABI clearerr_unlocked_nid_postfix(FileStream* stream); +int APS5_VABI fileno_unlocked_nid_postfix(FileStream* stream); +int APS5_VABI setvbuf_nid_postfix(FileStream* stream, char* buffer, int mode, std::size_t size); +void APS5_VABI setbuf_nid_postfix(FileStream* stream, char* buffer); +const char* APS5_VABI setlocale_nid_postfix(int, const char* locale); +GuestNewHandler APS5_VABI _ZSt15set_new_handlerPFvvE_nid_postfix(GuestNewHandler handler); +GuestNewHandler APS5_VABI _ZSt15get_new_handlerv_nid_postfix(); +void* APS5_VABI _Znwm_nid_postfix(std::size_t size); +void* APS5_VABI _Znam_nid_postfix(std::size_t size); +void* APS5_VABI _ZnwmSt11align_val_t_nid_postfix(std::size_t size, std::size_t alignment); +void* APS5_VABI _ZnwmRKSt9nothrow_t_nid_postfix(std::size_t size, const void*) noexcept; +void* APS5_VABI _ZnamRKSt9nothrow_t_nid_postfix(std::size_t size, const void*) noexcept; +void APS5_VABI _ZdlPv_nid_postfix(void* pointer); +void APS5_VABI _ZdlPvRKSt9nothrow_t_nid_postfix(void* pointer, const void*) noexcept; +void APS5_VABI _ZdaPv_nid_postfix(void* pointer); +void APS5_VABI _ZdlPvm_nid_postfix(void* pointer, std::size_t); +void APS5_VABI _ZdaPvm_nid_postfix(void* pointer, std::size_t); +void APS5_VABI _ZdlPvSt11align_val_t_nid_postfix(void* pointer, std::size_t alignment); +void APS5_VABI _ZdlPvmSt11align_val_t_nid_postfix(void* pointer, std::size_t, std::size_t alignment); +long long APS5_VABI strtonum_nid_postfix(const char* text, long long minimum, long long maximum, const char** error); +char* APS5_VABI basename_r_nid_postfix(const char* path, char* buffer); +char* APS5_VABI basename_nid_postfix(const char* path); +char* APS5_VABI __inet_ntoa_nid_postfix(unsigned int address); +char* APS5_VABI dirname_nid_postfix(const char* path); +std::size_t APS5_VABI strnlen_nid_postfix(const char* text, std::size_t limit); +std::size_t APS5_VABI strnlen_s_nid_postfix(const char* text, std::size_t limit); +char* APS5_VABI strsep_nid_postfix(char** text, const char* delimiters); +char* APS5_VABI strncat_nid_postfix(char* destination, const char* source, std::size_t limit); +char* APS5_VABI strpbrk_nid_postfix(const char* text, const char* accept); +std::size_t APS5_VABI strcspn_nid_postfix(const char* text, const char* reject); +std::size_t APS5_VABI strlcat_nid_postfix(char* destination, const char* source, std::size_t capacity); +char* APS5_VABI stpcpy_nid_postfix(char* destination, const char* source); +char* APS5_VABI strtok_r_nid_postfix(char* text, const char* delimiters, char** state); +char* APS5_VABI strtok_nid_postfix(char* text, const char* delimiters); +int APS5_VABI __inet_aton_nid_postfix(const char* text, void* address); +std::uint32_t APS5_VABI __inet_addr_nid_postfix(const char* text); +void* APS5_VABI memset_nid_postfix(void* s, int c, size_t n); +void APS5_VABI bzero_nid_postfix(void* destination, size_t count); +void APS5_VABI bcopy_nid_postfix(const void* source, void* destination, size_t count); +void* APS5_VABI memcpy_nid_postfix(void* dest, const void* src, size_t n); +void* APS5_VABI memmove_nid_postfix(void* dest, const void* src, size_t n); +int APS5_VABI memcmp_nid_postfix(const void* s1, const void* s2, size_t n); +const void* APS5_VABI memchr_nid_postfix(const void* s, int c, size_t n); +void* APS5_VABI memrchr_nid_postfix(const void* s, int c, size_t n); +void* APS5_VABI memccpy_nid_postfix(void* dest, const void* src, int c, size_t n); +void* APS5_VABI memmem_nid_postfix(const void* haystack, size_t haystacklen, const void* needle, size_t needlelen); +int APS5_VABI strcmp_nid_postfix(const char* s1, const char* s2); +int APS5_VABI strncmp_nid_postfix(const char* s1, const char* s2, size_t n); +size_t APS5_VABI strlen_nid_postfix(const char* s); +char* APS5_VABI strcpy_nid_postfix(char* dest, const char* src); +char* APS5_VABI strncpy_nid_postfix(char* dest, const char* src, size_t count); +char* APS5_VABI strcat_nid_postfix(char* dest, const char* src); +const char* APS5_VABI strchr_nid_postfix(const char* s, int c); +char* APS5_VABI index_nid_postfix(const char* s, int c); +char* APS5_VABI strrchr_nid_postfix(const char* s, int c); +char* APS5_VABI rindex_nid_postfix(const char* s, int c); +int APS5_VABI flsl_nid_postfix(std::int64_t mask); +char* APS5_VABI strstr_nid_postfix(const char* haystack, const char* needle); +size_t APS5_VABI strlcpy_nid_postfix(char* dest, const char* src, size_t size); +std::int64_t APS5_VABI strtol_nid_postfix(const char* str, char** endptr, int base); +std::uint64_t APS5_VABI strtoul_nid_postfix(const char* str, char** endptr, int base); +long long APS5_VABI strtoll_nid_postfix(const char* str, char** endptr, int base); +unsigned long long APS5_VABI strtoull_nid_postfix(const char* str, char** endptr, int base); +unsigned long long APS5_VABI strtouq_nid_postfix(const char* str, char** endptr, int base); +double APS5_VABI strtod_nid_postfix(const char* str, char** endptr); +double APS5_VABI atof_nid_postfix(const char* str); +float APS5_VABI strtof_nid_postfix(const char* str, char** endptr); +long double APS5_VABI strtold_nid_postfix(const char* str, char** endptr); +int APS5_VABI atoi_nid_postfix(const char* str); +std::int64_t APS5_VABI atol_nid_postfix(const char* str); +long long APS5_VABI atoll_nid_postfix(const char* str); +std::div_t APS5_VABI div_nid_postfix(int numerator, int denominator); +const char16_t* APS5_VABI wmemchr_nid_postfix(const char16_t* s, char16_t c, size_t n); +int APS5_VABI wmemcmp_nid_postfix(const char16_t* s1, const char16_t* s2, size_t n); +char16_t* APS5_VABI wmemcpy_nid_postfix(char16_t* dest, const char16_t* src, size_t n); +char16_t* APS5_VABI wmemmove_nid_postfix(char16_t* dest, const char16_t* src, size_t n); +int APS5_VABI strcasecmp_nid_postfix(const char* s1, const char* s2); +int APS5_VABI strncasecmp_nid_postfix(const char* s1, const char* s2, size_t n); +int APS5_VABI bcmp_nid_postfix(const void* s1, const void* s2, size_t n); +size_t APS5_VABI strspn_nid_postfix(const char* s, const char* accept); +int APS5_VABI strcoll_nid_postfix(const char* s1, const char* s2); +int APS5_VABI strncpy_s_nid_postfix(char* dest, size_t destsz, const char* src, size_t count); +int APS5_VABI strcpy_s_nid_postfix(char* dest, size_t destsz, const char* src); +int APS5_VABI strncat_s_nid_postfix(char* dest, size_t destsz, const char* src, size_t count); +int APS5_VABI strcat_s_nid_postfix(char* dest, size_t destsz, const char* src); +int APS5_VABI memcpy_s_nid_postfix(void* dest, size_t destsz, const void* src, size_t count); +int APS5_VABI memmove_s_nid_postfix(void* dest, size_t destsz, const void* src, size_t count); +int APS5_VABI memset_s_nid_postfix(void* dest, size_t destsz, int value, size_t count); +char* APS5_VABI strnstr_nid_postfix(const char* haystack, const char* needle, size_t length); +unsigned long long APS5_VABI _Stoull_nid_postfix(const char* str, char** endptr, int base); +size_t APS5_VABI wcslen_nid_postfix(const char16_t* s); +size_t APS5_VABI wcsnlen_s_nid_postfix(const char16_t* s, size_t maxlen); +int APS5_VABI wcscmp_nid_postfix(const char16_t* s1, const char16_t* s2); +int APS5_VABI wcsncmp_nid_postfix(const char16_t* s1, const char16_t* s2, size_t n); +char16_t* APS5_VABI wcscpy_nid_postfix(char16_t* dest, const char16_t* src); +char16_t* APS5_VABI wcscat_nid_postfix(char16_t* dest, const char16_t* src); +char16_t* APS5_VABI wcsncpy_nid_postfix(char16_t* dest, const char16_t* src, size_t n); +const char16_t* APS5_VABI wcschr_nid_postfix(const char16_t* s, char16_t c); +const char16_t* APS5_VABI wcsrchr_nid_postfix(const char16_t* s, char16_t c); +const char16_t* APS5_VABI wcsstr_nid_postfix(const char16_t* haystack, const char16_t* needle); +const char16_t* APS5_VABI wcspbrk_nid_postfix(const char16_t* s, const char16_t* accept); +size_t APS5_VABI wcsspn_nid_postfix(const char16_t* s, const char16_t* accept); +size_t APS5_VABI wcscspn_nid_postfix(const char16_t* s, const char16_t* reject); +char16_t* APS5_VABI wcstok_nid_postfix(char16_t* text, const char16_t* delimiters, char16_t** last); +char16_t* APS5_VABI wmemset_nid_postfix(char16_t* s, char16_t c, size_t n); +double APS5_VABI wcstod_nid_postfix(const char16_t* str, char16_t** endptr); +float APS5_VABI wcstof_nid_postfix(const char16_t* str, char16_t** endptr); +long double APS5_VABI wcstold_nid_postfix(const char16_t* str, char16_t** endptr); +unsigned long long APS5_VABI wcstoul_nid_postfix(const char16_t* str, char16_t** endptr, int base); +unsigned long long APS5_VABI wcstoull_nid_postfix(const char16_t* str, char16_t** endptr, int base); +long long APS5_VABI wcstoll_nid_postfix(const char16_t* str, char16_t** endptr, int base); +long long APS5_VABI wcstol_nid_postfix(const char16_t* str, char16_t** endptr, int base); +long long APS5_VABI wcstoimax_nid_postfix(const char16_t* str, char16_t** endptr, int base); +unsigned long long APS5_VABI wcstoumax_nid_postfix(const char16_t* str, char16_t** endptr, int base); +std::uint64_t APS5_VABI _WStoul_nid_postfix(const char16_t* str, char16_t** endptr, int base); +int APS5_VABI wcscoll_nid_postfix(const char16_t* first, const char16_t* second); +size_t APS5_VABI wcsxfrm_nid_postfix(char16_t* destination, const char16_t* source, size_t count); +size_t APS5_VABI strxfrm_nid_postfix(char* destination, const char* source, size_t count); +char* APS5_VABI strtok_s_nid_postfix(char* str, const char* delim, char** context); +int APS5_VABI wmemcpy_s_nid_postfix(char16_t* dest, size_t destsz, const char16_t* src, size_t count); +int APS5_VABI wmemmove_s_nid_postfix(char16_t* dest, size_t destsz, const char16_t* src, size_t count); +int APS5_VABI wcsncpy_s_nid_postfix(char16_t* dest, size_t destsz, const char16_t* src, size_t count); +char16_t* APS5_VABI wcsncat_nid_postfix(char16_t* dest, const char16_t* src, size_t n); +int APS5_VABI wcsncat_s_nid_postfix(char16_t* dest, size_t destsz, const char16_t* src, size_t count); +int APS5_VABI wcscat_s_nid_postfix(char16_t* dest, size_t destsz, const char16_t* src); +void APS5_VABI openlog_nid_postfix(const char* identity, int options, int facility); +void APS5_VABI closelog_nid_postfix(); +int APS5_VABI setlogmask_nid_postfix(int mask); +void APS5_VABI vsyslog_nid_postfix(int priority, const char* format, VaList* args); +void APS5_VABI syslog_nid_postfix(int priority, const char* format, ...); +int APS5_VABI _Mtx_init_nid_postfix(void** handle, int type); +int APS5_VABI _Mtx_init_with_name_nid_postfix(void** handle, int type, const char*); +void APS5_VABI _Mtx_destroy_nid_postfix(void** handle); +int APS5_VABI _Mtx_lock_nid_postfix(void** handle); +int APS5_VABI _Mtx_trylock_nid_postfix(void** handle); +int APS5_VABI _Mtx_unlock_nid_postfix(void** handle); +int APS5_VABI _Cnd_init_nid_postfix(void** handle); +int APS5_VABI _Cnd_init_with_default_name_override_nid_postfix(void** handle, const char*); +void APS5_VABI _Cnd_destroy_nid_postfix(void** handle); +int APS5_VABI _Cnd_wait_nid_postfix(void** conditionHandle, void** mutexHandle); +int APS5_VABI _Cnd_timedwait_nid_postfix(void** conditionHandle, void** mutexHandle, const Xtime* target); +int APS5_VABI _Cnd_broadcast_nid_postfix(void** handle); +unsigned APS5_VABI _ZNSt6thread20hardware_concurrencyEv_nid_postfix(); +int APS5_VABI _Thrd_sleep_nid_postfix(const Xtime* target, Xtime*); +int APS5_VABI _Thrd_yield_nid_postfix(); +int APS5_VABI _Cnd_signal_nid_postfix(void** handle); +void APS5_VABI _ZNSt4_PadC2Ev_nid_postfix(GuestPad* pad); +void APS5_VABI _ZNSt4_PadD2Ev_nid_postfix(GuestPad* pad); +void APS5_VABI _ZNSt4_Pad8_ReleaseEv_nid_postfix(GuestPad* pad); +void APS5_VABI _ZNSt4_Pad7_LaunchEPP7pthread_nid_postfix(GuestPad* pad, void** thread); +int APS5_VABI _Thrd_join_nid_postfix(void* thread, int* code); +int APS5_VABI _Thrd_detach_nid_postfix(void* thread); +int APS5_VABI _Thrd_id_nid_postfix(void); +void APS5_VABI _Call_once_nid_postfix(std::int32_t* flag, void (APS5_VABI* function)(void)); +int APS5_VABI _Tss_create_nid_postfix(int* key, void (APS5_VABI* destructor)(void*)); +int APS5_VABI _Tss_delete_nid_postfix(int key); +void* APS5_VABI _Tss_get_nid_postfix(int key); +int APS5_VABI _Tss_set_nid_postfix(int key, void* value); +int APS5_VABI _Thrd_equal_nid_postfix(void* first, void* second); +void* APS5_VABI _Thrd_current_nid_postfix(void); +int APS5_VABI _Mtx_current_owns_nid_postfix(void**); +int APS5_VABI _ZNSt8__sce_v219_Mtx_init_with_nameEPP13pthread_mutexiPKc_nid_postfix(void** mutex, int type, const char* name); +int APS5_VABI _ZNSt8__sce_v29_Mtx_initEPP13pthread_mutexi_nid_postfix(void** mutex, int type); +int APS5_VABI _ZNSt8__sce_v212_Mtx_destroyEPP13pthread_mutex_nid_postfix(void** mutex); +int APS5_VABI _ZNSt8__sce_v29_Mtx_lockEPP13pthread_mutex_nid_postfix(void** mutex); +int APS5_VABI _ZNSt8__sce_v212_Mtx_trylockEPP13pthread_mutex_nid_postfix(void** mutex); +int APS5_VABI _ZNSt8__sce_v211_Mtx_unlockEPP13pthread_mutex_nid_postfix(void** mutex); +int APS5_VABI _ZNSt8__sce_v219_Cnd_init_with_nameEPP12pthread_condPKc_nid_postfix(void** condition, const char* name); +int APS5_VABI _ZNSt8__sce_v29_Cnd_initEPP12pthread_cond_nid_postfix(void** condition); +int APS5_VABI _ZNSt8__sce_v212_Cnd_destroyEPP12pthread_cond_nid_postfix(void** condition); +int APS5_VABI _ZNSt8__sce_v29_Cnd_waitEPP12pthread_condPP13pthread_mutex_nid_postfix(void** condition, void** mutex); +int APS5_VABI _ZNSt8__sce_v211_Cnd_signalEPP12pthread_cond_nid_postfix(void** condition); +int APS5_VABI _ZNSt8__sce_v214_Cnd_broadcastEPP12pthread_cond_nid_postfix(void** condition); +int APS5_VABI _ZNSt8__sce_v212_Thrd_detachEP7pthread_nid_postfix(void* thread); +int APS5_VABI _ZNSt8__sce_v210_Thrd_joinEP7pthreadPi_nid_postfix(void* thread, int* code); +void APS5_VABI _ZNSt8__sce_v211_Thrd_yieldEv_nid_postfix(); +void* APS5_VABI _ZNSt8__sce_v28_Thrd_idEv_nid_postfix(); +void APS5_VABI tzset_nid_postfix(void); +int64_t APS5_VABI libc_time_nid_postfix(int64_t* timer); +int64_t APS5_VABI time_nid_postfix(int64_t* timer); +int64_t APS5_VABI _Xtime_get_ticks_nid_postfix(); +double APS5_VABI libc_difftime_nid_postfix(int64_t time1, int64_t time0); +double APS5_VABI difftime_nid_postfix(int64_t time1, int64_t time0); +GuestTm* APS5_VABI libc_gmtime_nid_postfix(const int64_t* timer); +GuestTm* APS5_VABI libc_localtime_nid_postfix(const int64_t* timer); +GuestTm* APS5_VABI localtime_nid_postfix(const int64_t* timer); +GuestTm* APS5_VABI gmtime_s_nid_postfix(const int64_t* timer, GuestTm* result); +GuestTm* APS5_VABI gmtime_nid_postfix(const int64_t* timer); +int64_t APS5_VABI libc_mktime_nid_postfix(GuestTm* timeptr); +int64_t APS5_VABI mktime_nid_postfix(GuestTm* timeptr); +size_t APS5_VABI libc_strftime_nid_postfix(char* str, size_t count, const char* format, const GuestTm* timeptr); +char* APS5_VABI asctime_nid_postfix(const GuestTm* timeptr); +char* APS5_VABI ctime_nid_postfix(const int64_t* timer); +size_t APS5_VABI strftime_nid_postfix(char* str, size_t count, const char* format, const GuestTm* timeptr); +size_t APS5_VABI wcsftime_nid_postfix(std::uint16_t* str, size_t count, const std::uint16_t* format, const GuestTm* timeptr); +int64_t APS5_VABI clock_nid_postfix(); +int APS5_VABI ctime_s_nid_postfix(char* buffer, std::size_t size, const std::int64_t* time); +int APS5_VABI asctime_s_nid_postfix(char* buffer, std::size_t size, const GuestTm* time); +GuestTm* APS5_VABI gmtime_r_nid_postfix(const std::int64_t* timer, GuestTm* result); +GuestTm* APS5_VABI localtime_r_nid_postfix(const std::int64_t* timer, GuestTm* result); +std::int64_t APS5_VABI timegm_nid_postfix(GuestTm* time); +int APS5_VABI xtime_get_nid_postfix(Xtime* time, int base); +Xtime APS5_VABI _Xtime_to_ts_nid_postfix(const Xtime* time); +Xtime APS5_VABI _Xtime_diff_to_ts_nid_postfix(const Xtime* target); +const void* APS5_VABI __std_find_trivial_1_nid_postfix(const void* first, const void* last, std::uint8_t value); +const void* APS5_VABI __std_find_trivial_2_nid_postfix(const void* first, const void* last, std::uint16_t value); +const void* APS5_VABI __std_find_trivial_4_nid_postfix(const void* first, const void* last, std::uint32_t value); +const void* APS5_VABI __std_find_trivial_8_nid_postfix(const void* first, const void* last, std::uint64_t value); +const void* APS5_VABI __std_find_trivial_unsized_1_nid_postfix(const void* first, std::uint8_t value); +const void* APS5_VABI __std_find_trivial_unsized_2_nid_postfix(const void* first, std::uint16_t value); +const void* APS5_VABI __std_find_trivial_unsized_4_nid_postfix(const void* first, std::uint32_t value); +const void* APS5_VABI __std_find_trivial_unsized_8_nid_postfix(const void* first, std::uint64_t value); +std::size_t APS5_VABI __std_count_trivial_1_nid_postfix(const void* first, const void* last, std::uint8_t value); +std::size_t APS5_VABI __std_count_trivial_2_nid_postfix(const void* first, const void* last, std::uint16_t value); +std::size_t APS5_VABI __std_count_trivial_4_nid_postfix(const void* first, const void* last, std::uint32_t value); +std::size_t APS5_VABI __std_count_trivial_8_nid_postfix(const void* first, const void* last, std::uint64_t value); +const void* APS5_VABI __std_min_element_1_nid_postfix(const void* first, const void* last, bool isSigned); +const void* APS5_VABI __std_min_element_2_nid_postfix(const void* first, const void* last, bool isSigned); +const void* APS5_VABI __std_min_element_4_nid_postfix(const void* first, const void* last, bool isSigned); +const void* APS5_VABI __std_min_element_8_nid_postfix(const void* first, const void* last, bool isSigned); +const void* APS5_VABI __std_max_element_1_nid_postfix(const void* first, const void* last, bool isSigned); +const void* APS5_VABI __std_max_element_2_nid_postfix(const void* first, const void* last, bool isSigned); +const void* APS5_VABI __std_max_element_4_nid_postfix(const void* first, const void* last, bool isSigned); +const void* APS5_VABI __std_max_element_8_nid_postfix(const void* first, const void* last, bool isSigned); +MinMaxPointers APS5_VABI __std_minmax_element_1_nid_postfix(const void* first, const void* last, bool isSigned); +MinMaxPointers APS5_VABI __std_minmax_element_2_nid_postfix(const void* first, const void* last, bool isSigned); +MinMaxPointers APS5_VABI __std_minmax_element_4_nid_postfix(const void* first, const void* last, bool isSigned); +MinMaxPointers APS5_VABI __std_minmax_element_8_nid_postfix(const void* first, const void* last, bool isSigned); +void APS5_VABI __std_reverse_trivially_swappable_1_nid_postfix(void* first, void* last); +void APS5_VABI __std_reverse_trivially_swappable_2_nid_postfix(void* first, void* last); +void APS5_VABI __std_reverse_trivially_swappable_4_nid_postfix(void* first, void* last); +void APS5_VABI __std_reverse_trivially_swappable_8_nid_postfix(void* first, void* last); +void APS5_VABI __std_reverse_copy_trivially_copyable_1_nid_postfix(const void* first, const void* last, void* destination); +void APS5_VABI __std_reverse_copy_trivially_copyable_2_nid_postfix(const void* first, const void* last, void* destination); +void APS5_VABI __std_reverse_copy_trivially_copyable_4_nid_postfix(const void* first, const void* last, void* destination); +void APS5_VABI __std_reverse_copy_trivially_copyable_8_nid_postfix(const void* first, const void* last, void* destination); +void APS5_VABI __std_swap_ranges_trivially_swappable_noalias_nid_postfix(void* first1, void* last1, void* first2); +void APS5_VABI ignore_handler_s_nid_postfix(const char* message, void* pointer, int error); +void* APS5_VABI set_constraint_handler_s_nid_postfix(void* handler); +std::size_t APS5_VABI wcstombs_nid_postfix(char* destination, const std::uint16_t* source, std::size_t capacity); +int APS5_VABI wcscpy_s_nid_postfix(std::uint16_t* dest, std::size_t size, const std::uint16_t* src); +std::size_t APS5_VABI strerrorlen_s_nid_postfix(int error); +int APS5_VABI strerror_s_nid_postfix(char* buffer, std::size_t capacity, int error); +void APS5_VABI __cxa_vec_cleanup_nid_postfix(void* array, std::size_t count, std::size_t size, void (APS5_VABI *destroy)(void*)); +void APS5_VABI __cxa_vec_ctor_nid_postfix(void* array, std::size_t count, std::size_t size, void (APS5_VABI *construct)(void*), void (APS5_VABI *destroy)(void*)); +void APS5_VABI __cxa_vec_cctor_nid_postfix(void* destination, void* source, std::size_t count, std::size_t size, void (APS5_VABI *copy)(void*, void*), void (APS5_VABI *destroy)(void*)); +void APS5_VABI __cxa_vec_dtor_nid_postfix(void* array, std::size_t count, std::size_t size, void (APS5_VABI *destroy)(void*)); +void* APS5_VABI __cxa_vec_new_nid_postfix(std::size_t n, std::size_t s, std::size_t p, void (APS5_VABI *ctor)(void*), void (APS5_VABI *dtor)(void*)); +void* APS5_VABI __cxa_vec_new2_nid_postfix(std::size_t n, std::size_t s, std::size_t p, void (APS5_VABI *ctor)(void*), void (APS5_VABI *dtor)(void*), void* (APS5_VABI *alloc)(std::size_t), void (APS5_VABI *dealloc)(void*)); +void* APS5_VABI __cxa_vec_new3_nid_postfix(std::size_t n, std::size_t s, std::size_t p, void (APS5_VABI *ctor)(void*), void (APS5_VABI *dtor)(void*), void* (APS5_VABI *alloc)(std::size_t), void (APS5_VABI *dealloc)(void*, std::size_t)); +void APS5_VABI __cxa_vec_delete_nid_postfix(void* array, std::size_t s, std::size_t p, void (APS5_VABI *dtor)(void*)); +void APS5_VABI __cxa_vec_delete2_nid_postfix(void* array, std::size_t s, std::size_t p, void (APS5_VABI *dtor)(void*), void (APS5_VABI *dealloc)(void*)); +void APS5_VABI __cxa_vec_delete3_nid_postfix(void* array, std::size_t s, std::size_t p, void (APS5_VABI *dtor)(void*), void (APS5_VABI *dealloc)(void*, std::size_t)); +#ifndef _LIBCPP_VERSION +void APS5_VABI _ZNSt13__future_base12_Result_baseD2Ev_nid_postfix(std::__future_base::_Result_base* self) noexcept; +#endif +void APS5_VABI _ZNSt15__exception_ptr13exception_ptr9_M_addrefEv_nid_postfix(GuestExceptionPointer* self) noexcept; +void APS5_VABI _ZNSt15__exception_ptr13exception_ptr10_M_releaseEv_nid_postfix(GuestExceptionPointer* self) noexcept; +void* APS5_VABI _ZNKSt15__exception_ptr13exception_ptr6_M_getEv_nid_postfix(const GuestExceptionPointer* self) noexcept; +void APS5_VABI _ZNSt15__exception_ptr13exception_ptrC1EPv_nid_postfix(GuestExceptionPointer* self, void* exception) noexcept; +void APS5_VABI _ZNSt15__exception_ptr13exception_ptrC2EPv_nid_postfix(GuestExceptionPointer* self, void* exception) noexcept; +const std::type_info* APS5_VABI _ZNKSt15__exception_ptr13exception_ptr20__cxa_exception_typeEv_nid_postfix(const GuestExceptionPointer* self) noexcept; +GuestExceptionPointer APS5_VABI _ZSt17current_exceptionv_nid_postfix() noexcept; +int APS5_VABI __cxa_guard_acquire_nid_postfix(std::uint64_t* guardObject); +void APS5_VABI __cxa_guard_release_nid_postfix(std::uint64_t* guardObject); +void APS5_VABI __cxa_guard_abort_nid_postfix(std::uint64_t* guardObject); +LibcException::Header* APS5_VABI __cxa_init_primary_exception_nid_postfix(void* object, std::type_info* type, void (*destructor)(void*)); +void* APS5_VABI __cxa_get_exception_ptr_nid_postfix(void* exception); +std::type_info* APS5_VABI __cxa_current_exception_type_nid_postfix(); +void* APS5_VABI __cxa_get_globals_nid_postfix(); +void* APS5_VABI __cxa_get_globals_fast_nid_postfix(); +bool APS5_VABI __cxa_uncaught_exception_nid_postfix(); +unsigned APS5_VABI __cxa_uncaught_exceptions_nid_postfix(); +bool APS5_VABI _ZSt18uncaught_exceptionv_nid_postfix(); +int APS5_VABI _ZSt19uncaught_exceptionsv_nid_postfix(); +LibcTerminateHandler APS5_VABI _ZSt13set_terminatePFvvE_nid_postfix(LibcTerminateHandler handler); +LibcTerminateHandler APS5_VABI _ZSt13get_terminatev_nid_postfix(); +void APS5_VABI __cxa_increment_exception_refcount_nid_postfix(void* object); +void APS5_VABI __cxa_decrement_exception_refcount_nid_postfix(void* object); +void* APS5_VABI __cxa_current_primary_exception_nid_postfix(); +void* APS5_VABI __cxa_allocate_dependent_exception_nid_postfix(); +void APS5_VABI __cxa_free_dependent_exception_nid_postfix(void* storage); +void APS5_VABI __cxa_rethrow_primary_exception_nid_postfix(void* object); +void* APS5_VABI __dynamic_cast_nid_postfix(const void* source, const __cxxabiv1::__class_type_info* sourceType, const __cxxabiv1::__class_type_info* destinationType, std::ptrdiff_t); +const char* APS5_VABI _ZSt13_Syserror_mapi_nid_postfix(int value); +const LibcException::CategoryObject* APS5_VABI _ZSt16generic_categoryv_nid_postfix(); +const LibcException::CategoryObject* APS5_VABI _ZSt15system_categoryv_nid_postfix(); +GuestLocale::String* APS5_VABI _ZNKSt23_Generic_error_category7messageEi_nid_postfix( GuestLocale::String* result, const LibcException::CategoryObject* self, int value); +void APS5_VABI _ZNSt9exceptionD1Ev_nid_postfix(LibcException::ExceptionObject* self); +void APS5_VABI _ZNSt9exceptionD2Ev_nid_postfix(LibcException::ExceptionObject* self); +void APS5_VABI _ZNSt9exceptionD0Ev_nid_postfix(LibcException::ExceptionObject* self); +const char* APS5_VABI _ZNKSt9exception4whatEv_nid_postfix(const LibcException::ExceptionObject* self); +void APS5_VABI _ZNSt9exceptionC1Ev_nid_postfix(LibcException::ExceptionObject* self); +void APS5_VABI _ZNSt9exceptionC2Ev_nid_postfix(LibcException::ExceptionObject* self); +void APS5_VABI _ZNSt8bad_castD1Ev_nid_postfix(LibcException::ExceptionObject* self); +void APS5_VABI _ZNSt8bad_castD2Ev_nid_postfix(LibcException::ExceptionObject* self); +void APS5_VABI _ZNSt8bad_castD0Ev_nid_postfix(LibcException::ExceptionObject* self); +const char* APS5_VABI _ZNKSt8bad_cast4whatEv_nid_postfix(const LibcException::ExceptionObject* self); +void APS5_VABI _ZNSt8bad_castC1Ev_nid_postfix(LibcException::ExceptionObject* self); +void APS5_VABI _ZNSt8bad_castC2Ev_nid_postfix(LibcException::ExceptionObject* self); +void APS5_VABI _ZNSt10bad_typeidD1Ev_nid_postfix(LibcException::ExceptionObject* self); +void APS5_VABI _ZNSt10bad_typeidD2Ev_nid_postfix(LibcException::ExceptionObject* self); +void APS5_VABI _ZNSt10bad_typeidD0Ev_nid_postfix(LibcException::ExceptionObject* self); +const char* APS5_VABI _ZNKSt10bad_typeid4whatEv_nid_postfix(const LibcException::ExceptionObject* self); +void APS5_VABI _ZNSt10bad_typeidC1Ev_nid_postfix(LibcException::ExceptionObject* self); +void APS5_VABI _ZNSt10bad_typeidC2Ev_nid_postfix(LibcException::ExceptionObject* self); +void APS5_VABI _ZNSt9bad_allocD1Ev_nid_postfix(LibcException::ExceptionObject* self); +void APS5_VABI _ZNSt9bad_allocD2Ev_nid_postfix(LibcException::ExceptionObject* self); +void APS5_VABI _ZNSt9bad_allocD0Ev_nid_postfix(LibcException::ExceptionObject* self); +const char* APS5_VABI _ZNKSt9bad_alloc4whatEv_nid_postfix(const LibcException::ExceptionObject* self); +void APS5_VABI _ZNSt9bad_allocC1Ev_nid_postfix(LibcException::ExceptionObject* self); +void APS5_VABI _ZNSt9bad_allocC2Ev_nid_postfix(LibcException::ExceptionObject* self); +void APS5_VABI _ZNSt20bad_array_new_lengthD1Ev_nid_postfix(LibcException::ExceptionObject* self); +void APS5_VABI _ZNSt20bad_array_new_lengthD2Ev_nid_postfix(LibcException::ExceptionObject* self); +void APS5_VABI _ZNSt20bad_array_new_lengthD0Ev_nid_postfix(LibcException::ExceptionObject* self); +const char* APS5_VABI _ZNKSt20bad_array_new_length4whatEv_nid_postfix(const LibcException::ExceptionObject* self); +void APS5_VABI _ZNSt20bad_array_new_lengthC1Ev_nid_postfix(LibcException::ExceptionObject* self); +void APS5_VABI _ZNSt20bad_array_new_lengthC2Ev_nid_postfix(LibcException::ExceptionObject* self); +void APS5_VABI _ZNSt17bad_function_callD1Ev_nid_postfix(LibcException::ExceptionObject* self); +void APS5_VABI _ZNSt17bad_function_callD2Ev_nid_postfix(LibcException::ExceptionObject* self); +void APS5_VABI _ZNSt17bad_function_callD0Ev_nid_postfix(LibcException::ExceptionObject* self); +const char* APS5_VABI _ZNKSt17bad_function_call4whatEv_nid_postfix(const LibcException::ExceptionObject* self); +void APS5_VABI _ZNSt17bad_function_callC1Ev_nid_postfix(LibcException::ExceptionObject* self); +void APS5_VABI _ZNSt17bad_function_callC2Ev_nid_postfix(LibcException::ExceptionObject* self); +void APS5_VABI _ZNSt12bad_weak_ptrD1Ev_nid_postfix(LibcException::ExceptionObject* self); +void APS5_VABI _ZNSt12bad_weak_ptrD2Ev_nid_postfix(LibcException::ExceptionObject* self); +void APS5_VABI _ZNSt12bad_weak_ptrD0Ev_nid_postfix(LibcException::ExceptionObject* self); +const char* APS5_VABI _ZNKSt12bad_weak_ptr4whatEv_nid_postfix(const LibcException::ExceptionObject* self); +void APS5_VABI _ZNSt19bad_optional_accessD1Ev_nid_postfix(LibcException::ExceptionObject* self); +void APS5_VABI _ZNSt19bad_optional_accessD2Ev_nid_postfix(LibcException::ExceptionObject* self); +void APS5_VABI _ZNSt19bad_optional_accessD0Ev_nid_postfix(LibcException::ExceptionObject* self); +const char* APS5_VABI _ZNKSt19bad_optional_access4whatEv_nid_postfix(const LibcException::ExceptionObject* self); +void APS5_VABI _ZNSt19bad_optional_accessC1Ev_nid_postfix(LibcException::ExceptionObject* self); +void APS5_VABI _ZNSt19bad_optional_accessC2Ev_nid_postfix(LibcException::ExceptionObject* self); +void APS5_VABI _ZNSt11logic_errorD1Ev_nid_postfix(LibcException::ExceptionObject* self); +void APS5_VABI _ZNSt11logic_errorD2Ev_nid_postfix(LibcException::ExceptionObject* self); +void APS5_VABI _ZNSt11logic_errorD0Ev_nid_postfix(LibcException::ExceptionObject* self); +const char* APS5_VABI _ZNKSt11logic_error4whatEv_nid_postfix(const LibcException::ExceptionObject* self); +void APS5_VABI _ZNSt11logic_errorC1EPKc_nid_postfix(LibcException::ExceptionObject* self, const char* message); +void APS5_VABI _ZNSt11logic_errorC2EPKc_nid_postfix(LibcException::ExceptionObject* self, const char* message); +void APS5_VABI _ZNSt11logic_errorC1ERKS__nid_postfix(LibcException::ExceptionObject* self, const LibcException::ExceptionObject* source); +void APS5_VABI _ZNSt11logic_errorC2ERKS__nid_postfix(LibcException::ExceptionObject* self, const LibcException::ExceptionObject* source); +LibcException::ExceptionObject* APS5_VABI _ZNSt11logic_erroraSERKS__nid_postfix(LibcException::ExceptionObject* self, const LibcException::ExceptionObject* source); +void APS5_VABI _ZNSt13runtime_errorD1Ev_nid_postfix(LibcException::ExceptionObject* self); +void APS5_VABI _ZNSt13runtime_errorD2Ev_nid_postfix(LibcException::ExceptionObject* self); +void APS5_VABI _ZNSt13runtime_errorD0Ev_nid_postfix(LibcException::ExceptionObject* self); +const char* APS5_VABI _ZNKSt13runtime_error4whatEv_nid_postfix(const LibcException::ExceptionObject* self); +void APS5_VABI _ZNSt13runtime_errorC1EPKc_nid_postfix(LibcException::ExceptionObject* self, const char* message); +void APS5_VABI _ZNSt13runtime_errorC2EPKc_nid_postfix(LibcException::ExceptionObject* self, const char* message); +void APS5_VABI _ZNSt13runtime_errorC1ERKS__nid_postfix(LibcException::ExceptionObject* self, const LibcException::ExceptionObject* source); +void APS5_VABI _ZNSt13runtime_errorC2ERKS__nid_postfix(LibcException::ExceptionObject* self, const LibcException::ExceptionObject* source); +LibcException::ExceptionObject* APS5_VABI _ZNSt13runtime_erroraSERKS__nid_postfix(LibcException::ExceptionObject* self, const LibcException::ExceptionObject* source); +void APS5_VABI _ZNSt16invalid_argumentD1Ev_nid_postfix(LibcException::ExceptionObject* self); +void APS5_VABI _ZNSt16invalid_argumentD2Ev_nid_postfix(LibcException::ExceptionObject* self); +void APS5_VABI _ZNSt16invalid_argumentD0Ev_nid_postfix(LibcException::ExceptionObject* self); +const char* APS5_VABI _ZNKSt16invalid_argument4whatEv_nid_postfix(const LibcException::ExceptionObject* self); +void APS5_VABI _ZNSt16invalid_argumentC1EPKc_nid_postfix(LibcException::ExceptionObject* self, const char* message); +void APS5_VABI _ZNSt16invalid_argumentC2EPKc_nid_postfix(LibcException::ExceptionObject* self, const char* message); +void APS5_VABI _ZNSt16invalid_argumentC1ERKS__nid_postfix(LibcException::ExceptionObject* self, const LibcException::ExceptionObject* source); +void APS5_VABI _ZNSt16invalid_argumentC2ERKS__nid_postfix(LibcException::ExceptionObject* self, const LibcException::ExceptionObject* source); +LibcException::ExceptionObject* APS5_VABI _ZNSt16invalid_argumentaSERKS__nid_postfix(LibcException::ExceptionObject* self, const LibcException::ExceptionObject* source); +void APS5_VABI _ZNSt12out_of_rangeD1Ev_nid_postfix(LibcException::ExceptionObject* self); +void APS5_VABI _ZNSt12out_of_rangeD2Ev_nid_postfix(LibcException::ExceptionObject* self); +void APS5_VABI _ZNSt12out_of_rangeD0Ev_nid_postfix(LibcException::ExceptionObject* self); +const char* APS5_VABI _ZNKSt12out_of_range4whatEv_nid_postfix(const LibcException::ExceptionObject* self); +void APS5_VABI _ZNSt12out_of_rangeC1EPKc_nid_postfix(LibcException::ExceptionObject* self, const char* message); +void APS5_VABI _ZNSt12out_of_rangeC2EPKc_nid_postfix(LibcException::ExceptionObject* self, const char* message); +void APS5_VABI _ZNSt12out_of_rangeC1ERKS__nid_postfix(LibcException::ExceptionObject* self, const LibcException::ExceptionObject* source); +void APS5_VABI _ZNSt12out_of_rangeC2ERKS__nid_postfix(LibcException::ExceptionObject* self, const LibcException::ExceptionObject* source); +LibcException::ExceptionObject* APS5_VABI _ZNSt12out_of_rangeaSERKS__nid_postfix(LibcException::ExceptionObject* self, const LibcException::ExceptionObject* source); +void APS5_VABI _ZNSt12domain_errorD1Ev_nid_postfix(LibcException::ExceptionObject* self); +void APS5_VABI _ZNSt12domain_errorD2Ev_nid_postfix(LibcException::ExceptionObject* self); +void APS5_VABI _ZNSt12domain_errorD0Ev_nid_postfix(LibcException::ExceptionObject* self); +const char* APS5_VABI _ZNKSt12domain_error4whatEv_nid_postfix(const LibcException::ExceptionObject* self); +void APS5_VABI _ZNSt12domain_errorC1EPKc_nid_postfix(LibcException::ExceptionObject* self, const char* message); +void APS5_VABI _ZNSt12domain_errorC2EPKc_nid_postfix(LibcException::ExceptionObject* self, const char* message); +void APS5_VABI _ZNSt12domain_errorC1ERKS__nid_postfix(LibcException::ExceptionObject* self, const LibcException::ExceptionObject* source); +void APS5_VABI _ZNSt12domain_errorC2ERKS__nid_postfix(LibcException::ExceptionObject* self, const LibcException::ExceptionObject* source); +LibcException::ExceptionObject* APS5_VABI _ZNSt12domain_erroraSERKS__nid_postfix(LibcException::ExceptionObject* self, const LibcException::ExceptionObject* source); +void APS5_VABI _ZNSt12length_errorD1Ev_nid_postfix(LibcException::ExceptionObject* self); +void APS5_VABI _ZNSt12length_errorD2Ev_nid_postfix(LibcException::ExceptionObject* self); +void APS5_VABI _ZNSt12length_errorD0Ev_nid_postfix(LibcException::ExceptionObject* self); +const char* APS5_VABI _ZNKSt12length_error4whatEv_nid_postfix(const LibcException::ExceptionObject* self); +void APS5_VABI _ZNSt12length_errorC1EPKc_nid_postfix(LibcException::ExceptionObject* self, const char* message); +void APS5_VABI _ZNSt12length_errorC2EPKc_nid_postfix(LibcException::ExceptionObject* self, const char* message); +void APS5_VABI _ZNSt12length_errorC1ERKS__nid_postfix(LibcException::ExceptionObject* self, const LibcException::ExceptionObject* source); +void APS5_VABI _ZNSt12length_errorC2ERKS__nid_postfix(LibcException::ExceptionObject* self, const LibcException::ExceptionObject* source); +LibcException::ExceptionObject* APS5_VABI _ZNSt12length_erroraSERKS__nid_postfix(LibcException::ExceptionObject* self, const LibcException::ExceptionObject* source); +void APS5_VABI _ZNSt12system_errorD1Ev_nid_postfix(LibcException::ExceptionObject* self); +void APS5_VABI _ZNSt12system_errorD2Ev_nid_postfix(LibcException::ExceptionObject* self); +void APS5_VABI _ZNSt12system_errorD0Ev_nid_postfix(LibcException::ExceptionObject* self); +const char* APS5_VABI _ZNKSt12system_error4whatEv_nid_postfix(const LibcException::ExceptionObject* self); +void APS5_VABI _ZNSt12system_errorC1ERKS__nid_postfix(LibcException::SystemErrorObject* self, const LibcException::SystemErrorObject* source); +void APS5_VABI _ZNSt12system_errorC2ERKS__nid_postfix(LibcException::SystemErrorObject* self, const LibcException::SystemErrorObject* source); +LibcException::SystemErrorObject* APS5_VABI _ZNSt12system_erroraSERKS__nid_postfix(LibcException::SystemErrorObject* self, const LibcException::SystemErrorObject* source); +void APS5_VABI _ZNSt11regex_errorD1Ev_nid_postfix(LibcException::ExceptionObject* self); +void APS5_VABI _ZNSt11regex_errorD2Ev_nid_postfix(LibcException::ExceptionObject* self); +void APS5_VABI _ZNSt11regex_errorD0Ev_nid_postfix(LibcException::ExceptionObject* self); +const char* APS5_VABI _ZNKSt11regex_error4whatEv_nid_postfix(const LibcException::ExceptionObject* self); +void APS5_VABI _ZNSt11regex_errorC1ERKS__nid_postfix(LibcException::ExceptionObject* self, const LibcException::ExceptionObject* source); +void APS5_VABI _ZNSt11regex_errorC2ERKS__nid_postfix(LibcException::ExceptionObject* self, const LibcException::ExceptionObject* source); +LibcException::ExceptionObject* APS5_VABI _ZNSt11regex_erroraSERKS__nid_postfix(LibcException::ExceptionObject* self, const LibcException::ExceptionObject* source); +void APS5_VABI _ZNSt11range_errorD1Ev_nid_postfix(LibcException::ExceptionObject* self); +void APS5_VABI _ZNSt11range_errorD2Ev_nid_postfix(LibcException::ExceptionObject* self); +void APS5_VABI _ZNSt11range_errorD0Ev_nid_postfix(LibcException::ExceptionObject* self); +void APS5_VABI _ZNSt14overflow_errorD1Ev_nid_postfix(LibcException::ExceptionObject* self); +void APS5_VABI _ZNSt8ios_base7failureD1Ev_nid_postfix(LibcException::ExceptionObject* self); +void APS5_VABI _ZNSt8ios_base7failureD2Ev_nid_postfix(LibcException::ExceptionObject* self); +void APS5_VABI _ZNSt8ios_base7failureD0Ev_nid_postfix(LibcException::ExceptionObject* self); +const char* APS5_VABI _ZNKSt8ios_base7failure4whatEv_nid_postfix(const LibcException::ExceptionObject* self); +_Unwind_Word APS5_VABI _Unwind_GetGR_nid_postfix(_Unwind_Context* context, int index); +void APS5_VABI _Unwind_SetGR_nid_postfix(_Unwind_Context* context, int index, _Unwind_Word value); +_Unwind_Ptr APS5_VABI _Unwind_GetIP_nid_postfix(_Unwind_Context* context); +void APS5_VABI _Unwind_SetIP_nid_postfix(_Unwind_Context* context, _Unwind_Ptr value); +_Unwind_Ptr APS5_VABI _Unwind_GetIPInfo_nid_postfix(_Unwind_Context* context, int* before); +_Unwind_Word APS5_VABI _Unwind_GetCFA_nid_postfix(_Unwind_Context* context); +_Unwind_Ptr APS5_VABI _Unwind_GetLanguageSpecificData_nid_postfix(_Unwind_Context* context); +_Unwind_Ptr APS5_VABI _Unwind_GetRegionStart_nid_postfix(_Unwind_Context* context); +_Unwind_Ptr APS5_VABI _Unwind_GetDataRelBase_nid_postfix(_Unwind_Context* context); +_Unwind_Ptr APS5_VABI _Unwind_GetTextRelBase_nid_postfix(_Unwind_Context* context); +_Unwind_Reason_Code APS5_VABI _Unwind_ForcedUnwind_nid_postfix(_Unwind_Exception* exception, _Unwind_Stop_Fn stop, void* argument); +_Unwind_Reason_Code APS5_VABI _Unwind_Backtrace_nid_postfix(_Unwind_Trace_Fn trace, void* argument); +int APS5_VABI dl_iterate_phdr_nid_postfix(int (*callback)(dl_phdr_info*, std::size_t, void*), void* data); + +[[noreturn]] void APS5_VABI _Exit_nid_postfix(int code); +[[noreturn]] void APS5_VABI catchReturnFromMain_nid_postfix(int status); +[[noreturn]] void APS5_VABI quick_exit_nid_postfix(int status); +[[noreturn]] void APS5_VABI _ZSt14_Throw_C_errori_nid_postfix(int code); +[[noreturn]] char* APS5_VABI fgetln_nid_postfix(FileStream*, std::size_t*); +[[noreturn]] void APS5_VABI _Assert_nid_postfix(const char* message, const char* location); +[[noreturn]] void APS5_VABI _ZSt16_Throw_Cpp_errori_nid_postfix(int code); +[[noreturn]] void APS5_VABI _Thrd_exit_nid_postfix(int code); +[[noreturn]] void APS5_VABI _ZSt17rethrow_exceptionNSt15__exception_ptr13exception_ptrE_nid_postfix(GuestExceptionPointerArgument exception); +[[noreturn]] void APS5_VABI _ZSt9terminatev_nid_postfix(); +[[noreturn]] void APS5_VABI __cxa_call_terminate_nid_postfix(void* exception); +[[noreturn]] void APS5_VABI __cxa_pure_virtual_nid_postfix(); +[[noreturn]] void APS5_VABI __cxa_deleted_virtual_nid_postfix(); +[[noreturn]] void APS5_VABI _ZNKSt9exception8_DoraiseEv_nid_postfix(const LibcException::ExceptionObject* self); +[[noreturn]] void APS5_VABI _ZNKSt9exception6_RaiseEv_nid_postfix(const LibcException::ExceptionObject* self); +[[noreturn]] void APS5_VABI _ZNKSt8bad_cast8_DoraiseEv_nid_postfix(const LibcException::ExceptionObject* self); +[[noreturn]] void APS5_VABI _ZNKSt11logic_error8_DoraiseEv_nid_postfix(const LibcException::ExceptionObject* self); +[[noreturn]] void APS5_VABI __cxa_bad_cast_nid_postfix(); +[[noreturn]] void APS5_VABI __cxa_bad_typeid_nid_postfix(); +[[noreturn]] void APS5_VABI __cxa_throw_bad_array_new_length_nid_postfix(); +[[noreturn]] void APS5_VABI _ZSt11_Xbad_allocv_nid_postfix(); +[[noreturn]] void APS5_VABI _ZSt14_Xout_of_rangePKc_nid_postfix(const char* message); +[[noreturn]] void APS5_VABI _ZSt14_Xlength_errorPKc_nid_postfix(const char* message); +[[noreturn]] void APS5_VABI _ZSt18_Xinvalid_argumentPKc_nid_postfix(const char* message); +[[noreturn]] void APS5_VABI _ZSt15_Xruntime_errorPKc_nid_postfix(const char* message); +[[noreturn]] void APS5_VABI _ZSt13_Xrange_errorPKc_nid_postfix(const char* message); +[[noreturn]] void APS5_VABI _ZSt19_Xbad_function_callv_nid_postfix(); +[[noreturn]] void APS5_VABI _ZNSt8__sce_v219_Xbad_function_callEv_nid_postfix(); +[[noreturn]] void APS5_VABI _ZSt19_Throw_bad_weak_ptrv_nid_postfix(); +[[noreturn]] void APS5_VABI _ZSt26__throw_bad_variant_accessv_nid_postfix(); +[[noreturn]] void APS5_VABI _ZSt26_Throw_bad_optional_accessv_nid_postfix(); +[[noreturn]] void APS5_VABI _ZSt13_Xregex_errorNSt15regex_constants10error_typeE_nid_postfix(std::regex_constants::error_type code); + +[[gnu::returns_twice]] int APS5_VABI setjmp_nid_postfix(std::uint64_t* buffer); +[[noreturn]] void APS5_VABI longjmp_nid_postfix(std::uint64_t* buffer, int value); + +std::uint8_t APS5_VABI __atomic_load_1_nid_postfix(const volatile std::uint8_t* target, int); +std::uint16_t APS5_VABI __atomic_load_2_nid_postfix(const volatile std::uint16_t* target, int); +std::uint32_t APS5_VABI __atomic_load_4_nid_postfix(const volatile std::uint32_t* target, int); +std::uint64_t APS5_VABI __atomic_load_8_nid_postfix(const volatile std::uint64_t* target, int); +void APS5_VABI __atomic_store_1_nid_postfix(volatile std::uint8_t* target, std::uint8_t value, int); +void APS5_VABI __atomic_store_2_nid_postfix(volatile std::uint16_t* target, std::uint16_t value, int); +void APS5_VABI __atomic_store_4_nid_postfix(volatile std::uint32_t* target, std::uint32_t value, int); +void APS5_VABI __atomic_store_8_nid_postfix(volatile std::uint64_t* target, std::uint64_t value, int); +std::uint8_t APS5_VABI __atomic_exchange_1_nid_postfix(volatile std::uint8_t* target, std::uint8_t value, int); +std::uint16_t APS5_VABI __atomic_exchange_2_nid_postfix(volatile std::uint16_t* target, std::uint16_t value, int); +std::uint32_t APS5_VABI __atomic_exchange_4_nid_postfix(volatile std::uint32_t* target, std::uint32_t value, int); +std::uint64_t APS5_VABI __atomic_exchange_8_nid_postfix(volatile std::uint64_t* target, std::uint64_t value, int); +int APS5_VABI __atomic_compare_exchange_1_nid_postfix(volatile std::uint8_t* target, std::uint8_t* expected, std::uint8_t desired, int, int); +int APS5_VABI __atomic_compare_exchange_2_nid_postfix(volatile std::uint16_t* target, std::uint16_t* expected, std::uint16_t desired, int, int); +int APS5_VABI __atomic_compare_exchange_4_nid_postfix(volatile std::uint32_t* target, std::uint32_t* expected, std::uint32_t desired, int, int); +int APS5_VABI __atomic_compare_exchange_8_nid_postfix(volatile std::uint64_t* target, std::uint64_t* expected, std::uint64_t desired, int, int); +std::uint8_t APS5_VABI __atomic_fetch_add_1_nid_postfix(volatile std::uint8_t* target, std::uint8_t value, int); +std::uint16_t APS5_VABI __atomic_fetch_add_2_nid_postfix(volatile std::uint16_t* target, std::uint16_t value, int); +std::uint32_t APS5_VABI __atomic_fetch_add_4_nid_postfix(volatile std::uint32_t* target, std::uint32_t value, int); +std::uint64_t APS5_VABI __atomic_fetch_add_8_nid_postfix(volatile std::uint64_t* target, std::uint64_t value, int); +std::uint8_t APS5_VABI __atomic_fetch_sub_1_nid_postfix(volatile std::uint8_t* target, std::uint8_t value, int); +std::uint16_t APS5_VABI __atomic_fetch_sub_2_nid_postfix(volatile std::uint16_t* target, std::uint16_t value, int); +std::uint32_t APS5_VABI __atomic_fetch_sub_4_nid_postfix(volatile std::uint32_t* target, std::uint32_t value, int); +std::uint64_t APS5_VABI __atomic_fetch_sub_8_nid_postfix(volatile std::uint64_t* target, std::uint64_t value, int); +std::uint8_t APS5_VABI __atomic_fetch_and_1_nid_postfix(volatile std::uint8_t* target, std::uint8_t value, int); +std::uint16_t APS5_VABI __atomic_fetch_and_2_nid_postfix(volatile std::uint16_t* target, std::uint16_t value, int); +std::uint32_t APS5_VABI __atomic_fetch_and_4_nid_postfix(volatile std::uint32_t* target, std::uint32_t value, int); +std::uint64_t APS5_VABI __atomic_fetch_and_8_nid_postfix(volatile std::uint64_t* target, std::uint64_t value, int); +std::uint8_t APS5_VABI __atomic_fetch_or_1_nid_postfix(volatile std::uint8_t* target, std::uint8_t value, int); +std::uint16_t APS5_VABI __atomic_fetch_or_2_nid_postfix(volatile std::uint16_t* target, std::uint16_t value, int); +std::uint32_t APS5_VABI __atomic_fetch_or_4_nid_postfix(volatile std::uint32_t* target, std::uint32_t value, int); +std::uint64_t APS5_VABI __atomic_fetch_or_8_nid_postfix(volatile std::uint64_t* target, std::uint64_t value, int); +std::uint8_t APS5_VABI __atomic_fetch_xor_1_nid_postfix(volatile std::uint8_t* target, std::uint8_t value, int); +std::uint16_t APS5_VABI __atomic_fetch_xor_2_nid_postfix(volatile std::uint16_t* target, std::uint16_t value, int); +std::uint32_t APS5_VABI __atomic_fetch_xor_4_nid_postfix(volatile std::uint32_t* target, std::uint32_t value, int); +std::uint64_t APS5_VABI __atomic_fetch_xor_8_nid_postfix(volatile std::uint64_t* target, std::uint64_t value, int); +void APS5_VABI _ZNSt13__sce_cxxvers16_Error_exceptionC1EPKc_nid_postfix(LibcException::ExceptionObject* self, const char* message); +void APS5_VABI _ZNSt13__sce_cxxvers16_Error_exceptionC2EPKc_nid_postfix(LibcException::ExceptionObject* self, const char* message); +void APS5_VABI _ZNSt13__sce_cxxvers16_Error_exceptionC1ERKS0__nid_postfix(LibcException::ExceptionObject* self, const LibcException::ExceptionObject* source); +void APS5_VABI _ZNSt13__sce_cxxvers16_Error_exceptionC2ERKS0__nid_postfix(LibcException::ExceptionObject* self, const LibcException::ExceptionObject* source); +void APS5_VABI _ZNSt13__sce_cxxvers16_Error_exceptionD1Ev_nid_postfix(LibcException::ExceptionObject* self); +void APS5_VABI _ZNSt13__sce_cxxvers16_Error_exceptionD2Ev_nid_postfix(LibcException::ExceptionObject* self); +void APS5_VABI _ZNSt13__sce_cxxvers16_Error_exceptionD0Ev_nid_postfix(LibcException::ExceptionObject* self); +const char* APS5_VABI _ZNKSt13__sce_cxxvers16_Error_exception4whatEv_nid_postfix(const LibcException::ExceptionObject* self); +[[noreturn]] void APS5_VABI _ZNSt8__sce_v214_Xlength_errorEPKc_nid_postfix(const char* message); +[[noreturn]] void APS5_VABI _ZNSt8__sce_v214_Xout_of_rangeEPKc_nid_postfix(const char* message); +[[noreturn]] void APS5_VABI _ZNSt8__sce_v218_Xinvalid_argumentEPKc_nid_postfix(const char* message); +[[noreturn]] void APS5_VABI _ZNSt8__sce_v215_Xruntime_errorEPKc_nid_postfix(const char* message); +[[noreturn]] void APS5_VABI _ZNSt8__sce_v216_Xoverflow_errorEPKc_nid_postfix(const char* message); +[[noreturn]] void APS5_VABI _ZNSt8__sce_v211_Xbad_allocEv_nid_postfix(); +[[noreturn]] void APS5_VABI _ZNSt8__sce_v26_ThrowERKNS_19bad_optional_accessE_nid_postfix(const LibcException::ExceptionObject*); +[[noreturn]] void APS5_VABI _ZNSt8__sce_v26_ThrowERKNS_12bad_weak_ptrE_nid_postfix(const LibcException::ExceptionObject*); +[[noreturn]] void APS5_VABI _ZNSt8__sce_v26_ThrowERKNS_18bad_variant_accessE_nid_postfix(const LibcException::ExceptionObject*); +[[noreturn]] void APS5_VABI _ZNSt8__sce_v26_ThrowERKNS_11range_errorE_nid_postfix(const LibcException::ExceptionObject* error); +[[noreturn]] void APS5_VABI _ZNSt8__sce_v26_ThrowERKNS_12system_errorE_nid_postfix(const LibcException::SystemErrorObject* error); +[[noreturn]] void APS5_VABI _ZNSt8__sce_v28ios_base6_ThrowERKNS0_7failureE_nid_postfix(const LibcException::SystemErrorObject* failure); +[[noreturn]] void APS5_VABI _ZNSt8__sce_v216_Throw_Cpp_errorEi_nid_postfix(int code); +std::int64_t APS5_VABI _ZNSt8__sce_v216_Xtime_get_ticksEv_nid_postfix(); +const char* APS5_VABI _ZNSt8__sce_v213_Syserror_mapEi_nid_postfix(int value); +int APS5_VABI feupdateenv_nid_postfix(const GuestFloatingPointEnvironment* environment); +int APS5_VABI feholdexcept_nid_postfix(GuestFloatingPointEnvironment* environment); +void APS5_VABI srandomdev_nid_postfix(); + +double APS5_VABI _Stodx_nid_postfix(const char* text, char** end, std::int64_t pten, int* error); +float APS5_VABI _Stofx_nid_postfix(const char* text, char** end, std::int64_t pten, int* error); +long double APS5_VABI _Stoldx_nid_postfix(const char* text, char** end, std::int64_t pten, int* error); +float APS5_VABI _Stof_nid_postfix(const char* text, char** end, std::int64_t pten); +long double APS5_VABI _Stold_nid_postfix(const char* text, char** end, std::int64_t pten); +long long APS5_VABI _Stollx_nid_postfix(const char* text, char** end, int base, int* error); +unsigned long long APS5_VABI _Stoullx_nid_postfix(const char* text, char** end, int base, int* error); +std::uint64_t APS5_VABI _Stoulx_nid_postfix(const char* text, char** end, int base, int* error); +std::int64_t APS5_VABI _Stolx_nid_postfix(const char* text, char** end, int base, int* error); +std::size_t APS5_VABI _ZNSt7codecvtIcc9_MbstatetE7_GetcatEPPKNSt6locale5facetEPKS2__nid_postfix(GuestLocale::Facet** facet, const GuestLocale::Implementation* const*); +std::size_t APS5_VABI _ZNSt8numpunctIcE7_GetcatEPPKNSt6locale5facetEPKS1__nid_postfix(GuestLocale::Facet** facet, const GuestLocale::Implementation* const*); +std::size_t APS5_VABI _ZNSt7num_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE7_GetcatEPPKNSt6locale5facetEPKS5__nid_postfix(GuestLocale::Facet** facet, const GuestLocale::Implementation* const*); +std::size_t APS5_VABI _ZNSt8time_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE7_GetcatEPPKNSt6locale5facetEPKS5__nid_postfix(GuestLocale::Facet** facet, const GuestLocale::Implementation* const*); +int APS5_VABI siginterrupt_nid_postfix(int guest, int flag); + +} diff --git a/core/libs/prx/libc/include/General.hpp b/core/libs/prx/libc/include/General.hpp index b45386ab48..4d4db4d068 100644 --- a/core/libs/prx/libc/include/General.hpp +++ b/core/libs/prx/libc/include/General.hpp @@ -27,8 +27,10 @@ extern "C" std::FILE* HostStandardErrorFile_nid_no_patch(); #endif extern "C" bool CopyGuestEnvironment_nid_no_patch(const char* name, std::string& value); +extern "C" int CopyGuestPath_nid_no_patch(const char* source, std::string& destination); extern "C" std::filesystem::path ResolvePath_nid_no_patch(const char* path); +extern "C" bool GuestCopyOut_nid_no_patch(void* destination, const void* source, std::size_t bytes); extern "C" std::filesystem::path ResolvePathOrRelinkedModule_nid_no_patch(const char* path); extern "C" std::filesystem::path ResolveArchivedPath_nid_no_patch(const char* path, bool module = false); extern "C" std::filesystem::path ResolveDiskPath_nid_no_patch(const char* path); diff --git a/core/libs/prx/libc/include/SonyCrt.hpp b/core/libs/prx/libc/include/SonyCrt.hpp index db53cd3d54..fc97c753f1 100644 --- a/core/libs/prx/libc/include/SonyCrt.hpp +++ b/core/libs/prx/libc/include/SonyCrt.hpp @@ -88,7 +88,7 @@ inline int SonyFormatAsctime(char* buffer, std::size_t size, const GuestTm& time static const char* const days[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; static const char* const months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; if (!buffer || size < 26) return EINVAL; - const int year = 1900 + time.tm_year; + const std::int64_t year = std::int64_t{time.tm_year} + 1900; if (time.tm_wday < 0 || time.tm_wday > 6 || time.tm_mon < 0 || time.tm_mon > 11 || time.tm_mday < 1 || time.tm_mday > 31 || time.tm_hour < 0 || time.tm_hour > 23 || time.tm_min < 0 || time.tm_min > 59 || time.tm_sec < 0 || time.tm_sec > 60 || @@ -97,7 +97,7 @@ inline int SonyFormatAsctime(char* buffer, std::size_t size, const GuestTm& time return EINVAL; } std::snprintf(buffer, size, "%.3s %.3s %2d %.2d:%.2d:%.2d %4d\n", days[time.tm_wday], months[time.tm_mon], - time.tm_mday, time.tm_hour, time.tm_min, time.tm_sec, year); + time.tm_mday, time.tm_hour, time.tm_min, time.tm_sec, static_cast(year)); return 0; } diff --git a/core/libs/prx/libc/include/WindowsFormatting.hpp b/core/libs/prx/libc/include/WindowsFormatting.hpp index f0ee4f771d..2023452e25 100644 --- a/core/libs/prx/libc/include/WindowsFormatting.hpp +++ b/core/libs/prx/libc/include/WindowsFormatting.hpp @@ -2,7 +2,9 @@ #define CORE_LIBS_PRX_LIBC_INCLUDE_WINDOWSFORMATTING_HPP #include "SceTypes.hpp" +#include #include +#include #include #include #include @@ -160,6 +162,278 @@ inline void AppendUtf8(std::string& utf8, char32_t code) { } } +struct FloatSpec { + bool left = false; + bool plus = false; + bool space = false; + bool alternate = false; + bool zero = false; + std::size_t width = 0; + int precision = -1; +}; + +inline FloatSpec ParseFloatSpec(const std::string& spec) { + FloatSpec result; + std::size_t index = 1; + for (; index < spec.size() && std::strchr("-+ #0", spec[index]); ++index) { + result.left |= spec[index] == '-'; + result.plus |= spec[index] == '+'; + result.space |= spec[index] == ' '; + result.alternate |= spec[index] == '#'; + result.zero |= spec[index] == '0'; + } + for (; index < spec.size() && spec[index] >= '0' && spec[index] <= '9'; ++index) { + const auto digit = static_cast(spec[index] - '0'); + if (result.width > (static_cast(INT_MAX) - digit) / 10) + throw std::overflow_error("Formatted output exceeds INT_MAX"); + result.width = result.width * 10 + digit; + } + if (index < spec.size() && spec[index] == '.') { + result.precision = 0; + for (++index; index < spec.size(); ++index) { + const int digit = spec[index] - '0'; + if (result.precision > (INT_MAX - digit) / 10) + throw std::overflow_error("Floating precision exceeds int range"); + result.precision = result.precision * 10 + digit; + } + } + return result; +} + +inline std::string PadFloat(const FloatSpec& spec, const std::string& prefix, const std::string& body) { + const std::size_t length = prefix.size() + body.size(); + if (length >= spec.width) return prefix + body; + const std::string padding(spec.width - length, spec.left || !spec.zero ? ' ' : '0'); + if (spec.left) return prefix + body + padding; + return spec.zero ? prefix + padding + body : padding + prefix + body; +} + +inline std::string HexFloat(const std::string& spec, char conversion, double value, std::size_t maximumLength = INT_MAX) { + const FloatSpec parsed = ParseFloatSpec(spec); + const bool plus = parsed.plus, space = parsed.space, alternate = parsed.alternate; + const std::size_t width = parsed.width; + const int precision = parsed.precision; + const bool upper = conversion == 'A'; + const std::uint64_t bits = std::bit_cast(value); + int exponent = static_cast((bits >> 52) & 0x7ff); + std::uint64_t fraction = bits & ((std::uint64_t{1} << 52) - 1); + std::uint64_t lead = 1; + if (exponent != 0) { + exponent -= 1023; + } else if (fraction == 0) { + lead = 0; + } else { + exponent = -1022; + while ((fraction & (std::uint64_t{1} << 52)) == 0) { + fraction <<= 1; + --exponent; + } + fraction &= (std::uint64_t{1} << 52) - 1; + } + int digits = 13; + if (precision >= 0 && precision < 13) { + const int dropped = (13 - precision) * 4; + const std::uint64_t remainder = fraction & ((std::uint64_t{1} << dropped) - 1); + fraction >>= dropped; + if (remainder >= std::uint64_t{1} << (dropped - 1) && ++fraction >> (precision * 4)) { + fraction &= (std::uint64_t{1} << (precision * 4)) - 1; + ++lead; + } + digits = precision; + } else if (precision < 0) { + for (; digits > 0 && (fraction & 0xf) == 0; --digits) fraction >>= 4; + } + const char* hex = upper ? "0123456789ABCDEF" : "0123456789abcdef"; + std::string suffix = upper ? "P" : "p"; + suffix += exponent < 0 ? '-' : '+'; + suffix += std::to_string(exponent < 0 ? -exponent : exponent); + std::string prefix = (bits >> 63) != 0 ? "-" : plus ? "+" : space ? " " : ""; + prefix += upper ? "0X" : "0x"; + const auto fractionalDigits = static_cast(precision > 13 ? precision : digits); + const bool point = fractionalDigits != 0 || alternate; + const std::size_t length = prefix.size() + 1 + point + fractionalDigits + suffix.size(); + if (length > maximumLength || width > maximumLength) + throw std::overflow_error("Formatted output exceeds INT_MAX"); + std::string body(1, hex[lead]); + if (point) body += '.'; + for (int digit = digits - 1; digit >= 0; --digit) body += hex[(fraction >> (digit * 4)) & 0xf]; + if (precision > 13) body.append(static_cast(precision - 13), '0'); + body += suffix; + return PadFloat(parsed, prefix, body); +} + +struct DecimalDigits { + std::string digits; + long long exponent = 0; + bool truncated = false; + bool tiesDown = false; +}; + +inline std::string DecimalChunks(std::vector words) { + std::string text; + while (!words.empty()) { + std::uint64_t remainder = 0; + for (std::size_t index = words.size(); index-- > 0;) { + const std::uint64_t current = (remainder << 32) | words[index]; + words[index] = static_cast(current / 1000000000u); + remainder = current % 1000000000u; + } + while (!words.empty() && words.back() == 0) words.pop_back(); + std::string chunk = std::to_string(remainder); + if (!words.empty()) chunk.insert(0, 9 - chunk.size(), '0'); + text.insert(0, chunk); + } + return text; +} + +inline DecimalDigits ConsoleDecimalDigits(long double value) { + DecimalDigits result; + if (value == 0) return result; + int binary = 0; + const auto mantissa = static_cast(std::ldexp(std::frexp(std::fabs(value), &binary), 64)); + const long long estimate = static_cast(binary) * 30103 / 100000; + const long long last = (estimate >= 0 ? estimate / 4 : -((3 - estimate) / 4)) * 4 - 20; + result.tiesDown = estimate >= 8; + binary -= 64; + std::string integer; + std::string fraction; + bool remaining = false; + if (binary >= 0) { + const auto word = static_cast(binary) / 32; + const auto bit = static_cast(binary) % 32; + std::vector words(word + 3, 0); + for (std::size_t part = 0; part < 2; ++part) { + const std::uint64_t shifted = ((mantissa >> (32 * part)) & 0xffffffffu) << bit; + words[word + part] |= static_cast(shifted); + words[word + part + 1] |= static_cast(shifted >> 32); + } + while (!words.empty() && words.back() == 0) words.pop_back(); + integer = DecimalChunks(std::move(words)); + } else { + const auto shift = static_cast(-static_cast(binary)); + const std::uint64_t whole = shift >= 64 ? 0 : mantissa >> shift; + if (whole != 0) integer = std::to_string(whole); + std::vector words(shift / 32 + 2, 0); + const std::uint64_t remainder = shift >= 64 ? mantissa : mantissa & ((std::uint64_t{1} << shift) - 1); + words[0] = static_cast(remainder); + words[1] = static_cast(remainder >> 32); + const std::size_t top = shift / 32; + const auto bit = static_cast(shift % 32); + const auto significant = [&] { + const std::size_t leading = fraction.find_first_not_of('0'); + return integer.size() + (leading == std::string::npos ? 0 : fraction.size() - leading); + }; + remaining = remainder != 0; + while (remaining && significant() < 30) { + std::uint64_t carry = 0; + for (auto& word : words) { + const std::uint64_t product = static_cast(word) * 1000000000u + carry; + word = static_cast(product); + carry = product >> 32; + } + const std::uint64_t window = (static_cast(words[top + 1]) << 32) | words[top]; + const std::string chunk = std::to_string(static_cast(window >> bit)); + words[top + 1] = 0; + words[top] &= bit == 0 ? 0 : (std::uint32_t{1} << bit) - 1; + fraction += std::string(9 - chunk.size(), '0') + chunk; + remaining = std::any_of(words.begin(), words.end(), [](std::uint32_t word) { return word != 0; }); + } + } + if (!integer.empty()) { + result.exponent = static_cast(integer.size()) - 1; + result.digits = integer + fraction; + } else { + const std::size_t leading = fraction.find_first_not_of('0'); + result.exponent = -static_cast(leading) - 1; + result.digits = fraction.substr(leading); + } + const long long kept = result.exponent - last + 1; + if (static_cast(result.digits.size()) > kept) { + result.truncated = result.digits.find_first_not_of('0', static_cast(kept)) != std::string::npos; + result.digits.resize(static_cast(kept)); + } + result.truncated |= remaining; + return result; +} + +inline DecimalDigits RoundDecimal(const DecimalDigits& value, long long count) { + if (value.digits.empty()) return value; + if (count <= 0) { + if (count == 0 && value.digits[0] >= '5') return {"1", value.exponent + 1}; + return {}; + } + if (count >= static_cast(value.digits.size())) return value; + DecimalDigits result{value.digits.substr(0, static_cast(count)), value.exponent}; + const auto next = static_cast(count); + if (value.digits[next] < '5') return result; + if (value.digits[next] == '5' && value.tiesDown && !value.truncated && value.digits.find_first_not_of('0', next + 1) == std::string::npos) + return result; + for (std::size_t index = result.digits.size(); index-- > 0;) { + if (result.digits[index] != '9') { + ++result.digits[index]; + return result; + } + result.digits[index] = '0'; + } + result.digits.insert(result.digits.begin(), '1'); + result.digits.pop_back(); + ++result.exponent; + return result; +} + +inline char DigitAt(const DecimalDigits& value, long long position) { + const long long index = value.exponent - position; + if (value.digits.empty() || index < 0 || index >= static_cast(value.digits.size())) return '0'; + return value.digits[static_cast(index)]; +} + +inline std::string DecimalFloat(const std::string& spec, char conversion, long double value, std::size_t maximumLength = INT_MAX) { + const FloatSpec parsed = ParseFloatSpec(spec); + const DecimalDigits exact = ConsoleDecimalDigits(value); + const bool upper = conversion == 'E' || conversion == 'G'; + const char lower = static_cast(conversion | 0x20); + long long precision = parsed.precision < 0 ? 6 : parsed.precision; + bool exponential = lower == 'e'; + bool strip = false; + if (lower == 'g') { + if (precision == 0) precision = 1; + const long long exponent = exact.digits.empty() ? 0 : RoundDecimal(exact, precision).exponent; + exponential = !(precision > exponent && exponent >= -4); + precision = exponential ? precision - 1 : precision - 1 - exponent; + strip = !parsed.alternate; + } + const DecimalDigits rounded = RoundDecimal(exact, exponential ? precision + 1 : exact.exponent + 1 + precision); + const long long exponent = rounded.digits.empty() ? 0 : rounded.exponent; + if (strip) { + const long long last = rounded.digits.empty() ? 0 : rounded.exponent - static_cast(rounded.digits.size()) + 1; + long long needed = exponential ? exponent - last : -last; + while (needed > 0 && DigitAt(rounded, (exponential ? exponent : 0) - needed) == '0') --needed; + precision = std::max(0LL, std::min(precision, needed)); + } + const std::string prefix = std::signbit(value) ? "-" : parsed.plus ? "+" : parsed.space ? " " : ""; + const bool point = precision > 0 || parsed.alternate; + const std::string magnitude = std::to_string(exponent < 0 ? -exponent : exponent); + const long long whole = exponential || exponent < 0 ? 1 : exponent + 1; + const long long exponentLength = exponential ? 2 + static_cast(std::max(magnitude.size(), 2)) : 0; + const long long length = static_cast(prefix.size()) + whole + point + precision + exponentLength; + if (length > static_cast(maximumLength) || parsed.width > maximumLength) + throw std::overflow_error("Formatted output exceeds INT_MAX"); + std::string body; + body.reserve(static_cast(length)); + const long long first = exponential ? exponent : std::max(exponent, 0LL); + for (long long position = first; position >= (exponential ? exponent : 0); --position) body += DigitAt(rounded, position); + if (point) body += '.'; + const long long start = exponential ? exponent - 1 : -1; + for (long long position = start; position > start - precision; --position) body += DigitAt(rounded, position); + if (exponential) { + body += upper ? 'E' : 'e'; + body += exponent < 0 ? '-' : '+'; + if (magnitude.size() < 2) body += '0'; + body += magnitude; + } + return PadFloat(parsed, prefix, body); +} + inline std::string PaddedStringSpec(const std::string& spec) { std::string result = "%"; std::size_t index = 1; @@ -373,13 +647,28 @@ inline int FormatWindows(char* buffer, size_t size, const char* format, const vo static_assert(sizeof(long double) == 16); static_assert(std::numeric_limits::digits == 64); const long double value = args.Next(); - if (std::isnan(value)) output.Value(PaddedStringSpec(spec), NanText(spec, std::signbit(value), conversion < 'a').c_str()); - else output.Value(spec + "L" + conversion, value); + if (std::isnan(value)) { + output.Value(PaddedStringSpec(spec), NanText(spec, std::signbit(value), conversion < 'a').c_str()); + } else if (conversion != 'a' && conversion != 'A' && std::isfinite(value)) { + const std::string text = DecimalFloat(spec, conversion, value, static_cast(INT_MAX - output.Count())); + output.Append(text.data(), text.size()); + } else { + output.Value(spec + "L" + conversion, value); + } } else { if (!length.empty() && length != "l") throw std::invalid_argument("Invalid floating length"); const double value = args.Next(); - if (std::isnan(value)) output.Value(PaddedStringSpec(spec), NanText(spec, std::signbit(value), conversion < 'a').c_str()); - else output.Value(spec + conversion, value); + if (std::isnan(value)) { + output.Value(PaddedStringSpec(spec), NanText(spec, std::signbit(value), conversion < 'a').c_str()); + } else if ((conversion == 'a' || conversion == 'A') && std::isfinite(value)) { + const std::string text = HexFloat(spec, conversion, value, static_cast(INT_MAX - output.Count())); + output.Append(text.data(), text.size()); + } else if (std::isfinite(value)) { + const std::string text = DecimalFloat(spec, conversion, value, static_cast(INT_MAX - output.Count())); + output.Append(text.data(), text.size()); + } else { + output.Value(spec + conversion, value); + } } } else if (conversion == 'c' && (length.empty() || length == "h")) { output.Value(spec + conversion, args.Next()); diff --git a/core/libs/prx/libc/include/WindowsMappings.hpp b/core/libs/prx/libc/include/WindowsMappings.hpp index 9e348301a8..993121060f 100644 --- a/core/libs/prx/libc/include/WindowsMappings.hpp +++ b/core/libs/prx/libc/include/WindowsMappings.hpp @@ -264,15 +264,11 @@ public: const auto found = views.find(base); if (found == views.end() || !writable(found->second.protection)) return false; auto& view = found->second; - const auto written = subpagesOf(base, address, address + 1); - if (view.resident && (view.armed & written) == 0) { + if (view.resident) { const auto memory = query(address); return memory.State == MEM_COMMIT && writable(memory.Protect & 0xffu); } - if (view.resident) { - resumeResidentWrites(base); - return true; - } + const auto written = subpagesOf(base, address, address + 1); invalidate(*view.page, written); protectSubpages(base, written, view.protection, "resume shared memory write", view.viewBytes); view.armed &= static_cast(~written); @@ -651,7 +647,6 @@ private: std::uintptr_t end; std::array collected; std::uint32_t fresh; - bool writeObserved = false; }; struct Window { void* view = nullptr; @@ -665,14 +660,12 @@ private: void collectResident(std::uintptr_t start, Run& run, std::uintptr_t from, std::uintptr_t stop, void** pages, std::size_t* count, bool clear, Collection collection) { const auto first = from & ~std::uintptr_t{4095}; - const bool armed = clear && run.fresh == 0 && !run.writeObserved && collection != Collection::Fresh && run.end - start >= 0x40000 && armResident(first, stop); if (run.fresh == 0 && collection != Collection::Fresh) { ULONG_PTR reported = (stop - first + 4095) / 4096; DWORD granularity = 0; if (GetWriteWatch(clear ? WRITE_WATCH_FLAG_RESET : 0, reinterpret_cast(first), stop - first, pages + *count, &reported, &granularity) != 0) fail("collect resident guest writes"); for (ULONG_PTR index = 0; index < reported; ++index) pages[*count + index] = reinterpret_cast(std::max(from, reinterpret_cast(pages[*count + index]))); *count += reported; - if (armed) rememberClean(from, stop); return; } std::vector written; @@ -710,44 +703,6 @@ private: if (collection == Collection::Fresh) flushReset(stop); } - void resumeResidentWrites(std::uintptr_t address) { - const auto run = std::prev(residentRuns.upper_bound(address)); - run->second.writeObserved = true; - forgetClean(run->first, run->second.end); - auto first = views.lower_bound(run->first); - while (first != views.end() && first->first < run->second.end) { - const auto begin = first->first; - auto end = begin; - const auto protection = first->second.protection; - auto next = first; - bool armed = false; - do { - armed = armed || next->second.armed != 0; - end = next->first + pageBytes; - ++next; - } while (next != views.end() && next->first == end && end < run->second.end && next->second.protection == protection); - if (armed) { - DWORD previous; - if (!VirtualProtect(reinterpret_cast(begin), end - begin, protection, &previous)) fail("resume resident guest writes"); - } - for (; first != next; ++first) first->second.armed = 0; - } - } - - bool armResident(std::uintptr_t from, std::uintptr_t stop) { - const auto first = views.lower_bound(from & ~(pageBytes - 1)); - if (first == views.end() || !writable(first->second.protection)) return false; - const auto protection = first->second.protection; - for (auto it = first; it != views.end() && it->first < stop; ++it) { - if (!it->second.resident || it->second.protection != protection || it->second.hostWrites != 0 || it->second.hostImports != 0 || it->second.page->pins != 0) return false; - } - DWORD previous; - const auto readOnly = protection == PAGE_EXECUTE_READWRITE ? PAGE_EXECUTE_READ : PAGE_READONLY; - if (!VirtualProtect(reinterpret_cast(from), stop - from, readOnly, &previous)) fail("arm resident memory write tracking"); - for (auto it = first; it != views.end() && it->first < stop; ++it) it->second.armed |= subpagesOf(it->first, from, stop); - return true; - } - Window open(HANDLE section, std::uint64_t offset, std::size_t bytes) { const auto lead = offset % granularity; Window window; diff --git a/core/libs/prx/libc/include/specifics/linux/ElfTypes.hpp b/core/libs/prx/libc/include/specifics/linux/ElfTypes.hpp index 89dd7d3bcd..d61f017608 100644 --- a/core/libs/prx/libc/include/specifics/linux/ElfTypes.hpp +++ b/core/libs/prx/libc/include/specifics/linux/ElfTypes.hpp @@ -1,6 +1,10 @@ #ifndef PRX_LIBC_INCLUDE_SPECIFICS_LINUX_ELFTYPES_HPP #define PRX_LIBC_INCLUDE_SPECIFICS_LINUX_ELFTYPES_HPP +#ifdef __linux__ +#include +#else + #include #include @@ -34,3 +38,5 @@ extern "C" int dl_iterate_phdr(int (*callback)(dl_phdr_info*, std::size_t, void* #endif #endif + +#endif diff --git a/core/libs/prx/libc/libc.hpp b/core/libs/prx/libc/libc.hpp new file mode 100644 index 0000000000..f5bfb1510b --- /dev/null +++ b/core/libs/prx/libc/libc.hpp @@ -0,0 +1,7 @@ +#pragma once + +#include "prx/libc/include/Api.hpp" +#include "prx/libc/include/exceptions/Runtime.hpp" +#include "prx/libc/include/exceptions/Unwind.hpp" +#include "prx/libc/include/SonyCrt.hpp" +#include "prx/libc/include/WindowsFormatting.hpp" diff --git a/core/libs/prx/libc/src/AllocatingStrings.cpp b/core/libs/prx/libc/src/AllocatingStrings.cpp index 1605fbd125..9f346a90f3 100644 --- a/core/libs/prx/libc/src/AllocatingStrings.cpp +++ b/core/libs/prx/libc/src/AllocatingStrings.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/ApplicationHeap.hpp" #include "prx/libc/include/General.hpp" #include "SceTypes.hpp" @@ -8,8 +9,6 @@ extern "C" { -int APS5_VABI vasprintf_nid_postfix(char** destination, const char* format, VaList* args); - char* APS5_VABI strndup_nid_postfix(const char* source, std::size_t limit) { if (!source) { errno = 22; return nullptr; } std::size_t length = 0; diff --git a/core/libs/prx/libc/src/ApplicationHeap.cpp b/core/libs/prx/libc/src/ApplicationHeap.cpp index 5fc17a5651..af64afc313 100644 --- a/core/libs/prx/libc/src/ApplicationHeap.cpp +++ b/core/libs/prx/libc/src/ApplicationHeap.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/ApplicationHeap.hpp" #include "prx/libc/include/GuestHeap.hpp" #include "prx/libc/include/general/VabiMacros.hpp" diff --git a/core/libs/prx/libc/src/AtomicBuiltins.cpp b/core/libs/prx/libc/src/AtomicBuiltins.cpp index 93df860262..bca7b11a4d 100644 --- a/core/libs/prx/libc/src/AtomicBuiltins.cpp +++ b/core/libs/prx/libc/src/AtomicBuiltins.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include #include #include @@ -7,8 +8,6 @@ namespace { -using Uint128 = unsigned __int128; - [[noreturn]] void ConsoleTrap(const char* function) { throw std::runtime_error(std::string(function) + ": the console implementation traps (ud2)"); } diff --git a/core/libs/prx/libc/src/Backtrace.cpp b/core/libs/prx/libc/src/Backtrace.cpp index a07a476b4a..ad454b77cc 100644 --- a/core/libs/prx/libc/src/Backtrace.cpp +++ b/core/libs/prx/libc/src/Backtrace.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include #include #include @@ -14,8 +15,7 @@ #include #include "prx/libc/include/exceptions/Unwind.hpp" extern "C" { -_Unwind_Reason_Code APS5_VABI _Unwind_Backtrace_nid_postfix(_Unwind_Trace_Fn, void*); -_Unwind_Ptr APS5_VABI _Unwind_GetIP_nid_postfix(_Unwind_Context*); + std::string BacktraceModulePath_nid_no_patch(HMODULE handle, std::size_t initialCapacity) { std::string module; std::size_t capacity = initialCapacity == 0 ? 1 : initialCapacity; @@ -74,6 +74,7 @@ static_assert(sizeof(FrameRecord) == NameOffset); }; TraceState state{addresses, MaxFrames, 0}; _Unwind_Backtrace_nid_postfix(traceCallback, &state); + const int captured = state.count; #endif std::vector frames; diff --git a/core/libs/prx/libc/src/Bessel.cpp b/core/libs/prx/libc/src/Bessel.cpp index 7ba3585ad3..3ef4643d2a 100644 --- a/core/libs/prx/libc/src/Bessel.cpp +++ b/core/libs/prx/libc/src/Bessel.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include #include #include diff --git a/core/libs/prx/libc/src/BinaryWordIo.cpp b/core/libs/prx/libc/src/BinaryWordIo.cpp index 733aadff22..c3e3be0748 100644 --- a/core/libs/prx/libc/src/BinaryWordIo.cpp +++ b/core/libs/prx/libc/src/BinaryWordIo.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/FileStream.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -7,13 +8,6 @@ static_assert(sizeof(int) == 4 && std::endian::native == std::endian::little); -extern "C" { -std::size_t APS5_VABI fread_nid_postfix(void*, std::size_t, std::size_t, FileStream*); -int APS5_VABI putc_unlocked_nid_postfix(int, FileStream*); -void APS5_VABI flockfile_nid_postfix(FileStream*); -void APS5_VABI funlockfile_nid_postfix(FileStream*); -} - namespace { class LockedStream { diff --git a/core/libs/prx/libc/src/BoundsChecking.cpp b/core/libs/prx/libc/src/BoundsChecking.cpp index 2acc1aa95c..634f860c06 100644 --- a/core/libs/prx/libc/src/BoundsChecking.cpp +++ b/core/libs/prx/libc/src/BoundsChecking.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include #include #include @@ -8,13 +9,7 @@ #include "prx/libc/include/SonyCrt.hpp" extern "C" { -std::size_t APS5_VABI mbrtowc_nid_postfix(std::uint16_t* destination, const char* source, std::size_t count, void* state); -std::size_t APS5_VABI wcrtomb_nid_postfix(char* destination, std::uint16_t value, void* state); -int APS5_VABI wctomb_nid_postfix(char* destination, std::uint16_t value); -int APS5_VABI _Getmbcurmax_nid_postfix(); -int APS5_VABI getchar_nid_postfix(); -int APS5_VABI fputs_nid_postfix(const char* str, FileStream* stream); -int APS5_VABI fputc_nid_postfix(int value, FileStream* stream); + extern FileStream* __stderrp_nid_postfix; [[noreturn]] void abort_nid_postfix(std::uint64_t, std::uint64_t, std::uint64_t, std::uint64_t, std::uint64_t, std::uint64_t); } @@ -29,8 +24,6 @@ constexpr std::size_t failed = static_cast(-1); constexpr std::size_t rsizeMax = (std::size_t{1} << 61) - 1; constexpr std::size_t guestStateSize = 128; -using GuestContextCompare = int (APS5_VABI*)(const void*, const void*, void*); - bool usableSize(std::size_t size) { return size != 0 && size <= rsizeMax; } @@ -51,6 +44,7 @@ extern "C" { void APS5_VABI abort_handler_s_nid_postfix(const char* message, void*, int) { fputs_nid_postfix(message, __stderrp_nid_postfix); fputc_nid_postfix('\n', __stderrp_nid_postfix); + abort_nid_postfix(0, 0, 0, 0, 0, 0); } diff --git a/core/libs/prx/libc/src/CxxAbiSupport.cpp b/core/libs/prx/libc/src/CxxAbiSupport.cpp index ccecea01a8..c8fa3ef0de 100644 --- a/core/libs/prx/libc/src/CxxAbiSupport.cpp +++ b/core/libs/prx/libc/src/CxxAbiSupport.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/exceptions/Runtime.hpp" #include #ifndef _UNWIND_H diff --git a/core/libs/prx/libc/src/DinkumwareAtomics.cpp b/core/libs/prx/libc/src/DinkumwareAtomics.cpp index 73ee0dbcd1..13af94ddea 100644 --- a/core/libs/prx/libc/src/DinkumwareAtomics.cpp +++ b/core/libs/prx/libc/src/DinkumwareAtomics.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include #include #include diff --git a/core/libs/prx/libc/src/DinkumwareInternals.cpp b/core/libs/prx/libc/src/DinkumwareInternals.cpp index ab80ee57d9..be7ef61900 100644 --- a/core/libs/prx/libc/src/DinkumwareInternals.cpp +++ b/core/libs/prx/libc/src/DinkumwareInternals.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include #include #include @@ -7,27 +8,6 @@ #include "prx/libc/include/General.hpp" -extern "C" { -int* APS5_VABI __error_nid_postfix(); -double APS5_VABI strtod_nid_postfix(const char* str, char** endptr); -float APS5_VABI strtof_nid_postfix(const char* str, char** endptr); -long double APS5_VABI strtold_nid_postfix(const char* str, char** endptr); -long long APS5_VABI strtoll_nid_postfix(const char* str, char** endptr, int base); -unsigned long long APS5_VABI strtoull_nid_postfix(const char* str, char** endptr, int base); -double APS5_VABI sin_nid_postfix(double x); -double APS5_VABI cos_nid_postfix(double x); -float APS5_VABI sinf_nid_postfix(float x); -float APS5_VABI cosf_nid_postfix(float x); -long double APS5_VABI sinl_nid_postfix(long double x); -long double APS5_VABI cosl_nid_postfix(long double x); -double APS5_VABI log_nid_postfix(double x); -double APS5_VABI log10_nid_postfix(double x); -double APS5_VABI log2_nid_postfix(double x); -float APS5_VABI logf_nid_postfix(float x); -float APS5_VABI log10f_nid_postfix(float x); -float APS5_VABI log2f_nid_postfix(float x); -} - namespace { constexpr long long ExponentLimit = 1000000000; @@ -163,6 +143,22 @@ long double APS5_VABI _LSin_nid_postfix(long double x, unsigned int quadrant) { return quadrant != 0 ? cosl_nid_postfix(x) : sinl_nid_postfix(x); } +double APS5_VABI _Divide_nid_postfix(double x, double y) { + return x / y; +} + +float APS5_VABI _FDivide_nid_postfix(float x, float y) { + return x / y; +} + +double APS5_VABI _Recip_nid_postfix(double x) { + return 1.0 / x; +} + +float APS5_VABI _FRecip_nid_postfix(float x) { + return 1.0f / x; +} + double APS5_VABI _Log_nid_postfix(double x, int base) { if (base > 0) return log10_nid_postfix(x); return base == 0 ? log_nid_postfix(x) : log2_nid_postfix(x); @@ -173,4 +169,17 @@ float APS5_VABI _FLog_nid_postfix(float x, int base) { return base == 0 ? logf_nid_postfix(x) : log2f_nid_postfix(x); } +long double APS5_VABI _LLog_nid_postfix(long double x, int base) { + if (base > 0) return log10l_nid_postfix(x); + return base == 0 ? logl_nid_postfix(x) : log2l_nid_postfix(x); +} + +long double APS5_VABI _LDivide_nid_postfix(long double x, long double y) { + return x / y; +} + +long double APS5_VABI _LRecip_nid_postfix(long double x) { + return 1.0L / x; +} + } diff --git a/core/libs/prx/libc/src/Directory.cpp b/core/libs/prx/libc/src/Directory.cpp index 425669cdcf..69d3670e80 100644 --- a/core/libs/prx/libc/src/Directory.cpp +++ b/core/libs/prx/libc/src/Directory.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/GuestDirectory.hpp" #include "prx/libc/include/General.hpp" #include "prx/libc/include/FilesystemError.hpp" diff --git a/core/libs/prx/libc/src/Environment.cpp b/core/libs/prx/libc/src/Environment.cpp index f77b8727f9..a04c872b46 100644 --- a/core/libs/prx/libc/src/Environment.cpp +++ b/core/libs/prx/libc/src/Environment.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include #include #include diff --git a/core/libs/prx/libc/src/Errors.cpp b/core/libs/prx/libc/src/Errors.cpp index 3ca96f18ce..04d0187df9 100644 --- a/core/libs/prx/libc/src/Errors.cpp +++ b/core/libs/prx/libc/src/Errors.cpp @@ -1,10 +1,10 @@ +#include "prx/libc/include/WindowsFormatting.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/FileStream.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include -extern "C" int* APS5_VABI __error_nid_postfix(); - namespace { // Guest FreeBSD errno numbering, not the host CRT's numbering. constexpr const char* messages[] = { @@ -77,6 +77,7 @@ void APS5_VABI perror_nid_postfix(const char* prefix) { const int saved = *__error_nid_postfix(); char message[128]; strerror_r_nid_postfix(saved, message, sizeof(message)); + auto* stream = GetNativeStream(&_Stderr_nid_postfix); if (prefix && *prefix) std::fprintf(stream, "%s: %s\n", prefix, message); else std::fprintf(stream, "%s\n", message); diff --git a/core/libs/prx/libc/src/FileAndHeap.cpp b/core/libs/prx/libc/src/FileAndHeap.cpp index c5a44fa29e..d50cdfad16 100644 --- a/core/libs/prx/libc/src/FileAndHeap.cpp +++ b/core/libs/prx/libc/src/FileAndHeap.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include #include #include @@ -158,9 +159,6 @@ static bool IsPipeStream(std::FILE* native) { } #endif -using GuestCompare = int (APS5_VABI *)(const void*, const void*); -using GuestContextCompare = int (APS5_VABI *)(const void*, const void*, void*); - static void SwapElements(unsigned char* left, unsigned char* right, size_t size) { for (size_t index = 0; index < size; ++index) std::swap(left[index], right[index]); } @@ -303,8 +301,6 @@ void* heapAllocation(std::size_t bytes, TAllocate allocate) { extern "C" { -[[noreturn]] void APS5_VABI _ZSt11_Xbad_allocv_nid_postfix(); - FileStream* APS5_VABI fdopen_nid_postfix(int descriptor, const char* mode) { if (descriptor < 0) { errno = 9; return nullptr; } if (!mode) { errno = 22; return nullptr; } @@ -480,8 +476,6 @@ int APS5_VABI fclose_nid_postfix(FileStream* stream) { return stream->Close(); } -int APS5_VABI fseek_nid_postfix(FileStream* stream, std::int64_t offset, int origin); - FileStream* APS5_VABI _ZSt7_FiopenPKcNSt5_IosbIiE9_OpenmodeEi_nid_postfix(const char* filename, int mode, int protection) { static_cast(protection); constexpr int In = 0x01, Out = 0x02, Ate = 0x04, App = 0x08, Trunc = 0x10, Nocreate = 0x20, Noreplace = 0x40, @@ -502,6 +496,7 @@ FileStream* APS5_VABI _ZSt7_FiopenPKcNSt5_IosbIiE9_OpenmodeEi_nid_postfix(const auto* stream = fopen_nid_postfix(filename, openMode); if (!stream || !(mode & Ate) || fseek_nid_postfix(stream, 0, SEEK_END) == 0) return stream; fclose_nid_postfix(stream); + return nullptr; } @@ -744,6 +739,7 @@ int APS5_VABI mergesort_nid_postfix(void* base, size_t count, size_t size, Guest } if (source != base) std::memcpy(base, source, count * size); free_nid_postfix(scratch); + return 0; } diff --git a/core/libs/prx/libc/src/Filesystem.cpp b/core/libs/prx/libc/src/Filesystem.cpp index 510477eb7a..617ebf6e63 100644 --- a/core/libs/prx/libc/src/Filesystem.cpp +++ b/core/libs/prx/libc/src/Filesystem.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/FilesystemError.hpp" #include "prx/libc/include/General.hpp" #include diff --git a/core/libs/prx/libc/src/FloatBuiltins.cpp b/core/libs/prx/libc/src/FloatBuiltins.cpp index b059652259..235c74f27a 100644 --- a/core/libs/prx/libc/src/FloatBuiltins.cpp +++ b/core/libs/prx/libc/src/FloatBuiltins.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include #include #include @@ -8,9 +9,6 @@ namespace { -using Int128 = __int128; -using Uint128 = unsigned __int128; - constexpr std::uint32_t DefaultMxcsr = 0x1f80; template diff --git a/core/libs/prx/libc/src/FloatingPoint.cpp b/core/libs/prx/libc/src/FloatingPoint.cpp index e63d702609..ea910f0f3b 100644 --- a/core/libs/prx/libc/src/FloatingPoint.cpp +++ b/core/libs/prx/libc/src/FloatingPoint.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -61,8 +62,6 @@ int APS5_VABI fegetexceptflag_nid_postfix(std::uint16_t* flags, int exceptions) return 0; } -int* APS5_VABI __error_nid_postfix(); - void APS5_VABI _Feraise_nid_postfix(int exceptions) { constexpr unsigned Invalid = 0x01, Ranges = 0x1c, Overflows = 0x18, Inexact = 0x20; constexpr int GuestEdom = 33, GuestErange = 34; @@ -96,7 +95,6 @@ int APS5_VABI feclearexcept_nid_postfix(int exceptions) { return 0; } - int APS5_VABI feenableexcept_nid_postfix(int exceptions) { return ChangeTraps(exceptions, true); } diff --git a/core/libs/prx/libc/src/Formatting.cpp b/core/libs/prx/libc/src/Formatting.cpp index ad2e65acda..f44d577f43 100644 --- a/core/libs/prx/libc/src/Formatting.cpp +++ b/core/libs/prx/libc/src/Formatting.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include #include #include @@ -44,6 +45,7 @@ bool RequiresGuestFormatting(const char* format) { (*format == 'l' && (format[1] == 's' || format[1] == 'c' || format[1] == 'p'))) return true; while (*format && std::strchr("hljztL", *format)) ++format; if (*format && !std::strchr(LibcDetail::KnownConversions, *format)) return true; + if (*format && std::strchr("aAeEfFgG", *format)) return true; if (*format) ++format; } return false; @@ -86,7 +88,6 @@ bool IsWideScan(const std::string& length, char conversion) { return conversion == 'S' || conversion == 'C' || (length == "l" && (conversion == 's' || conversion == 'c' || conversion == '[')); } - #endif std::string HostLength(const std::string& length, char conversion) { @@ -653,6 +654,7 @@ extern FileStream* __stdinp_nid_postfix; int APS5_VABI vfscanf_nid_postfix(FileStream* stream, const char* format, VaList* args) { if (stream && !stream->IsOpen()) { errno = 9; return -1; } auto* native = GetNativeStream(stream); + if (!stream->SwitchToReading()) return EOF; #ifdef _WIN32 const int result = LibcDetail::ScanFileWindows_nid_no_patch(native, format, args); #else diff --git a/core/libs/prx/libc/src/FormattingWide.cpp b/core/libs/prx/libc/src/FormattingWide.cpp index ac1f820c1d..67a7fce10f 100644 --- a/core/libs/prx/libc/src/FormattingWide.cpp +++ b/core/libs/prx/libc/src/FormattingWide.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include #include #include @@ -218,8 +219,6 @@ std::u16string FormatWide(const char16_t* format, VaList* source, bool secure = extern "C" { extern FileStream* __stdoutp_nid_postfix; -std::int32_t APS5_VABI fgetwc_nid_postfix(FileStream* stream); -int APS5_VABI ferror_nid_postfix(FileStream* stream); int APS5_VABI vswprintf_nid_postfix(char16_t* buffer, std::size_t size, const char16_t* format, VaList* args) { if (buffer == nullptr || size == 0) { errno = 22; return -1; } @@ -322,6 +321,7 @@ int APS5_VABI vsnwprintf_s_nid_postfix(char16_t* buffer, std::size_t size, const } int APS5_VABI wprintf_nid_postfix(const char16_t* format, ...) { + if (!__stdoutp_nid_postfix->IsOpen()) { errno = 9; return -1; } APS5_VA_BEGIN(format); int result = -1; try { @@ -363,6 +363,7 @@ int APS5_VABI vwprintf_nid_postfix(const char16_t* format, VaList* args) { int APS5_VABI fputwc_nid_postfix(char16_t value, FileStream* stream) { if (stream == nullptr) { errno = 22; return -1; } + if (!stream->IsOpen()) { errno = 9; return -1; } try { const std::string bytes = ToUtf8(std::u16string(1, value)); auto* native = GetNativeStream(stream); @@ -377,6 +378,7 @@ int APS5_VABI fputwc_nid_postfix(char16_t value, FileStream* stream) { int APS5_VABI fputws_nid_postfix(const char16_t* str, FileStream* stream) { if (str == nullptr || stream == nullptr) { errno = 22; return -1; } + if (!stream->IsOpen()) { errno = 9; return -1; } try { const std::u16string text(str); const std::string bytes = ToUtf8(text); diff --git a/core/libs/prx/libc/src/General.cpp b/core/libs/prx/libc/src/General.cpp index 34c4457efe..e84d6caafc 100644 --- a/core/libs/prx/libc/src/General.cpp +++ b/core/libs/prx/libc/src/General.cpp @@ -1,4 +1,7 @@ +#include "prx/libc/include/Api.hpp" +#include #include +#include #include #include #include @@ -7,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -28,12 +32,26 @@ #include #include #include +#ifdef __linux__ +#include +#elif defined(__APPLE__) +#include +#include +#endif #include +#ifdef __linux__ +#include +#elif defined(__APPLE__) +#include +#include +#endif #endif #include "prx/libc/include/General.hpp" #include "prx/libc/include/FilesystemError.hpp" #include "prx/libc/include/AppArchive.hpp" +#include "prx/libc/include/GuestArena.hpp" #include "prx/libc/include/ApplicationHeap.hpp" +#include "prx/libc/include/GuestArena.hpp" namespace { // Guest prefixes (without leading slashes) mapped to host directories, e.g. save-data mount points: @@ -50,6 +68,41 @@ PathAliases& Aliases() { return *aliases; } +std::size_t HostPageSize() { + static const std::size_t size = [] { +#ifdef _WIN32 + SYSTEM_INFO info{}; + GetSystemInfo(&info); + return static_cast(info.dwPageSize); +#else + const long value = sysconf(_SC_PAGESIZE); + if (value <= 0) throw std::runtime_error("cannot query the host page size"); + return static_cast(value); +#endif + }(); + return size; +} + +bool CopyGuestBytes(void* destination, const void* source, std::size_t bytes) { + GuestArena::GuestArenaPrepareHostRead_nid_no_patch(source, bytes); +#ifdef _WIN32 + SIZE_T copied = 0; + return ReadProcessMemory(GetCurrentProcess(), source, destination, bytes, &copied) != 0 && copied == bytes; +#elif defined(__linux__) + iovec local{destination, bytes}; + iovec remote{const_cast(source), bytes}; + const auto copied = process_vm_readv(getpid(), &local, 1, &remote, 1, 0); + if (copied < 0 && errno != EFAULT) throw std::runtime_error("guest path: process_vm_readv failed with errno " + std::to_string(errno)); + return copied >= 0 && static_cast(copied) == bytes; +#elif defined(__APPLE__) + mach_vm_size_t copied = 0; + return mach_vm_read_overwrite(mach_task_self(), reinterpret_cast(source), bytes, + reinterpret_cast(destination), &copied) == KERN_SUCCESS && copied == bytes; +#else + throw std::runtime_error("checked guest path copies are not implemented on this host"); +#endif +} + std::string TrimSlashes(const char* path) { std::string s(path); std::size_t start = 0; @@ -488,6 +541,31 @@ int SetWorkingDirectory(WorkingDirectory& state, const std::filesystem::path& re } } +extern "C" int CopyGuestPath_nid_no_patch(const char* source, std::string& destination) { + constexpr std::size_t maximum = 1024; + if (source == nullptr) return 14; + const auto address = reinterpret_cast(source); + std::array bytes{}; + std::size_t offset = 0; + while (offset < bytes.size()) { + if (address > std::numeric_limits::max() - offset) return 14; + const auto current = address + offset; + const auto pageRemaining = HostPageSize() - current % HostPageSize(); + const auto count = std::min(pageRemaining, bytes.size() - offset); + if (!CopyGuestBytes(bytes.data() + offset, reinterpret_cast(current), count)) return 14; + if (const auto* end = static_cast(std::memchr(bytes.data() + offset, 0, count))) { + try { + destination.assign(bytes.data(), static_cast(end - bytes.data())); + } catch (const std::bad_alloc&) { + return 12; + } + return 0; + } + offset += count; + } + return 63; +} + #ifndef _WIN32 namespace { std::mutex g_hostStandardErrorMutex; @@ -726,6 +804,39 @@ extern "C" std::filesystem::path ResolveArchivedPath_nid_no_patch(const char* pa return ResolveLocked(path, module, true); } +extern "C" bool GuestCopyOut_nid_no_patch(void* destination, const void* source, std::size_t bytes) { + if (bytes == 0) return true; + const auto start = reinterpret_cast(destination); + if (start == 0 || bytes > UINTPTR_MAX - start) return false; + const GuestArena::HostWrite guard(destination, bytes); + if (!guard.Open()) return false; +#ifdef _WIN32 + for (auto address = start; address < start + bytes;) { + MEMORY_BASIC_INFORMATION memory{}; + if (VirtualQuery(reinterpret_cast(address), &memory, sizeof(memory)) != sizeof(memory) || memory.State != MEM_COMMIT || + (memory.Protect & PAGE_GUARD) != 0 || + (memory.Protect & (PAGE_READWRITE | PAGE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY)) == 0) return false; + address = reinterpret_cast(memory.BaseAddress) + memory.RegionSize; + } + std::memcpy(destination, source, bytes); + return true; +#elif defined(__linux__) + iovec local{const_cast(source), bytes}; + iovec remote{destination, bytes}; + const ssize_t copied = ::process_vm_writev(::getpid(), &local, 1, &remote, 1, 0); + if (copied < 0) { + if (errno == EFAULT) return false; + throw std::runtime_error("GuestCopyOut: process_vm_writev failed with errno " + std::to_string(errno)); + } + return static_cast(copied) == bytes; +#elif defined(__APPLE__) + return ::mach_vm_write(::mach_task_self(), reinterpret_cast(destination), + reinterpret_cast(source), static_cast(bytes)) == KERN_SUCCESS; +#else + throw std::runtime_error("GuestCopyOut: no checked write is available on this host"); +#endif +} + extern "C" std::filesystem::path ResolvePath_nid_no_patch(const char* path) { auto resolved = ResolveLocked(path, false, true); AppArchiveRefuseOnly_nid_no_patch(resolved, path, "reading"); diff --git a/core/libs/prx/libc/src/HeapDiagnostics.cpp b/core/libs/prx/libc/src/HeapDiagnostics.cpp index c8f99ed0d2..15f420f9c7 100644 --- a/core/libs/prx/libc/src/HeapDiagnostics.cpp +++ b/core/libs/prx/libc/src/HeapDiagnostics.cpp @@ -1,3 +1,5 @@ +#include "prx/libc/include/Api.hpp" +#include "prx/libc/include/FileStream.hpp" #include "prx/libc/include/General.hpp" #include "prx/libc/include/HeapDiagnostics.hpp" #include @@ -76,13 +78,15 @@ void APS5_VABI sceLibcInternalHeapErrorReportForGame_nid_postfix(void* heap, voi const auto* state = static_cast(heap); std::uint32_t number = 0; std::memcpy(&number, state + MspaceNumberOffset, sizeof(number)); - std::FILE* output = GuestStandardOutputFile_nid_no_patch(); - std::fprintf(output, "[SceLibc] A heap error is detected.\n[SceLibc] -- Mspace Name --\n[SceLibc] %s", state + MspaceNameOffset); - if (number != 0) std::fprintf(output, " (%2u)", number); - std::fputc('\n', output); - if (error == SegmentOutOfRange) std::fprintf(output, "[SceLibc] -- Error reason --\n[SceLibc] segment out of range.\n"); - std::fprintf(output, "[SceLibc] pid:<0x%lx> tid:<0x%lx>\n", CurrentProcessId(), CurrentThreadId()); - std::fflush(output); + if (_Stdout_nid_postfix.IsOpen()) { + std::FILE* output = GuestStandardOutputFile_nid_no_patch(); + std::fprintf(output, "[SceLibc] A heap error is detected.\n[SceLibc] -- Mspace Name --\n[SceLibc] %s", state + MspaceNameOffset); + if (number != 0) std::fprintf(output, " (%2u)", number); + std::fputc('\n', output); + if (error == SegmentOutOfRange) std::fprintf(output, "[SceLibc] -- Error reason --\n[SceLibc] segment out of range.\n"); + std::fprintf(output, "[SceLibc] pid:<0x%lx> tid:<0x%lx>\n", CurrentProcessId(), CurrentThreadId()); + std::fflush(output); + } std::fprintf(stderr, "[libc] heap error 0x%x: heap %p, block %p, reported from guest 0x%llx\n", error, heap, block, static_cast(reinterpret_cast(__builtin_return_address(0)))); } diff --git a/core/libs/prx/libc/src/Hostname.cpp b/core/libs/prx/libc/src/Hostname.cpp index 7b205e3659..a8a74cc4af 100644 --- a/core/libs/prx/libc/src/Hostname.cpp +++ b/core/libs/prx/libc/src/Hostname.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include diff --git a/core/libs/prx/libc/src/IntegerBuiltins.cpp b/core/libs/prx/libc/src/IntegerBuiltins.cpp index 2df42c3913..44a6e6df13 100644 --- a/core/libs/prx/libc/src/IntegerBuiltins.cpp +++ b/core/libs/prx/libc/src/IntegerBuiltins.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include #include #include @@ -8,9 +9,6 @@ namespace { -using Int128 = __int128; -using Uint128 = unsigned __int128; - constexpr Uint128 Int128SignBit = static_cast(1) << 127; constexpr Int128 Int128Max = static_cast(~Int128SignBit); constexpr Int128 Int128Min = static_cast(Int128SignBit); diff --git a/core/libs/prx/libc/src/Interfaces.cpp b/core/libs/prx/libc/src/Interfaces.cpp index a5be240839..9b82031aae 100644 --- a/core/libs/prx/libc/src/Interfaces.cpp +++ b/core/libs/prx/libc/src/Interfaces.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN #include @@ -31,17 +32,6 @@ #include #include -extern "C" int* APS5_VABI __error_nid_postfix(); - -struct GuestInterfaceAddress { - GuestInterfaceAddress* next; - char* name; - std::uint32_t flags; - void* address; - void* netmask; - void* destination; - void* data; -}; static_assert(sizeof(GuestInterfaceAddress) == 56); static_assert(offsetof(GuestInterfaceAddress, flags) == 16); static_assert(offsetof(GuestInterfaceAddress, address) == 24); diff --git a/core/libs/prx/libc/src/LocaleSupport.cpp b/core/libs/prx/libc/src/LocaleSupport.cpp index 9c3138778b..2546de6389 100644 --- a/core/libs/prx/libc/src/LocaleSupport.cpp +++ b/core/libs/prx/libc/src/LocaleSupport.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include #include #include @@ -24,11 +25,6 @@ #include "prx/libc/include/GuestLocale.hpp" #include "SceTypes.hpp" -extern "C" { -void* APS5_VABI _Znwm_nid_postfix(std::size_t size); -void APS5_VABI _ZdlPv_nid_postfix(void* pointer); -} - namespace { std::mutex g_localeInitMutex; @@ -110,6 +106,7 @@ void APS5_VABI DestroyCollate(GuestLocale::Facet*) {} void APS5_VABI DeleteCollate(GuestLocale::Facet* self) { if (self == nullptr) throw std::invalid_argument("collate delete: null facet"); _ZdlPv_nid_postfix(self); + } void APS5_VABI RetainFacet(GuestLocale::Facet* self) { @@ -411,11 +408,6 @@ GuestLocale::IosBase* APS5_VABI SetStreamWidth(GuestLocale::IosBase* stream, std return stream; } -struct StreamManipulator { - GuestLocale::IosBase* (APS5_VABI* function)(GuestLocale::IosBase*, std::int32_t); - std::int32_t argument; -}; - static_assert(sizeof(StreamManipulator) == 0x10); StreamManipulator APS5_VABI _ZSt4setwi_nid_postfix(std::int32_t width) { @@ -455,9 +447,7 @@ GuestLocale::Implementation* APS5_VABI _ZNSt6locale16_GetgloballocaleEv_nid_post } namespace { -struct GuestLocaleFacade { - GuestLocale::Implementation* implementation; -}; + GuestLocaleFacade g_classicLocaleFacade{&g_classicLocale}; } @@ -638,6 +628,7 @@ void APS5_VABI _init_env_nid_postfix() { void APS5_VABI init_env_nid_postfix(const InitEnvParams* params) { (void)params; _init_env_nid_postfix(); + } SonyLconv* APS5_VABI localeconv_nid_postfix(void) { diff --git a/core/libs/prx/libc/src/Math.cpp b/core/libs/prx/libc/src/Math.cpp index 84177877d1..e635b0b1e1 100644 --- a/core/libs/prx/libc/src/Math.cpp +++ b/core/libs/prx/libc/src/Math.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include #include #include @@ -328,6 +329,49 @@ double APS5_VABI hypot_nid_postfix(double x, double y) { } float APS5_VABI log10f_nid_postfix(float x) { return std::log10(x); } float APS5_VABI logbf_nid_postfix(float x) { return std::logb(x); } +float APS5_VABI exp2f_nid_postfix(float x) { + static constexpr double exp2ft[16] = { + 0x1.6a09e667f3bcdp-1, 0x1.7a11473eb0187p-1, 0x1.8ace5422aa0dbp-1, 0x1.9c49182a3f090p-1, + 0x1.ae89f995ad3adp-1, 0x1.c199bdd85529cp-1, 0x1.d5818dcfba487p-1, 0x1.ea4afa2a490dap-1, + 0x1.0000000000000p+0, 0x1.0b5586cf9890fp+0, 0x1.172b83c7d517bp+0, 0x1.2387a6e756238p+0, + 0x1.306fe0a31b715p+0, 0x1.3dea64c123422p+0, 0x1.4bfdad5362a27p+0, 0x1.5ab07dd485429p+0, + }; + static volatile float huge = 0x1p100f; + static volatile float twom100 = 0x1p-100f; + const float redux = 0x1.8p23f / 16; + const float P1 = 0x1.62e430p-1f; + const float P2 = 0x1.ebfbe0p-3f; + const float P3 = 0x1.c6b348p-5f; + const float P4 = 0x1.3b2c9cp-7f; + const std::uint32_t hx = std::bit_cast(x); + const std::uint32_t ix = hx & 0x7fffffff; + if (ix >= 0x43000000) { + if (ix >= 0x7f800000) { + return (ix & 0x7fffff) != 0 || (hx & 0x80000000) == 0 ? x + x : 0.0f; + } + if (x >= 0x1.0p7f) { + errno = ERANGE; + return huge * huge; + } + if (x <= -0x1.2cp7f) { + errno = ERANGE; + return twom100 * twom100; + } + } else if (ix <= 0x33000000) { + return 1.0f + x; + } + volatile float rounded = x + redux; + float t = rounded; + std::uint32_t i0 = std::bit_cast(t) + 8; + const std::int32_t k = static_cast(i0 >> 4) << 20; + i0 &= 15; + t -= redux; + const double z = x - t; + const double twopk = std::bit_cast(static_cast(static_cast(0x3ff00000 + k)) << 32); + const double u = exp2ft[i0] * z; + const double tv = exp2ft[i0] + u * (P1 + z * P2) + u * (z * z) * (P3 + z * P4); + return static_cast(tv * twopk); +} double APS5_VABI exp2_nid_postfix(double x) { int saved_errno = errno; double result = std::exp2(x); @@ -460,7 +504,95 @@ double APS5_VABI atan_nid_postfix(double x) { return std::atan(x); } double APS5_VABI tan_nid_postfix(double x) { return std::tan(x); } double APS5_VABI log2_nid_postfix(double x) { return std::log2(x); } double APS5_VABI log_nid_postfix(double x) { return std::log(x); } -double APS5_VABI log1p_nid_postfix(double x) { return std::log1p(x); } +double APS5_VABI log1p_nid_postfix(double x) { + const double ln2_hi = 6.93147180369123816490e-01; + const double ln2_lo = 1.90821492927058770002e-10; + const double two54 = 1.80143985094819840000e+16; + const double Lp1 = 6.666666666666735130e-01; + const double Lp2 = 3.999999999940941908e-01; + const double Lp3 = 2.857142874366239149e-01; + const double Lp4 = 2.222219843214978396e-01; + const double Lp5 = 1.818357216161805012e-01; + const double Lp6 = 1.531383769920937332e-01; + const double Lp7 = 1.479819860511658591e-01; + static volatile double vzero = 0.0; + const std::int32_t hx = static_cast(std::bit_cast(x) >> 32); + const std::int32_t ax = hx & 0x7fffffff; + std::int32_t k = 1; + std::int32_t hu = 0; + double f = 0.0; + double c = 0.0; + if (hx < 0x3fda827a) { + if (ax >= 0x3ff00000) { + if (x == -1.0) { + return -two54 / vzero; + } + errno = EDOM; + return (x - x) / (x - x); + } + if (ax < 0x3e200000) { + if (two54 + x > 0.0 && ax < 0x3c900000) { + return x; + } + return x - x * x * 0.5; + } + if (hx > 0 || hx <= static_cast(0xbfd2bec4)) { + k = 0; + f = x; + hu = 1; + } + } + if (hx >= 0x7ff00000) { + return x + x; + } + if (k != 0) { + double u; + if (hx < 0x43400000) { + u = 1.0 + x; + hu = static_cast(std::bit_cast(u) >> 32); + k = (hu >> 20) - 1023; + c = k > 0 ? 1.0 - (u - x) : x - (u - 1.0); + c /= u; + } else { + u = x; + hu = static_cast(std::bit_cast(u) >> 32); + k = (hu >> 20) - 1023; + c = 0; + } + hu &= 0x000fffff; + const std::uint64_t ulow = std::bit_cast(u) & 0xffffffffull; + if (hu < 0x6a09e) { + u = std::bit_cast((static_cast(static_cast(hu | 0x3ff00000)) << 32) | ulow); + } else { + k += 1; + u = std::bit_cast((static_cast(static_cast(hu | 0x3fe00000)) << 32) | ulow); + hu = (0x00100000 - hu) >> 2; + } + f = u - 1.0; + } + const double hfsq = 0.5 * f * f; + if (hu == 0) { + if (f == 0.0) { + if (k == 0) { + return 0.0; + } + c += k * ln2_lo; + return k * ln2_hi + c; + } + const double R = hfsq * (1.0 - 0.66666666666666666 * f); + if (k == 0) { + return f - R; + } + return k * ln2_hi - ((R - (k * ln2_lo + c)) - f); + } + const double s = f / (2.0 + f); + const double z = s * s; + const double R = z * (Lp1 + z * (Lp2 + z * (Lp3 + z * (Lp4 + z * (Lp5 + z * (Lp6 + z * Lp7)))))); + if (k == 0) { + return f - (hfsq - s * (hfsq + R)); + } + return k * ln2_hi - ((hfsq - (s * (hfsq + R) + (k * ln2_lo + c))) - f); +} float APS5_VABI log1pf_nid_postfix(float x) { return std::log1p(x); } static double Expm1(double x) { const double tiny = 1.0e-300; @@ -1022,7 +1154,6 @@ double APS5_VABI __powidf2_nid_postfix(double base, int exponent) { return reciprocal ? 1.0 / result : result; } float APS5_VABI expf_nid_postfix(float x) { return std::exp(x); } -float APS5_VABI exp2f_nid_postfix(float x) { return std::exp2(x); } float APS5_VABI logf_nid_postfix(float x) { const float ln2_hi = static_cast(6.9313812256e-01); const float ln2_lo = static_cast(9.0580006145e-06); @@ -1306,13 +1437,6 @@ int APS5_VABI _Fltrounds_nid_postfix(void) { return SonyFltrounds(); } -struct GuestFloatingPointEnvironment { - std::uint32_t control; - std::uint32_t status; - std::uint32_t tag; - unsigned char other[16]; - std::uint32_t mxcsr; -}; static_assert(sizeof(GuestFloatingPointEnvironment) == 32 && alignof(GuestFloatingPointEnvironment) == 4 && offsetof(GuestFloatingPointEnvironment, mxcsr) == 28); int APS5_VABI feupdateenv_nid_postfix(const GuestFloatingPointEnvironment* environment) { diff --git a/core/libs/prx/libc/src/MathExact.cpp b/core/libs/prx/libc/src/MathExact.cpp index 1217ca4a4c..bbfe5114ef 100644 --- a/core/libs/prx/libc/src/MathExact.cpp +++ b/core/libs/prx/libc/src/MathExact.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include #include #include diff --git a/core/libs/prx/libc/src/Mspace.cpp b/core/libs/prx/libc/src/Mspace.cpp index 8830e5c75c..53e55f6199 100644 --- a/core/libs/prx/libc/src/Mspace.cpp +++ b/core/libs/prx/libc/src/Mspace.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/MallocManagedSize.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -13,8 +14,6 @@ #include #include -extern "C" int* APS5_VABI __error_nid_postfix(); - namespace { constexpr unsigned MspaceThreadUnsafe = 1; @@ -322,6 +321,7 @@ void* APS5_VABI sceLibcPafMspaceMemalign_nid_postfix(void* handle, std::size_t a void APS5_VABI sceLibcPafMspaceFree_nid_postfix(void* handle, void* pointer, const void* owner) { (void)owner; sceLibcMspaceFree_nid_postfix(handle, pointer); + } void* APS5_VABI sceLibcPafMspaceCalloc_nid_postfix(void* handle, std::size_t count, std::size_t size, const void* owner) { diff --git a/core/libs/prx/libc/src/Multibyte.cpp b/core/libs/prx/libc/src/Multibyte.cpp index a1dc52cb4b..330701624b 100644 --- a/core/libs/prx/libc/src/Multibyte.cpp +++ b/core/libs/prx/libc/src/Multibyte.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libc/include/SonyCrt.hpp" #include diff --git a/core/libs/prx/libc/src/Process.cpp b/core/libs/prx/libc/src/Process.cpp index c200af881d..17f1889ed0 100644 --- a/core/libs/prx/libc/src/Process.cpp +++ b/core/libs/prx/libc/src/Process.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include #include #include @@ -21,8 +22,6 @@ #include "prx/libc/include/General.hpp" #include "SceTypes.hpp" -extern "C" int APS5_VABI __cxa_atexit_nid_postfix(void (APS5_VABI *func)(void*), void* arg, void* dsoHandle); - namespace { std::mutex shutdownMutex; @@ -35,7 +34,7 @@ std::exception_ptr shutdownFailure; std::stop_source shutdownSource; std::atomic exitRequested{false}; std::atomic exitStarted{false}; -using GuestExitCallback = void (APS5_VABI*)(); + thread_local bool runningExit = false; void APS5_VABI RunGuestExitCallback(void* callback) { @@ -272,6 +271,7 @@ int APS5_VABI at_quick_exit_nid_postfix(GuestExitCallback func) { } for (auto it = callbacks.rbegin(); it != callbacks.rend(); ++it) (*it)(); _Exit_nid_postfix(status); + } int APS5_VABI daemon_nid_postfix(int noChdir, int noClose) { diff --git a/core/libs/prx/libc/src/Random.cpp b/core/libs/prx/libc/src/Random.cpp index 5fee1280e8..03aba20b2e 100644 --- a/core/libs/prx/libc/src/Random.cpp +++ b/core/libs/prx/libc/src/Random.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libc/include/HostEntropy.hpp" #include diff --git a/core/libs/prx/libc/src/RealPath.cpp b/core/libs/prx/libc/src/RealPath.cpp index 10a0193b94..92c58204d9 100644 --- a/core/libs/prx/libc/src/RealPath.cpp +++ b/core/libs/prx/libc/src/RealPath.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/ApplicationHeap.hpp" #include "prx/libc/include/General.hpp" #include "prx/libc/include/general/VabiMacros.hpp" @@ -10,8 +11,6 @@ #include #include -extern "C" char* APS5_VABI getcwd_nid_postfix(char* buffer, std::size_t size); - namespace { constexpr std::size_t PathMax = 1024; constexpr std::string_view Separators = "/\\"; diff --git a/core/libs/prx/libc/src/Rename.cpp b/core/libs/prx/libc/src/Rename.cpp index 9ac9f5ad57..8c41ae277f 100644 --- a/core/libs/prx/libc/src/Rename.cpp +++ b/core/libs/prx/libc/src/Rename.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/FilesystemError.hpp" #include "prx/libc/include/RenameDot.hpp" #include "prx/libc/include/General.hpp" @@ -106,10 +107,17 @@ static int SourceLookupError_nid_no_patch(const std::filesystem::path& source) { } extern "C" int RenameGuestPath_nid_no_patch(const char* from, const char* to) { - if (!from) { errno = 14; return -1; } - if (!*from) { errno = 2; return -1; } + std::string fromCopy; + if (const int error = CopyGuestPath_nid_no_patch(from, fromCopy)) { errno = error; return -1; } + from = fromCopy.c_str(); + if (fromCopy.empty()) { errno = 2; return -1; } if (const int dot = RenameDotError_nid_no_patch(from)) { errno = dot; return -1; } - const int destinationError = !to ? 14 : !*to ? 2 : RenameDotError_nid_no_patch(to); + std::string toCopy; + int destinationError = CopyGuestPath_nid_no_patch(to, toCopy); + if (destinationError == 0) { + to = toCopy.c_str(); + destinationError = toCopy.empty() ? 2 : RenameDotError_nid_no_patch(to); + } try { const auto source = ResolvePath_nid_no_patch(from); if (destinationError) { diff --git a/core/libs/prx/libc/src/RuneLocale.cpp b/core/libs/prx/libc/src/RuneLocale.cpp index da1e4ace53..f038c5cd42 100644 --- a/core/libs/prx/libc/src/RuneLocale.cpp +++ b/core/libs/prx/libc/src/RuneLocale.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -109,6 +110,7 @@ int APS5_VABI iswpunct_nid_postfix(std::uint32_t c) { return GuestRune::Is(c, Gu int APS5_VABI iswspace_nid_postfix(std::uint32_t c) { return GuestRune::Is(c, GuestRune::Space); } int APS5_VABI iswupper_nid_postfix(std::uint32_t c) { return GuestRune::Is(c, GuestRune::Upper); } int APS5_VABI iswxdigit_nid_postfix(std::uint32_t c) { return GuestRune::Is(c, GuestRune::Hex); } +int APS5_VABI iswascii_nid_postfix(std::uint32_t c) { return (c & ~0x7Fu) == 0; } int APS5_VABI iswctype_nid_postfix(std::uint32_t c, std::uint64_t mask) { return GuestRune::Is(c, mask); } int APS5_VABI _Iswctype_nid_postfix(std::uint32_t c, std::uint64_t type) { @@ -160,10 +162,6 @@ int APS5_VABI wctob_nid_postfix(std::uint32_t c) { return unit < 0x80 ? static_cast(unit) : -1; } -std::uint32_t APS5_VABI _Towctrans_nid_postfix(std::uint32_t c, std::uint64_t desc); -const short* APS5_VABI _Getptolower_nid_postfix(); -const short* APS5_VABI _Getptoupper_nid_postfix(); - std::uint64_t APS5_VABI wctrans_nid_postfix(const char* property) { if (std::strcmp(property, "tolower") == 0) return 1; if (std::strcmp(property, "toupper") == 0) return 2; diff --git a/core/libs/prx/libc/src/RuntimeSupport.cpp b/core/libs/prx/libc/src/RuntimeSupport.cpp index 63c7955a92..dbaf710627 100644 --- a/core/libs/prx/libc/src/RuntimeSupport.cpp +++ b/core/libs/prx/libc/src/RuntimeSupport.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include #include #include @@ -165,10 +166,12 @@ void APS5_VABI _Unlockfilelock_nid_postfix(FileStream* stream) { void APS5_VABI flockfile_nid_postfix(FileStream* stream) { _Lockfilelock_nid_postfix(stream); + } void APS5_VABI funlockfile_nid_postfix(FileStream* stream) { _Unlockfilelock_nid_postfix(stream); + } int APS5_VABI ftrylockfile_nid_postfix(FileStream* stream) { diff --git a/core/libs/prx/libc/src/ScanningWide.cpp b/core/libs/prx/libc/src/ScanningWide.cpp index aeca7eae6a..0390ecd6cb 100644 --- a/core/libs/prx/libc/src/ScanningWide.cpp +++ b/core/libs/prx/libc/src/ScanningWide.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include #include #include @@ -22,13 +23,6 @@ #define APS5_VA_END() va_end(args) #endif -extern "C" int APS5_VABI iswspace_nid_postfix(std::uint32_t c); -extern "C" std::size_t APS5_VABI wcrtomb_nid_postfix(char* destination, std::uint16_t value, void* state); -extern "C" std::int32_t APS5_VABI fgetwc_nid_postfix(FileStream* stream); -extern "C" int APS5_VABI ungetc_nid_postfix(int value, FileStream* stream); -extern "C" void APS5_VABI flockfile_nid_postfix(FileStream* stream); -extern "C" void APS5_VABI funlockfile_nid_postfix(FileStream* stream); - namespace { enum class Fit { Invalid, Prefix, Valid }; diff --git a/core/libs/prx/libc/src/StandardStreams.cpp b/core/libs/prx/libc/src/StandardStreams.cpp index 05767fd5f4..b40f822753 100644 --- a/core/libs/prx/libc/src/StandardStreams.cpp +++ b/core/libs/prx/libc/src/StandardStreams.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/FileStream.hpp" #include "prx/libc/include/General.hpp" #include "prx/libc/include/general/VabiMacros.hpp" @@ -80,8 +81,7 @@ const bool standardDescriptorsOpen = [] { FileStream input{stdin}; } extern "C" { -void APS5_VABI flockfile_nid_postfix(FileStream*); -void APS5_VABI funlockfile_nid_postfix(FileStream*); + FileStream* __stdinp_nid_postfix = &input; FileStream* __stdoutp_nid_postfix = &_Stdout_nid_postfix; FileStream* __stderrp_nid_postfix = &_Stderr_nid_postfix; @@ -124,8 +124,8 @@ std::int32_t APS5_VABI fgetwc_nid_postfix(FileStream* stream) { return static_cast(code); } - std::int32_t APS5_VABI ungetwc_nid_postfix(std::int32_t value, FileStream* stream) { + if (stream && !stream->IsOpen()) { errno = 9; return -1; } if (value == -1) return -1; if (value < 0 || value > 255) { errno = 86; @@ -159,6 +159,7 @@ char* APS5_VABI gets_nid_postfix(char* buffer) { auto* stream = __stdinp_nid_postfix; if (stream && !stream->IsOpen()) { errno = 9; return nullptr; } flockfile_nid_postfix(stream); + struct Unlock { FileStream* stream; ~Unlock() { funlockfile_nid_postfix(stream); } @@ -281,5 +282,6 @@ int APS5_VABI setvbuf_nid_postfix(FileStream* stream, char* buffer, int mode, st } void APS5_VABI setbuf_nid_postfix(FileStream* stream, char* buffer) { setvbuf_nid_postfix(stream, buffer, buffer ? 0 : 2, buffer ? 1024 : 0); + } } diff --git a/core/libs/prx/libc/src/StdioExtras.cpp b/core/libs/prx/libc/src/StdioExtras.cpp index 5cc08407b7..f6ebcc9784 100644 --- a/core/libs/prx/libc/src/StdioExtras.cpp +++ b/core/libs/prx/libc/src/StdioExtras.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include #include #include @@ -18,8 +19,6 @@ namespace { -using GuestNewHandler = void (APS5_VABI*)(); - std::atomic g_newHandler{nullptr}; void* Allocate(std::size_t size) { @@ -132,6 +131,7 @@ void APS5_VABI _ZdlPv_nid_postfix(void* pointer) { void APS5_VABI _ZdlPvRKSt9nothrow_t_nid_postfix(void* pointer, const void*) noexcept { _ZdlPv_nid_postfix(pointer); + } void APS5_VABI _ZdaPv_nid_postfix(void* pointer) { diff --git a/core/libs/prx/libc/src/StringExtensions.cpp b/core/libs/prx/libc/src/StringExtensions.cpp index 18b9cb6f18..35eed9a5f4 100644 --- a/core/libs/prx/libc/src/StringExtensions.cpp +++ b/core/libs/prx/libc/src/StringExtensions.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -169,7 +170,6 @@ char* APS5_VABI strtok_nid_postfix(char* text, const char* delimiters) { return strtok_r_nid_postfix(text, delimiters, &state); } - int APS5_VABI __inet_aton_nid_postfix(const char* text, void* address) { std::uint8_t parts[3]; std::size_t count = 0; diff --git a/core/libs/prx/libc/src/Strings.cpp b/core/libs/prx/libc/src/Strings.cpp index 721ede0c0a..18d1df74bc 100644 --- a/core/libs/prx/libc/src/Strings.cpp +++ b/core/libs/prx/libc/src/Strings.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include #include #include @@ -20,6 +21,16 @@ int CompareUnits(char16_t left, char16_t right) { return left < right ? -1 : 1; } +int ByteDifference(const void* s1, const void* s2, size_t n, bool stopAtNul) { + const auto* left = static_cast(s1); + const auto* right = static_cast(s2); + for (size_t index = 0; index < n; ++index) { + if (left[index] != right[index]) return left[index] - right[index]; + if (stopAtNul && left[index] == 0) return 0; + } + return 0; +} + bool Contains(const char16_t* set, char16_t character) { for (; *set != 0; ++set) { if (*set == character) return true; @@ -245,7 +256,7 @@ void* APS5_VABI memmove_nid_postfix(void* dest, const void* src, size_t n) { } int APS5_VABI memcmp_nid_postfix(const void* s1, const void* s2, size_t n) { - return std::memcmp(s1, s2, n); + return std::memcmp(s1, s2, n) == 0 ? 0 : ByteDifference(s1, s2, n, false); } const void* APS5_VABI memchr_nid_postfix(const void* s, int c, size_t n) { @@ -289,11 +300,11 @@ void* APS5_VABI memmem_nid_postfix(const void* haystack, size_t haystacklen, con } int APS5_VABI strcmp_nid_postfix(const char* s1, const char* s2) { - return std::strcmp(s1, s2); + return std::strcmp(s1, s2) == 0 ? 0 : ByteDifference(s1, s2, std::numeric_limits::max(), true); } int APS5_VABI strncmp_nid_postfix(const char* s1, const char* s2, size_t n) { - return std::strncmp(s1, s2, n); + return std::strncmp(s1, s2, n) == 0 ? 0 : ByteDifference(s1, s2, n, true); } size_t APS5_VABI strlen_nid_postfix(const char* s) { @@ -447,11 +458,8 @@ char16_t* APS5_VABI wmemmove_nid_postfix(char16_t* dest, const char16_t* src, si } - extern "C" { -int APS5_VABI tolower_nid_postfix(int); - int APS5_VABI strcasecmp_nid_postfix(const char* s1, const char* s2) { for (;; ++s1, ++s2) { const int a = tolower_nid_postfix(static_cast(*s1)); @@ -811,6 +819,7 @@ int APS5_VABI wmemcpy_s_nid_postfix(char16_t* dest, size_t destsz, const char16_ if (destsz > RsizeMax) return GuestErange; if (!src || count > destsz) { wmemset_nid_postfix(dest, 0, destsz); + return src ? GuestErange : GuestEinval; } const auto destination = reinterpret_cast(dest); @@ -818,6 +827,7 @@ int APS5_VABI wmemcpy_s_nid_postfix(char16_t* dest, size_t destsz, const char16_ const auto distance = destination < source ? source - destination : destination - source; if (count != 0 && distance < count * sizeof(char16_t)) { wmemset_nid_postfix(dest, 0, destsz); + return GuestEinval; } if (count != 0) std::memcpy(dest, src, count * sizeof(char16_t)); @@ -832,6 +842,7 @@ int APS5_VABI wmemmove_s_nid_postfix(char16_t* dest, size_t destsz, const char16 if (destsz > RsizeMax) return GuestErange; if (!src || count > destsz) { wmemset_nid_postfix(dest, 0, destsz); + return src ? GuestErange : GuestEinval; } if (count != 0) std::memmove(dest, src, count * sizeof(char16_t)); diff --git a/core/libs/prx/libc/src/Syslog.cpp b/core/libs/prx/libc/src/Syslog.cpp index a94f34e141..137566b52f 100644 --- a/core/libs/prx/libc/src/Syslog.cpp +++ b/core/libs/prx/libc/src/Syslog.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "SceTypes.hpp" #include @@ -13,12 +14,6 @@ #include #endif -extern "C" { -int* APS5_VABI __error_nid_postfix(); -int APS5_VABI strerror_r_nid_postfix(int error, char* buffer, std::size_t length); -int APS5_VABI vsnprintf_nid_postfix(char* buffer, std::size_t size, const char* format, VaList* args); -} - namespace { constexpr int priorityMask = 0x07; constexpr int facilityMask = 0x3f8; @@ -57,6 +52,7 @@ std::string ExpandErrorText(const char* format, int error) { if (cursor[0] == '%' && cursor[1] == 'm') { char text[128]; strerror_r_nid_postfix(error, text, sizeof(text)); + for (const char* character = text; *character; ++character) { expanded += *character; if (*character == '%') expanded += '%'; @@ -82,6 +78,7 @@ std::string Format(const char* format, VaList* args) { if (size <= 0) return {}; std::string buffer(static_cast(size) + 1, '\0'); vsnprintf_nid_postfix(buffer.data(), buffer.size(), format, args); + buffer.resize(static_cast(size)); return buffer; #endif @@ -135,6 +132,7 @@ void APS5_VABI syslog_nid_postfix(int priority, const char* format, ...) { va_start(args, format); #endif vsyslog_nid_postfix(priority, format, reinterpret_cast(args)); + #ifdef _WIN32 __builtin_sysv_va_end(args); #else diff --git a/core/libs/prx/libc/src/Threads.cpp b/core/libs/prx/libc/src/Threads.cpp index ae9bd58fa7..8f13974d7a 100644 --- a/core/libs/prx/libc/src/Threads.cpp +++ b/core/libs/prx/libc/src/Threads.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libc/include/General.hpp" #ifdef _WIN32 @@ -26,11 +27,6 @@ namespace { -struct Xtime { - std::int64_t sec; - std::int64_t nsec; -}; - constexpr std::int64_t nanosPerSecond = 1000000000; constexpr std::int64_t longestSleepSeconds = 86400; @@ -392,13 +388,6 @@ int APS5_VABI _Cnd_signal_nid_postfix(void** handle) { return SignalCondition_nid_no_patch(handle); } -struct GuestPad { - unsigned (APS5_VABI* const* vtable)(GuestPad*); - void* condition; - void* mutex; - bool started; -}; - static_assert(offsetof(GuestPad, condition) == 0x8 && offsetof(GuestPad, mutex) == 0x10 && offsetof(GuestPad, started) == 0x18 && sizeof(GuestPad) == 0x20); [[noreturn]] void ThrowCppError_nid_no_patch(int code); @@ -446,6 +435,7 @@ void APS5_VABI _ZNSt4_PadC2Ev_nid_postfix(GuestPad* pad) { const int created = _Mtx_init_nid_postfix(&pad->mutex, 1); if (created != threadSuccess) { _Cnd_destroy_nid_postfix(&pad->condition); + RequireThrd(created, "_Pad::_Pad: _Mtx_init"); } pad->started = false; @@ -453,6 +443,7 @@ void APS5_VABI _ZNSt4_PadC2Ev_nid_postfix(GuestPad* pad) { if (locked != threadSuccess) { _Mtx_destroy_nid_postfix(&pad->mutex); _Cnd_destroy_nid_postfix(&pad->condition); + RequireThrd(locked, "_Pad::_Pad: _Mtx_lock"); } } @@ -462,6 +453,7 @@ void APS5_VABI _ZNSt4_PadD2Ev_nid_postfix(GuestPad* pad) { RequireThrd(_Mtx_unlock_nid_postfix(&pad->mutex), "_Pad::~_Pad: _Mtx_unlock"); _Mtx_destroy_nid_postfix(&pad->mutex); _Cnd_destroy_nid_postfix(&pad->condition); + } void APS5_VABI _ZNSt4_Pad8_ReleaseEv_nid_postfix(GuestPad* pad) { @@ -673,4 +665,3 @@ void* APS5_VABI _ZNSt8__sce_v28_Thrd_idEv_nid_postfix() { } } - diff --git a/core/libs/prx/libc/src/Time.cpp b/core/libs/prx/libc/src/Time.cpp index 544c4bc63e..14a1b8bc68 100644 --- a/core/libs/prx/libc/src/Time.cpp +++ b/core/libs/prx/libc/src/Time.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include #include #include @@ -20,6 +21,7 @@ #include "prx/libc/include/SonyCrt.hpp" extern "C" char* tzname_nid_postfix[2]; +extern "C" int64_t timezone_nid_postfix; namespace { @@ -161,8 +163,6 @@ const bool timeZoneFixed = [] { } // namespace #endif -extern "C" int64_t APS5_VABI libc_mktime_nid_postfix(GuestTm* timeptr); - namespace { bool setHostZone(const char* zone) { @@ -244,19 +244,6 @@ constexpr const char* MONTH_FULL_NAMES[] = {"January", "February", "March", "Apr "October", "November", "December"}; constexpr int YEAR_BASE = 1900; -enum class Padding { Default, Less, Space, Zero }; - -const char* paddingFormat(int width, Padding padding, bool spaced) { - static constexpr const char* formats[][4] = { - {"%02d", "%d", "%2d", "%02d"}, - {"%2d", "%d", "%2d", "%02d"}, - {"%03d", "%d", "%3d", "%03d"}, - {"%04d", "%d", "%4d", "%04d"}, - }; - const int row = width == 2 ? (spaced ? 1 : 0) : width == 3 ? 2 : 3; - return formats[row][static_cast(padding)]; -} - bool isLeapYearSum(int year, int base) { return isLeapYear(year % 400 + base % 400); } @@ -264,248 +251,151 @@ bool isLeapYearSum(int year, int base) { struct FormatBuffer { char* cursor; char* limit; + bool full; }; -void addText(FormatBuffer& buffer, const char* text) { - while (buffer.cursor < buffer.limit && (*buffer.cursor = *text++) != '\0') ++buffer.cursor; +void addPiece(FormatBuffer& buffer, const char* text, std::size_t length) { + if (buffer.full) return; + if (length > static_cast(buffer.limit - buffer.cursor)) { + buffer.full = true; + return; + } + std::memcpy(buffer.cursor, text, length); + buffer.cursor += length; } -void addNumber(FormatBuffer& buffer, int value, const char* format) { +void addText(FormatBuffer& buffer, const char* text) { + addPiece(buffer, text, std::strlen(text)); +} + +int clampedField(std::int64_t value, int modulus) { + return value < 0 ? 0 : static_cast(value % modulus); +} + +void addNumber(FormatBuffer& buffer, std::int64_t value, int modulus, const char* format) { char text[16]; - std::snprintf(text, sizeof(text), format, value); + std::snprintf(text, sizeof(text), format, clampedField(value, modulus)); addText(buffer, text); } -void addYear(FormatBuffer& buffer, int year, int base, bool century, bool lastDigits) { - int trail = year % 100 + base % 100; - int lead = year / 100 + base / 100 + trail / 100; - trail %= 100; - if (trail < 0 && lead > 0) { - trail += 100; - --lead; - } else if (lead < 0 && trail > 0) { - trail -= 100; - ++lead; - } - if (century) { - if (lead == 0 && trail < 0) addText(buffer, "-0"); - else addNumber(buffer, lead, "%02d"); - } - if (lastDigits) addNumber(buffer, trail < 0 ? -trail : trail, "%02d"); +const char* tableName(int index, const char* const* names, const char* const* shortNames, int count) { + if (index < 0) return shortNames[0]; + return index < count ? names[index] : ""; } -const char* guestZoneName(const GuestTm& guest) { - if (guest.tm_zone != nullptr) return guest.tm_zone; - if (guest.tm_isdst < 0) return ""; -#ifdef _WIN32 - return _tzname[guest.tm_isdst != 0 ? 1 : 0]; -#else - return tzname[guest.tm_isdst != 0 ? 1 : 0]; -#endif +int twoDigitYear(std::int64_t year) { + return static_cast((year % 100 + 100) % 100); } -void addIsoWeek(FormatBuffer& buffer, char conversion, Padding padding, const GuestTm& time) { +std::int64_t weekOfYear(const GuestTm& time, int shift) { + return (static_cast(time.tm_yday) + 7 - (static_cast(time.tm_wday) + shift) % 7) / 7; +} + +struct IsoWeek { + std::int64_t year; + int week; +}; + +IsoWeek isoWeek(const GuestTm& time) { + if (time.tm_yday < 0) NotImplemented_nid_no_patch("strftime: ISO week of a negative tm_yday"); + if (time.tm_yday >= (isLeapYearSum(time.tm_year, YEAR_BASE) ? 366 : 365)) NotImplemented_nid_no_patch("strftime: ISO week of a tm_yday past the year"); + if (time.tm_wday < -6) NotImplemented_nid_no_patch("strftime: ISO week of a tm_wday below -6"); int base = YEAR_BASE; - int yday = time.tm_yday; - int week = 0; + std::int64_t yday = time.tm_yday; for (;;) { const int length = isLeapYearSum(time.tm_year, base) ? 366 : 365; - const int bottom = (yday + 11 - time.tm_wday) % 7 - 3; - int top = bottom - length % 7; + const std::int64_t bottom = (yday + 11 - time.tm_wday) % 7 - 3; + std::int64_t top = bottom - length % 7; if (top < -3) top += 7; top += length; - if (yday >= top) { - ++base; - week = 1; - break; - } - if (yday >= bottom) { - week = 1 + (yday - bottom) / 7; - break; - } + if (yday >= top) return {static_cast(time.tm_year) + base + 1, 1}; + if (yday >= bottom) return {static_cast(time.tm_year) + base, static_cast(1 + (yday - bottom) / 7)}; --base; yday += isLeapYearSum(time.tm_year, base) ? 366 : 365; } - if (conversion == 'V') addNumber(buffer, week, paddingFormat(2, padding, false)); - else addYear(buffer, time.tm_year, base, conversion == 'G', true); +} + +void formatTime(FormatBuffer& buffer, const char* format, const GuestTm& time); + +void addZoneOffset(FormatBuffer& buffer, const GuestTm& time) { + std::int64_t east = -timezone_nid_postfix + (time.tm_isdst > 0 ? 3600 : 0); + const char sign = east < 0 ? '-' : '+'; + if (east < 0) east = -east; + char text[32]; + std::snprintf(text, sizeof(text), "%c%02lld%02lld", sign, static_cast(east / 3600), static_cast(east / 60 % 60)); + addText(buffer, text); +} + +bool addConversion(FormatBuffer& buffer, char conversion, const GuestTm& time) { + const std::int64_t year = static_cast(time.tm_year) + YEAR_BASE; + switch (conversion) { + case 'a': addText(buffer, tableName(time.tm_wday, WEEKDAY_NAMES, WEEKDAY_NAMES, 7)); return true; + case 'A': addText(buffer, tableName(time.tm_wday, WEEKDAY_FULL_NAMES, WEEKDAY_NAMES, 7)); return true; + case 'b': + case 'h': addText(buffer, tableName(time.tm_mon, MONTH_NAMES, MONTH_NAMES, 12)); return true; + case 'B': addText(buffer, tableName(time.tm_mon, MONTH_FULL_NAMES, MONTH_NAMES, 12)); return true; + case 'c': formatTime(buffer, "%a %b %e %H:%M:%S %Y", time); return true; + case 'C': addNumber(buffer, time.tm_year / 100 + YEAR_BASE / 100, 100, "%02d"); return true; + case 'd': addNumber(buffer, time.tm_mday, 100, "%02d"); return true; + case 'D': + case 'x': formatTime(buffer, "%m/%d/%y", time); return true; + case 'e': addNumber(buffer, time.tm_mday, 100, "%2d"); return true; + case 'F': formatTime(buffer, "%Y-%m-%d", time); return true; + case 'g': addNumber(buffer, twoDigitYear(isoWeek(time).year), 100, "%02d"); return true; + case 'G': addNumber(buffer, isoWeek(time).year, 10000, "%04d"); return true; + case 'H': addNumber(buffer, time.tm_hour, 100, "%02d"); return true; + case 'I': addNumber(buffer, (static_cast(time.tm_hour) + 11) % 12 + 1, 100, "%02d"); return true; + case 'j': addNumber(buffer, static_cast(time.tm_yday) + 1, 1000, "%03d"); return true; + case 'm': addNumber(buffer, static_cast(time.tm_mon) + 1, 100, "%02d"); return true; + case 'M': addNumber(buffer, time.tm_min, 100, "%02d"); return true; + case 'n': addText(buffer, "\n"); return true; + case 'p': addText(buffer, time.tm_hour < 12 ? "AM" : "PM"); return true; + case 'r': formatTime(buffer, "%I:%M:%S %p", time); return true; + case 'R': formatTime(buffer, "%H:%M", time); return true; + case 'S': addNumber(buffer, time.tm_sec, 100, "%02d"); return true; + case 't': addText(buffer, "\t"); return true; + case 'T': + case 'X': formatTime(buffer, "%H:%M:%S", time); return true; + case 'u': addNumber(buffer, time.tm_wday == 0 ? 7 : time.tm_wday, 10, "%d"); return true; + case 'U': addNumber(buffer, weekOfYear(time, 7), 100, "%02d"); return true; + case 'V': addNumber(buffer, isoWeek(time).week, 100, "%02d"); return true; + case 'w': addNumber(buffer, time.tm_wday, 10, "%d"); return true; + case 'W': addNumber(buffer, weekOfYear(time, 6), 100, "%02d"); return true; + case 'y': addNumber(buffer, twoDigitYear(year), 100, "%02d"); return true; + case 'Y': addNumber(buffer, year, 10000, "%04d"); return true; + case 'z': addZoneOffset(buffer, time); return true; + case 'Z': { + const char* name = tzname_nid_postfix[time.tm_isdst > 0 ? 1 : 0]; + addText(buffer, name != nullptr ? name : ""); + return true; + } + case '%': addText(buffer, "%"); return true; + default: return false; + } } void formatTime(FormatBuffer& buffer, const char* format, const GuestTm& time) { - for (; *format != '\0'; ++format) { - if (*format == '%') { - bool alternative = false; - Padding padding = Padding::Default; - bool handled = true; - for (bool modifier = true; modifier;) { - modifier = false; - switch (*++format) { - case '\0': - --format; - handled = false; - break; - case 'A': - addText(buffer, time.tm_wday < 0 || time.tm_wday >= 7 ? "?" : WEEKDAY_FULL_NAMES[time.tm_wday]); - break; - case 'a': - addText(buffer, time.tm_wday < 0 || time.tm_wday >= 7 ? "?" : WEEKDAY_NAMES[time.tm_wday]); - break; - case 'B': - addText(buffer, time.tm_mon < 0 || time.tm_mon >= 12 ? "?" : MONTH_FULL_NAMES[time.tm_mon]); - break; - case 'b': - case 'h': - addText(buffer, time.tm_mon < 0 || time.tm_mon >= 12 ? "?" : MONTH_NAMES[time.tm_mon]); - break; - case 'C': - addYear(buffer, time.tm_year, YEAR_BASE, true, false); - break; - case 'c': - formatTime(buffer, "%a %b %e %H:%M:%S %Y", time); - break; - case 'D': - formatTime(buffer, "%m/%d/%y", time); - break; - case 'd': - addNumber(buffer, time.tm_mday, paddingFormat(2, padding, false)); - break; - case 'E': - case 'O': - if (alternative) { - handled = false; - break; - } - alternative = true; - modifier = true; - break; - case 'e': - addNumber(buffer, time.tm_mday, paddingFormat(2, padding, true)); - break; - case 'F': - formatTime(buffer, "%Y-%m-%d", time); - break; - case 'H': - addNumber(buffer, time.tm_hour, paddingFormat(2, padding, false)); - break; - case 'I': - addNumber(buffer, time.tm_hour % 12 != 0 ? time.tm_hour % 12 : 12, paddingFormat(2, padding, false)); - break; - case 'j': - addNumber(buffer, time.tm_yday + 1, paddingFormat(3, padding, false)); - break; - case 'k': - addNumber(buffer, time.tm_hour, paddingFormat(2, padding, true)); - break; - case 'l': - addNumber(buffer, time.tm_hour % 12 != 0 ? time.tm_hour % 12 : 12, paddingFormat(2, padding, true)); - break; - case 'M': - addNumber(buffer, time.tm_min, paddingFormat(2, padding, false)); - break; - case 'm': - addNumber(buffer, time.tm_mon + 1, paddingFormat(2, padding, false)); - break; - case 'n': - addText(buffer, "\n"); - break; - case 'p': - addText(buffer, time.tm_hour >= 12 ? "PM" : "AM"); - break; - case 'R': - formatTime(buffer, "%H:%M", time); - break; - case 'r': - formatTime(buffer, "%I:%M:%S %p", time); - break; - case 'S': - addNumber(buffer, time.tm_sec, paddingFormat(2, padding, false)); - break; - case 's': { - GuestTm copy = time; - char text[24]; - std::snprintf(text, sizeof(text), "%lld", static_cast(libc_mktime_nid_postfix(©))); - addText(buffer, text); - break; - } - case 'T': - formatTime(buffer, "%H:%M:%S", time); - break; - case 't': - addText(buffer, "\t"); - break; - case 'U': - addNumber(buffer, (time.tm_yday + 7 - time.tm_wday) / 7, paddingFormat(2, padding, false)); - break; - case 'u': - addNumber(buffer, time.tm_wday == 0 ? 7 : time.tm_wday, "%d"); - break; - case 'V': - case 'G': - case 'g': - addIsoWeek(buffer, *format, padding, time); - break; - case 'v': - formatTime(buffer, "%e-%b-%Y", time); - break; - case 'W': - addNumber(buffer, (time.tm_yday + 7 - (time.tm_wday != 0 ? time.tm_wday - 1 : 6)) / 7, - paddingFormat(2, padding, false)); - break; - case 'w': - addNumber(buffer, time.tm_wday, "%d"); - break; - case 'X': - formatTime(buffer, "%H:%M:%S", time); - break; - case 'x': - formatTime(buffer, "%m/%d/%y", time); - break; - case 'y': - addYear(buffer, time.tm_year, YEAR_BASE, false, true); - break; - case 'Y': - addYear(buffer, time.tm_year, YEAR_BASE, true, true); - break; - case 'Z': - addText(buffer, guestZoneName(time)); - break; - case 'z': { - if (time.tm_isdst < 0) break; - int difference = static_cast(time.tm_gmtoff); - addText(buffer, difference < 0 ? "-" : "+"); - if (difference < 0) difference = -difference; - difference /= 60; - addNumber(buffer, difference / 60 * 100 + difference % 60, paddingFormat(4, padding, false)); - break; - } - case '+': - formatTime(buffer, "%a %b %e %H:%M:%S %Z %Y", time); - break; - case '-': - case '_': - case '0': - if (padding != Padding::Default) { - handled = false; - break; - } - padding = *format == '-' ? Padding::Less : *format == '_' ? Padding::Space : Padding::Zero; - modifier = true; - break; - default: - handled = false; - break; - } - } - if (handled) continue; + for (; *format != '\0' && !buffer.full; ++format) { + if (*format != '%' || format[1] == '\0') { + addPiece(buffer, format, 1); + continue; + } + ++format; + if (*format == 'E' || *format == 'O') { + if (format[1] == '\0') throw std::invalid_argument("strftime: the format ends after an E or O modifier"); + ++format; + } + if (!addConversion(buffer, *format, time)) { + const char unknown[] = {'%', *format}; + addPiece(buffer, unknown, sizeof(unknown)); } - if (buffer.cursor == buffer.limit) break; - *buffer.cursor++ = *format; } } std::size_t formatGuestTime(char* destination, std::size_t size, const char* format, const GuestTm& time) { - FormatBuffer buffer{destination, destination + size}; + FormatBuffer buffer{destination, destination + size, false}; formatTime(buffer, format == nullptr ? "%c" : format, time); - if (buffer.cursor == buffer.limit) return 0; + if (buffer.full || buffer.cursor == buffer.limit) return 0; *buffer.cursor = '\0'; return static_cast(buffer.cursor - destination); } @@ -538,14 +428,6 @@ char* tzname_nid_postfix[2] = {GuestZoneName(0), GuestZoneName(1)}; int64_t timezone_nid_postfix = 0; int daylight_nid_postfix = 0; -GuestTm* APS5_VABI localtime_s_nid_postfix(const int64_t* timer, GuestTm* result); -GuestTm* APS5_VABI gmtime_s_nid_postfix(const int64_t* timer, GuestTm* result); -int64_t APS5_VABI libc_time_nid_postfix(int64_t* timer); -double APS5_VABI libc_difftime_nid_postfix(int64_t time1, int64_t time0); -std::size_t APS5_VABI wcsrtombs_nid_postfix(char* destination, const std::uint16_t** source, std::size_t capacity, void* state); -std::size_t APS5_VABI mbsrtowcs_nid_postfix(std::uint16_t* destination, const char** source, std::size_t capacity, void* state); -int APS5_VABI _Getmbcurmax_nid_postfix(); - void APS5_VABI tzset_nid_postfix(void) { const ZoneScope zone; tzname_nid_postfix[0] = GuestZoneName(0); @@ -555,6 +437,7 @@ void APS5_VABI tzset_nid_postfix(void) { GuestTm local{}; gmtime_s_nid_postfix(&now, &universal); localtime_s_nid_postfix(&now, &local); + daylight_nid_postfix = local.tm_isdst >= 0 ? 1 : 0; timezone_nid_postfix = static_cast(libc_difftime_nid_postfix(libc_mktime_nid_postfix(&universal), libc_mktime_nid_postfix(&local))); } @@ -702,6 +585,7 @@ int64_t APS5_VABI mktime_nid_postfix(GuestTm* timeptr) { size_t APS5_VABI libc_strftime_nid_postfix(char* str, size_t count, const char* format, const GuestTm* timeptr) { const ZoneScope zone; tzset_nid_postfix(); + return formatGuestTime(str, count, format, *timeptr); } @@ -712,12 +596,9 @@ char* APS5_VABI asctime_nid_postfix(const GuestTm* timeptr) { std::memcpy(result, "??? ??? ?? ??:??:?? ????\n", sizeof("??? ??? ?? ??:??:?? ????\n")); return result; } - const char* weekday = timeptr->tm_wday >= 0 && timeptr->tm_wday < 7 ? WEEKDAY_NAMES[timeptr->tm_wday] : "???"; - const char* month = timeptr->tm_mon >= 0 && timeptr->tm_mon < 12 ? MONTH_NAMES[timeptr->tm_mon] : "???"; - char year[16]; - formatGuestTime(year, sizeof(year), "%Y", *timeptr); - std::snprintf(result, sizeof(result), std::strlen(year) <= 4 ? "%s %s%3d %.2d:%.2d:%.2d %-4s\n" : "%s %s%3d %.2d:%.2d:%.2d %s\n", - weekday, month, timeptr->tm_mday, timeptr->tm_hour, timeptr->tm_min, timeptr->tm_sec, year); + const std::int64_t year = static_cast(timeptr->tm_year) + YEAR_BASE; + std::snprintf(result, sizeof(result), "%s %s%3d %02d:%02d:%02d %04d\n", tableName(timeptr->tm_wday, WEEKDAY_NAMES, WEEKDAY_NAMES, 7), tableName(timeptr->tm_mon, MONTH_NAMES, MONTH_NAMES, 12), + clampedField(timeptr->tm_mday, 100), clampedField(timeptr->tm_hour, 100), clampedField(timeptr->tm_min, 100), clampedField(timeptr->tm_sec, 100), clampedField(year, 10000)); return result; } @@ -749,6 +630,7 @@ size_t APS5_VABI wcsftime_nid_postfix(std::uint16_t* str, size_t count, const st return 0; } wcsrtombs_nid_postfix(narrowFormat.get(), &formatCursor, formatLength + 1, nullptr); + const auto maxCharacterBytes = static_cast(_Getmbcurmax_nid_postfix()); if (std::numeric_limits::max() / maxCharacterBytes <= count) { errno = GuestEinval; @@ -768,6 +650,7 @@ size_t APS5_VABI wcsftime_nid_postfix(std::uint16_t* str, size_t count, const st const std::size_t length = mbsrtowcs_nid_postfix(nullptr, &narrowCursor, 0, nullptr); if (length == Failed || length >= count) return 0; mbsrtowcs_nid_postfix(str, &narrowCursor, count, nullptr); + return length; } diff --git a/core/libs/prx/libc/src/TimeExtras.cpp b/core/libs/prx/libc/src/TimeExtras.cpp index ee2a225b25..8b4baa0823 100644 --- a/core/libs/prx/libc/src/TimeExtras.cpp +++ b/core/libs/prx/libc/src/TimeExtras.cpp @@ -1,3 +1,5 @@ +#include "prx/libc/include/SonyCrt.hpp" +#include "prx/libc/include/Api.hpp" #include #include "prx/libc/include/General.hpp" @@ -5,11 +7,6 @@ namespace { -struct Xtime { - std::int64_t sec; - std::int64_t nsec; -}; - constexpr int timeUtc = 1; constexpr std::int64_t nanosPerSecond = 1000000000; constexpr std::int64_t secondsPerDay = 86400; @@ -35,10 +32,6 @@ std::int64_t wrappingAdd(std::int64_t left, std::int64_t right) { extern "C" { -GuestTm* APS5_VABI gmtime_s_nid_postfix(const std::int64_t* timer, GuestTm* result); -GuestTm* APS5_VABI localtime_s_nid_postfix(const std::int64_t* timer, GuestTm* result); -std::int64_t APS5_VABI _Xtime_get_ticks_nid_postfix(); - GuestTm* APS5_VABI gmtime_r_nid_postfix(const std::int64_t* timer, GuestTm* result) { return gmtime_s_nid_postfix(timer, result); } @@ -74,6 +67,7 @@ Xtime APS5_VABI _Xtime_to_ts_nid_postfix(const Xtime* time) { Xtime APS5_VABI _Xtime_diff_to_ts_nid_postfix(const Xtime* target) { Xtime now{}; xtime_get_nid_postfix(&now, timeUtc); + std::int64_t seconds = wrappingAdd(target->sec, target->nsec / nanosPerSecond); std::int64_t nanos = target->nsec % nanosPerSecond; if (nanos < 0) { diff --git a/core/libs/prx/libc/src/VectorAlgorithms.cpp b/core/libs/prx/libc/src/VectorAlgorithms.cpp index 169c0a23d8..80b1a8f99c 100644 --- a/core/libs/prx/libc/src/VectorAlgorithms.cpp +++ b/core/libs/prx/libc/src/VectorAlgorithms.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include #include #include @@ -7,11 +8,6 @@ namespace { -struct MinMaxPointers { - const void* minimum; - const void* maximum; -}; - template TValue Read(const unsigned char* address) { TValue value; diff --git a/core/libs/prx/libc/src/WideConversion.cpp b/core/libs/prx/libc/src/WideConversion.cpp index 640effd1de..109dae7f16 100644 --- a/core/libs/prx/libc/src/WideConversion.cpp +++ b/core/libs/prx/libc/src/WideConversion.cpp @@ -1,3 +1,5 @@ +#include "prx/libc/include/WindowsFormatting.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libc/include/SonyCrt.hpp" #include @@ -18,8 +20,6 @@ extern "C" void* APS5_VABI set_constraint_handler_s_nid_postfix(void* handler) { return SonySetConstraintHandlerS(handler); } -extern "C" std::size_t APS5_VABI wcrtomb_nid_postfix(char* destination, std::uint16_t value, void* state); - extern "C" std::size_t APS5_VABI wcstombs_nid_postfix(char* destination, const std::uint16_t* source, std::size_t capacity) { std::size_t count = 0; for (;; ++source) { @@ -38,8 +38,6 @@ extern "C" int APS5_VABI wcscpy_s_nid_postfix(std::uint16_t* dest, std::size_t s return SonyWcscpyS(dest, size, src); } -extern "C" int APS5_VABI strerror_r_nid_postfix(int error, char* buffer, std::size_t capacity); - namespace { std::size_t ReadErrorMessage(int error, char (&message)[128]) { diff --git a/core/libs/prx/libc/src/exception/ArraySupport.cpp b/core/libs/prx/libc/src/exception/ArraySupport.cpp index 6b5302ac9e..961f834282 100644 --- a/core/libs/prx/libc/src/exception/ArraySupport.cpp +++ b/core/libs/prx/libc/src/exception/ArraySupport.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/exceptions/Runtime.hpp" #include @@ -15,6 +16,7 @@ void APS5_VABI __cxa_vec_ctor_nid_postfix(void* array, std::size_t count, std::s for (; complete < count; ++complete) construct(static_cast(array) + complete * size); } catch (...) { __cxa_vec_cleanup_nid_postfix(array, complete, size, destroy); + throw; } } @@ -26,6 +28,7 @@ void APS5_VABI __cxa_vec_cctor_nid_postfix(void* destination, void* source, std: copy(static_cast(destination) + complete * size, static_cast(source) + complete * size); } catch (...) { __cxa_vec_cleanup_nid_postfix(destination, complete, size, destroy); + throw; } } @@ -37,6 +40,7 @@ void APS5_VABI __cxa_vec_dtor_nid_postfix(void* array, std::size_t count, std::s } catch (...) { if (unwinding) LibcException::Terminate(); __cxa_vec_cleanup_nid_postfix(array, count, size, destroy); + throw; } } diff --git a/core/libs/prx/libc/src/exception/ExceptionPointer.cpp b/core/libs/prx/libc/src/exception/ExceptionPointer.cpp index 447d85ac45..6b808a870c 100644 --- a/core/libs/prx/libc/src/exception/ExceptionPointer.cpp +++ b/core/libs/prx/libc/src/exception/ExceptionPointer.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include #ifndef _LIBCPP_VERSION @@ -62,6 +63,7 @@ exception_ptr current_exception() noexcept { void rethrow_exception(exception_ptr exception) { __cxa_rethrow_primary_exception_nid_postfix(exception._M_exception_object); + LibcException::Terminate(); } @@ -73,10 +75,12 @@ exception_ptr::exception_ptr(void* exception) noexcept : _M_exception_object(exc void exception_ptr::_M_addref() noexcept { __cxa_increment_exception_refcount_nid_postfix(_M_exception_object); + } void exception_ptr::_M_release() noexcept { __cxa_decrement_exception_refcount_nid_postfix(_M_exception_object); + _M_exception_object = nullptr; } @@ -94,22 +98,15 @@ const type_info* exception_ptr::__cxa_exception_type() const noexcept { #else -namespace { -struct GuestExceptionPointer { - void* object {}; - explicit GuestExceptionPointer(void* primary) noexcept : object(primary) {} - GuestExceptionPointer(const GuestExceptionPointer&) = delete; - ~GuestExceptionPointer() {} -}; -} - extern "C" { void APS5_VABI _ZNSt15__exception_ptr13exception_ptr9_M_addrefEv_nid_postfix(GuestExceptionPointer* self) noexcept { __cxa_increment_exception_refcount_nid_postfix(self->object); + } void APS5_VABI _ZNSt15__exception_ptr13exception_ptr10_M_releaseEv_nid_postfix(GuestExceptionPointer* self) noexcept { __cxa_decrement_exception_refcount_nid_postfix(self->object); + self->object = nullptr; } @@ -120,10 +117,12 @@ void* APS5_VABI _ZNKSt15__exception_ptr13exception_ptr6_M_getEv_nid_postfix(cons void APS5_VABI _ZNSt15__exception_ptr13exception_ptrC1EPv_nid_postfix(GuestExceptionPointer* self, void* exception) noexcept { self->object = exception; __cxa_increment_exception_refcount_nid_postfix(exception); + } void APS5_VABI _ZNSt15__exception_ptr13exception_ptrC2EPv_nid_postfix(GuestExceptionPointer* self, void* exception) noexcept { _ZNSt15__exception_ptr13exception_ptrC1EPv_nid_postfix(self, exception); + } const std::type_info* APS5_VABI _ZNKSt15__exception_ptr13exception_ptr20__cxa_exception_typeEv_nid_postfix(const GuestExceptionPointer* self) noexcept { @@ -136,6 +135,7 @@ GuestExceptionPointer APS5_VABI _ZSt17current_exceptionv_nid_postfix() noexcept [[noreturn]] void APS5_VABI _ZSt17rethrow_exceptionNSt15__exception_ptr13exception_ptrE_nid_postfix(GuestExceptionPointer& exception) { __cxa_rethrow_primary_exception_nid_postfix(exception.object); + LibcException::Terminate(); } } diff --git a/core/libs/prx/libc/src/exception/GuardSupport.cpp b/core/libs/prx/libc/src/exception/GuardSupport.cpp index 7eaab8684f..09f9cbf02d 100644 --- a/core/libs/prx/libc/src/exception/GuardSupport.cpp +++ b/core/libs/prx/libc/src/exception/GuardSupport.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/exceptions/Runtime.hpp" #include diff --git a/core/libs/prx/libc/src/exception/Personality.cpp b/core/libs/prx/libc/src/exception/Personality.cpp index 87826a2dc8..d4ed0a681f 100644 --- a/core/libs/prx/libc/src/exception/Personality.cpp +++ b/core/libs/prx/libc/src/exception/Personality.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/exceptions/Unwind.hpp" #include "prx/libc/include/exceptions/Runtime.hpp" extern "C" _Unwind_Reason_Code APS5_VABI __gxx_personality_v0_nid_postfix( diff --git a/core/libs/prx/libc/src/exception/Runtime.cpp b/core/libs/prx/libc/src/exception/Runtime.cpp index e790d1a2db..33a0c5485d 100644 --- a/core/libs/prx/libc/src/exception/Runtime.cpp +++ b/core/libs/prx/libc/src/exception/Runtime.cpp @@ -1,3 +1,5 @@ +#include "prx/libc/include/exceptions/Unwind.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/exceptions/Runtime.hpp" #include #include @@ -117,7 +119,7 @@ void Release(void* object) { } } -void APS5_VABI Cleanup(_Unwind_Reason_Code reason, _Unwind_Exception* exception) { +static void APS5_VABI Cleanup(_Unwind_Reason_Code reason, _Unwind_Exception* exception) { if (reason != _URC_FOREIGN_EXCEPTION_CAUGHT) Terminate(); auto* header = FromUnwind(exception); if (exception->exception_class == DependentClass) { @@ -285,8 +287,10 @@ void APS5_VABI __cxa_free_exception_nid_postfix(void* object) { header->unwind.exception_cleanup = Cleanup; ++globals.uncaught; _Unwind_RaiseException_nid_postfix(&header->unwind); + RawLog("[libc] unhandled exception '%s' thrown from %p\n", type ? type->name() : "?", throwSite); __cxa_begin_catch_nid_postfix(&header->unwind); + InvokeTerminate(header->terminate); } @@ -343,6 +347,7 @@ void APS5_VABI __cxa_end_catch_nid_postfix() { globals.caught = header->next; bool foreign = !Native(header->unwind.exception_class); _Unwind_DeleteException_nid_postfix(UnwindOf(header)); + if (foreign) DeleteForeignHeader(header); } } @@ -355,6 +360,7 @@ void APS5_VABI __cxa_end_catch_nid_postfix() { if (Native(header->unwind.exception_class)) ++globals.uncaught; _Unwind_RaiseException_nid_postfix(UnwindOf(header)); __cxa_begin_catch_nid_postfix(UnwindOf(header)); + InvokeTerminate(header->terminate ? header->terminate : terminateHandler.load()); } @@ -373,7 +379,7 @@ unsigned APS5_VABI __cxa_uncaught_exceptions_nid_postfix() { return LibcExceptio bool APS5_VABI _ZSt18uncaught_exceptionv_nid_postfix() { return __cxa_uncaught_exception_nid_postfix(); } int APS5_VABI _ZSt19uncaught_exceptionsv_nid_postfix() { return static_cast(__cxa_uncaught_exceptions_nid_postfix()); } [[noreturn]] void APS5_VABI _ZSt9terminatev_nid_postfix() { LibcException::Terminate(); } -using LibcTerminateHandler = void(*)(); + LibcTerminateHandler APS5_VABI _ZSt13set_terminatePFvvE_nid_postfix(LibcTerminateHandler handler) { return LibcException::terminateHandler.exchange(handler ? handler : std::abort); } @@ -388,6 +394,7 @@ void* APS5_VABI __cxa_current_primary_exception_nid_postfix() { if (!globals.caught || !Native(globals.caught->unwind.exception_class)) return nullptr; void* object = Primary(globals.caught) + 1; __cxa_increment_exception_refcount_nid_postfix(object); + return object; } void* APS5_VABI __cxa_allocate_dependent_exception_nid_postfix() { @@ -410,9 +417,11 @@ void APS5_VABI __cxa_rethrow_primary_exception_nid_postfix(void* object) { header->unwind.exception_class = DependentClass; header->unwind.exception_cleanup = Cleanup; __cxa_increment_exception_refcount_nid_postfix(object); + ++globals.uncaught; _Unwind_RaiseException_nid_postfix(&header->unwind); __cxa_begin_catch_nid_postfix(&header->unwind); + InvokeTerminate(header->terminate); } @@ -450,6 +459,7 @@ void* APS5_VABI __dynamic_cast_nid_postfix(const void* source, const __cxxabiv1: [[noreturn]] void APS5_VABI __cxa_call_terminate_nid_postfix(void* exception) { __cxa_begin_catch_nid_postfix(exception); + LibcException::Terminate(); } [[noreturn]] void APS5_VABI __cxa_pure_virtual_nid_postfix() { LibcException::Terminate(); } diff --git a/core/libs/prx/libc/src/exception/StandardExceptions.cpp b/core/libs/prx/libc/src/exception/StandardExceptions.cpp index 003a1af171..2cfb9918fb 100644 --- a/core/libs/prx/libc/src/exception/StandardExceptions.cpp +++ b/core/libs/prx/libc/src/exception/StandardExceptions.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/exceptions/Runtime.hpp" #include "prx/libc/include/GuestLocale.hpp" #include @@ -7,11 +8,9 @@ #include #include -extern "C" void* APS5_VABI _Znwm_nid_postfix(std::size_t size); - namespace LibcException { struct TypeRecord { const void* const* vtable; const char* name; const TypeRecord* base; }; -struct ExceptionObject { const void* vtable; const char* message; }; + struct ExceptionVtable { std::ptrdiff_t offset; const TypeRecord* type; @@ -128,9 +127,6 @@ ExceptionObject* Assign(ExceptionObject* object, const ExceptionObject* source) __cxa_throw_nid_postfix(object, reinterpret_cast(const_cast(table.type)), [](void* p) { DestroyPlain(static_cast(p)); }); } -struct CategoryObject { const void* vtable; }; -struct ErrorCode { int reserved; int value; const CategoryObject* category; }; -struct SystemErrorObject { ExceptionObject base; ErrorCode code; }; static_assert(sizeof(ErrorCode) == 16 && offsetof(ErrorCode, value) == 4 && offsetof(ErrorCode, category) == 8); static_assert(sizeof(SystemErrorObject) == 32 && offsetof(SystemErrorObject, code) == 16); struct CppError { int value; const char* message; }; @@ -627,7 +623,6 @@ const char* APS5_VABI _ZNKSt13__sce_cxxvers16_Error_exception4whatEv_nid_postfix [[noreturn]] void APS5_VABI _ZNSt8__sce_v28ios_base6_ThrowERKNS0_7failureE_nid_postfix(const LibcException::SystemErrorObject* failure) { LibcException::SceV2::ThrowSystemCopy(failure, LibcException::SceV2::IosFailure); } [[noreturn]] void APS5_VABI _ZNSt8__sce_v216_Throw_Cpp_errorEi_nid_postfix(int code) { LibcException::ThrowCppError(code, LibcException::SceV2::SystemError); } -std::int64_t APS5_VABI _Xtime_get_ticks_nid_postfix(); std::int64_t APS5_VABI _ZNSt8__sce_v216_Xtime_get_ticksEv_nid_postfix() { return _Xtime_get_ticks_nid_postfix(); } const char* APS5_VABI _ZNSt8__sce_v213_Syserror_mapEi_nid_postfix(int value) { if (value == 0) return "success"; diff --git a/core/libs/prx/libc/src/exception/TypeInfo.cpp b/core/libs/prx/libc/src/exception/TypeInfo.cpp index 49ba0e47ee..a1d58f019b 100644 --- a/core/libs/prx/libc/src/exception/TypeInfo.cpp +++ b/core/libs/prx/libc/src/exception/TypeInfo.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/exceptions/Runtime.hpp" #include diff --git a/core/libs/prx/libc/src/exception/Unwind.cpp b/core/libs/prx/libc/src/exception/Unwind.cpp index 94226226e0..a690410bee 100644 --- a/core/libs/prx/libc/src/exception/Unwind.cpp +++ b/core/libs/prx/libc/src/exception/Unwind.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/exceptions/Unwind.hpp" #include "prx/libc/include/exceptions/Runtime.hpp" #include "prx/libc/include/specifics/linux/ElfTypes.hpp" diff --git a/core/libs/prx/libc/src/specifics/linux/DlIteratePhdr.cpp b/core/libs/prx/libc/src/specifics/linux/DlIteratePhdr.cpp index cc2ff7b9e3..516a53933a 100644 --- a/core/libs/prx/libc/src/specifics/linux/DlIteratePhdr.cpp +++ b/core/libs/prx/libc/src/specifics/linux/DlIteratePhdr.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include #include diff --git a/core/libs/prx/libkernel/Aio/src/Aio.cpp b/core/libs/prx/libkernel/Aio/src/Aio.cpp index 1e71f9cd7e..54fb54921f 100644 --- a/core/libs/prx/libkernel/Aio/src/Aio.cpp +++ b/core/libs/prx/libkernel/Aio/src/Aio.cpp @@ -1,3 +1,4 @@ +#include "prx/libkernel/include/Api.hpp" #include #include #include diff --git a/core/libs/prx/libkernel/Apr/src/Apr.cpp b/core/libs/prx/libkernel/Apr/src/Apr.cpp index 42e4274d9e..49676567f6 100644 --- a/core/libs/prx/libkernel/Apr/src/Apr.cpp +++ b/core/libs/prx/libkernel/Apr/src/Apr.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include #include #include @@ -35,8 +37,6 @@ #include #endif -extern "C" int* APS5_VABI __error_nid_postfix(); - namespace { constexpr int GUEST_ENOENT = 2; @@ -674,6 +674,7 @@ std::optional _execute(const Apr::CommandBufferObject& buffer, std::ui case Apr::Opcode::WriteKernelEventQueue: { const auto command = _read(buffer, cursor); EqueueTriggerEvent_nid_postfix(static_cast(command.equeue), static_cast(command.ident), EVFILT_AMPR, reinterpret_cast(command.data)); + break; } case Apr::Opcode::WriteAddressFromTimeCounter: { @@ -701,8 +702,6 @@ std::optional _execute(const Apr::CommandBufferObject& buffer, std::ui extern "C" { -int APS5_VABI sceKernelAllocateDirectMemory(int64_t searchStart, int64_t searchEnd, size_t length, size_t alignment, int memoryType, int64_t* offset); - int AmmGiveDirectMemory_nid_no_patch(std::int64_t searchStart, std::int64_t searchEnd, std::size_t size, std::size_t alignment, int usage, std::int64_t* offset) { if (!offset || (usage != 0 && usage != 1)) return SCE_KERNEL_ERROR_EINVAL; const int result = sceKernelAllocateDirectMemory(searchStart, searchEnd, size, alignment, 0, offset); @@ -826,7 +825,6 @@ bool AmmSubmitted_nid_no_patch(std::uint32_t id) { return true; } - int APS5_VABI sceKernelAprResolveFilepathsToIds(const char** paths, uint32_t count, uint32_t* ids, uint32_t* error_index) { if (!paths || !ids) return _fail(GUEST_EINVAL); for (uint32_t index = 0; index < count; ++index) { diff --git a/core/libs/prx/libkernel/CMakeLists.txt b/core/libs/prx/libkernel/CMakeLists.txt index 92cbd44e5e..b974a09d57 100644 --- a/core/libs/prx/libkernel/CMakeLists.txt +++ b/core/libs/prx/libkernel/CMakeLists.txt @@ -56,6 +56,7 @@ add_library(libkernel SHARED EXCLUDE_FROM_ALL ${CMAKE_CURRENT_SOURCE_DIR}/Module/src/Module.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Module/src/DynamicLoader.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Module/src/ModuleInfo.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/Module/src/Tls.cpp ${LIBS_INCLUDE_DIR}/nid/src/NidCompute.cpp ${LIBS_INCLUDE_DIR}/nid/src/Sha1.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Aio/src/Aio.cpp @@ -564,6 +565,16 @@ if(BUILD_TESTING) set_tests_properties(guest_kernel_stack_protect PROPERTIES ENVIRONMENT_MODIFICATION "PATH=path_list_prepend:$") endif() + add_test_executable(guest_tls_get_addr_tests ${LIBS_INCLUDE_DIR}/tests/GuestTlsGetAddr.cpp) + target_include_directories(guest_tls_get_addr_tests PRIVATE ${LIBS_INCLUDE_DIR}) + target_link_libraries(guest_tls_get_addr_tests PRIVATE libkernel libc) + configure_windows_unwind(guest_tls_get_addr_tests) + add_test(NAME guest_tls_get_addr COMMAND guest_tls_get_addr_tests) + set_tests_properties(guest_tls_get_addr PROPERTIES TIMEOUT 20) + if(WIN32) + set_tests_properties(guest_tls_get_addr PROPERTIES ENVIRONMENT_MODIFICATION + "PATH=path_list_prepend:$") + endif() add_test_executable(guest_thread_self_tests ${LIBS_INCLUDE_DIR}/tests/GuestThreadSelf.cpp) target_include_directories(guest_thread_self_tests PRIVATE ${LIBS_INCLUDE_DIR}) target_link_libraries(guest_thread_self_tests PRIVATE libkernel libc) @@ -990,6 +1001,16 @@ if(BUILD_TESTING) target_link_libraries(guest_signal_tests PRIVATE libkernel libc) configure_windows_unwind(guest_signal_tests) add_test(NAME guest_signals COMMAND guest_signal_tests) + add_test_executable(guest_signal_interrupt_tests ${LIBS_INCLUDE_DIR}/tests/GuestSignalInterrupt.cpp) + target_include_directories(guest_signal_interrupt_tests PRIVATE ${LIBS_INCLUDE_DIR}) + target_link_libraries(guest_signal_interrupt_tests PRIVATE libkernel libc) + configure_windows_unwind(guest_signal_interrupt_tests) + add_test(NAME guest_signal_interrupt COMMAND guest_signal_interrupt_tests) + set_tests_properties(guest_signal_interrupt PROPERTIES TIMEOUT 20) + if(WIN32) + set_tests_properties(guest_signal_interrupt PROPERTIES ENVIRONMENT_MODIFICATION + "PATH=path_list_prepend:$") + endif() if(WIN32) set_tests_properties(guest_signals PROPERTIES ENVIRONMENT_MODIFICATION "PATH=path_list_prepend:$") diff --git a/core/libs/prx/libkernel/DirectMemory/Export.cpp b/core/libs/prx/libkernel/DirectMemory/Export.cpp index fa42c29e9d..93101cb207 100644 --- a/core/libs/prx/libkernel/DirectMemory/Export.cpp +++ b/core/libs/prx/libkernel/DirectMemory/Export.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include #include #include @@ -32,8 +34,6 @@ #include extern "C" std::uint64_t GuestImageSegmentBytes_nid_no_patch(); -extern "C" void* APS5_VABI mmap_nid_postfix(void* address, std::size_t length, int protection, int flags, int descriptor, std::int64_t offset) noexcept; -extern "C" int* APS5_VABI __error_nid_postfix(); namespace { @@ -276,8 +276,6 @@ int APS5_VABI sceKernelMapFlexibleMemory(void** addr_in_out, size_t len, int pro return _mapFlexible(addr_in_out, len, prot, flags & ~IgnoredHeapFlag); } -int APS5_VABI sceKernelSetVirtualRangeName(const void* addr, uint64_t len, const char* name); - int APS5_VABI sceKernelMapNamedDirectMemory(void** addr, size_t len, int prot, int flags, int64_t direct_memory_start, size_t alignment, const char* name) { const int result = DoMapDirect(addr, len, prot, flags, direct_memory_start, alignment); if (result == 0) _releaseFlexible(reinterpret_cast(*addr), len); @@ -525,8 +523,6 @@ int APS5_VABI sceKernelSetPrtAperture(int index, void* addr, size_t len) { return 0; } -int APS5_VABI sceKernelBatchMap2(KernelBatchMapEntry* entries, int num_entries, int* num_entries_out, int flags); - int APS5_VABI sceKernelBatchMap(KernelBatchMapEntry* entries, int num_entries, int* num_entries_out) { constexpr int MapFixed = 0x10; return sceKernelBatchMap2(entries, num_entries, num_entries_out, MapFixed); diff --git a/core/libs/prx/libkernel/DirectMemory/Jit.cpp b/core/libs/prx/libkernel/DirectMemory/Jit.cpp index 968a36641d..60e266a543 100644 --- a/core/libs/prx/libkernel/DirectMemory/Jit.cpp +++ b/core/libs/prx/libkernel/DirectMemory/Jit.cpp @@ -1,3 +1,4 @@ +#include "prx/libkernel/include/Api.hpp" #include "prx/libc/include/General.hpp" #include "prx/libc/include/GuestArena.hpp" #include "prx/libkernel/DirectMemory/DirectMemory.hpp" diff --git a/core/libs/prx/libkernel/DirectMemory/MemoryPoolExport.cpp b/core/libs/prx/libkernel/DirectMemory/MemoryPoolExport.cpp index 7f15f884a1..d20fb3c364 100644 --- a/core/libs/prx/libkernel/DirectMemory/MemoryPoolExport.cpp +++ b/core/libs/prx/libkernel/DirectMemory/MemoryPoolExport.cpp @@ -1,3 +1,4 @@ +#include "prx/libkernel/include/Api.hpp" #include #include #include diff --git a/core/libs/prx/libkernel/DirectMemory/PosixMemory.cpp b/core/libs/prx/libkernel/DirectMemory/PosixMemory.cpp index 89c8d28df4..24ad4c0331 100644 --- a/core/libs/prx/libkernel/DirectMemory/PosixMemory.cpp +++ b/core/libs/prx/libkernel/DirectMemory/PosixMemory.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "DirectMemory.hpp" #include "SceTypes.hpp" #include "prx/libc/include/general/VabiMacros.hpp" @@ -21,16 +23,6 @@ #include "prx/libkernel/File/include/RandomDevice.hpp" #endif -extern "C" int* APS5_VABI __error_nid_postfix(); -extern "C" int APS5_VABI sceKernelMunmap(std::uint64_t address, std::size_t length); -extern "C" int APS5_VABI sceKernelMlock_nid_postfix(void* address, std::uint64_t length); -extern "C" int APS5_VABI sceKernelMunlock_nid_postfix(void* address, std::uint64_t length); -extern "C" int APS5_VABI sceKernelMunlockall_nid_postfix(); -extern "C" int APS5_VABI sceKernelVirtualQuery(const void* addr, int flags, VirtualQueryInfo* info, uint64_t info_size); -extern "C" std::int64_t APS5_VABI sceKernelPread(int descriptor, void* buffer, std::size_t length, std::int64_t offset); -extern "C" int APS5_VABI munmap_nid_postfix(void* address, std::size_t length) noexcept; -extern "C" int APS5_VABI mprotect_nid_postfix(void* address, std::size_t length, int protection) noexcept; - namespace { // FreeBSD/PS5 ABI values, independent of the host's errno and mmap constants. constexpr int GuestInvalid = 22; @@ -131,6 +123,7 @@ void* MapPrivateFileCopy(void* address, std::size_t rounded, int protection, int const auto read = sceKernelPread(descriptor, static_cast(mapped) + done, static_cast(copied - done), static_cast(start + done)); if (read <= 0) { munmap_nid_postfix(mapped, rounded); + return failed(read < 0 ? static_cast(read & 0xffff) : GuestIoError); } done += static_cast(read); @@ -138,6 +131,7 @@ void* MapPrivateFileCopy(void* address, std::size_t rounded, int protection, int if (protection != 3 && mprotect_nid_postfix(mapped, rounded, protection) != 0) { const int error = *__error_nid_postfix(); munmap_nid_postfix(mapped, rounded); + return failed(error); } return mapped; @@ -369,6 +363,7 @@ int APS5_VABI mincore_nid_postfix(const void* address, std::size_t length, char* for (auto cursor = first; cursor < end;) { VirtualQueryInfo info{}; sceKernelVirtualQuery(reinterpret_cast(cursor), 0, &info, sizeof(info)); + const auto extentEnd = std::min(info.end, end); std::fill_n(vec + (cursor - first) / PS5_PAGE_SIZE, (extentEnd - cursor) / PS5_PAGE_SIZE, static_cast(info.is_committed != 0 ? 1 : 0)); cursor = extentEnd; diff --git a/core/libs/prx/libkernel/Equeue/Equeue.cpp b/core/libs/prx/libkernel/Equeue/Equeue.cpp index a0d5532a03..48f6c286d1 100644 --- a/core/libs/prx/libkernel/Equeue/Equeue.cpp +++ b/core/libs/prx/libkernel/Equeue/Equeue.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libkernel/Equeue/Equeue.hpp" #include "Equeue.hpp" #include "prx/libkernel/Time/include/Time.hpp" #include "prx/libc/include/General.hpp" @@ -12,8 +14,6 @@ #include #include -extern "C" int APS5_VABI sceKernelFstat(int d, FileStat* sb); - static constexpr std::uint64_t FileRepollNs = 1000000; struct UnreadFile { @@ -287,6 +287,10 @@ int KernelEqueuePrivate::CollectTriggered(KernelEvent* ev, int num) { while (e.triggered && ret < num) { ev[ret++] = e.event; if ((e.event.flags & EV_ONESHOT) != 0) { + if (e.filter.deleteEventFunc != nullptr) { + auto owner = e.filter.owner; + e.filter.deleteEventFunc(m_handle, &e); + } erase = true; break; } @@ -615,7 +619,6 @@ int APS5_VABI EqueueDeleteEvent_nid_postfix(KernelEqueue eq, uintptr_t ident, in return owner->DeleteEvent(ident, filter); } - int APS5_VABI sceKernelCreateEqueue(KernelEqueue* eq, const char* name) { if (eq == nullptr || name == nullptr) { return SCE_KERNEL_ERROR_EINVAL; @@ -797,6 +800,7 @@ int APS5_VABI sceKernelAddAmprEvent(KernelEqueue eq, int id, void* udata) { } }; EqueueAddEvent_nid_postfix(eq, event); + return EQUEUE_OK; } @@ -809,6 +813,7 @@ int APS5_VABI sceKernelDeleteAmprEvent(KernelEqueue eq, int id) { return EQUEUE_OK; } EqueueDeleteEvent_nid_postfix(eq, static_cast(id), EVFILT_AMPR); + return EQUEUE_OK; } diff --git a/core/libs/prx/libkernel/Equeue/src/EventAccessors.cpp b/core/libs/prx/libkernel/Equeue/src/EventAccessors.cpp index fb42c6e073..9065ffd156 100644 --- a/core/libs/prx/libkernel/Equeue/src/EventAccessors.cpp +++ b/core/libs/prx/libkernel/Equeue/src/EventAccessors.cpp @@ -1,3 +1,4 @@ +#include "prx/libkernel/include/Api.hpp" #include #include #include diff --git a/core/libs/prx/libkernel/Equeue/src/FileEvent.cpp b/core/libs/prx/libkernel/Equeue/src/FileEvent.cpp index cd24ff30d0..a0b5e49fd3 100644 --- a/core/libs/prx/libkernel/Equeue/src/FileEvent.cpp +++ b/core/libs/prx/libkernel/Equeue/src/FileEvent.cpp @@ -1,3 +1,4 @@ +#include "prx/libkernel/include/Api.hpp" #include "prx/libkernel/Equeue/Equeue.hpp" #include "prx/libc/include/General.hpp" #include "prx/libkernel/File/include/File.hpp" @@ -192,7 +193,7 @@ bool TakeSnapshot(HANDLE handle, Snapshot& snapshot) { } bool IsDeleted(const Snapshot& snapshot) { - return snapshot.deletePending || snapshot.links == 0; + return snapshot.deletePending || snapshot.links == 0 || snapshot.path.find(L"\\$Extend\\$Deleted\\") != std::wstring::npos; } std::vector SnapshotHints(const Snapshot& before, const Snapshot& after, bool directory) { @@ -212,7 +213,7 @@ std::vector SnapshotHints(const Snapshot& before, const Snapshot& } else if (!directory && hints.empty() && after.change != before.change) { hints.push_back(NOTE_ATTRIB); } - if ((after.deletePending && !before.deletePending) || after.links < before.links) { + if ((after.deletePending && !before.deletePending) || after.links < before.links || (!IsDeleted(before) && IsDeleted(after))) { hints.push_back(NOTE_DELETE); } if (!after.path.empty() && after.path != before.path && !IsDeleted(after)) { diff --git a/core/libs/prx/libkernel/Equeue/src/Kqueue.cpp b/core/libs/prx/libkernel/Equeue/src/Kqueue.cpp index 609da35b20..cbddf855ce 100644 --- a/core/libs/prx/libkernel/Equeue/src/Kqueue.cpp +++ b/core/libs/prx/libkernel/Equeue/src/Kqueue.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libkernel/Equeue/Equeue.hpp" #include "prx/libkernel/Equeue/include/EdgeWatch.hpp" #include "prx/libc/include/General.hpp" @@ -32,8 +34,6 @@ #include #endif -extern "C" int* APS5_VABI __error_nid_postfix(); - namespace { constexpr int GUEST_EPERM = 1; @@ -401,7 +401,7 @@ int ModifyTimerKnote(const KernelEqueueRef& queue, KernelEvent& change) { } int ModifyKnote(const KernelEqueueRef& queue, KernelEvent& change) { - if (change.filter == EVFILT_TIMER) { + if (change.filter == EVFILT_TIMER && ((change.flags & EV_ADD) != 0 || change.data != 0 || change.fflags != 0)) { NotImplemented_nid_no_patch("kevent: changing an existing EVFILT_TIMER"); } const bool descriptor = change.filter == EVFILT_READ || change.filter == EVFILT_WRITE; diff --git a/core/libs/prx/libkernel/EventFlag/src/EventFlag.cpp b/core/libs/prx/libkernel/EventFlag/src/EventFlag.cpp index 698b8ceb0e..29f13e6df2 100644 --- a/core/libs/prx/libkernel/EventFlag/src/EventFlag.cpp +++ b/core/libs/prx/libkernel/EventFlag/src/EventFlag.cpp @@ -1,3 +1,5 @@ +#include "prx/libSceSaveData/SaveDataCore.hpp" +#include "prx/libkernel/include/Api.hpp" #include #include #include diff --git a/core/libs/prx/libkernel/File/src/DescriptorControl.cpp b/core/libs/prx/libkernel/File/src/DescriptorControl.cpp index 2e59d5d1e4..c41a2bd853 100644 --- a/core/libs/prx/libkernel/File/src/DescriptorControl.cpp +++ b/core/libs/prx/libkernel/File/src/DescriptorControl.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libkernel/File/include/DescriptorControl.hpp" #include "prx/libkernel/File/include/DirectoryDescriptor.hpp" #include "prx/libkernel/File/include/File.hpp" @@ -34,9 +36,6 @@ #include #endif -extern "C" int* APS5_VABI __error_nid_postfix(); -extern "C" int APS5_VABI dup2_nid_postfix(int from, int to); - namespace { constexpr int GuestEintr = 4; diff --git a/core/libs/prx/libkernel/File/src/Open.cpp b/core/libs/prx/libkernel/File/src/Open.cpp index 7c0cdd2a33..d6b562779f 100644 --- a/core/libs/prx/libkernel/File/src/Open.cpp +++ b/core/libs/prx/libkernel/File/src/Open.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libkernel/File/include/FileFlags.hpp" #include "prx/libkernel/File/include/NativeStat.hpp" #include "prx/libc/include/General.hpp" @@ -176,9 +178,6 @@ static int MapFlags(int sceFlags) { } #endif -extern "C" int* APS5_VABI __error_nid_postfix(); -extern "C" int APS5_VABI fcntl_nid_postfix(int descriptor, int command, ...); - static int SceErrorFromErrno(int error) { const int guest = error > 0 && error <= 34 ? error : FilesystemError(std::error_code(error, std::generic_category())); return static_cast(0x80020000u | static_cast(guest)); @@ -268,7 +267,10 @@ extern "C" { int APS5_VABI sceKernelOpen(const char* path, int flags, std::uint16_t mode) { if (File::InvalidOpenFlags(flags)) return SCE_KERNEL_ERROR_EINVAL; - if (path != nullptr && *path == '\0') return SCE_KERNEL_ERROR_ENOENT; + std::string copy; + if (const int error = CopyGuestPath_nid_no_patch(path, copy)) return SceKernelError(error); + path = copy.c_str(); + if (copy.empty()) return SCE_KERNEL_ERROR_ENOENT; APS5_LOG_OUT("path=%s flags=0x%X nativeFlags=0x%X mode=0%o", path, flags, MapFlags(flags), mode); if (path != nullptr && File::IsRandomDevicePath(path)) { if ((flags & SCE_KERNEL_O_ACCMODE) != SCE_KERNEL_O_RDONLY) throw std::runtime_error(std::string(__func__) + ": writing to " + path + " is not implemented"); @@ -417,13 +419,17 @@ static int StatNative(const std::filesystem::path& native, bool directory, FileS } if (directory && !std::filesystem::is_directory(status)) return SceErrorFromErrno(GuestEnotdir); if (sb == nullptr) return SceErrorFromErrno(GuestEfault); - if (!File::TryFillFileStat(metadataPath, sb)) return SceStatErrorFromErrno(errno); + FileStat result{}; + if (!File::TryFillFileStat(metadataPath, &result)) return SceStatErrorFromErrno(errno); + if (!GuestCopyOut_nid_no_patch(sb, &result, sizeof(result))) return SceErrorFromErrno(GuestEfault); return 0; } int APS5_VABI sceKernelStat(const char* path, FileStat* sb) { - if (path == nullptr) return SceErrorFromErrno(GuestEfault); - if (*path == '\0') return SceErrorFromErrno(2); + std::string copy; + if (const int error = CopyGuestPath_nid_no_patch(path, copy)) return SceErrorFromErrno(error); + path = copy.c_str(); + if (copy.empty()) return SceErrorFromErrno(2); std::filesystem::path native; if (const int error = ResolvePathError_nid_no_patch(path, native, true, true)) return SceKernelError(error); return StatNative(native, std::string_view(path).back() == '/', sb); @@ -441,8 +447,10 @@ int StatInDirectory_nid_no_patch(int directory, const char* path, FileStat* sb, } int APS5_VABI sceKernelUnlink(const char* path) { - if (path == nullptr) return SceErrorFromErrno(GuestEfault); - if (*path == '\0') return SceErrorFromErrno(2); + std::string copy; + if (const int error = CopyGuestPath_nid_no_patch(path, copy)) return SceErrorFromErrno(error); + path = copy.c_str(); + if (copy.empty()) return SceErrorFromErrno(2); if (const int dot = RenameDotError_nid_no_patch(path)) return SceKernelError(dot); std::filesystem::path native; if (const int error = ResolvePathError_nid_no_patch(path, native)) return SceKernelError(error); diff --git a/core/libs/prx/libkernel/File/src/SandboxCertificates.cpp b/core/libs/prx/libkernel/File/src/SandboxCertificates.cpp index a5af2341a3..40ed2effdb 100644 --- a/core/libs/prx/libkernel/File/src/SandboxCertificates.cpp +++ b/core/libs/prx/libkernel/File/src/SandboxCertificates.cpp @@ -1,3 +1,4 @@ +#include "prx/libkernel/include/Api.hpp" #include "prx/libc/include/General.hpp" #include @@ -21,8 +22,6 @@ #include #endif -extern "C" const char* APS5_VABI sceKernelGetFsSandboxRandomWord(); - namespace { constexpr char CertificateBegin[] = "-----BEGIN CERTIFICATE-----"; constexpr char CertificateEnd[] = "-----END CERTIFICATE-----"; diff --git a/core/libs/prx/libkernel/File/src/SharedMemory.cpp b/core/libs/prx/libkernel/File/src/SharedMemory.cpp index 578901ad9a..bd573d3d74 100644 --- a/core/libs/prx/libkernel/File/src/SharedMemory.cpp +++ b/core/libs/prx/libkernel/File/src/SharedMemory.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/General.hpp" #include "prx/libkernel/File/include/FileFlags.hpp" #include "prx/libkernel/File/include/SharedMemory.hpp" @@ -41,8 +43,6 @@ extern "C" _invalid_parameter_handler _set_thread_local_invalid_parameter_handle #include #endif -extern "C" int* APS5_VABI __error_nid_postfix(); - namespace { #ifdef _WIN32 @@ -993,6 +993,9 @@ extern "C" int APS5_VABI shm_open_nid_postfix(const char* path, int flags, int m if (accessMode != SCE_KERNEL_O_RDONLY && accessMode != SCE_KERNEL_O_RDWR) return Fail(GuestInvalid); if ((flags & ~AcceptedFlags) != 0) return Fail(GuestInvalid); if (path != anonymousObject) { + std::string copy; + if (const int error = CopyGuestPath_nid_no_patch(path, copy)) return Fail(error); + path = copy.c_str(); #ifdef _WIN32 return OpenNamedFile(path, flags, mode); #else @@ -1013,6 +1016,9 @@ extern "C" int APS5_VABI shm_open_nid_postfix(const char* path, int flags, int m } extern "C" int APS5_VABI shm_unlink_nid_postfix(const char* path) { + std::string copy; + if (const int error = CopyGuestPath_nid_no_patch(path, copy)) return Fail(error); + path = copy.c_str(); #ifdef _WIN32 return UnlinkNamedFile(path); #else diff --git a/core/libs/prx/libkernel/File/src/Stdio.cpp b/core/libs/prx/libkernel/File/src/Stdio.cpp index eadc2361f5..be1154bce4 100644 --- a/core/libs/prx/libkernel/File/src/Stdio.cpp +++ b/core/libs/prx/libkernel/File/src/Stdio.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include #include #include @@ -43,10 +45,6 @@ #include #endif -struct KernelIovec { - void* base; - std::size_t length; -}; static_assert(sizeof(KernelIovec) == sizeof(GuestSockets::Iovec)); static_assert(sizeof(KernelIovec) == sizeof(AppArchiveBuffer) && offsetof(KernelIovec, length) == offsetof(AppArchiveBuffer, Length)); @@ -257,9 +255,13 @@ static std::int64_t NativePositionedTransfer(int descriptor, void* buf, std::siz if (nbytes > static_cast(std::numeric_limits::max())) { throw std::runtime_error("NativePositioned: nbytes exceeds platform limit"); } - if (write && File::HasFixedSizeWrites(descriptor)) { - if (!File::LimitSharedMemoryWrite_nid_no_patch(descriptor, nbytes, offset)) return -1; - if (nbytes == 0) return 0; + if (write) { + if (File::HasFixedSizeWrites(descriptor)) { + if (!File::LimitSharedMemoryWrite_nid_no_patch(descriptor, nbytes, offset)) return -1; + if (nbytes == 0) return 0; + } + const auto result = File::PwriteSharedMemory_nid_no_patch(descriptor, buf, nbytes, offset); + if (result != -2) return result; } const auto handle = reinterpret_cast(WithoutParameterHandler([descriptor] { return ::_get_osfhandle(descriptor); })); if (handle == INVALID_HANDLE_VALUE) { @@ -497,8 +499,6 @@ static int PathLookupFailure(const std::error_code& error) { return lookup ? SceErrorFromErrno(error.default_error_condition().value()) : 0; } -extern "C" int* APS5_VABI __error_nid_postfix(); - static int PosixFailure(int error) { *__error_nid_postfix() = error; return -1; @@ -614,9 +614,9 @@ extern "C" int APS5_VABI pipe_nid_postfix(int* descriptors) { return 0; } -static int PathError(const char* path) { - if (path == nullptr) return GUEST_EFAULT; - return *path == '\0' ? GUEST_ENOENT : 0; +static int PathError(const char* path, std::string& copy) { + if (const int error = CopyGuestPath_nid_no_patch(path, copy)) return error; + return copy.empty() ? GUEST_ENOENT : 0; } #ifdef _WIN32 @@ -642,11 +642,10 @@ static bool HasNonDirectoryPrefix(const std::filesystem::path& native) { return false; } -extern "C" int APS5_VABI dup_nid_postfix(int d); -extern "C" int APS5_VABI close_nid_postfix(int d); - int File::DuplicateFrom(int fd, int start) { #ifdef _WIN32 + GuestResourceLimit openFileLimit{}; + if (getrlimit_nid_postfix(8, &openFileLimit) == 0 && start >= openFileLimit.rlim_cur) return PosixFailure(GUEST_EINVAL); std::vector below; int duplicate; while ((duplicate = dup_nid_postfix(fd)) >= 0 && duplicate < start) below.push_back(duplicate); @@ -702,7 +701,9 @@ static int SetFileFlags(const char* function, const std::string& target, std::ui extern "C" { int APS5_VABI chmod_nid_postfix(const char* path, int mode) { - if (const int error = PathError(path)) return PosixFailure(error); + std::string copy; + if (const int error = PathError(path, copy)) return PosixFailure(error); + path = copy.c_str(); std::filesystem::path native; if (const int error = ResolvePathError_nid_no_patch(path, native)) return PosixFailure(error); if (NativeChmod(native, mode & 07777) != 0) return PosixResult(SceErrorFromErrno(errno == ENOENT ? NotFoundError_nid_no_patch(native) : errno)); @@ -710,7 +711,9 @@ int APS5_VABI chmod_nid_postfix(const char* path, int mode) { } int APS5_VABI chflags_nid_postfix(const char* path, std::uint64_t flags) { - if (const int error = PathError(path)) return PosixFailure(error); + std::string copy; + if (const int error = PathError(path, copy)) return PosixFailure(error); + path = copy.c_str(); std::filesystem::path native; if (const int error = ResolvePathError_nid_no_patch(path, native)) return PosixFailure(error); if (const int error = LookupError(native)) return PosixFailure(error); @@ -908,10 +911,7 @@ int APS5_VABI _fstatfs_nid_postfix(int d, KernelStatfs* buf) { KernelStatfs result{}; result.f_version = KERNEL_STATFS_VERSION; if (const int error = NativeFstatfs(d, &result)) return PosixFailure(error); - if (buf == nullptr) return PosixFailure(GUEST_EFAULT); - const GuestArena::HostWrite destination(buf, sizeof(result)); - if (!destination.Open()) return PosixFailure(GUEST_EFAULT); - std::memcpy(buf, &result, sizeof(result)); + if (!GuestCopyOut_nid_no_patch(buf, &result, sizeof(result))) return PosixFailure(GUEST_EFAULT); return 0; } @@ -921,11 +921,13 @@ int64_t APS5_VABI fstat_nid_disambig1_nid_postfix(int d, FileStat* sb) { if (fstat_nid_disambig1_nid_postfix(d, &ignored) != 0) return -1; return PosixFailure(GUEST_EFAULT); } + FileStat result{}; if (GuestSockets::IsOpen(d)) { - if (const int error = GuestSockets::Stat(d, sb)) return PosixFailure(error); - return 0; + if (const int error = GuestSockets::Stat(d, &result)) return PosixFailure(error); + } else if (!File::FillFileStatFromDescriptor(d, &result)) { + return PosixFailure(SceErrorFromErrno(errno) & 0xffff); } - if (!File::FillFileStatFromDescriptor(d, sb)) return PosixFailure(SceErrorFromErrno(errno) & 0xffff); + if (!GuestCopyOut_nid_no_patch(sb, &result, sizeof(result))) return PosixFailure(GUEST_EFAULT); return 0; } @@ -963,7 +965,9 @@ int64_t APS5_VABI lseek_nid_postfix(int d, int64_t offset, int whence) { } int APS5_VABI mkdir_nid_postfix(const char* path, uint16_t mode) { - if (const int error = PathError(path)) return PosixFailure(error); + std::string copy; + if (const int error = PathError(path, copy)) return PosixFailure(error); + path = copy.c_str(); std::filesystem::path native; if (const int error = ResolvePathError_nid_no_patch(path, native)) return PosixFailure(error); if (NativeMkdir(native, mode) != 0) { @@ -980,7 +984,9 @@ int APS5_VABI mkdir_nid_postfix(const char* path, uint16_t mode) { int APS5_VABI open_nid_postfix(const char* path, int flags, int mode) { if (File::InvalidOpenFlags(flags)) return PosixFailure(GUEST_EINVAL); - if (const int error = PathError(path)) return PosixFailure(error); + std::string copy; + if (const int error = PathError(path, copy)) return PosixFailure(error); + path = copy.c_str(); return PosixResult(sceKernelOpen(path, flags, static_cast(mode))); } @@ -1067,27 +1073,38 @@ std::int64_t APS5_VABI _write_nid_postfix(int descriptor, const void* buffer, st int APS5_VABI stat_nid_postfix(const char* path, FileStat* sb) { if (sb == nullptr) return PosixFailure(GUEST_EFAULT); - if (const int error = PathError(path)) return PosixFailure(error); + std::string copy; + if (const int error = PathError(path, copy)) return PosixFailure(error); + path = copy.c_str(); return PosixResult(sceKernelStat(path, sb)); } int APS5_VABI lstat_nid_postfix(const char* path, FileStat* sb) { if (sb == nullptr) return PosixFailure(GUEST_EFAULT); - if (const int error = PathError(path)) return PosixFailure(error); + std::string copy; + if (const int error = PathError(path, copy)) return PosixFailure(error); + path = copy.c_str(); std::filesystem::path native; if (const int error = ResolvePathError_nid_no_patch(path, native)) return PosixFailure(error); - if (!File::FillLinkStat(native, sb)) return PosixResult(SceErrorFromErrno(errno == ENOENT ? NotFoundError_nid_no_patch(native) : errno)); + FileStat result{}; + if (!File::FillLinkStat(native, &result)) return PosixResult(SceErrorFromErrno(errno == ENOENT ? NotFoundError_nid_no_patch(native) : errno)); + if (!GuestCopyOut_nid_no_patch(sb, &result, sizeof(result))) return PosixFailure(GUEST_EFAULT); return 0; } int APS5_VABI unlink_nid_postfix(const char* path) { - if (const int error = PathError(path)) return PosixFailure(error); + std::string copy; + if (const int error = PathError(path, copy)) return PosixFailure(error); + path = copy.c_str(); return PosixResult(sceKernelUnlink(path)); } int APS5_VABI sceKernelCheckReachability(const char* path) { if (path == nullptr) return SCE_KERNEL_ERROR_EINVAL; - if (*path == '\0') return SCE_KERNEL_ERROR_ENOENT; + std::string copy; + if (const int error = CopyGuestPath_nid_no_patch(path, copy)) return SceKernelError(error); + path = copy.c_str(); + if (copy.empty()) return SCE_KERNEL_ERROR_ENOENT; if (std::strlen(path) > 255) return SCE_KERNEL_ERROR_ENAMETOOLONG; std::filesystem::path native; if (const int error = ResolvePathError_nid_no_patch(path, native, true, true)) return SceKernelError(error); @@ -1102,11 +1119,14 @@ int APS5_VABI sceKernelFstat(int d, FileStat* sb) { if (const int error = sceKernelFstat(d, &ignored)) return error; return SceErrorFromErrno(GUEST_EFAULT); } + FileStat result{}; if (GuestSockets::IsOpen(d)) { - const int error = GuestSockets::Stat(d, sb); - return error == 0 ? 0 : SceErrorFromErrno(error); + const int error = GuestSockets::Stat(d, &result); + if (error != 0) return SceErrorFromErrno(error); + } else if (!File::FillFileStatFromDescriptor(d, &result)) { + return SceErrorFromErrno(errno); } - if (!File::FillFileStatFromDescriptor(d, sb)) return SceErrorFromErrno(errno); + if (!GuestCopyOut_nid_no_patch(sb, &result, sizeof(result))) return SceErrorFromErrno(GUEST_EFAULT); return 0; } @@ -1262,8 +1282,10 @@ int APS5_VABI getdents_nid_postfix(int fd, char* buf, int nbytes) { int APS5_VABI sceKernelMkdir(const char* path, uint16_t mode) { (void)mode; - if (!path) return SceErrorFromErrno(GUEST_EFAULT); - if (!*path) return SceErrorFromErrno(GUEST_ENOENT); + std::string copy; + if (const int error = CopyGuestPath_nid_no_patch(path, copy)) return SceErrorFromErrno(error); + path = copy.c_str(); + if (copy.empty()) return SceErrorFromErrno(GUEST_ENOENT); std::filesystem::path native; if (const int error = ResolvePathError_nid_no_patch(path, native)) return SceKernelError(error); while (!native.has_filename() && native.has_relative_path()) native = native.parent_path(); @@ -1528,8 +1550,10 @@ int APS5_VABI sceKernelRename(const char* from, const char* to) { } int APS5_VABI sceKernelRmdir(const char* path) { - if (!path) return SceErrorFromErrno(GUEST_EFAULT); - if (*path == '\0') return SceErrorFromErrno(GUEST_ENOENT); + std::string copy; + if (const int error = CopyGuestPath_nid_no_patch(path, copy)) return SceErrorFromErrno(error); + path = copy.c_str(); + if (copy.empty()) return SceErrorFromErrno(GUEST_ENOENT); if (const int dot = RenameDotError_nid_no_patch(path)) return SceKernelError(dot); std::filesystem::path native; if (const int error = ResolvePathError_nid_no_patch(path, native)) return SceKernelError(error); @@ -1550,7 +1574,9 @@ int APS5_VABI sceKernelRmdir(const char* path) { } int APS5_VABI rmdir_nid_postfix(const char* path) { - if (const int error = PathError(path)) return PosixFailure(error); + std::string copy; + if (const int error = PathError(path, copy)) return PosixFailure(error); + path = copy.c_str(); return PosixResult(sceKernelRmdir(path)); } @@ -1559,8 +1585,10 @@ int APS5_VABI rmdir_nid_postfix(const char* path) { extern "C" { int APS5_VABI sceKernelChmod_nid_postfix(const char* path, std::uint16_t mode) { - if (!path) return SceErrorFromErrno(GUEST_EFAULT); - if (!*path) return SceErrorFromErrno(GUEST_ENOENT); + std::string copy; + if (const int error = CopyGuestPath_nid_no_patch(path, copy)) return SceErrorFromErrno(error); + path = copy.c_str(); + if (copy.empty()) return SceErrorFromErrno(GUEST_ENOENT); std::filesystem::path native; if (const int error = ResolvePathError_nid_no_patch(path, native)) return SceKernelError(error); if (NativeChmod(native, mode & 07777) != 0) return SceErrorFromErrno(errno); @@ -1588,8 +1616,10 @@ static bool InvalidTimes(const KernelTimeval* times) { int APS5_VABI sceKernelTruncate_nid_postfix(const char* path, std::int64_t length) { if (length < 0) return SceErrorFromErrno(GUEST_EINVAL); - if (!path) return SceErrorFromErrno(GUEST_EFAULT); - if (*path == '\0') return SceErrorFromErrno(GUEST_ENOENT); + std::string copy; + if (const int error = CopyGuestPath_nid_no_patch(path, copy)) return SceErrorFromErrno(error); + path = copy.c_str(); + if (copy.empty()) return SceErrorFromErrno(GUEST_ENOENT); std::filesystem::path native; if (const int error = ResolvePathError_nid_no_patch(path, native)) return SceKernelError(error); std::error_code error; @@ -1609,14 +1639,18 @@ int APS5_VABI sceKernelTruncate_nid_postfix(const char* path, std::int64_t lengt int APS5_VABI truncate_nid_postfix(const char* path, std::int64_t length) { if (length < 0) return PosixFailure(GUEST_EINVAL); - if (const int error = PathError(path)) return PosixFailure(error); + std::string copy; + if (const int error = PathError(path, copy)) return PosixFailure(error); + path = copy.c_str(); return PosixResult(sceKernelTruncate_nid_postfix(path, length)); } int APS5_VABI sceKernelUtimes_nid_postfix(const char* path, const KernelTimeval* times) { if (InvalidTimes(times)) return SCE_KERNEL_ERROR_EINVAL; - if (!path) return SceErrorFromErrno(GUEST_EFAULT); - if (*path == '\0') return SceErrorFromErrno(GUEST_ENOENT); + std::string copy; + if (const int error = CopyGuestPath_nid_no_patch(path, copy)) return SceErrorFromErrno(error); + path = copy.c_str(); + if (copy.empty()) return SceErrorFromErrno(GUEST_ENOENT); std::filesystem::path native; if (const int error = ResolvePathError_nid_no_patch(path, native)) return SceKernelError(error); if (NativeUtimes(native, times) != 0) return SceErrorFromErrno(errno == ENOENT ? NotFoundError_nid_no_patch(native) : errno); @@ -1625,13 +1659,17 @@ int APS5_VABI sceKernelUtimes_nid_postfix(const char* path, const KernelTimeval* int APS5_VABI utimes_nid_postfix(const char* path, const KernelTimeval* times) { if (InvalidTimes(times)) return PosixFailure(GUEST_EINVAL); - if (const int error = PathError(path)) return PosixFailure(error); + std::string copy; + if (const int error = PathError(path, copy)) return PosixFailure(error); + path = copy.c_str(); return PosixResult(sceKernelUtimes_nid_postfix(path, times)); } int APS5_VABI lutimes_nid_postfix(const char* path, const KernelTimeval* times) { if (InvalidTimes(times)) return PosixFailure(GUEST_EINVAL); - if (const int error = PathError(path)) return PosixFailure(error); + std::string copy; + if (const int error = PathError(path, copy)) return PosixFailure(error); + path = copy.c_str(); std::filesystem::path native; if (const int error = ResolvePathError_nid_no_patch(path, native)) return PosixFailure(error); if (NativeUtimes(native, times, false) != 0) return PosixResult(SceErrorFromErrno(errno)); diff --git a/core/libs/prx/libkernel/File/src/Terminal.cpp b/core/libs/prx/libkernel/File/src/Terminal.cpp index 25f8a85526..d8220e00bb 100644 --- a/core/libs/prx/libkernel/File/src/Terminal.cpp +++ b/core/libs/prx/libkernel/File/src/Terminal.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libkernel/Socket/include/SocketRuntime.hpp" #include @@ -13,7 +15,6 @@ #include #endif -extern "C" int* APS5_VABI __error_nid_postfix(); #ifdef _WIN32 extern "C" _invalid_parameter_handler _set_thread_local_invalid_parameter_handler(_invalid_parameter_handler); #endif diff --git a/core/libs/prx/libkernel/Module/src/DynamicLoader.cpp b/core/libs/prx/libkernel/Module/src/DynamicLoader.cpp index 64c1b9b553..b9feacb7d1 100644 --- a/core/libs/prx/libkernel/Module/src/DynamicLoader.cpp +++ b/core/libs/prx/libkernel/Module/src/DynamicLoader.cpp @@ -1,3 +1,4 @@ +#include "prx/libkernel/include/Api.hpp" #include "prx/libc/include/General.hpp" #include "prx/libc/include/GuestAllocations.hpp" #include "prx/libkernel/Module/ModuleArgs.hpp" diff --git a/core/libs/prx/libkernel/Module/src/Module.cpp b/core/libs/prx/libkernel/Module/src/Module.cpp index 44877cf635..9a9b712fcc 100644 --- a/core/libs/prx/libkernel/Module/src/Module.cpp +++ b/core/libs/prx/libkernel/Module/src/Module.cpp @@ -1,3 +1,4 @@ +#include "prx/libkernel/include/Api.hpp" #include #include #include @@ -111,7 +112,6 @@ extern "C" void ForgetUnloadedUnwindImages_nid_no_patch() { for (const auto base : unloaded) UnwindImages().erase(base); } #elif !defined(__APPLE__) -extern "C" int APS5_VABI sceKernelGetModuleInfoFromAddr(std::uint64_t address, int flags, ModuleInfoEx* info); namespace { struct ImageSearch { @@ -151,13 +151,6 @@ void FillGuestUnwindInfo(std::uint64_t address, ModuleInfoForUnwind* info) { } #endif -extern "C" { -void* APS5_VABI dlopen_nid_postfix(const char* path, int flags); -void* APS5_VABI dlsym_nid_postfix(void* handle, const char* name); -int APS5_VABI dlclose_nid_postfix(void* handle); -const char* APS5_VABI sceKernelGetFsSandboxRandomWord(); -} - namespace { constexpr int kRtldNow = 2; diff --git a/core/libs/prx/libkernel/Module/src/ModuleInfo.cpp b/core/libs/prx/libkernel/Module/src/ModuleInfo.cpp index f3931ee478..2df8293175 100644 --- a/core/libs/prx/libkernel/Module/src/ModuleInfo.cpp +++ b/core/libs/prx/libkernel/Module/src/ModuleInfo.cpp @@ -1,3 +1,4 @@ +#include "prx/libkernel/include/Api.hpp" #include #include #include diff --git a/core/libs/prx/libkernel/Module/src/Tls.cpp b/core/libs/prx/libkernel/Module/src/Tls.cpp new file mode 100644 index 0000000000..bc3f81240f --- /dev/null +++ b/core/libs/prx/libkernel/Module/src/Tls.cpp @@ -0,0 +1,44 @@ +#include +#include +#include +#include "SceTypes.hpp" +#include "prx/libc/include/General.hpp" +#include "prx/libkernel/include/Api.hpp" +#ifdef _WIN32 +#ifndef NOMINMAX +#define NOMINMAX +#endif +#include +#endif + +namespace { + +#ifdef _WIN32 +constexpr std::size_t ThreadLocalStoragePointerOffset = 0x58; +#endif + +} + +#if defined(__linux__) +extern "C" void* __tls_get_addr(void* index); +#endif + +extern "C" { + +void* APS5_VABI __tls_get_addr_nid_postfix(const KernelTlsIndex* index) { + if (index == nullptr || index->module == 0) throw std::invalid_argument("__tls_get_addr: null TLS index or module"); +#if defined(_WIN32) + const auto slot = *reinterpret_cast(static_cast(index->module)); + auto* blocks = *reinterpret_cast(reinterpret_cast(NtCurrentTeb()) + ThreadLocalStoragePointerOffset); + if (blocks == nullptr || blocks[slot] == nullptr) throw std::logic_error("__tls_get_addr: thread has no TLS block for the module"); + return blocks[slot] + index->offset; +#elif defined(__linux__) + KernelTlsIndex host = *index; + return __tls_get_addr(&host); +#else + NotImplemented_nid_no_patch("__tls_get_addr on this host"); + return nullptr; +#endif +} + +} diff --git a/core/libs/prx/libkernel/Pthread/Posix/Atfork.cpp b/core/libs/prx/libkernel/Pthread/Posix/Atfork.cpp index 2becc20064..1f49be53c4 100644 --- a/core/libs/prx/libkernel/Pthread/Posix/Atfork.cpp +++ b/core/libs/prx/libkernel/Pthread/Posix/Atfork.cpp @@ -1,3 +1,4 @@ +#include "prx/libkernel/Pthread/include/Atfork.hpp" #include "../include/Atfork.hpp" #include #include diff --git a/core/libs/prx/libkernel/Pthread/Posix/Attr.cpp b/core/libs/prx/libkernel/Pthread/Posix/Attr.cpp index 86fd01c134..a71ae71597 100644 --- a/core/libs/prx/libkernel/Pthread/Posix/Attr.cpp +++ b/core/libs/prx/libkernel/Pthread/Posix/Attr.cpp @@ -1,3 +1,4 @@ +#include "prx/libkernel/include/Api.hpp" #include #include #include @@ -7,16 +8,6 @@ #include "../include/Pthread.hpp" #include "Common.hpp" -extern "C" { -int APS5_VABI scePthreadAttrInit(PthreadAttr* attr); -int APS5_VABI scePthreadAttrDestroy(PthreadAttr* attr); -int APS5_VABI scePthreadAttrSetstacksize(PthreadAttr* attr, std::size_t stacksize); -int APS5_VABI scePthreadAttrSetstack(PthreadAttr* attr, void* addr, std::size_t size); -int APS5_VABI scePthreadAttrSetsolosched(PthreadAttr* attr, int solosched); -int APS5_VABI sched_get_priority_max_nid_postfix(int policy); -int APS5_VABI sched_get_priority_min_nid_postfix(int policy); -} - static constexpr int GuestSchedFifo = 1; static constexpr int GuestSchedRr = 3; diff --git a/core/libs/prx/libkernel/Pthread/Posix/Barrier.cpp b/core/libs/prx/libkernel/Pthread/Posix/Barrier.cpp index 4f4c7884db..9d98ca6274 100644 --- a/core/libs/prx/libkernel/Pthread/Posix/Barrier.cpp +++ b/core/libs/prx/libkernel/Pthread/Posix/Barrier.cpp @@ -1,3 +1,4 @@ +#include "prx/libkernel/include/Api.hpp" #include "prx/libc/include/General.hpp" #include #include @@ -7,25 +8,12 @@ #include #include -struct PthreadBarrierPrivate { - std::mutex mutex; - std::condition_variable changed; - unsigned count; - unsigned arrived = 0; - unsigned active = 0; - std::uint64_t generation = 0; -}; - namespace { constexpr int PROCESS_PRIVATE = 0; } -struct PthreadBarrierattrPrivate { - int pshared = PROCESS_PRIVATE; -}; - extern "C" { int APS5_VABI pthread_barrierattr_init_nid_postfix(PthreadBarrierattrPrivate** attr) { diff --git a/core/libs/prx/libkernel/Pthread/Posix/Common.hpp b/core/libs/prx/libkernel/Pthread/Posix/Common.hpp index 334842c761..e16aa453c6 100644 --- a/core/libs/prx/libkernel/Pthread/Posix/Common.hpp +++ b/core/libs/prx/libkernel/Pthread/Posix/Common.hpp @@ -1,3 +1,4 @@ +#include "prx/libkernel/Time/include/Time.hpp" #ifndef CORE_LIBS_PRX_LIBKERNEL_PTHREAD_POSIX_COMMON_HPP #define CORE_LIBS_PRX_LIBKERNEL_PTHREAD_POSIX_COMMON_HPP @@ -6,8 +7,6 @@ #include #include "SceTypes.hpp" -extern "C" int APS5_VABI clock_gettime_nid_postfix(int clockId, KernelTimespec* tp); - namespace PosixThread { constexpr int GUEST_ESRCH = 3; @@ -29,6 +28,7 @@ inline bool RelativeMicroseconds(int clockId, const KernelTimespec* abstime, Ker if (!abstime || abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) return false; KernelTimespec now{}; clock_gettime_nid_postfix(clockId, &now); + constexpr auto maximum = std::numeric_limits::max(); if (abstime->tv_sec < now.tv_sec - 1) { *usec = 0; diff --git a/core/libs/prx/libkernel/Pthread/Posix/Cond.cpp b/core/libs/prx/libkernel/Pthread/Posix/Cond.cpp index 324ee35216..43f18c44ce 100644 --- a/core/libs/prx/libkernel/Pthread/Posix/Cond.cpp +++ b/core/libs/prx/libkernel/Pthread/Posix/Cond.cpp @@ -1,3 +1,4 @@ +#include "prx/libkernel/include/Api.hpp" #include "prx/libkernel/Pthread/include/Pthread.hpp" #include "prx/libkernel/Pthread/include/Cond.hpp" #include "Common.hpp" diff --git a/core/libs/prx/libkernel/Pthread/Posix/Mutex.cpp b/core/libs/prx/libkernel/Pthread/Posix/Mutex.cpp index fbf631b696..6f41a86fde 100644 --- a/core/libs/prx/libkernel/Pthread/Posix/Mutex.cpp +++ b/core/libs/prx/libkernel/Pthread/Posix/Mutex.cpp @@ -1,3 +1,5 @@ +#include "prx/libc/include/Api.hpp" +#include "prx/libkernel/include/Api.hpp" #include #include #include "SceTypes.hpp" @@ -38,9 +40,6 @@ void _initializeStatic(PthreadMutex* mutex, const char* funcName) { extern "C" { -int APS5_VABI sched_get_priority_max_nid_postfix(int policy); -int* APS5_VABI __error_nid_postfix(); - int APS5_VABI pthread_mutex_destroy_nid_postfix(PthreadMutex* mutex) { if (!mutex) throw std::runtime_error("pthread_mutex_destroy: null mutex"); if (_isStaticInitializer(*mutex)) { diff --git a/core/libs/prx/libkernel/Pthread/Posix/Once.cpp b/core/libs/prx/libkernel/Pthread/Posix/Once.cpp index 6919e008be..220e54a0a1 100644 --- a/core/libs/prx/libkernel/Pthread/Posix/Once.cpp +++ b/core/libs/prx/libkernel/Pthread/Posix/Once.cpp @@ -1,3 +1,4 @@ +#include "prx/libkernel/include/Api.hpp" #include "prx/libc/include/General.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libkernel/Pthread/include/Cancel.hpp" @@ -8,10 +9,7 @@ namespace { // FreeBSD guest ABI: PTHREAD_ONCE_INIT is {0, nullptr}; completed state is 1. -struct GuestOnce { - std::int32_t state; - void* mutex; -}; + static_assert(offsetof(GuestOnce, mutex) == 8 && sizeof(GuestOnce) == 16); std::mutex onceMutex; std::condition_variable onceChanged; @@ -39,6 +37,7 @@ extern "C" int APS5_VABI pthread_once_nid_postfix( CleanupHandler reset{}; void* const mark = ThreadCancel::CleanupMark(); __pthread_cleanup_push_imp_nid_postfix(ResetOnce, control, &reset); + try { initialize(); } catch (...) { diff --git a/core/libs/prx/libkernel/Pthread/Posix/Rwlock.cpp b/core/libs/prx/libkernel/Pthread/Posix/Rwlock.cpp index a15fe61fb0..c82db18c88 100644 --- a/core/libs/prx/libkernel/Pthread/Posix/Rwlock.cpp +++ b/core/libs/prx/libkernel/Pthread/Posix/Rwlock.cpp @@ -1,3 +1,4 @@ +#include "prx/libkernel/include/Api.hpp" #include #include #include "SceTypes.hpp" @@ -37,8 +38,6 @@ void initializeStatic(PthreadRwlock* rwlock, const char* funcName) { extern "C" { -int APS5_VABI pthread_rwlock_wrlock_nid_postfix(PthreadRwlock* rwlock); - int APS5_VABI pthread_rwlock_destroy_nid_postfix(PthreadRwlock* rwlock) { if (!rwlock) throw std::runtime_error("pthread_rwlock_destroy: null rwlock"); if (*rwlock == nullptr) return 0; diff --git a/core/libs/prx/libkernel/Pthread/Posix/Sem.cpp b/core/libs/prx/libkernel/Pthread/Posix/Sem.cpp index 70faa0359a..d755e0cf46 100644 --- a/core/libs/prx/libkernel/Pthread/Posix/Sem.cpp +++ b/core/libs/prx/libkernel/Pthread/Posix/Sem.cpp @@ -1,3 +1,4 @@ +#include "prx/libkernel/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libkernel/Pthread/Posix/Spinlock.cpp b/core/libs/prx/libkernel/Pthread/Posix/Spinlock.cpp index 9101c62da8..92c36969eb 100644 --- a/core/libs/prx/libkernel/Pthread/Posix/Spinlock.cpp +++ b/core/libs/prx/libkernel/Pthread/Posix/Spinlock.cpp @@ -1,3 +1,4 @@ +#include "prx/libkernel/include/Api.hpp" #include "SceTypes.hpp" #include "Common.hpp" #include @@ -5,10 +6,6 @@ #include #include -struct PthreadSpinlockPrivate { - std::atomic owner{}; -}; - namespace { constexpr int GUEST_EPERM = 1; diff --git a/core/libs/prx/libkernel/Pthread/Posix/Thread.cpp b/core/libs/prx/libkernel/Pthread/Posix/Thread.cpp index c8671c5c4f..160ce82945 100644 --- a/core/libs/prx/libkernel/Pthread/Posix/Thread.cpp +++ b/core/libs/prx/libkernel/Pthread/Posix/Thread.cpp @@ -1,3 +1,8 @@ +#include "prx/libkernel/Pthread/include/ThreadLifecycle.hpp" +#include "prx/libkernel/Pthread/include/Mutex.hpp" +#include "prx/libkernel/Pthread/include/Cond.hpp" +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include #include #include @@ -14,40 +19,9 @@ #include extern "C" { -int APS5_VABI scePthreadCreate(Pthread* thread, const PthreadAttr* attr, PthreadEntry entry, void* arg, const char* name); -int APS5_VABI scePthreadDetach(Pthread thread); -void APS5_VABI scePthreadExit(void* retval); -int APS5_VABI scePthreadJoin(Pthread thread, void** retval); + int APS5_VABI JoinThread_nid_no_patch(Pthread thread, void** retval, const KernelTimespec* abstime); -int APS5_VABI scePthreadRename(Pthread thread, const char* name); -int APS5_VABI scePthreadGetname(Pthread thread, char* name); -Pthread APS5_VABI scePthreadSelf(); -int APS5_VABI scePthreadEqual(Pthread thread1, Pthread thread2); -int APS5_VABI scePthreadOnce(int32_t* once, void (APS5_VABI* init)(void)); -int APS5_VABI scePthreadKeyCreate(PthreadKey* key, pthread_key_destructor_func_t destructor); -int APS5_VABI scePthreadKeyDelete(PthreadKey key); -void* APS5_VABI scePthreadGetspecific(PthreadKey key); -int APS5_VABI scePthreadSetspecific(PthreadKey key, void* value); -int APS5_VABI scePthreadMutexattrInit(PthreadMutexattr* attr); -int APS5_VABI scePthreadMutexattrSettype(PthreadMutexattr* attr, int type); -int APS5_VABI scePthreadMutexattrDestroy(PthreadMutexattr* attr); -int APS5_VABI scePthreadMutexInit(PthreadMutex* mutex, const PthreadMutexattr* attr, const char* name); -int APS5_VABI scePthreadMutexDestroy(PthreadMutex* mutex); -int APS5_VABI scePthreadMutexLock(PthreadMutex* mutex); -int APS5_VABI scePthreadMutexTrylock(PthreadMutex* mutex); -int APS5_VABI scePthreadMutexUnlock(PthreadMutex* mutex); -int APS5_VABI scePthreadCondInit(PthreadCond* cond, const PthreadCondattr* attr, const char* name); -int APS5_VABI scePthreadCondDestroy(PthreadCond* cond); -int APS5_VABI scePthreadCondWait(PthreadCond* cond, PthreadMutex* mutex); -int APS5_VABI scePthreadCondSignal(PthreadCond* cond); -int APS5_VABI scePthreadCondBroadcast(PthreadCond* cond); -int APS5_VABI scePthreadCancel(Pthread thread); -int APS5_VABI scePthreadSetcancelstate(int state, int* old_state); -int APS5_VABI scePthreadSetcanceltype(int type, int* old_type); -void APS5_VABI scePthreadTestcancel(); -int APS5_VABI scePthreadSetprio(Pthread thread, int prio); -int APS5_VABI scePthreadGetprio(Pthread thread, int* prio); -void APS5_VABI scePthreadYield(); + } static constexpr int GUEST_SCHED_FIFO = 1; @@ -65,11 +39,6 @@ static constexpr std::size_t GUEST_CPUSET_BYTES = 32; static constexpr int GUEST_ERANGE = 34; extern "C" { -int* APS5_VABI __error_nid_postfix(); -int APS5_VABI scePthreadGetaffinity(Pthread thread, KernelCpumask* mask); -int APS5_VABI scePthreadSetaffinity(Pthread thread, KernelCpumask mask); -KernelCpumask APS5_VABI sceKernelGetAvailableCpumask(void); -int APS5_VABI getpid_nid_postfix(void); int APS5_VABI cpuset_getaffinity_nid_postfix(int level, int which, std::int64_t id, std::size_t size, void* mask) { constexpr int LevelWhich = 3, WhichThread = 1, WhichProcess = 2; @@ -138,11 +107,6 @@ int APS5_VABI cpuset_setaffinity_nid_postfix(int level, int which, std::int64_t return 0; } -struct GuestRtPrio { - std::uint16_t type; - std::uint16_t prio; -}; - int APS5_VABI rtprio_thread_nid_postfix(int function, int lwpid, GuestRtPrio* priority) { constexpr int Lookup = 0, Set = 1; constexpr int GuestEsrch = 3, GuestEfault = 14; @@ -196,6 +160,7 @@ int APS5_VABI pthread_detach_nid_postfix(Pthread thread) { void APS5_VABI pthread_exit_nid_postfix(void* value) { scePthreadExit(value); + } int APS5_VABI scePthreadGetschedparam(Pthread thread, int* policy, KernelSchedParam* param) { @@ -320,14 +285,13 @@ int APS5_VABI pthread_getname_np_nid_postfix(Pthread thread, char* name) { void APS5_VABI pthread_set_name_np_nid_postfix(Pthread thread, const char* name) { scePthreadRename(thread, name != nullptr ? name : ""); + } Pthread APS5_VABI pthread_self_nid_postfix(void) { return scePthreadSelf(); } -int APS5_VABI scePthreadGetthreadid(void); - int APS5_VABI pthread_getthreadid_np_nid_postfix(void) { return scePthreadGetthreadid(); } @@ -346,6 +310,7 @@ int APS5_VABI pthread_getcpuclockid_nid_postfix(Pthread thread, int* clockId) { int APS5_VABI sched_yield_nid_postfix(void) { scePthreadYield(); + return 0; } @@ -372,10 +337,12 @@ int APS5_VABI pthread_setschedparam_nid_postfix(Pthread thread, int policy, cons void APS5_VABI pthread_testcancel_nid_postfix(void) { scePthreadTestcancel(); + } void APS5_VABI pthread_yield_nid_postfix(void) { scePthreadYield(); + } unsigned int APS5_VABI sleep_nid_postfix(unsigned int seconds) { diff --git a/core/libs/prx/libkernel/Pthread/Posix/Tsd.cpp b/core/libs/prx/libkernel/Pthread/Posix/Tsd.cpp index d46ac1d42d..f715d153be 100644 --- a/core/libs/prx/libkernel/Pthread/Posix/Tsd.cpp +++ b/core/libs/prx/libkernel/Pthread/Posix/Tsd.cpp @@ -1,16 +1,10 @@ +#include "prx/libkernel/include/Api.hpp" #include #include #include "SceTypes.hpp" #include "prx/libc/include/General.hpp" #include "Common.hpp" -extern "C" { -int APS5_VABI scePthreadKeyCreate(PthreadKey* key, pthread_key_destructor_func_t destructor); -int APS5_VABI scePthreadKeyDelete(PthreadKey key); -void* APS5_VABI scePthreadGetspecific(PthreadKey key); -int APS5_VABI scePthreadSetspecific(PthreadKey key, void* value); -} - extern "C" { void* APS5_VABI pthread_getspecific_nid_postfix(PthreadKey key) { diff --git a/core/libs/prx/libkernel/Pthread/src/Attr.cpp b/core/libs/prx/libkernel/Pthread/src/Attr.cpp index 0b3b82078c..0c26eb6762 100644 --- a/core/libs/prx/libkernel/Pthread/src/Attr.cpp +++ b/core/libs/prx/libkernel/Pthread/src/Attr.cpp @@ -1,3 +1,4 @@ +#include "prx/libkernel/include/Api.hpp" #include "prx/libkernel/Pthread/include/Pthread.hpp" #include "prx/libc/include/General.hpp" #include "prx/libkernel/KernelErrors.hpp" diff --git a/core/libs/prx/libkernel/Pthread/src/Mutex.cpp b/core/libs/prx/libkernel/Pthread/src/Mutex.cpp index 6e8cc3df59..84eee73602 100644 --- a/core/libs/prx/libkernel/Pthread/src/Mutex.cpp +++ b/core/libs/prx/libkernel/Pthread/src/Mutex.cpp @@ -1,3 +1,4 @@ +#include "prx/libkernel/Pthread/include/Mutex.hpp" #include "../include/Pthread.hpp" #include "../include/Mutex.hpp" #include "prx/libkernel/KernelErrors.hpp" @@ -219,6 +220,10 @@ int APS5_VABI scePthreadMutexUnlock(PthreadMutex* mutex) { int APS5_VABI scePthreadMutexTimedlock(PthreadMutex* mutex, KernelUseconds usec) { const auto deadline = TimedWait::DeadlineNanos(usec); auto* current = resolveMutex(mutex, true); + if (current && current->_type != MutexType::Recursive && current->_owner.load(std::memory_order_acquire) == std::this_thread::get_id()) { + TimedWait::SleepUntil(deadline); + return sceTimedOut; + } return acquireMutex(current, [=](auto& native) { return TimedWait::AcquireUntil(current, deadline, [&] { return native.try_lock(); }, [&](std::uint64_t micros) { return native.try_lock_for(std::chrono::microseconds(micros)); }); }, sceTimedOut, false); diff --git a/core/libs/prx/libkernel/Pthread/src/Rwlock.cpp b/core/libs/prx/libkernel/Pthread/src/Rwlock.cpp index 36d7301077..8d06b7e9ea 100644 --- a/core/libs/prx/libkernel/Pthread/src/Rwlock.cpp +++ b/core/libs/prx/libkernel/Pthread/src/Rwlock.cpp @@ -1,3 +1,4 @@ +#include "prx/libkernel/Pthread/include/Rwlock.hpp" #include "../include/Pthread.hpp" #include "../include/Rwlock.hpp" #include "prx/libc/include/General.hpp" @@ -104,8 +105,11 @@ int APS5_VABI scePthreadRwlockTryrdlock(PthreadRwlock* rwlock) { int APS5_VABI scePthreadRwlockTimedrdlock(PthreadRwlock* rwlock, KernelUseconds usec) { auto* lock = RequireRwlock(rwlock, __func__); if (!lock) return SCE_KERNEL_ERROR_EINVAL; - if (OwnsWrite(lock)) return SCE_KERNEL_ERROR_EDEADLK; const std::uint64_t deadline = TimedWait::DeadlineNanos(usec); + if (OwnsWrite(lock)) { + TimedWait::SleepUntil(deadline); + return SCE_KERNEL_ERROR_ETIMEDOUT; + } std::unique_lock state(lock->_state); if (!lock->_changed.WaitUntil(state, deadline, [&] { return ReaderMayEnter(lock); })) return SCE_KERNEL_ERROR_ETIMEDOUT; return EnterRead(lock); @@ -133,8 +137,11 @@ int APS5_VABI scePthreadRwlockTrywrlock(PthreadRwlock* rwlock) { int APS5_VABI scePthreadRwlockTimedwrlock(PthreadRwlock* rwlock, KernelUseconds usec) { auto* lock = RequireRwlock(rwlock, __func__); if (!lock) return SCE_KERNEL_ERROR_EINVAL; - if (OwnsWrite(lock)) return SCE_KERNEL_ERROR_EDEADLK; const std::uint64_t deadline = TimedWait::DeadlineNanos(usec); + if (OwnsWrite(lock)) { + TimedWait::SleepUntil(deadline); + return SCE_KERNEL_ERROR_ETIMEDOUT; + } std::unique_lock state(lock->_state); ++lock->_waitingWriters; const bool acquired = lock->_changed.WaitUntil(state, deadline, [&] { return WriterMayEnter(lock); }); diff --git a/core/libs/prx/libkernel/Pthread/src/Sem.cpp b/core/libs/prx/libkernel/Pthread/src/Sem.cpp index ea9006380e..5d6c44715d 100644 --- a/core/libs/prx/libkernel/Pthread/src/Sem.cpp +++ b/core/libs/prx/libkernel/Pthread/src/Sem.cpp @@ -1,3 +1,4 @@ +#include "prx/libkernel/include/Api.hpp" #include "../include/Pthread.hpp" #include "../include/Cancel.hpp" #include "prx/libc/include/General.hpp" diff --git a/core/libs/prx/libkernel/Pthread/src/Thread.cpp b/core/libs/prx/libkernel/Pthread/src/Thread.cpp index 3268744271..d4505b8d1b 100644 --- a/core/libs/prx/libkernel/Pthread/src/Thread.cpp +++ b/core/libs/prx/libkernel/Pthread/src/Thread.cpp @@ -1,3 +1,6 @@ +#include "prx/libkernel/Pthread/include/ThreadLifecycle.hpp" +#include "prx/libkernel/Pthread/include/Cancel.hpp" +#include "prx/libkernel/include/Api.hpp" #include "../include/Pthread.hpp" #include "../include/ThreadLifecycle.hpp" #include "../include/WindowsThreadLocal.hpp" @@ -34,6 +37,20 @@ #include #endif +#ifdef __linux__ +#include +#else +static const auto initialThreadId = std::this_thread::get_id(); +#endif + +extern "C" bool IsInitialPthread_nid_no_patch() { +#ifdef __linux__ + return ::syscall(SYS_gettid) == ::getpid(); +#else + return std::this_thread::get_id() == initialThreadId; +#endif +} + static constexpr int SCE_OK = 0; static constexpr std::size_t GUEST_THREAD_NAME_CAPACITY = 32; @@ -1185,6 +1202,7 @@ int APS5_VABI scePthreadCancel(Pthread thread) { thread->cancelWait->NotifyAll(); } scePthreadYield(); + } } @@ -1212,6 +1230,7 @@ void APS5_VABI pthread_cleanup_push_nid_postfix(void (APS5_VABI* routine)(void*) void APS5_VABI pthread_cleanup_pop_nid_postfix(int execute) { __pthread_cleanup_pop_imp_nid_postfix(execute); + } int APS5_VABI scePthreadEqual(Pthread thread1, Pthread thread2) { @@ -1311,6 +1330,7 @@ int APS5_VABI scePthreadOnce(int32_t* once, void (APS5_VABI* init)(void)) { CleanupHandler reset{}; void* const mark = ThreadCancel::CleanupMark(); __pthread_cleanup_push_imp_nid_postfix(ResetOnce, once, &reset); + try { init(); } catch (...) { diff --git a/core/libs/prx/libkernel/Pthread/src/Tsd.cpp b/core/libs/prx/libkernel/Pthread/src/Tsd.cpp index 03c706c202..2cf90e324a 100644 --- a/core/libs/prx/libkernel/Pthread/src/Tsd.cpp +++ b/core/libs/prx/libkernel/Pthread/src/Tsd.cpp @@ -1,3 +1,4 @@ +#include "prx/libkernel/include/Api.hpp" #include "../include/Pthread.hpp" #include "../include/ThreadLifecycle.hpp" #include "../include/WindowsThreadLocal.hpp" diff --git a/core/libs/prx/libkernel/Socket/include/SocketOptions.hpp b/core/libs/prx/libkernel/Socket/include/SocketOptions.hpp index 18a966c5da..44990b4654 100644 --- a/core/libs/prx/libkernel/Socket/include/SocketOptions.hpp +++ b/core/libs/prx/libkernel/Socket/include/SocketOptions.hpp @@ -23,6 +23,8 @@ struct SocketOptionState { unsigned int tcpKeepInterval = 0; unsigned int tcpKeepCount = 0; int keptFlags = 0; + int tcpFlags = 0; + int ipReceiveOptions = 0; std::uint32_t multicastInterface = 0; std::vector memberships; }; diff --git a/core/libs/prx/libkernel/Socket/src/AddressConversion.cpp b/core/libs/prx/libkernel/Socket/src/AddressConversion.cpp index bbcb17e637..5ffab9d013 100644 --- a/core/libs/prx/libkernel/Socket/src/AddressConversion.cpp +++ b/core/libs/prx/libkernel/Socket/src/AddressConversion.cpp @@ -1,11 +1,11 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include #include #include -extern "C" int* APS5_VABI __error_nid_postfix(); - namespace { constexpr int kGuestInet = 2; constexpr int kGuestInet6 = 28; diff --git a/core/libs/prx/libkernel/Socket/src/Pselect.cpp b/core/libs/prx/libkernel/Socket/src/Pselect.cpp index 931cc83a54..8ae40d8549 100644 --- a/core/libs/prx/libkernel/Socket/src/Pselect.cpp +++ b/core/libs/prx/libkernel/Socket/src/Pselect.cpp @@ -1,12 +1,10 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include extern "C" { -int* APS5_VABI __error_nid_postfix(); -int APS5_VABI select_nid_postfix(int nfds, void* readfds, void* writefds, void* exceptfds, const void* timeout); -int APS5_VABI sigprocmask_nid_postfix(int how, const void* set, void* previousSet); - int APS5_VABI pselect_nid_postfix(int nfds, void* readfds, void* writefds, void* exceptfds, const void* timeout, const void* sigmask) { constexpr int SetMask = 3; struct Timeval { @@ -25,6 +23,7 @@ int APS5_VABI pselect_nid_postfix(int nfds, void* readfds, void* writefds, void* if (sigmask != nullptr) { const int error = *__error_nid_postfix(); sigprocmask_nid_postfix(SetMask, previous, nullptr); + *__error_nid_postfix() = error; } return result; diff --git a/core/libs/prx/libkernel/Socket/src/Socket.cpp b/core/libs/prx/libkernel/Socket/src/Socket.cpp index 6cc428f617..7fb42adbcb 100644 --- a/core/libs/prx/libkernel/Socket/src/Socket.cpp +++ b/core/libs/prx/libkernel/Socket/src/Socket.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include #include #include "SceTypes.hpp" @@ -49,6 +51,14 @@ void ClearDescriptor(void* set, int descriptor) { if (set != nullptr) static_cast(set)[descriptor / 64] &= ~(std::uint64_t{1} << (descriptor % 64)); } +void ClearDescriptorsFrom(int nfds, void* readfds, void* writefds, void* exceptfds) { + if (nfds % 64 == 0) return; + const std::uint64_t kept = (std::uint64_t{1} << (nfds % 64)) - 1; + for (void* set : {readfds, writefds, exceptfds}) { + if (set != nullptr) static_cast(set)[nfds / 64] &= kept; + } +} + struct PollGroup { KernelSocketPoll::Poller poll; std::vector entries; @@ -131,9 +141,6 @@ int HostPoll(KernelSocketPoll::Entry* descriptors, int count, int timeoutMillise extern "C" { -const char* APS5_VABI __inet_ntop_nid_postfix(int family, const void* source, char* destination, std::uint32_t capacity); -int APS5_VABI __inet_pton_nid_postfix(int family, const char* text, void* destination); - const char* APS5_VABI inet_ntop_nid_postfix(int af, const void* src, char* dst, uint32_t size) { return __inet_ntop_nid_postfix(af, src, dst, size); } @@ -142,8 +149,6 @@ int APS5_VABI inet_pton_nid_postfix(int af, const char* src, void* dst) { return __inet_pton_nid_postfix(af, src, dst); } -int* APS5_VABI __error_nid_postfix(); - void KernelSetSocketPoller_nid_no_patch(KernelSocketPoll::Poller poller) { g_socketPoller.store(poller); } @@ -314,6 +319,7 @@ int APS5_VABI select_nid_postfix(int nfds, void* readfds, void* writefds, void* if ((entry.revents & (KernelSocketPoll::Writable | KernelSocketPoll::Error)) == 0) ClearDescriptor(writefds, entry.descriptor); if ((entry.revents & KernelSocketPoll::Urgent) == 0) ClearDescriptor(exceptfds, entry.descriptor); } + ClearDescriptorsFrom(nfds, readfds, writefds, exceptfds); return ready; } if (limit != nullptr && std::chrono::steady_clock::now() >= deadline) { @@ -322,6 +328,7 @@ int APS5_VABI select_nid_postfix(int nfds, void* readfds, void* writefds, void* ClearDescriptor(writefds, entry.descriptor); ClearDescriptor(exceptfds, entry.descriptor); } + ClearDescriptorsFrom(nfds, readfds, writefds, exceptfds); return 0; } } diff --git a/core/libs/prx/libkernel/Socket/src/SocketOptions.cpp b/core/libs/prx/libkernel/Socket/src/SocketOptions.cpp index fd7ea3cfd8..83b5231843 100644 --- a/core/libs/prx/libkernel/Socket/src/SocketOptions.cpp +++ b/core/libs/prx/libkernel/Socket/src/SocketOptions.cpp @@ -49,6 +49,9 @@ constexpr int GuestTcpMaximumSegment = 2; constexpr int GuestTcpKeepIdle = 0x100; constexpr int GuestTcpKeepInterval = 0x200; constexpr int GuestTcpKeepCount = 0x400; +constexpr int GuestTcpNoPush = 4; +constexpr int GuestTcpNoOptions = 8; +constexpr int GuestTcpOption80 = 0x80; constexpr int MinimumSegment = 216; constexpr unsigned int TicksPerSecond = 1000; constexpr unsigned int DefaultKeepIdle = 7200; @@ -62,6 +65,9 @@ constexpr int GuestIpMulticastLoop = 11; constexpr int GuestIpMulticastInterface = 9; constexpr int GuestIpAddMembership = 12; constexpr int GuestIpDropMembership = 13; +constexpr int GuestIpReceiveDestination = 7; +constexpr int GuestIpReceiveInterface = 20; +constexpr int GuestIpReceiveTimeToLive = 65; constexpr std::uint32_t MulticastRequestWithIndex = 12; constexpr int ErrorNotSupported = 45; constexpr int ErrorAddressInUse = 48; @@ -130,6 +136,24 @@ void EnsureBuffers(SocketOptionState& state, int family, int type) { state.receiveLowWater = 1; } +int TcpFlagBit(int option) { + switch (option) { + case GuestTcpNoPush: return 0x1000; + case GuestTcpNoOptions: return 0x8; + case GuestTcpOption80: return 0x10000; + default: return 0; + } +} + +int IpReceiveBit(int option) { + switch (option) { + case GuestIpReceiveDestination: return 1; + case GuestIpReceiveInterface: return 2; + case GuestIpReceiveTimeToLive: return 4; + default: return 0; + } +} + int Copy(void* output, std::uint32_t* length, const void* value, std::uint32_t size) { const std::uint32_t count = output ? std::min(*length, size) : 0; if (count != 0) std::memcpy(output, value, count); @@ -301,11 +325,15 @@ int GetSocketLevelOption(std::uintptr_t native, SocketOptionState& state, int fa int SetTcpLevelOption(std::uintptr_t native, SocketOptionState& state, bool tcp, int option, const void* value, std::uint32_t length) { if (!tcp) return ErrorInvalid; if (option != GuestTcpNoDelay && option != GuestTcpMaximumSegment && option != GuestTcpKeepIdle && option != GuestTcpKeepInterval && - option != GuestTcpKeepCount) + option != GuestTcpKeepCount && TcpFlagBit(option) == 0) return ErrorNoProtocolOption; if (length < sizeof(int)) return ErrorInvalid; int number; std::memcpy(&number, value, sizeof(number)); + if (const int bit = TcpFlagBit(option); bit != 0) { + state.tcpFlags = number != 0 ? state.tcpFlags | bit : state.tcpFlags & ~bit; + return 0; + } const auto unsignedNumber = static_cast(number); if (option == GuestTcpMaximumSegment) { if (number <= 0 || number > state.tcpMaximumSegment || number + 40 < MinimumSegment) return ErrorInvalid; @@ -335,6 +363,10 @@ int GetTcpLevelOption(std::uintptr_t native, SocketOptionState& state, bool tcp, : (state.tcpKeepCount != 0 ? state.tcpKeepCount : DefaultKeepCount); return Copy(value, length, &number, sizeof(number)); } + if (const int bit = TcpFlagBit(option); bit != 0) { + const int number = state.tcpFlags & bit; + return Copy(value, length, &number, sizeof(number)); + } if (option != GuestTcpNoDelay) return ErrorNoProtocolOption; int enabled = 0; socklen_t size = sizeof(enabled); @@ -396,6 +428,13 @@ int SetIpLevelOption(std::uintptr_t native, SocketOptionState& state, bool ipv4, std::memcpy(&state.multicastInterface, &address, sizeof(address)); return 0; } + if (const int bit = IpReceiveBit(option); bit != 0) { + if (length < sizeof(int)) return ErrorInvalid; + int number; + std::memcpy(&number, value, sizeof(number)); + state.ipReceiveOptions = number != 0 ? state.ipReceiveOptions | bit : state.ipReceiveOptions & ~bit; + return 0; + } if (option == GuestIpTimeToLive || option == GuestIpTypeOfService) { if (length < sizeof(int)) return ErrorInvalid; int number; @@ -438,7 +477,8 @@ int GetIpLevelOption(SocketOptionState& state, bool ipv4, bool datagram, int opt return Copy(value, length, &state.multicastInterface, sizeof(state.multicastInterface)); } int number; - if (option == GuestIpTimeToLive) number = state.ipTimeToLive; + if (const int bit = IpReceiveBit(option); bit != 0) number = (state.ipReceiveOptions & bit) != 0 ? 1 : 0; + else if (option == GuestIpTimeToLive) number = state.ipTimeToLive; else if (option == GuestIpTypeOfService) number = state.ipTypeOfService; else if (option == GuestIpMulticastTimeToLive) number = state.multicastTimeToLive; else if (option == GuestIpMulticastLoop) number = state.multicastLoop ? 1 : 0; diff --git a/core/libs/prx/libkernel/Socket/src/Udp.cpp b/core/libs/prx/libkernel/Socket/src/Udp.cpp index 61a0d07b10..65eadfe9a5 100644 --- a/core/libs/prx/libkernel/Socket/src/Udp.cpp +++ b/core/libs/prx/libkernel/Socket/src/Udp.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN #include @@ -38,6 +40,7 @@ #include "prx/libkernel/Equeue/Equeue.hpp" #include "prx/libkernel/File/include/File.hpp" #include "prx/libkernel/File/include/RandomDevice.hpp" +#include "prx/libkernel/File/include/SharedMemory.hpp" #include "prx/libkernel/Time/include/TimedWait.hpp" #include "prx/libkernel/Socket/include/SocketPoll.hpp" #include "prx/libkernel/Socket/include/SocketConnect.hpp" @@ -57,8 +60,6 @@ #include #include -extern "C" int* APS5_VABI __error_nid_postfix(); -extern "C" int APS5_VABI dup2_nid_postfix(int from, int to); namespace { #ifdef _WIN32 using NativeSocket = SOCKET; @@ -122,6 +123,7 @@ struct Socket : KernelSocketPoll::NativeOwner { GuestSockets::SocketOptionState options; bool receiveShut = false; bool sendShut = false; + std::weak_ptr peer; Socket(NativeSocket value, int family, int type) : value(value), family(family), type(type) {} ~Socket() { if (value == Invalid) return; @@ -272,11 +274,14 @@ int AddressLengthError(const void* input, std::uint32_t length) { if (length < 2) return 22; return input ? 0 : 14; } -bool Address(const void* input, std::uint32_t length, sockaddr_storage& native, socklen_t& size) { +bool Address(int family, const void* input, std::uint32_t length, sockaddr_storage& native, socklen_t& size, bool lengthFirst = false) { if (const int error = AddressLengthError(input, length)) { Fail(error); return false; } const auto* bytes = static_cast(input); - if ((bytes[1] == 2 && length < 16) || (bytes[1] == 28 && length < 28)) { Fail(22); return false; } - if (bytes[1] == 2 && length >= 16) { + const bool wrongLength = (family == 2 && length != 16) || (family == 28 && length != 28); + if (lengthFirst && wrongLength) { Fail(22); return false; } + if (family == 2 && bytes[1] != 2) { Fail(47); return false; } + if (wrongLength) { Fail(22); return false; } + if (family == 2) { auto& v4 = reinterpret_cast(native); v4.sin_family = AF_INET; std::memcpy(&v4.sin_port, bytes + 2, 2); @@ -284,7 +289,7 @@ bool Address(const void* input, std::uint32_t length, sockaddr_storage& native, size = sizeof(v4); return true; } - if (bytes[1] == 28 && length >= 28) { + if (family == 28 && bytes[1] == 28) { auto& v6 = reinterpret_cast(native); v6.sin6_family = AF_INET6; std::memcpy(&v6.sin6_port, bytes + 2, 2); @@ -297,14 +302,15 @@ bool Address(const void* input, std::uint32_t length, sockaddr_storage& native, Fail(47); return false; } -int LongAddressError(const Socket& socket, const void* address, std::uint32_t length) { - if ((socket.family != 2 && socket.family != 28) || length <= (socket.family == 2 ? 16u : 28u)) return 0; +int LongMappedDualStack(const Socket& socket, const void* address, std::uint32_t length) { + if (socket.family != 28 || socket.type != 2 || address == nullptr || length <= 28 || length > 255) return 0; + const auto* bytes = static_cast(address); constexpr unsigned char mapped[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff}; - if (socket.family != 28 || socket.type != 2 || std::memcmp(static_cast(address) + 8, mapped, sizeof(mapped)) != 0) return 22; + if (bytes[1] != 28 || std::memcmp(bytes + 8, mapped, sizeof(mapped)) != 0) return 0; int ipv6Only = 0; socklen_t size = sizeof(ipv6Only); - if (::getsockopt(socket.value, IPPROTO_IPV6, IPV6_V6ONLY, reinterpret_cast(&ipv6Only), &size)) return NativeError(); - return ipv6Only ? 22 : 0; + if (::getsockopt(socket.value, IPPROTO_IPV6, IPV6_V6ONLY, reinterpret_cast(&ipv6Only), &size)) return Fail(NativeError()); + return ipv6Only ? 0 : 1; } std::uint16_t& PortOf(sockaddr_storage& address) { return address.ss_family == AF_INET ? reinterpret_cast(address).sin_port : reinterpret_cast(address).sin6_port; @@ -313,6 +319,11 @@ bool Listening(const Socket& socket) { bool listening = false; return GuestSockets::NativeListening(static_cast(socket.value), listening) && listening; } +bool PeerConnected(const Socket& socket) { + sockaddr_storage peer{}; + socklen_t size = sizeof(peer); + return ::getpeername(socket.value, reinterpret_cast(&peer), &size) == 0; +} constexpr std::int64_t NotAnswered = -2; std::int64_t ZeroPortSend(const Socket& socket, const sockaddr_storage& destination, std::uint64_t length) { if (socket.type != 2 || socket.family != 2 || destination.ss_family != AF_INET) return NotAnswered; @@ -536,11 +547,7 @@ using NativePollDescriptor = WSAPOLLFD; #else using NativePollDescriptor = pollfd; #endif -struct GuestPollDescriptor { - int descriptor; - short events; - short revents; -}; + struct PollFlag { short guest; short native; @@ -1175,7 +1182,7 @@ int APS5_VABI socket_nid_postfix(int family, int type, int protocol) { if (family != 2 && family != 28) return Fail(47); const int nativeType = plainType == 1 ? SOCK_STREAM : plainType == 2 ? SOCK_DGRAM : -1; const int expectedProtocol = plainType == 1 ? 6 : 17; - const bool inetKnowsType = plainType == 3 || plainType == 5; + const bool inetKnowsType = plainType == 3; if (nativeType == -1) return Fail(protocol == 0 && plainType != 0 && !inetKnowsType ? 41 : 43); if (protocol != 0 && protocol != expectedProtocol) return Fail(43); #ifdef _WIN32 @@ -1229,6 +1236,8 @@ int APS5_VABI socketpair_nid_postfix(int family, int type, int protocol, int* de firstGuard.value = Invalid; auto second = std::make_shared(native[1], GuestUnix, plainType); secondGuard.value = Invalid; + first->peer = second; + second->peer = first; if (nonblocking && (SetNonBlocking(*first) || SetNonBlocking(*second))) return -1; const int firstDescriptor = Install(std::move(first)); if (firstDescriptor < 0) return -1; @@ -1257,16 +1266,16 @@ int APS5_VABI connect_nid_postfix(int descriptor, const void* address, std::uint if (socket->family != GuestUnix && socket->type == 2 && address && length >= 2 && static_cast(address)[1] == 0 && Disconnect(*socket) != 0) return -1; + if (socket->type == 1 && Listening(*socket)) return Fail(45); + const int mapped = LongMappedDualStack(*socket, address, length); + if (mapped < 0) return -1; sockaddr_storage native{}; socklen_t size; - if (!Address(address, length, native, size)) return -1; + if (!Address(socket->family, address, mapped ? 28 : length, native, size)) return -1; #ifdef _WIN32 if (socket->type == 1) RefuseClosedLoopbackAtOnce_nid_no_patch(socket->value, reinterpret_cast(&native)); #endif - if (socket->type == 1 && Listening(*socket)) return Fail(45); - if (const int error = LongAddressError(*socket, address, length)) return Fail(error); if (ZeroPortConnect(*socket, address, length)) return -1; - if (native.ss_family != (socket->family == 2 ? AF_INET : AF_INET6)) return Fail(47); { std::lock_guard lock(socket->modeMutex); socket->options.reportedError = 0; @@ -1311,6 +1320,7 @@ int APS5_VABI accept_nid_postfix(int descriptor, void* address, std::uint32_t* l accepted->options.tcpKeepIdle = listener->options.tcpKeepIdle; accepted->options.tcpKeepInterval = listener->options.tcpKeepInterval; accepted->options.tcpKeepCount = listener->options.tcpKeepCount; + accepted->options.tcpFlags = listener->options.tcpFlags & 0x1000; } if (inheritNonblocking && SetNonBlocking(*accepted)) return -1; const int acceptedDescriptor = Install(std::move(accepted)); @@ -1354,8 +1364,9 @@ int APS5_VABI bind_nid_postfix(int descriptor, const void* address, std::uint32_ if (!socket) return -1; sockaddr_storage native{}; socklen_t size; - if (!Address(address, length, native, size)) return -1; - if (const int error = LongAddressError(*socket, address, length)) return Fail(error); + const int mapped = LongMappedDualStack(*socket, address, length); + if (mapped < 0) return -1; + if (!Address(socket->family, address, mapped ? 28 : length, native, size)) return -1; return ::bind(socket->value, reinterpret_cast(&native), size) ? Fail(NativeError()) : 0; } int APS5_VABI shutdown_nid_postfix(int descriptor, int how) { @@ -1390,6 +1401,7 @@ int APS5_VABI getsockname_nid_postfix(int descriptor, void* address, std::uint32 int APS5_VABI getpeername_nid_postfix(int descriptor, void* address, std::uint32_t* length) { const auto socket = Lookup(descriptor); if (!socket) return -1; + if (socket->family == GuestUnix && socket->peer.expired()) return Fail(57); if (!address || !length) return Fail(14); if (socket->family == GuestUnix) return UnnamedAddress(address, length); sockaddr_storage native{}; @@ -1435,15 +1447,13 @@ std::int64_t APS5_VABI sendto_nid_postfix(int descriptor, const void* buffer, st if (!buffer && length) return Fail(14); if (const int waited = WaitForTransfer(*socket, true, flags)) return Fail(waited); int result; - if (!address) { - if (addressLength != 0) return Fail(22); + if (!address || (socket->type == 1 && PeerConnected(*socket))) { + if (!address && addressLength != 0) return Fail(22); result = ::send(socket->value, static_cast(buffer), static_cast(length), SocketSendFlags(*socket, flags)); } else { sockaddr_storage native{}; socklen_t size; - if (!Address(address, addressLength, native, size)) return -1; - if (socket->family == 28 && socket->type == 2 && addressLength > 28) return Fail(22); - if (native.ss_family != (socket->family == 2 ? AF_INET : AF_INET6)) return Fail(47); + if (!Address(socket->family, address, addressLength, native, size, true)) return -1; if (const auto answered = ZeroPortSend(*socket, native, length); answered != NotAnswered) return answered; result = static_cast(::sendto(socket->value, static_cast(buffer), static_cast(length), SocketSendFlags(*socket, flags), reinterpret_cast(&native), size)); @@ -1483,19 +1493,7 @@ std::int64_t APS5_VABI recvfrom_nid_postfix(int descriptor, void* buffer, std::u } return result; } -struct GuestIovec { - void* base; - std::uint64_t length; -}; -struct GuestMsghdr { - void* name; - std::uint32_t nameLength; - GuestIovec* iov; - int iovLength; - void* control; - std::uint32_t controlLength; - int flags; -}; + static_assert(sizeof(GuestMsghdr) == 48 && offsetof(GuestMsghdr, iov) == 16 && offsetof(GuestMsghdr, control) == 32 && offsetof(GuestMsghdr, flags) == 44); static std::int64_t MessageLength(const GuestMsghdr* message) { if (!message) return Fail(14); @@ -1597,8 +1595,8 @@ std::int64_t APS5_VABI recvmsg_nid_postfix(int descriptor, GuestMsghdr* message, GuestMsghdr header{}; if (!message || !ReadGuest(&header, message, sizeof(header))) return Fail(14); if (header.iovLength < 0 || header.iovLength > 1024) return Fail(40); - std::vector vectors(static_cast(header.iovLength)); - if (!ReadGuest(vectors.data(), header.iov, vectors.size() * sizeof(GuestIovec))) return Fail(14); + std::vector vectors(static_cast(header.iovLength)); + if (!ReadGuest(vectors.data(), header.iov, vectors.size() * sizeof(KernelIovec))) return Fail(14); header.iov = vectors.data(); const auto total = MessageLength(&header); if (total < 0) return -1; @@ -1658,15 +1656,10 @@ std::int64_t APS5_VABI recvmsg_nid_postfix(int descriptor, GuestMsghdr* message, if (!WriteGuest(reinterpret_cast(message) + results, reinterpret_cast(&header) + results, sizeof(header) - results)) return Fail(14); return received; } -struct GuestSendfileHeaders { - GuestIovec* headers; - int headerCount; - GuestIovec* trailers; - int trailerCount; -}; + static_assert(sizeof(GuestSendfileHeaders) == 32 && offsetof(GuestSendfileHeaders, trailers) == 16); -std::int64_t APS5_VABI sceKernelPread(int descriptor, void* buffer, std::size_t length, std::int64_t offset); -static bool SendfileIovecs(const GuestIovec* iov, int count) { + +static bool SendfileIovecs(const KernelIovec* iov, int count) { if (!iov) return true; if (count < 0 || count > 1024) return false; std::uint64_t total = 0; @@ -1688,7 +1681,7 @@ static int SendAll(const Socket& socket, const void* data, std::uint64_t length, } return 0; } -static int SendIovecs(const Socket& socket, const GuestIovec* iov, int count, std::int64_t& sent) { +static int SendIovecs(const Socket& socket, const KernelIovec* iov, int count, std::int64_t& sent) { for (int i = 0; iov && i < count; ++i) if (const int error = SendAll(socket, iov[i].base, iov[i].length, sent)) return error; return 0; @@ -1699,6 +1692,12 @@ int APS5_VABI sendfile_nid_postfix(int file, int descriptor, std::int64_t offset if (offset < 0) return Fail(22); if (headers && (!SendfileIovecs(headers->headers, headers->headerCount) || !SendfileIovecs(headers->trailers, headers->trailerCount))) return Fail(22); + std::int64_t sent = 0; + const auto finish = [&](int error) { + if (sbytes) *sbytes = sent; + return error ? Fail(error) : 0; + }; + if (DescriptorIsOpen_nid_no_patch(file) && !File::IsVnode(file) && !File::IsSharedMemoryDescriptor_nid_no_patch(file)) return finish(22); std::vector chunk; try { chunk.resize(0x10000); @@ -1712,11 +1711,6 @@ int APS5_VABI sendfile_nid_postfix(int file, int descriptor, std::int64_t offset std::uint64_t remaining = length ? length : UINT64_MAX; auto received = read(offset, remaining); if (received == -9) return Fail(9); - std::int64_t sent = 0; - const auto finish = [&](int error) { - if (sbytes) *sbytes = sent; - return error ? Fail(error) : 0; - }; if (received < 0) return finish(received == -21 || received == -29 ? 22 : static_cast(-received)); const auto socket = Lookup(descriptor); if (!socket) return finish(*__error_nid_postfix()); diff --git a/core/libs/prx/libkernel/SyncOnAddress/src/SyncOnAddress.cpp b/core/libs/prx/libkernel/SyncOnAddress/src/SyncOnAddress.cpp index ae7d9a7b13..a83f3e3c2d 100644 --- a/core/libs/prx/libkernel/SyncOnAddress/src/SyncOnAddress.cpp +++ b/core/libs/prx/libkernel/SyncOnAddress/src/SyncOnAddress.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include #include #include @@ -16,8 +18,6 @@ #include "prx/libkernel/Time/include/Time.hpp" #include "prx/libkernel/Time/include/TimedWait.hpp" -extern "C" int* APS5_VABI __error_nid_postfix(); - namespace { constexpr int SYNC_ON_ADDRESS_OK = 0; @@ -201,6 +201,7 @@ int UmtxDeadline(const void* sizeArgument, const void* timeArgument, std::option } else { KernelTimespec now{}; clock_gettime_nid_postfix(static_cast(time.clockId), &now); + remaining = SaturatingNanos(time.timeout.tv_sec - now.tv_sec, time.timeout.tv_nsec - now.tv_nsec); } if (remaining < UNBOUNDED_WAIT_NANOS) { diff --git a/core/libs/prx/libkernel/System/src/Coredump.cpp b/core/libs/prx/libkernel/System/src/Coredump.cpp index f6502ea438..7f041e1b61 100644 --- a/core/libs/prx/libkernel/System/src/Coredump.cpp +++ b/core/libs/prx/libkernel/System/src/Coredump.cpp @@ -1,3 +1,4 @@ +#include "prx/libkernel/include/Api.hpp" #include #include #include @@ -48,7 +49,6 @@ int APS5_VABI sceKernelDebugWriteCppExceptionInfo(const void* exception, uint64_ return 0; } - int APS5_VABI sceCoredumpAttachUserFile(std::uint32_t userValue, const char* path) { if (!path || !validUserFileFlags(userValue)) return SCE_COREDUMP_ERROR_INVALID_ARGUMENT; if (static_cast(std::strlen(path)) < 0) return 0; diff --git a/core/libs/prx/libkernel/System/src/Error.cpp b/core/libs/prx/libkernel/System/src/Error.cpp index a0eb19f9b6..5b3452fd77 100644 --- a/core/libs/prx/libkernel/System/src/Error.cpp +++ b/core/libs/prx/libkernel/System/src/Error.cpp @@ -1,3 +1,4 @@ +#include "prx/libkernel/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include diff --git a/core/libs/prx/libkernel/System/src/Exception.cpp b/core/libs/prx/libkernel/System/src/Exception.cpp index a6b313d86a..8882083584 100644 --- a/core/libs/prx/libkernel/System/src/Exception.cpp +++ b/core/libs/prx/libkernel/System/src/Exception.cpp @@ -1,3 +1,4 @@ +#include "prx/libkernel/include/Api.hpp" #include #include #include "SceTypes.hpp" @@ -27,7 +28,6 @@ #include #endif -extern "C" Pthread APS5_VABI scePthreadSelf(); #ifdef _WIN32 extern "C" void Aps5RedirectedEntryStub(); extern "C" [[noreturn]] void Aps5RedirectedExit(CONTEXT* context, const void* vectors, void (*restore)(CONTEXT*, EXCEPTION_RECORD*)); diff --git a/core/libs/prx/libkernel/System/src/Login.cpp b/core/libs/prx/libkernel/System/src/Login.cpp index 80f9eaabc9..e188559977 100644 --- a/core/libs/prx/libkernel/System/src/Login.cpp +++ b/core/libs/prx/libkernel/System/src/Login.cpp @@ -1,3 +1,4 @@ +#include "prx/libkernel/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include diff --git a/core/libs/prx/libkernel/System/src/Notification.cpp b/core/libs/prx/libkernel/System/src/Notification.cpp index 9d94d2b291..df976eac7f 100644 --- a/core/libs/prx/libkernel/System/src/Notification.cpp +++ b/core/libs/prx/libkernel/System/src/Notification.cpp @@ -1,3 +1,4 @@ +#include "prx/libkernel/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libkernel/File/include/File.hpp" #include diff --git a/core/libs/prx/libkernel/System/src/Process.cpp b/core/libs/prx/libkernel/System/src/Process.cpp index 397b42409f..cce4173934 100644 --- a/core/libs/prx/libkernel/System/src/Process.cpp +++ b/core/libs/prx/libkernel/System/src/Process.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #ifdef _WIN32 #ifndef NOMINMAX #define NOMINMAX @@ -51,10 +53,6 @@ #include #endif -extern "C" int* APS5_VABI __error_nid_postfix(); -extern "C" int APS5_VABI stat_nid_postfix(const char* path, FileStat* sb); -extern "C" int APS5_VABI sceKernelVirtualQuery(const void* addr, int flags, VirtualQueryInfo* info, std::uint64_t info_size); - namespace { constexpr int sceInvalidArgument = static_cast(0x80020016u); @@ -273,13 +271,6 @@ std::int64_t toGuestLimit(rlim_t value) { } -extern "C" int* APS5_VABI __error_nid_postfix(); - -struct GuestResourceLimit { - std::int64_t rlim_cur; - std::int64_t rlim_max; -}; - namespace { std::mutex openFileLimitMutex; std::optional guestOpenFileLimit; @@ -287,27 +278,6 @@ std::mutex processLimitMutex; GuestResourceLimit guestProcessResourceLimit{guestProcessLimit, guestProcessLimit}; } -struct GuestResourceUsage { - KernelTimeval ru_utime; - KernelTimeval ru_stime; - std::int64_t ru_maxrss; - std::int64_t ru_ixrss; - std::int64_t ru_idrss; - std::int64_t ru_isrss; - std::int64_t ru_minflt; - std::int64_t ru_majflt; - std::int64_t ru_nswap; - std::int64_t ru_inblock; - std::int64_t ru_oublock; - std::int64_t ru_msgsnd; - std::int64_t ru_msgrcv; - std::int64_t ru_nsignals; - std::int64_t ru_nvcsw; - std::int64_t ru_nivcsw; -}; - -extern "C" Pthread APS5_VABI scePthreadSelf(); - extern "C" { // unknown data @@ -460,8 +430,6 @@ int APS5_VABI waitpid_nid_postfix(int pid, int* status, int options) { return -1; } -int APS5_VABI getrlimit_nid_postfix(int resource, GuestResourceLimit* limit); - int APS5_VABI setrlimit_nid_postfix(int resource, const GuestResourceLimit* limit) { if (limit == nullptr) { *__error_nid_postfix() = guestFault; @@ -482,6 +450,7 @@ int APS5_VABI setrlimit_nid_postfix(int resource, const GuestResourceLimit* limi GuestResourceLimit current{}; getrlimit_nid_postfix(resource, ¤t); + if (resource == guestRlimitNofile) { if (requested.rlim_max <= current.rlim_max && requested.rlim_cur <= requested.rlim_max) { std::lock_guard lock(openFileLimitMutex); @@ -600,6 +569,7 @@ void APS5_VABI sceKernelSync(void) { void APS5_VABI sync_nid_postfix(void) { sceKernelSync(); + } int APS5_VABI sched_get_priority_max_nid_postfix(int policy) { @@ -674,8 +644,12 @@ int APS5_VABI getrusage_nid_postfix(int who, GuestResourceUsage* usage) { *__error_nid_postfix() = guestFault; return -1; } + GuestResourceUsage result{}; if (who == -1) { - *usage = {}; + if (!WriteGuest(usage, &result, sizeof(result))) { + *__error_nid_postfix() = guestFault; + return -1; + } return 0; } #ifdef _WIN32 @@ -695,47 +669,37 @@ int APS5_VABI getrusage_nid_postfix(int who, GuestResourceUsage* usage) { }; const auto userMicros = toMicros(user); const auto kernelMicros = toMicros(kernel); - usage->ru_utime.tv_sec = static_cast(userMicros / 1000000ULL); - usage->ru_utime.tv_usec = static_cast(userMicros % 1000000ULL); - usage->ru_stime.tv_sec = static_cast(kernelMicros / 1000000ULL); - usage->ru_stime.tv_usec = static_cast(kernelMicros % 1000000ULL); - usage->ru_maxrss = 0; - usage->ru_ixrss = 0; - usage->ru_idrss = 0; - usage->ru_isrss = 0; - usage->ru_minflt = 0; - usage->ru_majflt = 0; - usage->ru_nswap = 0; - usage->ru_inblock = 0; - usage->ru_oublock = 0; - usage->ru_msgsnd = 0; - usage->ru_msgrcv = 0; - usage->ru_nsignals = 0; - usage->ru_nvcsw = 0; - usage->ru_nivcsw = 0; + result.ru_utime.tv_sec = static_cast(userMicros / 1000000ULL); + result.ru_utime.tv_usec = static_cast(userMicros % 1000000ULL); + result.ru_stime.tv_sec = static_cast(kernelMicros / 1000000ULL); + result.ru_stime.tv_usec = static_cast(kernelMicros % 1000000ULL); #else struct rusage native{}; if (::getrusage(who == 0 ? RUSAGE_SELF : RUSAGE_THREAD, &native) != 0) throw std::system_error(errno, std::generic_category(), "getrusage: getrusage failed"); - usage->ru_utime.tv_sec = static_cast(native.ru_utime.tv_sec); - usage->ru_utime.tv_usec = static_cast(native.ru_utime.tv_usec); - usage->ru_stime.tv_sec = static_cast(native.ru_stime.tv_sec); - usage->ru_stime.tv_usec = static_cast(native.ru_stime.tv_usec); - usage->ru_maxrss = static_cast(native.ru_maxrss); - usage->ru_ixrss = static_cast(native.ru_ixrss); - usage->ru_idrss = static_cast(native.ru_idrss); - usage->ru_isrss = static_cast(native.ru_isrss); - usage->ru_minflt = static_cast(native.ru_minflt); - usage->ru_majflt = static_cast(native.ru_majflt); - usage->ru_nswap = static_cast(native.ru_nswap); - usage->ru_inblock = static_cast(native.ru_inblock); - usage->ru_oublock = static_cast(native.ru_oublock); - usage->ru_msgsnd = static_cast(native.ru_msgsnd); - usage->ru_msgrcv = static_cast(native.ru_msgrcv); - usage->ru_nsignals = static_cast(native.ru_nsignals); - usage->ru_nvcsw = static_cast(native.ru_nvcsw); - usage->ru_nivcsw = static_cast(native.ru_nivcsw); + result.ru_utime.tv_sec = static_cast(native.ru_utime.tv_sec); + result.ru_utime.tv_usec = static_cast(native.ru_utime.tv_usec); + result.ru_stime.tv_sec = static_cast(native.ru_stime.tv_sec); + result.ru_stime.tv_usec = static_cast(native.ru_stime.tv_usec); + result.ru_maxrss = static_cast(native.ru_maxrss); + result.ru_ixrss = static_cast(native.ru_ixrss); + result.ru_idrss = static_cast(native.ru_idrss); + result.ru_isrss = static_cast(native.ru_isrss); + result.ru_minflt = static_cast(native.ru_minflt); + result.ru_majflt = static_cast(native.ru_majflt); + result.ru_nswap = static_cast(native.ru_nswap); + result.ru_inblock = static_cast(native.ru_inblock); + result.ru_oublock = static_cast(native.ru_oublock); + result.ru_msgsnd = static_cast(native.ru_msgsnd); + result.ru_msgrcv = static_cast(native.ru_msgrcv); + result.ru_nsignals = static_cast(native.ru_nsignals); + result.ru_nvcsw = static_cast(native.ru_nvcsw); + result.ru_nivcsw = static_cast(native.ru_nivcsw); #endif + if (!WriteGuest(usage, &result, sizeof(result))) { + *__error_nid_postfix() = guestFault; + return -1; + } return 0; } @@ -846,6 +810,7 @@ int APS5_VABI setpriority_nid_postfix(int which, int who, int niceval) { int APS5_VABI getdtablesize_nid_postfix(void) { GuestResourceLimit limit{}; getrlimit_nid_postfix(guestRlimitNofile, &limit); + std::int64_t tableSize = limit.rlim_cur; #ifndef _WIN32 tableSize = std::min(tableSize, static_cast(::getdtablesize())); diff --git a/core/libs/prx/libkernel/System/src/Rtld.cpp b/core/libs/prx/libkernel/System/src/Rtld.cpp index 90472da544..5d424ba846 100644 --- a/core/libs/prx/libkernel/System/src/Rtld.cpp +++ b/core/libs/prx/libkernel/System/src/Rtld.cpp @@ -1,3 +1,4 @@ +#include "prx/libkernel/include/Api.hpp" #include #include #include diff --git a/core/libs/prx/libkernel/System/src/Sandbox.cpp b/core/libs/prx/libkernel/System/src/Sandbox.cpp index dd3918c68a..e904dc5942 100644 --- a/core/libs/prx/libkernel/System/src/Sandbox.cpp +++ b/core/libs/prx/libkernel/System/src/Sandbox.cpp @@ -1,3 +1,4 @@ +#include "prx/libkernel/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" extern "C" const char* APS5_VABI sceKernelGetFsSandboxRandomWord() { diff --git a/core/libs/prx/libkernel/System/src/Sanitizer.cpp b/core/libs/prx/libkernel/System/src/Sanitizer.cpp index 0586eef7d7..15ff3e040f 100644 --- a/core/libs/prx/libkernel/System/src/Sanitizer.cpp +++ b/core/libs/prx/libkernel/System/src/Sanitizer.cpp @@ -1,3 +1,4 @@ +#include "prx/libkernel/include/Api.hpp" #include "SceTypes.hpp" extern "C" { diff --git a/core/libs/prx/libkernel/System/src/SignalSets.cpp b/core/libs/prx/libkernel/System/src/SignalSets.cpp index 688ad49ce8..8444422f5d 100644 --- a/core/libs/prx/libkernel/System/src/SignalSets.cpp +++ b/core/libs/prx/libkernel/System/src/SignalSets.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/AsmMacros.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -5,11 +7,6 @@ #include #include -extern "C" int* APS5_VABI __error_nid_postfix(); - -struct GuestSignalSet { - std::uint32_t bits[4]; -}; static_assert(sizeof(GuestSignalSet) == 16); namespace { diff --git a/core/libs/prx/libkernel/System/src/Signals.cpp b/core/libs/prx/libkernel/System/src/Signals.cpp index 1a281703a4..cc99d90231 100644 --- a/core/libs/prx/libkernel/System/src/Signals.cpp +++ b/core/libs/prx/libkernel/System/src/Signals.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "SceTypes.hpp" #include "prx/libc/include/General.hpp" #include "prx/libkernel/Pthread/Posix/Common.hpp" @@ -17,25 +19,12 @@ #include #include -extern "C" int* APS5_VABI __error_nid_postfix(); -extern "C" int APS5_VABI getpid_nid_postfix(void); -extern "C" Pthread APS5_VABI scePthreadSelf(void); - -struct GuestSignalSet { - std::uint32_t bits[4]; -}; - -struct GuestSigaction { - std::uintptr_t handler; - int flags; - GuestSignalSet mask; -}; static_assert(sizeof(GuestSigaction) == 32 && offsetof(GuestSigaction, flags) == 8 && offsetof(GuestSigaction, mask) == 12); extern "C" GuestSignalSet _sigintr_nid_postfix{}; namespace { -using GuestHandler = void (APS5_VABI *)(int); + constexpr int MaxSignal = 128; constexpr int GuestSigkill = 9; constexpr int GuestSigstop = 17; @@ -75,11 +64,8 @@ struct GuestSiginfo { static_assert(sizeof(GuestSiginfo) == 80 && offsetof(GuestSiginfo, code) == 8 && offsetof(GuestSiginfo, pid) == 12 && offsetof(GuestSiginfo, uid) == 16 && offsetof(GuestSiginfo, address) == 24 && offsetof(GuestSiginfo, value) == 32 && offsetof(GuestSiginfo, band) == 40); -struct GuestTimespec { - std::int64_t seconds; - std::int64_t nanoseconds; -}; -static_assert(sizeof(GuestTimespec) == 16 && offsetof(GuestTimespec, nanoseconds) == 8); + +static_assert(sizeof(KernelTimespec) == 16 && offsetof(KernelTimespec, tv_nsec) == 8); bool IgnoredByDefault(int guest) { return guest == 16 || guest == GuestSigcont || guest == 20 || guest == 23 || guest == 28 || guest == 29; } @@ -240,7 +226,7 @@ bool DeliverPendingSignal(int guest) { return false; } -int WaitForPendingInSet(const GuestSignalSet& set, bool waitForever, const GuestTimespec* timeout, int* guest) { +int WaitForPendingInSet(const GuestSignalSet& set, bool waitForever, const KernelTimespec* timeout, int* guest) { auto& pending = Pending(); std::unique_lock lock(pending.lock); std::optional deadline; @@ -250,8 +236,8 @@ int WaitForPendingInSet(const GuestSignalSet& set, bool waitForever, const Guest pending.changed.wait(lock); continue; } - if (!deadline) deadline = std::chrono::steady_clock::now() + std::chrono::seconds(timeout->seconds) + - std::chrono::nanoseconds(timeout->nanoseconds); + if (!deadline) deadline = std::chrono::steady_clock::now() + std::chrono::seconds(timeout->tv_sec) + + std::chrono::nanoseconds(timeout->tv_nsec); if (pending.changed.wait_until(lock, *deadline) == std::cv_status::no_timeout) continue; return PendingInSet(set, guest) ? 0 : GuestEagain; } @@ -279,8 +265,6 @@ void WaitForDeliverableSignal() { } } -extern "C" int APS5_VABI _sigprocmask_nid_postfix(int how, const GuestSignalSet* set, GuestSignalSet* previousSet); - } namespace { @@ -377,10 +361,6 @@ extern "C" unsigned int APS5_VABI GuestAlarm_nid_no_patch(unsigned int seconds) return remaining; } -struct GuestItimerval { - KernelTimeval interval; - KernelTimeval value; -}; static_assert(sizeof(GuestItimerval) == 32 && offsetof(GuestItimerval, value) == 16); extern "C" int APS5_VABI getitimer_nid_postfix(int which, GuestItimerval* output) { @@ -472,11 +452,6 @@ extern "C" int APS5_VABI setitimer_nid_postfix(int which, const GuestItimerval* return 0; } -struct GuestStack { - void* sp; - std::size_t size; - int flags; -}; static_assert(sizeof(GuestStack) == 24 && offsetof(GuestStack, flags) == 16); namespace { constexpr int SsDisable = 4; @@ -608,9 +583,9 @@ int APS5_VABI pthread_sigmask_nid_postfix(int how, const GuestSignalSet* set, Gu return _sigprocmask_nid_postfix(how, set, previousSet); } -int APS5_VABI sigtimedwait_nid_postfix(const GuestSignalSet* set, void* info, const GuestTimespec* timeout) { +int APS5_VABI sigtimedwait_nid_postfix(const GuestSignalSet* set, void* info, const KernelTimespec* timeout) { if (set == nullptr || !SetHasSignal(*set)) { *__error_nid_postfix() = 22; return -1; } - if (timeout != nullptr && (timeout->nanoseconds < 0 || timeout->nanoseconds >= 1000000000) && !PendingInSetPresent(*set)) { + if (timeout != nullptr && (timeout->tv_nsec < 0 || timeout->tv_nsec >= 1000000000) && !PendingInSetPresent(*set)) { *__error_nid_postfix() = 22; return -1; } @@ -654,6 +629,7 @@ int APS5_VABI sigsuspend_nid_postfix(const GuestSignalSet* set) { } WaitForDeliverableSignal(); _sigprocmask_nid_postfix(GuestSigsetmask, &previous, nullptr); + *__error_nid_postfix() = GuestEintr; return -1; } diff --git a/core/libs/prx/libkernel/System/src/SoftwareVersion.cpp b/core/libs/prx/libkernel/System/src/SoftwareVersion.cpp index 6f834ce2ff..9c6bf6029c 100644 --- a/core/libs/prx/libkernel/System/src/SoftwareVersion.cpp +++ b/core/libs/prx/libkernel/System/src/SoftwareVersion.cpp @@ -1,15 +1,10 @@ +#include "prx/libkernel/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libkernel/KernelErrors.hpp" #include #include #include -struct SceKernelProsperoSystemSwVersion { - std::uint64_t size; - char versionString[0x1C]; - std::uint32_t version; -}; - static_assert(offsetof(SceKernelProsperoSystemSwVersion, size) == 0x00); static_assert(offsetof(SceKernelProsperoSystemSwVersion, versionString) == 0x08); static_assert(offsetof(SceKernelProsperoSystemSwVersion, version) == 0x24); diff --git a/core/libs/prx/libkernel/System/src/SystemConfiguration.cpp b/core/libs/prx/libkernel/System/src/SystemConfiguration.cpp index 2a06853c32..7abef3192e 100644 --- a/core/libs/prx/libkernel/System/src/SystemConfiguration.cpp +++ b/core/libs/prx/libkernel/System/src/SystemConfiguration.cpp @@ -1,3 +1,6 @@ +#include "prx/libkernel/Time/include/Time.hpp" +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/GuestArena.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libkernel/DirectMemory/DirectMemory.hpp" @@ -21,22 +24,6 @@ #include #endif -extern "C" int* APS5_VABI __error_nid_postfix(); -extern "C" int APS5_VABI getpid_nid_postfix(); -extern "C" std::uint64_t APS5_VABI sceKernelGetTscFrequency(void); -struct GuestRlimit { - std::int64_t rlim_cur; - std::int64_t rlim_max; -}; -extern "C" int APS5_VABI getrlimit_nid_postfix(int resource, GuestRlimit* limit); - -struct SceKernelSystemSwVersion { - std::uint64_t size; - char versionString[0x1C]; - std::uint32_t version; -}; -extern "C" int APS5_VABI sceKernelVirtualQuery(const void* addr, int flags, VirtualQueryInfo* info, uint64_t info_size); - namespace { int CopyOut(const void* value, std::size_t size, void* oldValue, std::size_t* oldLength) { @@ -204,7 +191,7 @@ std::int64_t APS5_VABI sysconf_nid_postfix(int name) { result = 128; break; case 5: { // _SC_OPEN_MAX - GuestRlimit limit{}; + GuestResourceLimit limit{}; if (getrlimit_nid_postfix(8, &limit) == 0) { result = limit.rlim_cur; } diff --git a/core/libs/prx/libkernel/System/src/ThermalSensors.cpp b/core/libs/prx/libkernel/System/src/ThermalSensors.cpp index bd83c4282c..fcff781e17 100644 --- a/core/libs/prx/libkernel/System/src/ThermalSensors.cpp +++ b/core/libs/prx/libkernel/System/src/ThermalSensors.cpp @@ -1,3 +1,4 @@ +#include "prx/libkernel/include/Api.hpp" #include "prx/libkernel/System/include/ThermalSensors.hpp" #include "prx/libkernel/KernelErrors.hpp" #include "prx/libc/include/general/VabiMacros.hpp" diff --git a/core/libs/prx/libkernel/System/src/UserContext.cpp b/core/libs/prx/libkernel/System/src/UserContext.cpp index 92eaa7a389..0d3d7f5937 100644 --- a/core/libs/prx/libkernel/System/src/UserContext.cpp +++ b/core/libs/prx/libkernel/System/src/UserContext.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/GuestStacks.hpp" #include "prx/libc/include/general/AsmMacros.hpp" #include "prx/libc/include/general/VabiMacros.hpp" @@ -7,9 +9,6 @@ #include #include -extern "C" int* APS5_VABI __error_nid_postfix(); -extern "C" int APS5_VABI sigprocmask_nid_postfix(int how, const void* set, void* previousSet); - namespace { struct RegisterFrame { @@ -71,47 +70,58 @@ std::uint32_t HostMxcsrMask() { extern "C" [[noreturn]] void APS5_VABI Aps5ContextRestore_nid_no_patch(const RegisterFrame* frame); +#define APS5_CONTEXT_CAPTURE \ + " pushfq\n" \ + " push %rbp\n" \ + " mov %rsp, %rbp\n" \ + " sub $0x2a0, %rsp\n" \ + " and $-16, %rsp\n" \ + " mov %rax, 0x00(%rsp)\n" \ + " mov %rbx, 0x08(%rsp)\n" \ + " mov %rcx, 0x10(%rsp)\n" \ + " mov %rdx, 0x18(%rsp)\n" \ + " mov %rsi, 0x20(%rsp)\n" \ + " mov %rdi, 0x28(%rsp)\n" \ + " mov 0(%rbp), %rax\n" \ + " mov %rax, 0x30(%rsp)\n" \ + " lea 24(%rbp), %rax\n" \ + " mov %rax, 0x38(%rsp)\n" \ + " mov %r8, 0x40(%rsp)\n" \ + " mov %r9, 0x48(%rsp)\n" \ + " mov %r10, 0x50(%rsp)\n" \ + " mov %r11, 0x58(%rsp)\n" \ + " mov %r12, 0x60(%rsp)\n" \ + " mov %r13, 0x68(%rsp)\n" \ + " mov %r14, 0x70(%rsp)\n" \ + " mov %r15, 0x78(%rsp)\n" \ + " mov 16(%rbp), %rax\n" \ + " mov %rax, 0x80(%rsp)\n" \ + " mov 8(%rbp), %rax\n" \ + " mov %rax, 0x88(%rsp)\n" \ + " xor %eax, %eax\n" \ + " mov %cs, %ax\n" \ + " mov %rax, 0x90(%rsp)\n" \ + " mov %ss, %ax\n" \ + " mov %rax, 0x98(%rsp)\n" \ + " fxsave64 0xa0(%rsp)\n" + +#define APS5_CONTEXT_RETURN \ + " mov %rbp, %rsp\n" \ + " pop %rbp\n" \ + " lea 8(%rsp), %rsp\n" \ + " ret\n" + asm(".text\n" APS5_ASM_FUNCTION("getcontext_nid_postfix") - " pushfq\n" - " push %rbp\n" - " mov %rsp, %rbp\n" - " sub $0x2a0, %rsp\n" - " and $-16, %rsp\n" - " mov %rax, 0x00(%rsp)\n" - " mov %rbx, 0x08(%rsp)\n" - " mov %rcx, 0x10(%rsp)\n" - " mov %rdx, 0x18(%rsp)\n" - " mov %rsi, 0x20(%rsp)\n" - " mov %rdi, 0x28(%rsp)\n" - " mov 0(%rbp), %rax\n" - " mov %rax, 0x30(%rsp)\n" - " lea 24(%rbp), %rax\n" - " mov %rax, 0x38(%rsp)\n" - " mov %r8, 0x40(%rsp)\n" - " mov %r9, 0x48(%rsp)\n" - " mov %r10, 0x50(%rsp)\n" - " mov %r11, 0x58(%rsp)\n" - " mov %r12, 0x60(%rsp)\n" - " mov %r13, 0x68(%rsp)\n" - " mov %r14, 0x70(%rsp)\n" - " mov %r15, 0x78(%rsp)\n" - " mov 16(%rbp), %rax\n" - " mov %rax, 0x80(%rsp)\n" - " mov 8(%rbp), %rax\n" - " mov %rax, 0x88(%rsp)\n" - " xor %eax, %eax\n" - " mov %cs, %ax\n" - " mov %rax, 0x90(%rsp)\n" - " mov %ss, %ax\n" - " mov %rax, 0x98(%rsp)\n" - " fxsave64 0xa0(%rsp)\n" + APS5_CONTEXT_CAPTURE " mov %rsp, %rsi\n" " call " APS5_ASM_SYMBOL("Aps5GetcontextFinish_nid_no_patch") "\n" - " mov %rbp, %rsp\n" - " pop %rbp\n" - " lea 8(%rsp), %rsp\n" - " ret\n" + APS5_CONTEXT_RETURN + APS5_ASM_FUNCTION("swapcontext_nid_postfix") + APS5_CONTEXT_CAPTURE + " mov %rsp, %rdx\n" + " call " APS5_ASM_SYMBOL("Aps5SwapcontextFinish_nid_no_patch") "\n" + APS5_CONTEXT_RETURN APS5_ASM_FUNCTION("Aps5ContextRestore_nid_no_patch") " mov %rdi, %r12\n" " xor %eax, %eax\n" @@ -157,6 +167,7 @@ int APS5_VABI Aps5GetcontextFinish_nid_no_patch(UserUcontext* context, const Reg if (context == nullptr) return Fail(GuestEinval); UserUcontext captured{}; sigprocmask_nid_postfix(GuestSigBlock, nullptr, captured.sigmask); + auto& machine = captured.mcontext; machine.rdi = frame->rdi; machine.rsi = frame->rsi; @@ -213,7 +224,14 @@ int APS5_VABI setcontext_nid_postfix(const UserUcontext* context) { mxcsr &= HostMxcsrMask(); std::memcpy(frame.fxsave + FxsaveMxcsr, &mxcsr, sizeof(mxcsr)); sigprocmask_nid_postfix(GuestSigSetmask, context->sigmask, nullptr); + Aps5ContextRestore_nid_no_patch(&frame); } +int APS5_VABI Aps5SwapcontextFinish_nid_no_patch(UserUcontext* saved, const UserUcontext* next, const RegisterFrame* frame) { + if (saved == nullptr || next == nullptr) return Fail(GuestEinval); + Aps5GetcontextFinish_nid_no_patch(saved, frame); + return setcontext_nid_postfix(next); +} + } diff --git a/core/libs/prx/libkernel/Time/Ktimer.cpp b/core/libs/prx/libkernel/Time/Ktimer.cpp index 6dd8b16800..933a20bc60 100644 --- a/core/libs/prx/libkernel/Time/Ktimer.cpp +++ b/core/libs/prx/libkernel/Time/Ktimer.cpp @@ -1,11 +1,11 @@ +#include "prx/libkernel/Time/include/Time.hpp" +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "SceTypes.hpp" #include "prx/libc/include/General.hpp" #include #include -extern "C" int* APS5_VABI __error_nid_postfix(); -extern "C" int APS5_VABI clock_gettime_nid_postfix(int clockId, void* tp); - namespace { constexpr int GuestEfault = 14; @@ -29,21 +29,6 @@ constexpr int TimerMax = 32; constexpr long long NanosecondsPerSecond = 1000000000; constexpr long long TickNanoseconds = 1000000; -struct GuestSigevent { - int notify; - int signo; -}; - -struct GuestTimespec { - std::int64_t tv_sec; - std::int64_t tv_nsec; -}; - -struct GuestItimerspec { - GuestTimespec it_interval; - GuestTimespec it_value; -}; - using Nanoseconds = __int128; struct Ktimer { @@ -56,22 +41,23 @@ struct Ktimer { std::mutex g_ktimerLock; Ktimer g_ktimers[TimerMax]; -Nanoseconds ToNanoseconds(const GuestTimespec& time) { +Nanoseconds ToNanoseconds(const KernelTimespec& time) { return static_cast(time.tv_sec) * NanosecondsPerSecond + time.tv_nsec; } -GuestTimespec ToTimespec(Nanoseconds time) { +KernelTimespec ToTimespec(Nanoseconds time) { return {static_cast(time / NanosecondsPerSecond), static_cast(time % NanosecondsPerSecond)}; } Nanoseconds ClockNow(int clock) { - GuestTimespec now{}; + KernelTimespec now{}; clock_gettime_nid_postfix(clock, &now); + return ToNanoseconds(now); } -bool FixTimespec(GuestTimespec& time) { +bool FixTimespec(KernelTimespec& time) { if (time.tv_sec < 0 || time.tv_nsec < 0 || time.tv_nsec >= NanosecondsPerSecond) return false; if (time.tv_sec == 0 && time.tv_nsec != 0 && time.tv_nsec < TickNanoseconds) time.tv_nsec = TickNanoseconds; return true; @@ -95,7 +81,7 @@ GuestItimerspec Remaining(Ktimer& timer) { const Nanoseconds now = ClockNow(timer.clock); Expire(timer, now); GuestItimerspec result{ToTimespec(timer.interval), {}}; - if (timer.value != 0) result.it_value = timer.value > now ? ToTimespec(timer.value - now) : GuestTimespec{0, 1}; + if (timer.value != 0) result.it_value = timer.value > now ? ToTimespec(timer.value - now) : KernelTimespec{0, 1}; return result; } diff --git a/core/libs/prx/libkernel/Time/Time.cpp b/core/libs/prx/libkernel/Time/Time.cpp index 411f92751d..4e3d97ebca 100644 --- a/core/libs/prx/libkernel/Time/Time.cpp +++ b/core/libs/prx/libkernel/Time/Time.cpp @@ -1,3 +1,7 @@ +#include "prx/libkernel/Pthread/include/Mutex.hpp" +#include "prx/libkernel/Pthread/include/Cond.hpp" +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libkernel/Time/include/Time.hpp" #include "prx/libkernel/Time/include/TimedWait.hpp" #include "prx/libkernel/Time/include/SleepWake.hpp" @@ -36,8 +40,6 @@ #endif // __linux__ #endif -extern "C" int* APS5_VABI __error_nid_postfix(); - static constexpr int GUEST_EFAULT = 14; static constexpr int GUEST_EINVAL = 22; static constexpr int GUEST_CLOCK_REALTIME = 0; @@ -119,16 +121,6 @@ static const bool g_timerResolutionRaised = [] { return raised; }(); -extern "C" { -int APS5_VABI scePthreadCondInit(PthreadCond* cond, const PthreadCondattr* attr, const char* name); -int APS5_VABI scePthreadCondDestroy(PthreadCond* cond); -int APS5_VABI scePthreadCondTimedwait(PthreadCond* cond, PthreadMutex* mutex, unsigned int usec); -int APS5_VABI scePthreadMutexInit(PthreadMutex* mutex, const PthreadMutexattr* attr, const char* name); -int APS5_VABI scePthreadMutexDestroy(PthreadMutex* mutex); -int APS5_VABI scePthreadMutexLock(PthreadMutex* mutex); -int APS5_VABI scePthreadMutexUnlock(PthreadMutex* mutex); -} - static void ReportTimedWait(const char* name, const std::function& body) { std::vector samples(200); for (auto& sample : samples) { @@ -152,11 +144,13 @@ static const bool g_timerSelfTest = [] { scePthreadCondInit(&cond, nullptr, nullptr); scePthreadMutexInit(&guestMutex, nullptr, nullptr); scePthreadMutexLock(&guestMutex); + ReportTimedWait("scePthreadCondTimedwait(1000 us)", [&] { scePthreadCondTimedwait(&cond, &guestMutex, 1000); }); ReportTimedWait("scePthreadCondTimedwait(13000 us)", [&] { scePthreadCondTimedwait(&cond, &guestMutex, 13000); }); scePthreadMutexUnlock(&guestMutex); scePthreadMutexDestroy(&guestMutex); scePthreadCondDestroy(&cond); + ReportTimedWait("sceKernelUsleep(1000)", [&] { sceKernelUsleep_nid_postfix(1000); }); ReportTimedWait("Sleep(1)", [&] { Sleep(1); }); HANDLE event = CreateEventW(nullptr, TRUE, FALSE, nullptr); diff --git a/core/libs/prx/libkernel/Unimplemented.cpp b/core/libs/prx/libkernel/Unimplemented.cpp index 617dc506f1..20c5d80c94 100644 --- a/core/libs/prx/libkernel/Unimplemented.cpp +++ b/core/libs/prx/libkernel/Unimplemented.cpp @@ -1,3 +1,4 @@ +#include "prx/libkernel/include/Api.hpp" #include #include #include "SceTypes.hpp" @@ -5,11 +6,6 @@ extern "C" { -int APS5_VABI __tls_get_addr_nid_postfix(void) { - NotImplemented_nid_no_patch("vNe1w4diLCs"); - return 0; -} - int APS5_VABI physhm_open_nid_postfix(void) { NotImplemented_nid_no_patch("physhm_open"); return 0; @@ -141,9 +137,4 @@ int APS5_VABI __Ux86_64_setcontext() { return 0; } -int APS5_VABI sigreturn() { - NotImplemented_nid_no_patch(__func__); - return 0; -} - } diff --git a/core/libs/prx/libkernel/include/Api.hpp b/core/libs/prx/libkernel/include/Api.hpp new file mode 100644 index 0000000000..08bf7cab4f --- /dev/null +++ b/core/libs/prx/libkernel/include/Api.hpp @@ -0,0 +1,805 @@ +#pragma once + +#include "prx/libSceLibcInternal/include/Spawn.hpp" +#include "prx/libkernel/System/include/UserContext.hpp" +#include "prx/libkernel/File/include/KernelStatfs.hpp" +#include "prx/libkernel/Apr/include/AprCommandBuffer.hpp" +#include "prx/libc/include/specifics/linux/ElfTypes.hpp" +#include "SceTypes.hpp" +#include +#include +#include +#include + +struct KernelIovec { + void* base; + std::size_t length; +}; + +struct KernelTlsIndex { + std::uint64_t module; + std::uint64_t offset; +}; + +using GuestHandler = void (APS5_VABI *)(int); + +struct GuestItimerspec { + KernelTimespec it_interval; + KernelTimespec it_value; +}; + +struct GuestItimerval { + KernelTimeval interval; + KernelTimeval value; +}; + +struct GuestMsghdr { + void* name; + std::uint32_t nameLength; + KernelIovec* iov; + int iovLength; + void* control; + std::uint32_t controlLength; + int flags; +}; + +struct GuestOnce { + std::int32_t state; + void* mutex; +}; + +struct GuestPollDescriptor { + int descriptor; + short events; + short revents; +}; + +struct GuestResourceLimit { + std::int64_t rlim_cur; + std::int64_t rlim_max; +}; + +struct GuestResourceUsage { + KernelTimeval ru_utime; + KernelTimeval ru_stime; + std::int64_t ru_maxrss; + std::int64_t ru_ixrss; + std::int64_t ru_idrss; + std::int64_t ru_isrss; + std::int64_t ru_minflt; + std::int64_t ru_majflt; + std::int64_t ru_nswap; + std::int64_t ru_inblock; + std::int64_t ru_oublock; + std::int64_t ru_msgsnd; + std::int64_t ru_msgrcv; + std::int64_t ru_nsignals; + std::int64_t ru_nvcsw; + std::int64_t ru_nivcsw; +}; + +struct GuestRtPrio { + std::uint16_t type; + std::uint16_t prio; +}; + +struct GuestSendfileHeaders { + KernelIovec* headers; + int headerCount; + KernelIovec* trailers; + int trailerCount; +}; + +struct GuestSigaction { + std::uintptr_t handler; + int flags; + GuestSignalSet mask; +}; + +struct GuestSigevent { + int notify; + int signo; + std::int64_t value; + std::int64_t extra[8]; +}; + +struct GuestStack { + void* sp; + std::size_t size; + int flags; +}; + +struct PthreadBarrierPrivate { + std::mutex mutex; + std::condition_variable changed; + unsigned count; + unsigned arrived = 0; + unsigned active = 0; + std::uint64_t generation = 0; +}; + +struct PthreadBarrierattrPrivate { + int pshared = 0; +}; + +struct PthreadSpinlockPrivate { + std::atomic owner{}; +}; + +struct SceKernelProsperoSystemSwVersion { + std::uint64_t size; + char versionString[0x1C]; + std::uint32_t version; +}; + +struct SceKernelSystemSwVersion { + std::uint64_t size; + char versionString[0x1C]; + std::uint32_t version; +}; + +extern "C" { +int APS5_VABI sceKernelCreateEventFlag(KernelEventFlag* ef, const char* name, std::uint32_t attr, std::uint64_t initPattern, const void* param); +int APS5_VABI sceKernelDeleteEventFlag(KernelEventFlag ef); +int APS5_VABI sceKernelSetEventFlag(KernelEventFlag ef, std::uint64_t bitPattern); +int APS5_VABI sceKernelCancelEventFlag(KernelEventFlag ef, std::uint64_t setPattern, int* numWaitThreads); + +} + +extern "C" { + +void* APS5_VABI __tls_get_addr_nid_postfix(const KernelTlsIndex* index); +int APS5_VABI physhm_open_nid_postfix(void); +int APS5_VABI physhm_unlink_nid_postfix(void); +int APS5_VABI sceKernelUnknown03(void); +int APS5_VABI sceKernelUnknown04(void); +int APS5_VABI sceKernelUnknown05(void); +int APS5_VABI sceKernelUnknown06(void); +int APS5_VABI sceKernelUnknown07(void); +int APS5_VABI sceKernelUnknown08(void); +int APS5_VABI sceKernelUnknown09(void); +int APS5_VABI sceKernelUnknown10(void); +int APS5_VABI sceKernelUnknown11(void); +int APS5_VABI sceKernelUnknown12(void); +int APS5_VABI sceKernelUnknown13(void); +int APS5_VABI sceKernelUnknown14(void); +int APS5_VABI sceKernelUnknown15(void); +int APS5_VABI sceKernelUnknown16(void); +int APS5_VABI sceKernelUnknown17(void); +int APS5_VABI sceKernelUnknown18(void); +int APS5_VABI sceKernelUnknown19(void); +int APS5_VABI sceKernelPrintBacktraceWithModuleInfo(void); +int APS5_VABI sceKernelGetProcessAbiType(); +int APS5_VABI __Ux86_64_setcontext(); +int APS5_VABI sceKernelAioDeleteRequest(int32_t id, int32_t* ret); +int APS5_VABI sceKernelAioDeleteRequests(int32_t* id, int32_t num, int32_t* ret); +int APS5_VABI sceKernelAioCancelRequest(int32_t id, int32_t* state); +int APS5_VABI sceKernelAioCancelRequests(int32_t* id, int32_t num, int32_t* state); +int APS5_VABI sceKernelAioInitializeImpl(void* param, int32_t size); +void APS5_VABI sceKernelAioInitializeParam(void* param); +int APS5_VABI sceKernelAioSetParam(KernelAioSchedulingParam* param, int32_t schedulingWindowSize, int32_t delayedCountLimit, uint32_t enableSplit, uint32_t splitSize, uint32_t splitChunkSize); +int APS5_VABI sceKernelAioSubmitReadCommands(KernelAioRwRequest* req, int32_t size, int32_t prio, int32_t* id); +int APS5_VABI sceKernelAioSubmitWriteCommands(KernelAioRwRequest* req, int32_t size, int32_t prio, int32_t* id); +int APS5_VABI sceKernelAioSubmitReadCommandsMultiple(KernelAioRwRequest* req, int32_t size, int32_t prio, int32_t* id); +int APS5_VABI sceKernelAioSubmitWriteCommandsMultiple(KernelAioRwRequest* req, int32_t size, int32_t prio, int32_t* id); +int APS5_VABI sceKernelAioPollRequest(int32_t id, int32_t* state); +int APS5_VABI sceKernelAioWaitRequests(int32_t* id, int32_t num, int32_t* state, uint32_t mode, uint32_t* usec); +int APS5_VABI sceKernelAioWaitRequest(int32_t id, int32_t* state, uint32_t* usec); +int APS5_VABI sceKernelAioPollRequests(int32_t* id, int32_t num, int32_t* state); +int APS5_VABI sceKernelAprResolveFilepathsToIds(const char** paths, uint32_t count, uint32_t* ids, uint32_t* errorIndex); +int APS5_VABI sceKernelAprResolveFilepathsToIdsAndFileSizes(const char** paths, uint32_t count, uint32_t* ids, uint64_t* sizes, uint32_t* errorIndex); +int APS5_VABI sceKernelAprResolveFilepathsWithPrefixToIdsAndFileSizes(const char* prefix, const char** paths, uint32_t count, uint32_t* ids, uint64_t* sizes, uint32_t* errorIndex); +int APS5_VABI sceKernelAprResolveFilepathsWithPrefixToIds(const char* prefix, const char** paths, uint32_t count, uint32_t* ids, uint32_t* errorIndex); +int APS5_VABI sceKernelAprGetFileSize(uint32_t id, uint64_t* size); +int APS5_VABI sceKernelAprGetFileStat(uint32_t id, FileStat* stat); +int APS5_VABI sceKernelAprSubmitCommandBuffer(const Apr::CommandBufferObject* buffer, uint32_t priority); +int APS5_VABI sceKernelAprSubmitCommandBufferAndGetId(const Apr::CommandBufferObject* buffer, uint32_t priority, uint32_t* id); +int APS5_VABI sceKernelAprSubmitCommandBufferAndGetResult(const Apr::CommandBufferObject* buffer, uint32_t priority, uint32_t* result, uint32_t* id); +int APS5_VABI sceKernelAprWaitCommandBuffer(uint32_t id); +int APS5_VABI sceKernelAprResolveFilepathsToIdsForEach(const char** paths, uint32_t count, uint32_t* ids, int* results); +int APS5_VABI sceKernelAprResolveFilepathsToIdsAndFileSizesForEach(const char** paths, uint32_t count, uint32_t* ids, uint64_t* sizes, int* results); +int APS5_VABI sceKernelAprResolveFilepathsWithPrefixToIdsForEach(const char* prefix, const char** paths, uint32_t count, uint32_t* ids, int* results); +int APS5_VABI sceKernelAprResolveFilepathsWithPrefixToIdsAndFileSizesForEach(const char* prefix, const char** paths, uint32_t count, uint32_t* ids, uint64_t* sizes, int* results); +int APS5_VABI sceKernelWriteModifyMtypeProtectCommand(void* dst, std::uint64_t address, std::uint64_t size, std::uint64_t type, std::uint64_t protection, std::uint64_t mask, std::uint64_t* outSize); +int APS5_VABI sceKernelWriteRemapIntoPrtCommand(std::uint32_t* dst, std::uint64_t address, std::uint64_t source, std::uint64_t size, int protection, int opcode, std::uint64_t* outSize); +int APS5_VABI sceKernelAllocateDirectMemory(int64_t searchStart, int64_t searchEnd, size_t len, size_t alignment, int memoryType, int64_t* physAddrOut); +int APS5_VABI sceKernelAllocateMainDirectMemory(size_t len, size_t alignment, int memoryType, int64_t* physAddrOut); +int APS5_VABI sceKernelAvailableDirectMemorySize(int64_t searchStart, int64_t searchEnd, size_t alignment, int64_t* physAddrOut, size_t* sizeOut); +int APS5_VABI sceKernelDirectMemoryQuery(int64_t offset, int flags, void* info, size_t infoSize); +int APS5_VABI sceKernelGetDirectMemoryType(int64_t offset, int* memoryType, int64_t* start, int64_t* end); +size_t APS5_VABI sceKernelGetDirectMemorySize(void); +int APS5_VABI sceKernelEnableDmemAliasing(void); +int APS5_VABI sceKernelMapDirectMemory(void** addr, size_t len, int prot, int flags, int64_t directMemoryStart, size_t alignment); +int APS5_VABI sceKernelMapDirectMemory2(void** addr, size_t len, int type, int prot, int flags, int64_t directMemoryStart, size_t alignment); +int APS5_VABI sceKernelMapFlexibleMemory(void** addrInOut, size_t len, int prot, int flags); +int APS5_VABI sceKernelMapNamedDirectMemory(void** addr, size_t len, int prot, int flags, int64_t directMemoryStart, size_t alignment, const char* name); +int32_t APS5_VABI sceKernelMapNamedFlexibleMemory(void** addrInOut, size_t len, int prot, int flags, const char* name); +int32_t APS5_VABI sceKernelMapNamedFlexibleMemoryInternal(void** addrInOut, size_t len, int prot, int flags, const char* name); +int APS5_VABI sceKernelMprotect(const void* addr, size_t len, int prot); +int APS5_VABI sceKernelMunmap(uint64_t vaddr, size_t len); +int APS5_VABI sceKernelMmap(void* addr, size_t len, int prot, int flags, int fd, int64_t offset, void** res); +int APS5_VABI sceKernelReleaseFlexibleMemory(void* addr, size_t len); +int APS5_VABI sceKernelReleaseDirectMemory(int64_t start, size_t len); +int APS5_VABI sceKernelReserveVirtualRange(void** addr, size_t len, int flags, size_t alignment); +int APS5_VABI sceKernelVirtualQuery(const void* addr, int flags, VirtualQueryInfo* info, uint64_t infoSize); +int APS5_VABI sceKernelCheckedReleaseDirectMemory(int64_t start, size_t len); +int APS5_VABI sceKernelMtypeprotect(const void* addr, size_t len, int type, int prot); +int APS5_VABI sceKernelQueryMemoryProtection(void* addr, void** start, void** end, int* prot); +int APS5_VABI sceKernelIsStack(void* addr, void** start, void** end); +int APS5_VABI sceKernelAvailableFlexibleMemorySize(size_t* size); +int APS5_VABI sceKernelConfiguredFlexibleMemorySize(size_t* size); +int APS5_VABI sceKernelInternalMemoryGetAvailableSize(std::size_t* size); +int APS5_VABI sceKernelSetVirtualRangeName(const void* addr, uint64_t len, const char* name); +int APS5_VABI sceKernelClearVirtualRangeName(const void* addr, uint64_t len); +int APS5_VABI sceKernelGetPageTableStats(int* cpuTotal, int* cpuAvailable, int* gpuTotal, int* gpuAvailable); +int APS5_VABI sceKernelGetPrtAperture(int index, void** addr, size_t* len); +int APS5_VABI sceKernelSetPrtAperture(int index, void* addr, size_t len); +int APS5_VABI sceKernelBatchMap(KernelBatchMapEntry* entries, int numEntries, int* numEntriesOut); +int APS5_VABI sceKernelBatchMap2(KernelBatchMapEntry* entries, int numEntries, int* numEntriesOut, int flags); +int APS5_VABI sceKernelMlock_nid_postfix(void* address, std::uint64_t length); +int APS5_VABI sceKernelMunlock_nid_postfix(void* address, std::uint64_t length); +int APS5_VABI sceKernelMunlockall_nid_postfix(); +int APS5_VABI sceKernelJitCreateSharedMemory(const char* name, std::size_t len, int maxProt, int* fdOut); +int APS5_VABI sceKernelJitCreateAliasOfSharedMemory(int fd, int maxProt, int* fdOut); +int APS5_VABI sceKernelJitMapSharedMemory(int fd, int prot, void** startOut); +int APS5_VABI sceKernelMemoryPoolBatch(const KernelMemoryPoolBatchEntry* entries, int numEntries, int* numEntriesOut, int flags); +int APS5_VABI sceKernelMemoryPoolCommit(void* addr, size_t len, int type, int prot, int flags); +int APS5_VABI sceKernelMemoryPoolDecommit(void* addr, size_t len, int flags); +int APS5_VABI sceKernelMemoryPoolExpand(int64_t searchStart, int64_t searchEnd, size_t len, size_t alignment, int64_t* physAddrOut); +int APS5_VABI sceKernelMemoryPoolGetBlockStats(KernelMemoryPoolBlockStats* output, size_t outputSize); +int APS5_VABI sceKernelMemoryPoolReserve(void* addrIn, size_t len, size_t alignment, int flags, void** addrOut); +void* APS5_VABI mmap_nid_postfix(void* address, std::size_t length, int protection, int flags, int descriptor, std::int64_t offset) noexcept; +int APS5_VABI munmap_nid_postfix(void* address, std::size_t length) noexcept; +int APS5_VABI mprotect_nid_postfix(void* address, std::size_t length, int protection) noexcept; +int APS5_VABI mlock_nid_postfix(const void* address, std::size_t length); +int APS5_VABI munlock_nid_postfix(const void* address, std::size_t length); +int APS5_VABI mlockall_nid_postfix(int flags); +int APS5_VABI munlockall_nid_postfix(); +int APS5_VABI msync_nid_postfix(void* address, std::size_t length, int flags); +int APS5_VABI madvise_nid_postfix(void* address, std::size_t length, int advice); +int APS5_VABI mincore_nid_postfix(const void* address, std::size_t length, char* vec); +int APS5_VABI sceKernelCreateEqueue(KernelEqueue* eq, const char* name); +int APS5_VABI sceKernelDeleteEqueue(KernelEqueue eq); +int APS5_VABI sceKernelWaitEqueue(KernelEqueue eq, KernelEvent* ev, int num, int* out, const KernelUseconds* timo); +int APS5_VABI sceKernelAddUserEvent(KernelEqueue eq, int id); +int APS5_VABI sceKernelAddUserEventEdge(KernelEqueue eq, int id); +int APS5_VABI sceKernelTriggerUserEvent(KernelEqueue eq, int id, void* udata); +int APS5_VABI sceKernelDeleteUserEvent(KernelEqueue eq, int id); +int APS5_VABI sceKernelAddHRTimerEvent(KernelEqueue eq, int id, const KernelTimespec* ts, void* udata); +int APS5_VABI sceKernelDeleteHRTimerEvent(KernelEqueue eq, int id); +int APS5_VABI sceKernelAddTimerEvent(KernelEqueue eq, int id, KernelUseconds usec, void* udata); +int APS5_VABI sceKernelDeleteTimerEvent(KernelEqueue eq, int id); +int APS5_VABI sceKernelAddAmprEvent(KernelEqueue eq, int id, void* udata); +int APS5_VABI sceKernelAddAmprSystemEvent(KernelEqueue eq, int id, void* udata); +int APS5_VABI sceKernelDeleteAmprEvent(KernelEqueue eq, int id); +int APS5_VABI sceKernelDeleteAmprSystemEvent(KernelEqueue eq, int id); +int APS5_VABI sceKernelAddReadEvent(KernelEqueue eq, int fd, std::size_t size, void* udata); +int APS5_VABI sceKernelDeleteReadEvent(KernelEqueue eq, int fd); +int APS5_VABI sceKernelAddWriteEvent(KernelEqueue eq, int fd, std::size_t size, void* udata); +int APS5_VABI sceKernelDeleteWriteEvent(KernelEqueue eq, int fd); +intptr_t APS5_VABI sceKernelGetEventData(const KernelEvent* ev); +int APS5_VABI sceKernelGetEventError(const KernelEvent* ev); +intptr_t APS5_VABI sceKernelGetEventFflags(const KernelEvent* ev); +int APS5_VABI sceKernelGetEventFilter(const KernelEvent* ev); +uintptr_t APS5_VABI sceKernelGetEventId(const KernelEvent* ev); +void* APS5_VABI sceKernelGetEventUserData(const KernelEvent* ev); +int APS5_VABI sceKernelAddFileEvent(KernelEqueue eq, int fd, int watch, void* udata); +int APS5_VABI sceKernelDeleteFileEvent(KernelEqueue eq, int fd); +int APS5_VABI kqueue_nid_postfix(); +int APS5_VABI kevent_nid_postfix(int descriptor, const KernelEvent* changelist, int nchanges, KernelEvent* eventlist, int nevents, const KernelTimespec* timeout); +int APS5_VABI sceKernelOpenEventFlag(KernelEventFlag* ef, const char* name); +int APS5_VABI sceKernelCloseEventFlag(KernelEventFlag ef); +int APS5_VABI sceKernelClearEventFlag(KernelEventFlag ef, uint64_t bitPattern); +int APS5_VABI sceKernelPollEventFlag(KernelEventFlag ef, uint64_t bitPattern, uint32_t waitMode, uint64_t* resultPat); +int APS5_VABI sceKernelWaitEventFlag(KernelEventFlag ef, uint64_t bitPattern, uint32_t waitMode, uint64_t* resultPat, KernelUseconds* timeout); +int APS5_VABI shm_open_nid_postfix(const char* path, int flags, int mode); +int APS5_VABI shm_unlink_nid_postfix(const char* path); +int APS5_VABI pipe_nid_postfix(int* descriptors); +int APS5_VABI chmod_nid_postfix(const char* path, int mode); +int APS5_VABI chflags_nid_postfix(const char* path, std::uint64_t flags); +int APS5_VABI fchflags_nid_postfix(int d, std::uint64_t flags); +int APS5_VABI nmount_nid_postfix(const KernelIovec* iov, unsigned int niov, int flags); +int APS5_VABI close_nid_postfix(int d); +int APS5_VABI _close_nid_postfix(int descriptor); +int APS5_VABI dup_nid_postfix(int d); +int APS5_VABI dup2_nid_postfix(int from, int to); +int APS5_VABI flock_nid_postfix(int d, int operation); +int APS5_VABI _fstatfs_nid_postfix(int d, KernelStatfs* buf); +int64_t APS5_VABI fstat_nid_disambig1_nid_postfix(int d, FileStat* sb); +int64_t APS5_VABI _fstat_nid_postfix(int d, FileStat* sb); +int APS5_VABI ftruncate_nid_postfix(int d, int64_t length); +int APS5_VABI sceKernelFtruncate(int d, int64_t length); +int64_t APS5_VABI lseek_nid_postfix(int d, int64_t offset, int whence); +int APS5_VABI mkdir_nid_postfix(const char* path, uint16_t mode); +int APS5_VABI open_nid_postfix(const char* path, int flags, int mode); +int APS5_VABI creat_nid_postfix(const char* path, int mode); +int APS5_VABI _open_nid_postfix(const char* path, int flags, ...); +int64_t APS5_VABI pread_nid_postfix(int d, void* buf, size_t nbytes, int64_t offset); +int64_t APS5_VABI pwrite_nid_disambig1_nid_postfix(int d, const void* buf, size_t nbytes, int64_t offset); +int64_t APS5_VABI read_nid_postfix(int d, void* buf, uint64_t nbytes); +std::int64_t APS5_VABI _read_nid_postfix(int descriptor, void* buffer, std::size_t count); +int64_t APS5_VABI write_nid_postfix(int d, const char* str, int64_t size); +std::int64_t APS5_VABI _write_nid_postfix(int descriptor, const void* buffer, std::size_t count); +int APS5_VABI stat_nid_postfix(const char* path, FileStat* sb); +int APS5_VABI lstat_nid_postfix(const char* path, FileStat* sb); +int APS5_VABI unlink_nid_postfix(const char* path); +int APS5_VABI sceKernelCheckReachability(const char* path); +int APS5_VABI sceKernelFstat(int d, FileStat* sb); +int APS5_VABI sceKernelFsync(int fd); +int APS5_VABI sceKernelFdatasync(int fd); +int APS5_VABI sceKernelWriteThrottlingStatus(std::uint64_t* status); +int APS5_VABI sceKernelGetdirentries(int fd, char* buf, int nbytes, int64_t* basep); +int APS5_VABI sceKernelGetdents(int fd, char* buf, int nbytes); +int APS5_VABI getdirentries_nid_postfix(int fd, char* buf, int nbytes, int64_t* basep); +int APS5_VABI _getdirentries_nid_postfix(int fd, char* buf, int nbytes, int64_t* basep); +int APS5_VABI getdents_nid_postfix(int fd, char* buf, int nbytes); +int APS5_VABI sceKernelMkdir(const char* path, uint16_t mode); +int64_t APS5_VABI sceKernelPread(int d, void* buf, size_t nbytes, int64_t offset); +int64_t APS5_VABI sceKernelPwrite(int d, const void* buf, size_t nbytes, int64_t offset); +int64_t APS5_VABI sceKernelReadv(int d, const KernelIovec* iov, int iovcnt); +int64_t APS5_VABI sceKernelWritev(int d, const KernelIovec* iov, int iovcnt); +int64_t APS5_VABI sceKernelPreadv(int d, const KernelIovec* iov, int iovcnt, int64_t offset); +int64_t APS5_VABI sceKernelPwritev(int d, const KernelIovec* iov, int iovcnt, int64_t offset); +int64_t APS5_VABI preadv_nid_postfix(int d, const KernelIovec* iov, int iovcnt, int64_t offset); +int64_t APS5_VABI pwritev_nid_postfix(int d, const KernelIovec* iov, int iovcnt, int64_t offset); +int APS5_VABI sceKernelRename(const char* from, const char* to); +int APS5_VABI sceKernelRmdir(const char* path); +int APS5_VABI rmdir_nid_postfix(const char* path); +int APS5_VABI sceKernelChmod_nid_postfix(const char* path, std::uint16_t mode); +int APS5_VABI sceKernelFchmod(int d, std::uint16_t mode); +int APS5_VABI fchmod_nid_postfix(int d, int mode); +int APS5_VABI sceKernelTruncate_nid_postfix(const char* path, std::int64_t length); +int APS5_VABI truncate_nid_postfix(const char* path, std::int64_t length); +int APS5_VABI sceKernelUtimes_nid_postfix(const char* path, const KernelTimeval* times); +int APS5_VABI utimes_nid_postfix(const char* path, const KernelTimeval* times); +int APS5_VABI lutimes_nid_postfix(const char* path, const KernelTimeval* times); +int APS5_VABI sceKernelFutimes(int d, const KernelTimeval* times); +int APS5_VABI futimes_nid_postfix(int d, const KernelTimeval* times); +int APS5_VABI fsync_nid_postfix(int fd); +int APS5_VABI fdatasync_nid_postfix(int fd); +int64_t APS5_VABI readv_nid_postfix(int d, const KernelIovec* iov, int iovcnt); +int64_t APS5_VABI writev_nid_postfix(int d, const KernelIovec* iov, int iovcnt); +int64_t APS5_VABI _readv_nid_postfix(int d, const KernelIovec* iov, int iovcnt); +int64_t APS5_VABI _writev_nid_postfix(int d, const KernelIovec* iov, int iovcnt); +int APS5_VABI cfsetspeed_nid_postfix(void* attributes, std::uint32_t speed); +int APS5_VABI tcgetattr_nid_postfix(int descriptor, void* attributes); +int APS5_VABI tcsetattr_nid_postfix(int descriptor, int action, const void* attributes); +int APS5_VABI tcsendbreak_nid_postfix(int descriptor, int duration); +int APS5_VABI tcdrain_nid_postfix(int descriptor); +int APS5_VABI tcflush_nid_postfix(int descriptor, int queue); +int APS5_VABI tcflow_nid_postfix(int descriptor, int action); +int APS5_VABI tcgetpgrp_nid_postfix(int descriptor); +int APS5_VABI tcsetpgrp_nid_postfix(int descriptor, int group); +char* APS5_VABI dlerror_nid_postfix(); +void* APS5_VABI dlopen_nid_postfix(const char* path, int flags); +void* APS5_VABI dlsym_nid_postfix(void* handle, const char* name); +int APS5_VABI dlclose_nid_postfix(void* handle); +int APS5_VABI sceKernelDlsym(KernelModule handle, const char* symbol, void** addr); +int APS5_VABI sceKernelGetModuleInfoForUnwind(uint64_t addr, int flags, ModuleInfoForUnwind* info); +KernelModule APS5_VABI sceKernelLoadStartModule(const char* moduleFileName, size_t args, const void* argp, uint32_t flags, const KernelLoadModuleOpt* opt, int* res); +int APS5_VABI sceKernelStopUnloadModule(KernelModule handle, size_t args, const void* argp, uint32_t flags, const KernelUnloadModuleOpt* opt, int* res); +int APS5_VABI __elf_phdr_match_addr_nid_postfix(dl_phdr_info* phdrInfo, void* addr); +int APS5_VABI sceKernelGetModuleInfoFromAddr(std::uint64_t address, int flags, ModuleInfoEx* info); +int APS5_VABI sceKernelGetModuleList(KernelModule* handles, std::size_t count, std::size_t* actual); +int APS5_VABI sceKernelGetModuleList2(KernelModule* handles, std::size_t count, std::size_t* actual); +int APS5_VABI sceKernelGetModuleInfo(KernelModule handle, ModuleInfo* info); +int APS5_VABI sceKernelGetModuleInfo2(KernelModule handle, ModuleInfo* info); +std::int32_t APS5_VABI sceKernelGetLibkernelTextLocation_nid_postfix(void** address, std::size_t* size); +std::int32_t APS5_VABI sceKernelInternalMemoryGetModuleSegmentInfo_nid_postfix(InternalSegmentInfo* result); +int APS5_VABI pthread_attr_destroy_nid_postfix(PthreadAttr* attr); +int APS5_VABI pthread_attr_get_np_nid_postfix(Pthread thread, PthreadAttr* attr); +int APS5_VABI pthread_attr_getdetachstate_nid_postfix(const PthreadAttr* attr, int* state); +int APS5_VABI pthread_attr_getguardsize_nid_postfix(const PthreadAttr* attr, size_t* guardSize); +int APS5_VABI pthread_attr_getinheritsched_nid_postfix(const PthreadAttr* attr, int* inheritSched); +int APS5_VABI pthread_attr_getschedparam_nid_postfix(const PthreadAttr* attr, KernelSchedParam* param); +int APS5_VABI pthread_attr_getschedpolicy_nid_postfix(const PthreadAttr* attr, int* policy); +int APS5_VABI pthread_attr_getscope_nid_postfix(const PthreadAttr* attr, int* scope); +int APS5_VABI pthread_attr_getstack_nid_postfix(const PthreadAttr* __restrict attr, void** __restrict stackAddr, size_t* __restrict stackSize); +int APS5_VABI pthread_attr_getstackaddr_nid_postfix(const PthreadAttr* __restrict attr, void** __restrict stackAddr); +int APS5_VABI pthread_attr_getstacksize_nid_postfix(const PthreadAttr* attr, size_t* stackSize); +int APS5_VABI pthread_attr_init_nid_postfix(PthreadAttr* attr); +int APS5_VABI pthread_attr_setdetachstate_nid_postfix(PthreadAttr* attr, int state); +int APS5_VABI pthread_attr_setguardsize_nid_postfix(PthreadAttr* attr, size_t guardSize); +int APS5_VABI pthread_attr_setinheritsched_nid_postfix(PthreadAttr* attr, int inheritSched); +int APS5_VABI pthread_attr_setschedparam_nid_postfix(PthreadAttr* attr, const KernelSchedParam* param); +int APS5_VABI pthread_attr_setschedpolicy_nid_postfix(PthreadAttr* attr, int policy); +int APS5_VABI pthread_attr_setscope_nid_postfix(PthreadAttr* attr, int scope); +int APS5_VABI pthread_attr_setstacksize_nid_postfix(PthreadAttr* attr, size_t stackSize); +int APS5_VABI pthread_attr_setstack_nid_postfix(PthreadAttr* attr, void* stackAddr, size_t stackSize); +int APS5_VABI pthread_attr_setsolosched_np_nid_postfix(PthreadAttr* attr, int solosched); +int APS5_VABI pthread_barrierattr_init_nid_postfix(PthreadBarrierattrPrivate** attr); +int APS5_VABI pthread_barrierattr_destroy_nid_postfix(PthreadBarrierattrPrivate** attr); +int APS5_VABI pthread_barrierattr_getpshared_nid_postfix(PthreadBarrierattrPrivate* const* attr, int* pshared); +int APS5_VABI pthread_barrierattr_setpshared_nid_postfix(PthreadBarrierattrPrivate** attr, int pshared); +int APS5_VABI pthread_barrier_init_nid_postfix(PthreadBarrierPrivate** barrier, PthreadBarrierattrPrivate* const* attr, unsigned count); +int APS5_VABI pthread_barrier_wait_nid_postfix(PthreadBarrierPrivate** barrier); +int APS5_VABI pthread_barrier_destroy_nid_postfix(PthreadBarrierPrivate** barrier); +int APS5_VABI pthread_cond_destroy_nid_postfix(PthreadCond* cond); +int APS5_VABI pthread_cond_broadcast_nid_postfix(PthreadCond* cond); +int APS5_VABI pthread_cond_init_nid_postfix(PthreadCond* cond, const PthreadCondattr* attr); +int APS5_VABI pthread_cond_signal_nid_postfix(PthreadCond* cond); +int APS5_VABI pthread_cond_timedwait_nid_postfix(PthreadCond* cond, PthreadMutex* mutex, const KernelTimespec* abstime); +int APS5_VABI pthread_cond_reltimedwait_np_nid_postfix(PthreadCond* cond, PthreadMutex* mutex, KernelUseconds usec); +int APS5_VABI pthread_cond_wait_nid_postfix(PthreadCond* cond, PthreadMutex* mutex); +int APS5_VABI pthread_condattr_destroy_nid_postfix(PthreadCondattr* attr); +int APS5_VABI pthread_condattr_init_nid_postfix(PthreadCondattr* attr); +int APS5_VABI pthread_condattr_setclock_nid_postfix(PthreadCondattr* attr, KernelClockid clockId); +int APS5_VABI pthread_condattr_setpshared_nid_postfix(PthreadCondattr* attr, int pshared); +int APS5_VABI pthread_condattr_getpshared_nid_postfix(const PthreadCondattr* attr, int* pshared); +int APS5_VABI pthread_mutex_destroy_nid_postfix(PthreadMutex* mutex); +int APS5_VABI pthread_mutex_init_nid_postfix(PthreadMutex* mutex, const PthreadMutexattr* attr); +int APS5_VABI pthread_mutex_lock_nid_postfix(PthreadMutex* mutex); +int APS5_VABI pthread_mutex_timedlock_nid_postfix(PthreadMutex* mutex, const KernelTimespec* abstime); +int APS5_VABI pthread_mutex_trylock_nid_postfix(PthreadMutex* mutex); +int APS5_VABI pthread_mutex_unlock_nid_postfix(PthreadMutex* mutex); +int APS5_VABI pthread_mutex_reltimedlock_np_nid_postfix(PthreadMutex* mutex, KernelUseconds usec); +int APS5_VABI pthread_mutex_isowned_np_nid_postfix(PthreadMutex* mutex); +int APS5_VABI pthread_mutex_getspinloops_np_nid_postfix(PthreadMutex* mutex, int* count); +int APS5_VABI pthread_mutex_setspinloops_np_nid_postfix(PthreadMutex* mutex, int count); +int APS5_VABI pthread_mutex_getyieldloops_np_nid_postfix(PthreadMutex* mutex, int* count); +int APS5_VABI pthread_mutex_setyieldloops_np_nid_postfix(PthreadMutex* mutex, int count); +int APS5_VABI pthread_mutexattr_destroy_nid_postfix(PthreadMutexattr* attr); +int APS5_VABI pthread_mutexattr_init_nid_postfix(PthreadMutexattr* attr); +int APS5_VABI pthread_mutexattr_getpshared_nid_postfix(const PthreadMutexattr* attr, int* pshared); +int APS5_VABI pthread_mutexattr_setpshared_nid_postfix(PthreadMutexattr* attr, int pshared); +int APS5_VABI pthread_mutexattr_setprotocol_nid_postfix(PthreadMutexattr* attr, int protocol); +int APS5_VABI pthread_mutexattr_getprotocol_nid_postfix(const PthreadMutexattr* attr, int* protocol); +int APS5_VABI pthread_mutexattr_setprioceiling_nid_postfix(PthreadMutexattr* attr, int prioceiling); +int APS5_VABI pthread_mutexattr_getprioceiling_nid_postfix(const PthreadMutexattr* attr, int* prioceiling); +int APS5_VABI pthread_mutexattr_settype_nid_postfix(PthreadMutexattr* attr, int type); +int APS5_VABI pthread_mutexattr_gettype_nid_postfix(const PthreadMutexattr* attr, int* type); +int APS5_VABI pthread_once_nid_postfix( GuestOnce* control, void (APS5_VABI *initialize)()); +int APS5_VABI pthread_rwlock_destroy_nid_postfix(PthreadRwlock* rwlock); +int APS5_VABI pthread_rwlock_init_nid_postfix(PthreadRwlock* rwlock, const PthreadRwlockattr* attr); +int APS5_VABI pthread_rwlockattr_destroy_nid_postfix(PthreadRwlockattr* attr); +int APS5_VABI pthread_rwlockattr_init_nid_postfix(PthreadRwlockattr* attr); +int APS5_VABI pthread_rwlockattr_getpshared_nid_postfix(const PthreadRwlockattr* attr, int* pshared); +int APS5_VABI pthread_rwlockattr_setpshared_nid_postfix(PthreadRwlockattr* attr, int pshared); +int APS5_VABI pthread_rwlock_rdlock_nid_postfix(PthreadRwlock* rwlock); +int APS5_VABI pthread_rwlock_timedrdlock_nid_postfix(PthreadRwlock* rwlock, const KernelTimespec* abstime); +int APS5_VABI pthread_rwlock_timedwrlock_nid_postfix(PthreadRwlock* rwlock, const KernelTimespec* abstime); +int APS5_VABI pthread_rwlock_reltimedrdlock_np_nid_postfix(PthreadRwlock* rwlock, KernelUseconds usec); +int APS5_VABI pthread_rwlock_reltimedwrlock_np_nid_postfix(PthreadRwlock* rwlock, KernelUseconds usec); +int APS5_VABI pthread_rwlock_tryrdlock_nid_postfix(PthreadRwlock* rwlock); +int APS5_VABI pthread_rwlock_trywrlock_nid_postfix(PthreadRwlock* rwlock); +int APS5_VABI pthread_rwlock_unlock_nid_postfix(PthreadRwlock* rwlock); +int APS5_VABI pthread_rwlock_wrlock_nid_postfix(PthreadRwlock* rwlock); +int APS5_VABI sem_init_nid_postfix(void* sem, int pshared, unsigned int value); +int APS5_VABI sem_destroy_nid_postfix(void* sem); +int APS5_VABI sem_wait_nid_postfix(void* sem); +int APS5_VABI sem_trywait_nid_postfix(void* sem); +int APS5_VABI sem_timedwait_nid_postfix(void* sem, const KernelTimespec* abstime); +int APS5_VABI sem_reltimedwait_np_nid_postfix(void* sem, uint32_t usec); +int APS5_VABI sem_post_nid_postfix(void* sem); +int APS5_VABI sem_getvalue_nid_postfix(void* sem, int* value); +void* APS5_VABI sem_open_nid_postfix(const char* name, int flags, ...); +int APS5_VABI sem_close_nid_postfix(void* sem); +int APS5_VABI sem_unlink_nid_postfix(const char* name); +int APS5_VABI pthread_spin_init_nid_postfix(PthreadSpinlockPrivate** lock, int pshared); +int APS5_VABI pthread_spin_destroy_nid_postfix(PthreadSpinlockPrivate** lock); +int APS5_VABI pthread_spin_trylock_nid_postfix(PthreadSpinlockPrivate** lock); +int APS5_VABI pthread_spin_lock_nid_postfix(PthreadSpinlockPrivate** lock); +int APS5_VABI pthread_spin_unlock_nid_postfix(PthreadSpinlockPrivate** lock); +int APS5_VABI cpuset_getaffinity_nid_postfix(int level, int which, std::int64_t id, std::size_t size, void* mask); +int APS5_VABI cpuset_setaffinity_nid_postfix(int level, int which, std::int64_t id, std::size_t size, const void* mask); +int APS5_VABI rtprio_thread_nid_postfix(int function, int lwpid, GuestRtPrio* priority); +int APS5_VABI pthread_setconcurrency_nid_postfix(int newLevel); +int APS5_VABI pthread_getconcurrency_nid_postfix(); +int APS5_VABI pthread_create_nid_postfix(Pthread* thread, const PthreadAttr* attr, PthreadEntry entry, void* arg); +int APS5_VABI pthread_create_name_np_nid_postfix(Pthread* thread, const PthreadAttr* attr, PthreadEntry entry, void* arg, const char* name); +int APS5_VABI pthread_detach_nid_postfix(Pthread thread); +void APS5_VABI pthread_exit_nid_postfix(void* value); +int APS5_VABI scePthreadGetschedparam(Pthread thread, int* policy, KernelSchedParam* param); +int APS5_VABI scePthreadSetschedparam(Pthread thread, int policy, const KernelSchedParam* param); +int APS5_VABI pthread_getschedparam_nid_postfix(Pthread thread, int* policy, KernelSchedParam* param); +int APS5_VABI pthread_getprio_nid_postfix(Pthread thread); +int APS5_VABI pthread_getaffinity_np_nid_postfix(Pthread thread, std::size_t cpusetSize, void* cpuset); +int APS5_VABI pthread_setaffinity_np_nid_postfix(Pthread thread, std::size_t cpusetSize, const void* cpuset); +int APS5_VABI pthread_join_nid_postfix(Pthread thread, void** value); +int APS5_VABI pthread_timedjoin_np_nid_postfix(Pthread thread, void** value, const KernelTimespec* abstime); +int APS5_VABI pthread_rename_np_nid_postfix(Pthread thread, const char* name); +int APS5_VABI pthread_getname_np_nid_postfix(Pthread thread, char* name); +void APS5_VABI pthread_set_name_np_nid_postfix(Pthread thread, const char* name); +Pthread APS5_VABI pthread_self_nid_postfix(void); +int APS5_VABI pthread_getthreadid_np_nid_postfix(void); +int APS5_VABI pthread_equal_nid_postfix(Pthread first, Pthread second); +int APS5_VABI pthread_getcpuclockid_nid_postfix(Pthread thread, int* clockId); +int APS5_VABI sched_yield_nid_postfix(void); +int APS5_VABI pthread_cancel_nid_postfix(Pthread thread); +int APS5_VABI pthread_setcancelstate_nid_postfix(int state, int* oldState); +int APS5_VABI pthread_setcanceltype_nid_postfix(int type, int* oldType); +int APS5_VABI pthread_setprio_nid_postfix(Pthread thread, int prio); +int APS5_VABI pthread_setschedparam_nid_postfix(Pthread thread, int policy, const KernelSchedParam* param); +void APS5_VABI pthread_testcancel_nid_postfix(void); +void APS5_VABI pthread_yield_nid_postfix(void); +unsigned int APS5_VABI sleep_nid_postfix(unsigned int seconds); +void* APS5_VABI pthread_getspecific_nid_postfix(PthreadKey key); +int APS5_VABI pthread_setspecific_nid_postfix(PthreadKey key, void* value); +int APS5_VABI pthread_key_create_nid_postfix(PthreadKey* key, pthread_key_destructor_func_t destructor); +int APS5_VABI pthread_key_delete_nid_postfix(PthreadKey key); +int APS5_VABI scePthreadAttrInit(PthreadAttr* attr); +int APS5_VABI scePthreadAttrDestroy(PthreadAttr* attr); +int APS5_VABI scePthreadAttrSetdetachstate(PthreadAttr* attr, int detachstate); +int APS5_VABI scePthreadAttrSetschedparam(PthreadAttr* attr, const KernelSchedParam* param); +int APS5_VABI scePthreadAttrSetstacksize(PthreadAttr* attr, std::size_t stacksize); +int APS5_VABI scePthreadAttrGetstack(const PthreadAttr* attr, void** stackaddr, std::size_t* stacksize); +int APS5_VABI scePthreadAttrGet(Pthread thread, PthreadAttr* attr); +int APS5_VABI scePthreadAttrGetaffinity(const PthreadAttr* attr, KernelCpumask* mask); +int APS5_VABI scePthreadAttrGetdetachstate(const PthreadAttr* attr, int* state); +int APS5_VABI scePthreadAttrGetguardsize(const PthreadAttr* attr, size_t* guardSize); +int APS5_VABI scePthreadAttrGetinheritsched(const PthreadAttr* attr, int* inheritSched); +int APS5_VABI scePthreadAttrGetschedparam(const PthreadAttr* attr, KernelSchedParam* param); +int APS5_VABI scePthreadAttrGetschedpolicy(const PthreadAttr* attr, int* policy); +int APS5_VABI scePthreadAttrGetsolosched(const PthreadAttr* attr, int* solosched); +int APS5_VABI scePthreadAttrGetstackaddr(const PthreadAttr* attr, void** stackAddr); +int APS5_VABI scePthreadAttrGetstacksize(const PthreadAttr* attr, size_t* stackSize); +int APS5_VABI scePthreadAttrSetaffinity(PthreadAttr* attr, KernelCpumask mask); +int APS5_VABI scePthreadAttrSetguardsize(PthreadAttr* attr, size_t guardSize); +int APS5_VABI scePthreadAttrSetinheritsched(PthreadAttr* attr, int inheritSched); +int APS5_VABI scePthreadAttrSetschedpolicy(PthreadAttr* attr, int policy); +int APS5_VABI scePthreadAttrSetsolosched(PthreadAttr* attr, int solosched); +int APS5_VABI scePthreadAttrSetstack(PthreadAttr* attr, void* addr, size_t size); +int APS5_VABI scePthreadAttrSetstackaddr(PthreadAttr* attr, void* addr); +int APS5_VABI scePthreadSemInit(PthreadSem* sem, int flag, unsigned int value, const char* name); +int APS5_VABI scePthreadSemDestroy(PthreadSem* sem); +int APS5_VABI scePthreadSemPost(PthreadSem* sem); +int APS5_VABI scePthreadSemWait(PthreadSem* sem); +int APS5_VABI scePthreadSemTrywait(PthreadSem* sem); +int APS5_VABI scePthreadSemTimedwait(PthreadSem* sem, KernelUseconds usec); +int APS5_VABI scePthreadSemGetvalue(PthreadSem* sem, int* value); +int APS5_VABI scePthreadCreate(Pthread* thread, const PthreadAttr* attr, PthreadEntry entry, void* arg, const char* name); +int APS5_VABI scePthreadJoin(Pthread thread, void** retval); +int APS5_VABI scePthreadDetach(Pthread thread); +Pthread APS5_VABI scePthreadSelf(); +void APS5_VABI scePthreadYield(); +int APS5_VABI scePthreadCancel(Pthread thread); +int APS5_VABI scePthreadEqual(Pthread thread1, Pthread thread2); +KernelCpumask APS5_VABI sceKernelGetAvailableCpumask(void); +int APS5_VABI scePthreadGetaffinity(Pthread thread, KernelCpumask* mask); +int APS5_VABI scePthreadGetname(Pthread thread, char* name); +int APS5_VABI scePthreadGetprio(Pthread thread, int* prio); +int APS5_VABI scePthreadGetthreadid(void); +int APS5_VABI scePthreadRename(Pthread thread, const char* name); +int APS5_VABI scePthreadSetaffinity(Pthread thread, KernelCpumask mask); +int APS5_VABI scePthreadSetcancelstate(int state, int* oldState); +int APS5_VABI scePthreadSetcanceltype(int type, int* oldType); +void APS5_VABI scePthreadTestcancel(); +int APS5_VABI scePthreadSetprio(Pthread thread, int prio); +int APS5_VABI scePthreadOnce(int32_t* once, void (APS5_VABI* init)(void)); +void APS5_VABI __pthread_cxa_finalize_nid_postfix(void* argument); +int APS5_VABI scePthreadKeyCreate(PthreadKey* key, pthread_key_destructor_func_t destructor); +int APS5_VABI scePthreadKeyDelete(PthreadKey key); +void* APS5_VABI scePthreadGetspecific(PthreadKey key); +int APS5_VABI scePthreadSetspecific(PthreadKey key, void* value); +int APS5_VABI __inet_pton_nid_postfix(int family, const char* text, void* destination); +const char* APS5_VABI __inet_ntop_nid_postfix(int family, const void* source, char* destination, std::uint32_t capacity); +std::uint32_t APS5_VABI htonl_nid_postfix(std::uint32_t value); +std::uint32_t APS5_VABI ntohl_nid_postfix(std::uint32_t value); +std::uint16_t APS5_VABI htons_nid_postfix(std::uint16_t value); +std::uint16_t APS5_VABI ntohs_nid_postfix(std::uint16_t value); +int APS5_VABI pselect_nid_postfix(int nfds, void* readfds, void* writefds, void* exceptfds, const void* timeout, const void* sigmask); +const char* APS5_VABI inet_ntop_nid_postfix(int af, const void* src, char* dst, uint32_t size); +int APS5_VABI inet_pton_nid_postfix(int af, const char* src, void* dst); +int APS5_VABI select_nid_postfix(int nfds, void* readfds, void* writefds, void* exceptfds, const void* timeout); +int APS5_VABI fcntl_nid_postfix(int descriptor, int command, ...); +int APS5_VABI _fcntl_nid_postfix(int descriptor, int command, ...); +int APS5_VABI setsockopt_nid_postfix(int descriptor, int level, int option, const void* value, std::uint32_t length); +int APS5_VABI getsockopt_nid_postfix(int descriptor, int level, int option, void* value, std::uint32_t* length); +int APS5_VABI socket_nid_postfix(int family, int type, int protocol); +int APS5_VABI __sys_socketex_nid_postfix(const char* name, int family, int type, int protocol); +int APS5_VABI socketpair_nid_postfix(int family, int type, int protocol, int* descriptors); +int APS5_VABI connect_nid_postfix(int descriptor, const void* address, std::uint32_t length); +int APS5_VABI listen_nid_postfix(int descriptor, int backlog); +int APS5_VABI accept_nid_postfix(int descriptor, void* address, std::uint32_t* length); +std::int64_t APS5_VABI send_nid_postfix(int descriptor, const void* buffer, std::uint64_t length, int flags); +std::int64_t APS5_VABI recv_nid_postfix(int descriptor, void* buffer, std::uint64_t length, int flags); +int APS5_VABI bind_nid_postfix(int descriptor, const void* address, std::uint32_t length); +int APS5_VABI shutdown_nid_postfix(int descriptor, int how); +int APS5_VABI getsockname_nid_postfix(int descriptor, void* address, std::uint32_t* length); +int APS5_VABI getpeername_nid_postfix(int descriptor, void* address, std::uint32_t* length); +int APS5_VABI ioctl_nid_postfix(int descriptor, std::uint64_t request, void* argument); +int APS5_VABI _ioctl_nid_postfix(int descriptor, std::uint64_t request, void* argument); +std::int64_t APS5_VABI sendto_nid_postfix(int descriptor, const void* buffer, std::uint64_t length, int flags, const void* address, std::uint32_t addressLength); +std::int64_t APS5_VABI recvfrom_nid_postfix(int descriptor, void* buffer, std::uint64_t length, int flags, void* address, std::uint32_t* addressLength); +std::int64_t APS5_VABI sendmsg_nid_postfix(int descriptor, const GuestMsghdr* message, int flags); +std::int64_t APS5_VABI recvmsg_nid_postfix(int descriptor, GuestMsghdr* message, int flags); +int APS5_VABI sendfile_nid_postfix(int file, int descriptor, std::int64_t offset, std::uint64_t length, const GuestSendfileHeaders* headers, std::int64_t* sbytes, int flags); +int APS5_VABI poll_nid_postfix(GuestPollDescriptor* descriptors, std::uint32_t count, int timeout); +int APS5_VABI _setsockopt_nid_postfix(int descriptor, int level, int option, const void* value, std::uint32_t length); +int APS5_VABI _getsockopt_nid_postfix(int descriptor, int level, int option, void* value, std::uint32_t* length); +int APS5_VABI _connect_nid_postfix(int descriptor, const void* address, std::uint32_t length); +int APS5_VABI _listen_nid_postfix(int descriptor, int backlog); +int APS5_VABI _accept_nid_postfix(int descriptor, void* address, std::uint32_t* length); +int APS5_VABI _bind_nid_postfix(int descriptor, const void* address, std::uint32_t length); +int APS5_VABI _getsockname_nid_postfix(int descriptor, void* address, std::uint32_t* length); +int APS5_VABI _getpeername_nid_postfix(int descriptor, void* address, std::uint32_t* length); +std::int64_t APS5_VABI _sendto_nid_postfix(int descriptor, const void* buffer, std::uint64_t length, int flags, const void* address, std::uint32_t addressLength); +std::int64_t APS5_VABI _recvfrom_nid_postfix(int descriptor, void* buffer, std::uint64_t length, int flags, void* address, std::uint32_t* addressLength); +std::int64_t APS5_VABI _sendmsg_nid_postfix(int descriptor, const GuestMsghdr* message, int flags); +std::int64_t APS5_VABI _recvmsg_nid_postfix(int descriptor, GuestMsghdr* message, int flags); +int APS5_VABI sceKernelSyncOnAddressWait(std::uint32_t* address, std::uint32_t expected, const KernelUseconds* timeout, const char* name); +int APS5_VABI sceKernelSyncOnAddressWait8(std::uint8_t* address, std::uint8_t expected, const KernelUseconds* timeout, const char* name); +int APS5_VABI sceKernelSyncOnAddressWait16(std::uint16_t* address, std::uint16_t expected, const KernelUseconds* timeout, const char* name); +int APS5_VABI sceKernelSyncOnAddressWait32(std::uint32_t* address, std::uint32_t expected, const KernelUseconds* timeout, const char* name); +int APS5_VABI sceKernelSyncOnAddressWait64(std::uint64_t* address, std::uint64_t expected, const KernelUseconds* timeout, const char* name); +int APS5_VABI sceKernelSyncOnAddressWake(void* address, std::int32_t count); +int APS5_VABI _umtx_op_nid_postfix(void* object, int operation, std::uint64_t value, void* sizeArgument, void* timeArgument); +int APS5_VABI sceCoredumpRegisterCoredumpHandler(uint64_t handler, size_t stackSize, uint64_t context); +int APS5_VABI sceCoredumpUnregisterCoredumpHandler(void); +int APS5_VABI sceKernelDebugWriteCppExceptionInfo(const void* exception, uint64_t unknown, const char* typeName, const char* what); +int APS5_VABI sceCoredumpAttachUserFile(std::uint32_t userValue, const char* path); +int APS5_VABI sceCoredumpGetStopInfoGpu_Agc(void* info, size_t size); +int APS5_VABI sceCoredumpAttachMemoryRegionAsUserFile(std::uint32_t userValue, const void* mem, std::int32_t size, const char* name); +int APS5_VABI sceCoredumpSetUserDataType(std::int32_t type); +void APS5_VABI sceCoredumpDebugTextOut(const char* str, int len); +int64_t APS5_VABI sceCoredumpWriteUserData(const void* data, size_t size); +int APS5_VABI sceCoredumpGetStopInfoCpu(void* info, size_t size); +int APS5_VABI sceCoredumpGetThreadContextInfo(void* threadContextInfo, size_t threadContextInfoSize); +int APS5_VABI sceCoredumpWriteUserString(uint32_t first, const char* text, int third); +int APS5_VABI sceCoredumpConfigDumpMode(int mode); +int APS5_VABI sceCoredumpAttachUserMemoryFile(std::uint32_t userValue, const void* mem, std::int32_t size); +int APS5_VABI sceCoredumpAttachMemoryRegion(std::uint32_t userValue, const void* mem, std::int32_t size); +std::int32_t APS5_VABI sceKernelError(std::int32_t posixError); +int APS5_VABI sceKernelInstallExceptionHandler(int signum, void* handler); +int APS5_VABI sceKernelRemoveExceptionHandler(int signum); +int APS5_VABI sceKernelRaiseException(Pthread thread, int signum); +void APS5_VABI sceKernelDebugRaiseException(int c1, int c2); +void APS5_VABI sceKernelDebugRaiseExceptionOnReleaseMode(int c1, int c2); +int APS5_VABI getlogin_r_nid_postfix(char* output, int size); +int APS5_VABI sceKernelDebugOutText(int channel, const char* text); +int APS5_VABI sceKernelSendNotificationRequest(int device, const void* request, std::size_t size, int flags); +int APS5_VABI getargc_nid_postfix(void); +const char** APS5_VABI getargv_nid_postfix(void); +int APS5_VABI getpagesize_nid_postfix(void); +int APS5_VABI getpid_nid_postfix(void); +int APS5_VABI getsid_nid_postfix(int pid); +int APS5_VABI getppid_nid_postfix(void); +int APS5_VABI sceKernelGetAppInfo(int pid, void* info); +int APS5_VABI getuid_nid_postfix(void); +int APS5_VABI geteuid_nid_postfix(void); +int APS5_VABI getgid_nid_postfix(void); +int APS5_VABI getegid_nid_postfix(void); +int APS5_VABI issetugid_nid_postfix(void); +int APS5_VABI getresuid_nid_postfix(std::uint32_t* ruid, std::uint32_t* euid, std::uint32_t* suid); +int APS5_VABI getresgid_nid_postfix(std::uint32_t* rgid, std::uint32_t* egid, std::uint32_t* sgid); +int APS5_VABI system_nid_postfix(const char* command); +int APS5_VABI waitpid_nid_postfix(int pid, int* status, int options); +int APS5_VABI setrlimit_nid_postfix(int resource, const GuestResourceLimit* limit); +int APS5_VABI wait_nid_postfix(int* status); +int APS5_VABI execvp_nid_postfix(const char* file, char* const* arguments); +int APS5_VABI execv_nid_postfix(const char* path, char* const* arguments); +int APS5_VABI execve_nid_postfix(const char* path, char* const* arguments, char* const* environment); +int APS5_VABI sceKernelGetCurrentCpu(void); +int APS5_VABI sceKernelGetMainSocId(void); +int APS5_VABI sceKernelGetCpumode(void); +std::uint64_t APS5_VABI sceKernelGetGPI(void); +void APS5_VABI sceKernelSetGPO(std::uint32_t bits); +int APS5_VABI sceKernelGetOpenPsId(void* openPsIdOutput); +void* APS5_VABI sceKernelGetProcParam(void); +int APS5_VABI sceKernelUuidCreate(std::uint32_t* uuid); +int APS5_VABI sceKernelCreateUuidV4(std::uint8_t* uuid); +void APS5_VABI sceKernelSync(void); +void APS5_VABI sync_nid_postfix(void); +int APS5_VABI sched_get_priority_max_nid_postfix(int policy); +int APS5_VABI sched_get_priority_min_nid_postfix(int policy); +int APS5_VABI sysarch(int operation, void* parameters); +int APS5_VABI getrusage_nid_postfix(int who, GuestResourceUsage* usage); +int APS5_VABI getrlimit_nid_postfix(int resource, GuestResourceLimit* limit); +int APS5_VABI getpriority_nid_postfix(int which, int who); +int APS5_VABI setpriority_nid_postfix(int which, int who, int niceval); +int APS5_VABI getdtablesize_nid_postfix(void); +int APS5_VABI sceKernelIsTrinityMode(void); +void APS5_VABI sceKernelGetOperationMode(int* mode, int* submode); +int APS5_VABI seteuid_nid_postfix(std::uint32_t euid); +int APS5_VABI setegid_nid_postfix(std::uint32_t egid); +int APS5_VABI setuid_nid_postfix(std::uint32_t uid); +int APS5_VABI setgid_nid_postfix(std::uint32_t gid); +int APS5_VABI setreuid_nid_postfix(std::uint32_t ruid, std::uint32_t euid); +int APS5_VABI setregid_nid_postfix(std::uint32_t rgid, std::uint32_t egid); +int APS5_VABI setresuid_nid_postfix(std::uint32_t ruid, std::uint32_t euid, std::uint32_t suid); +int APS5_VABI setresgid_nid_postfix(std::uint32_t rgid, std::uint32_t egid, std::uint32_t sgid); +int APS5_VABI setgroups_nid_postfix(int count, const std::uint32_t* groups); +int APS5_VABI getgroups_nid_postfix(int capacity, std::uint32_t* groups); +void APS5_VABI sceKernelRtldSetApplicationHeapAPI(void* api[]); +int APS5_VABI sceKernelRtldThreadAtexitDecrement(const void* dsoSymbol); +int APS5_VABI sceKernelRtldThreadAtexitIncrement(const void* dsoSymbol); +void APS5_VABI sceKernelSetThreadAtexitCount(get_thread_atexit_count_func_t func); +void APS5_VABI sceKernelSetThreadAtexitReport(thread_atexit_report_func_t func); +void APS5_VABI sceKernelSetThreadDtors(thread_dtors_func_t dtors); +void APS5_VABI _sceKernelRtldSetApplicationHeapAPI_nid_postfix(void* api[]); +int APS5_VABI _sceKernelRtldThreadAtexitDecrement_nid_postfix(const void* dsoSymbol); +int APS5_VABI _sceKernelRtldThreadAtexitIncrement_nid_postfix(const void* dsoSymbol); +void APS5_VABI _sceKernelSetThreadAtexitCount_nid_postfix(get_thread_atexit_count_func_t callback); +void APS5_VABI _sceKernelSetThreadAtexitReport_nid_postfix(thread_atexit_report_func_t callback); +void APS5_VABI _sceKernelSetThreadDtors_nid_postfix(thread_dtors_func_t callback); +const char* APS5_VABI sceKernelGetFsSandboxRandomWord(); +int APS5_VABI sceKernelIsAddressSanitizerEnabled(void); +int APS5_VABI sceKernelIsThreadSanitizerEnabled(void); +MallocReplace* APS5_VABI sceKernelGetSanitizerMallocReplaceExternal(void); +NewReplace* APS5_VABI sceKernelGetSanitizerNewReplaceExternal(void); +int APS5_VABI getitimer_nid_postfix(int which, GuestItimerval* output); +int APS5_VABI setitimer_nid_postfix(int which, const GuestItimerval* value, GuestItimerval* previous); +GuestHandler APS5_VABI signal_nid_postfix(int guest, GuestHandler handler); +int APS5_VABI sigaction_nid_postfix(int guest, const GuestSigaction* action, GuestSigaction* previous); +int APS5_VABI _sigaction_nid_postfix(int guest, const GuestSigaction* action, GuestSigaction* previous); +int APS5_VABI raise_nid_postfix(int guest); +int APS5_VABI kill_nid_postfix(int pid, int guest); +int APS5_VABI killpg_nid_postfix(int pgrp, int guest); +int APS5_VABI pthread_kill_nid_postfix(Pthread thread, int guest); +int APS5_VABI sigaltstack_nid_postfix(const GuestStack* stack, GuestStack* previous); +int APS5_VABI _sigprocmask_nid_postfix(int how, const GuestSignalSet* set, GuestSignalSet* previousSet); +int APS5_VABI sigprocmask_nid_postfix(int how, const void* set, void* previousSet); +int APS5_VABI pthread_sigmask_nid_postfix(int how, const GuestSignalSet* set, GuestSignalSet* previousSet); +int APS5_VABI sigtimedwait_nid_postfix(const GuestSignalSet* set, void* info, const KernelTimespec* timeout); +int APS5_VABI sigwaitinfo_nid_postfix(const GuestSignalSet* set, void* info); +int APS5_VABI sigwait_nid_postfix(const GuestSignalSet* set, int* received); +int APS5_VABI pause_nid_postfix(void); +int APS5_VABI sigsuspend_nid_postfix(const GuestSignalSet* set); +int APS5_VABI _sigsuspend_nid_postfix(const GuestSignalSet* set); +int APS5_VABI sigpending_nid_postfix(GuestSignalSet* set); +int APS5_VABI _is_signal_return_nid_postfix(std::uint64_t programCounter); +int APS5_VABI sigemptyset_nid_postfix(GuestSignalSet* set); +int APS5_VABI sigfillset_nid_postfix(GuestSignalSet* set); +int APS5_VABI sigaddset_nid_postfix(GuestSignalSet* set, int signal); +int APS5_VABI sigdelset_nid_postfix(GuestSignalSet* set, int signal); +int APS5_VABI sigismember_nid_postfix(const GuestSignalSet* set, int signal); +int APS5_VABI sceKernelGetProsperoSystemSwVersion_nid_postfix(SceKernelProsperoSystemSwVersion* version); +int APS5_VABI sceKernelGetAllowedSdkVersionOnSystem_nid_postfix(std::uint32_t* version); +std::int64_t APS5_VABI sysconf_nid_postfix(int name); +int APS5_VABI sysctl_nid_postfix(const int* name, std::uint32_t nameLength, void* oldValue, std::size_t* oldLength, const void* newValue, std::size_t newLength); +int APS5_VABI sysctlbyname_nid_postfix(const char* name, void* oldValue, std::size_t* oldLength, const void* newValue, std::size_t newLength); +int APS5_VABI sceKernelGetSystemSwVersion_nid_postfix(SceKernelSystemSwVersion* version); +int APS5_VABI sysctlnametomib_nid_postfix(const char* name, int* mib, std::size_t* size); +int APS5_VABI sceKernelGetCpuTemperature(int* outCelsius); +int APS5_VABI sceKernelGetSocSensorTemperature(int sensorId, int* outCelsius); +int APS5_VABI sceKernelGetSocPowerConsumption(void* consumption); +int APS5_VABI setcontext_nid_postfix(const UserUcontext* context); +int APS5_VABI ktimer_create_nid_postfix(int clock, const GuestSigevent* event, int* timerid); +int APS5_VABI ktimer_delete_nid_postfix(int id); +int APS5_VABI ktimer_settime_nid_postfix(int id, int flags, const GuestItimerspec* value, GuestItimerspec* oldValue); +int APS5_VABI ktimer_gettime_nid_postfix(int id, GuestItimerspec* value); +int APS5_VABI ktimer_getoverrun_nid_postfix(int id); +int APS5_VABI _nanosleep_nid_postfix(const KernelTimespec* rqtp, KernelTimespec* rmtp); +int APS5_VABI usleep_nid_postfix(KernelUseconds microseconds); +int APS5_VABI clock_settime_nid_postfix(int clockId, const KernelTimespec* tp); +int APS5_VABI sceKernelClockGetres(KernelClockid clockId, KernelTimespec* tp); +int APS5_VABI sceKernelClockGettime(KernelClockid clockId, KernelTimespec* tp); +int APS5_VABI sceKernelConvertLocaltimeToUtc(int64_t localTime, int64_t reserved, int64_t* utcTime, KernelTimesec* timezone, int32_t* dstSeconds); +int APS5_VABI sceKernelConvertUtcToLocaltime(int64_t utcTime, int64_t* localTime, KernelTimesec* st, int32_t* dstSec); +int APS5_VABI sceKernelGettimeofday(KernelTimeval* tp); +int APS5_VABI sceKernelGettimezone(KernelTimezone* tz); +uint64_t APS5_VABI sceKernelReadTsc(void); +std::int64_t APS5_VABI sceKernelGetCpuFrequency(void); +unsigned int APS5_VABI sceKernelSleep(unsigned int seconds); + +[[noreturn]] void APS5_VABI _exit_nid_postfix(int status); + +[[gnu::returns_twice]] int APS5_VABI getcontext_nid_postfix(UserUcontext* context); +[[gnu::returns_twice]] int APS5_VABI swapcontext_nid_postfix(UserUcontext* oucp, const UserUcontext* ucp); + +[[gnu::returns_twice]] int APS5_VABI sigsetjmp_nid_postfix(std::uint64_t* buffer, int saveMask); +[[noreturn]] void APS5_VABI siglongjmp_nid_postfix(std::uint64_t* buffer, int value); + +int APS5_VABI sceKernelGetTraceMemoryStats(std::uint64_t* first, std::uint64_t* second); +int APS5_VABI pthread_cond_signalto_np_nid_postfix(PthreadCond* cond, Pthread thread); +int APS5_VABI scePthreadCondattrSetpshared(PthreadCondattr* attr, int pshared); +int APS5_VABI scePthreadCondattrGetpshared(const PthreadCondattr* attr, int* pshared); +int APS5_VABI pthread_mutexattr_setkind_np_nid_postfix(PthreadMutexattr* attr, int kind); +int APS5_VABI pthread_mutexattr_getkind_np_nid_postfix(PthreadMutexattr attr); +int APS5_VABI scePthreadMutexattrGettype(const PthreadMutexattr* attr, int* type); +int APS5_VABI scePthreadMutexattrGetprotocol(const PthreadMutexattr* attr, int* protocol); +int APS5_VABI scePthreadMutexattrSetprioceiling(PthreadMutexattr* attr, int prioceiling); +int APS5_VABI scePthreadMutexattrGetprioceiling(const PthreadMutexattr* attr, int* prioceiling); +int APS5_VABI scePthreadMutexattrSetpshared(PthreadMutexattr* attr, int pshared); +int APS5_VABI scePthreadMutexattrGetpshared(const PthreadMutexattr* attr, int* pshared); +int APS5_VABI pthread_rwlockattr_gettype_np_nid_postfix(const PthreadRwlockattr* attr, int* type); +int APS5_VABI scePthreadRwlockattrGettype(const PthreadRwlockattr* attr, int* type); +int APS5_VABI scePthreadRwlockattrSetpshared(PthreadRwlockattr* attr, int pshared); +int APS5_VABI scePthreadRwlockattrGetpshared(const PthreadRwlockattr* attr, int* pshared); +int APS5_VABI setpgid_nid_postfix(int pid, int pgid); +int APS5_VABI setpgrp_nid_postfix(int pid, int pgrp); +int APS5_VABI sceKernelGetSystemExVersion(char* first, char* second); +int APS5_VABI sysKernelGetLowerLimitSysexVersion_nid_postfix(char* version); +int APS5_VABI sysKernelGetLowerLimitUpdVersion_nid_postfix(std::uint32_t* version); + +} diff --git a/core/libs/prx/libkernel/libkernel.hpp b/core/libs/prx/libkernel/libkernel.hpp new file mode 100644 index 0000000000..3a32592846 --- /dev/null +++ b/core/libs/prx/libkernel/libkernel.hpp @@ -0,0 +1,14 @@ +#pragma once + +#include "prx/libc/include/Api.hpp" +#include "prx/libkernel/Equeue/Equeue.hpp" +#include "prx/libkernel/File/include/File.hpp" +#include "prx/libkernel/include/Api.hpp" +#include "prx/libkernel/Pthread/include/Atfork.hpp" +#include "prx/libkernel/Pthread/include/Cancel.hpp" +#include "prx/libkernel/Pthread/include/Cond.hpp" +#include "prx/libkernel/Pthread/include/Mutex.hpp" +#include "prx/libkernel/Pthread/include/Rwlock.hpp" +#include "prx/libkernel/Pthread/include/ThreadLifecycle.hpp" +#include "prx/libkernel/Semaphore/include/Semaphore.hpp" +#include "prx/libkernel/Time/include/Time.hpp" diff --git a/core/libs/prx/libkernel_sys/Aio.cpp b/core/libs/prx/libkernel_sys/Aio.cpp index 789b0c72d3..f81b5842de 100644 --- a/core/libs/prx/libkernel_sys/Aio.cpp +++ b/core/libs/prx/libkernel_sys/Aio.cpp @@ -1,3 +1,6 @@ +#include "prx/libkernel_sys/include/Api.hpp" +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include #include #include @@ -14,13 +17,6 @@ #include "SceTypes.hpp" #include "prx/libc/include/General.hpp" -extern "C" int* APS5_VABI __error_nid_postfix(); -extern "C" int APS5_VABI fcntl_nid_postfix(int descriptor, int command, ...); -extern "C" std::int64_t APS5_VABI _fstat_nid_postfix(int descriptor, FileStat* status); -extern "C" std::int64_t APS5_VABI pread_nid_postfix(int descriptor, void* buffer, std::size_t bytes, std::int64_t offset); -extern "C" std::int64_t APS5_VABI pwrite_nid_disambig1_nid_postfix(int descriptor, const void* buffer, std::size_t bytes, std::int64_t offset); -extern "C" int APS5_VABI fsync_nid_postfix(int descriptor); - namespace { constexpr int GuestEbadf = 9; @@ -56,36 +52,9 @@ constexpr std::uint64_t IoSizeMax = std::numeric_limits::max(); constexpr std::int64_t NanosecondsPerSecond = 1000000000; constexpr std::int64_t TickNanoseconds = 1000000; -struct GuestSigevent { - int notify; - int signo; - std::int64_t value; - std::int64_t extra[8]; -}; - -struct GuestAiocb { - int fildes; - std::int64_t offset; - void* buf; - std::uint64_t nbytes; - int spare[2]; - void* spare2; - int lioOpcode; - int reqprio; - std::int64_t status; - std::int64_t error; - void* kernelinfo; - GuestSigevent sigevent; -}; - static_assert(offsetof(GuestAiocb, lioOpcode) == 48 && offsetof(GuestAiocb, status) == 56 && offsetof(GuestAiocb, sigevent) == 80); static_assert(sizeof(GuestAiocb) == 160); -struct GuestTimespec { - std::int64_t tv_sec; - std::int64_t tv_nsec; -}; - enum class State { Queued, Running, Done }; struct Job { @@ -170,7 +139,7 @@ std::int64_t Consume(Aio& aio, std::list>::iterator found) return job->error != 0 ? Fail(job->error) : job->status; } -std::optional WaitTime(const GuestTimespec& time) { +std::optional WaitTime(const KernelTimespec& time) { if (time.tv_sec < 0 || time.tv_nsec < 0 || time.tv_nsec >= NanosecondsPerSecond) return std::nullopt; const auto microseconds = time.tv_nsec / 1000; const std::int64_t whole = microseconds * 1000; @@ -270,7 +239,7 @@ std::int64_t APS5_VABI aio_return_nid_postfix(GuestAiocb* aiocb) { return Fail(GuestEinval); } -int APS5_VABI aio_suspend_nid_postfix(const GuestAiocb* const* list, int count, const GuestTimespec* timeout) { +int APS5_VABI aio_suspend_nid_postfix(const GuestAiocb* const* list, int count, const KernelTimespec* timeout) { if (count < 0 || count > static_cast(QueuePerProcess)) return Fail(GuestEinval); std::optional wait; if (timeout != nullptr) { @@ -296,7 +265,7 @@ int APS5_VABI aio_suspend_nid_postfix(const GuestAiocb* const* list, int count, } } -std::int64_t APS5_VABI aio_waitcomplete_nid_postfix(GuestAiocb** result, const GuestTimespec* timeout) { +std::int64_t APS5_VABI aio_waitcomplete_nid_postfix(GuestAiocb** result, const KernelTimespec* timeout) { if (result != nullptr) *result = nullptr; std::optional wait; bool poll = false; diff --git a/core/libs/prx/libkernel_sys/CMakeLists.txt b/core/libs/prx/libkernel_sys/CMakeLists.txt index 8aead464a0..70631309ca 100644 --- a/core/libs/prx/libkernel_sys/CMakeLists.txt +++ b/core/libs/prx/libkernel_sys/CMakeLists.txt @@ -1,3 +1,3 @@ -add_library(${LIB_NAME} SHARED EXCLUDE_FROM_ALL Export.cpp Export.Discovery.cpp Aio.cpp) +add_library(${LIB_NAME} SHARED EXCLUDE_FROM_ALL Export.cpp Export.Discovery.cpp Aio.cpp ThreadQueries.cpp) target_include_directories(${LIB_NAME} PRIVATE ${LIBS_INCLUDE_DIR}) configure_windows_unwind(${LIB_NAME}) diff --git a/core/libs/prx/libkernel_sys/Export.Discovery.cpp b/core/libs/prx/libkernel_sys/Export.Discovery.cpp index 980608a53e..6a93c40f22 100644 --- a/core/libs/prx/libkernel_sys/Export.Discovery.cpp +++ b/core/libs/prx/libkernel_sys/Export.Discovery.cpp @@ -1,26 +1,12 @@ +#include "prx/libkernel_sys/include/Api.hpp" +#include "prx/libkernel/Pthread/include/Atfork.hpp" +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "SceTypes.hpp" #include "prx/libc/include/General.hpp" #include "prx/libkernel/KernelErrors.hpp" #include -extern "C" { -int* APS5_VABI __error_nid_postfix(); -int APS5_VABI pthread_barrier_init_nid_postfix(void** barrier, void* const* attr, unsigned count); -int APS5_VABI pthread_barrier_wait_nid_postfix(void** barrier); -int APS5_VABI pthread_barrier_destroy_nid_postfix(void** barrier); -int APS5_VABI pthread_barrierattr_init_nid_postfix(void** attr); -int APS5_VABI pthread_barrierattr_destroy_nid_postfix(void** attr); -int APS5_VABI pthread_barrierattr_getpshared_nid_postfix(void* const* attr, int* pshared); -int APS5_VABI pthread_barrierattr_setpshared_nid_postfix(void** attr, int pshared); -int APS5_VABI pthread_getcpuclockid_nid_postfix(void* thread, int* clockId); -int APS5_VABI pthread_getconcurrency_nid_postfix(); -int APS5_VABI pthread_setconcurrency_nid_postfix(int level); -int APS5_VABI pthread_attr_getscope_nid_postfix(void* const* attr, int* scope); -int APS5_VABI pthread_attr_setscope_nid_postfix(void** attr, int scope); -int APS5_VABI pthread_atfork_nid_postfix(void (APS5_VABI* prepare)(), void (APS5_VABI* parent)(), void (APS5_VABI* child)()); -int APS5_VABI msync_nid_postfix(void* address, std::size_t length, int flags); -} - namespace { int SceResult(int error) { @@ -336,11 +322,6 @@ int APS5_VABI pthread_getstack_np_nid_postfix(void) { return 0; } -int APS5_VABI pthread_main_np_nid_postfix(void) { - NotImplemented_nid_no_patch(__func__); - return 0; -} - int APS5_VABI pthread_multi_np_nid_postfix(void) { NotImplemented_nid_no_patch(__func__); return 0; @@ -427,13 +408,11 @@ int APS5_VABI pthread_suspend_user_context_np_nid_postfix(void) { } int APS5_VABI pthread_switch_add_np_nid_postfix(void) { - NotImplemented_nid_no_patch(__func__); - return 0; + return 45; } int APS5_VABI pthread_switch_delete_np_nid_postfix(void) { - NotImplemented_nid_no_patch(__func__); - return 0; + return 45; } int APS5_VABI ptrace_nid_postfix(void) { @@ -502,7 +481,6 @@ int APS5_VABI sceKernelAddProcessToCanvasMap(void) { } int APS5_VABI sceKernelAddResource(void) { - NotImplemented_nid_no_patch(__func__); return 0; } @@ -582,13 +560,11 @@ int APS5_VABI sceKernelClearBootReqNotifyCount(void) { } int APS5_VABI sceKernelClearGameDirectMemory(void) { - NotImplemented_nid_no_patch(__func__); - return 0; + return static_cast(0x8002004e); } int APS5_VABI sceKernelCloseEport(void) { - NotImplemented_nid_no_patch(__func__); - return 0; + return static_cast(0x80020001); } int APS5_VABI sceKernelCloseSema(void) { @@ -602,8 +578,7 @@ int APS5_VABI sceKernelCreateBudget(void) { } int APS5_VABI sceKernelCreateEport(void) { - NotImplemented_nid_no_patch(__func__); - return 0; + return static_cast(0x80020001); } int APS5_VABI sceKernelDebugAcquireAndUpdateDebugRegister(void) { @@ -682,8 +657,7 @@ int APS5_VABI sceKernelDeleteCpumodeEvent(void) { } int APS5_VABI sceKernelDeleteEport(void) { - NotImplemented_nid_no_patch(__func__); - return 0; + return static_cast(0x80020001); } int APS5_VABI sceKernelDeleteGpuExceptionEvent(void) { @@ -727,7 +701,6 @@ int APS5_VABI sceKernelEndAppMount2(void) { } int APS5_VABI sceKernelEventLogInit(void) { - NotImplemented_nid_no_patch(__func__); return 0; } @@ -1237,8 +1210,7 @@ int APS5_VABI sceKernelGiveDirectMemoryToMapper(void) { } int APS5_VABI sceKernelHasNeoMode(void) { - NotImplemented_nid_no_patch(__func__); - return 0; + return 1; } int APS5_VABI sceKernelHwGetBdDriveInfo(void) { @@ -1277,8 +1249,7 @@ int APS5_VABI sceKernelIccGetBootTimestamp(void) { } int APS5_VABI sceKernelIccGetCPMode(void) { - NotImplemented_nid_no_patch(__func__); - return 0; + return static_cast(0x8002002d); } int APS5_VABI sceKernelIccGetCountTime(void) { @@ -1372,8 +1343,7 @@ int APS5_VABI sceKernelIccSetBuzzer(void) { } int APS5_VABI sceKernelIccSetCPMode(void) { - NotImplemented_nid_no_patch(__func__); - return 0; + return static_cast(0x8002002d); } int APS5_VABI sceKernelIccSetCpuInfoBit(void) { @@ -1427,8 +1397,7 @@ int APS5_VABI sceKernelIsAllowedToSelectDvdRegion(void) { } int APS5_VABI sceKernelIsAuthenticNeo(void) { - NotImplemented_nid_no_patch(__func__); - return 0; + return 1; } int APS5_VABI sceKernelIsCEX(void) { @@ -1462,13 +1431,11 @@ int APS5_VABI sceKernelIsGenuineDevKit(void) { } int APS5_VABI sceKernelIsGenuineKratosCex(void) { - NotImplemented_nid_no_patch(__func__); return 0; } int APS5_VABI sceKernelIsGenuineN(void) { - NotImplemented_nid_no_patch(__func__); - return 0; + return 1; } int APS5_VABI sceKernelIsGenuineTestKit(void) { @@ -1587,8 +1554,7 @@ int APS5_VABI sceKernelMapToolMemory(void) { } int APS5_VABI sceKernelMapTraceMemory(void) { - NotImplemented_nid_no_patch(__func__); - return 0; + return static_cast(0x8002004e); } int APS5_VABI sceKernelMapperGetParam(void) { @@ -1636,8 +1602,7 @@ int APS5_VABI sceKernelNotifySystemSuspendStart(void) { } int APS5_VABI sceKernelOpenEport(void) { - NotImplemented_nid_no_patch(__func__); - return 0; + return static_cast(0x80020001); } int APS5_VABI sceKernelOpenInternal(void) { @@ -1681,8 +1646,7 @@ int APS5_VABI sceKernelQueryToolMemory(void) { } int APS5_VABI sceKernelQueryTraceMemory(void) { - NotImplemented_nid_no_patch(__func__); - return 0; + return static_cast(0x80020002); } int APS5_VABI sceKernelRandomizedPath(void) { @@ -1706,7 +1670,6 @@ int APS5_VABI sceKernelReleaseToolMemory(void) { } int APS5_VABI sceKernelReleaseTraceDirectMemory(void) { - NotImplemented_nid_no_patch(__func__); return 0; } @@ -2021,13 +1984,11 @@ int APS5_VABI sceKernelTitleWorkdaroundIsEnabled(void) { } int APS5_VABI sceKernelTraceMemoryTypeProtect(void) { - NotImplemented_nid_no_patch(__func__); - return 0; + return static_cast(0x8002004e); } int APS5_VABI sceKernelTriggerEport(void) { - NotImplemented_nid_no_patch(__func__); - return 0; + return static_cast(0x80020001); } int APS5_VABI sceKernelVirtualQueryAll(void) { @@ -2154,7 +2115,7 @@ int APS5_VABI scePthreadAtfork(void (APS5_VABI* prepare)(), void (APS5_VABI* par return SceResult(pthread_atfork_nid_postfix(prepare, parent, child)); } -int APS5_VABI scePthreadAttrGetscope(void* const* attr, int* scope) { +int APS5_VABI scePthreadAttrGetscope(const PthreadAttr* attr, int* scope) { return SceResult(pthread_attr_getscope_nid_postfix(attr, scope)); } @@ -2163,37 +2124,37 @@ int APS5_VABI scePthreadAttrSetcreatesuspend(void) { return 0; } -int APS5_VABI scePthreadAttrSetscope(void** attr, int scope) { +int APS5_VABI scePthreadAttrSetscope(PthreadAttr* attr, int scope) { return SceResult(pthread_attr_setscope_nid_postfix(attr, scope)); } -int APS5_VABI scePthreadBarrierDestroy(void** barrier) { +int APS5_VABI scePthreadBarrierDestroy(PthreadBarrierPrivate** barrier) { return SceResult(pthread_barrier_destroy_nid_postfix(barrier)); } -int APS5_VABI scePthreadBarrierInit(void** barrier, void* const* attr, unsigned count, const char* name) { +int APS5_VABI scePthreadBarrierInit(PthreadBarrierPrivate** barrier, PthreadBarrierattrPrivate* const* attr, unsigned count, const char* name) { (void)name; return SceResult(pthread_barrier_init_nid_postfix(barrier, attr, count)); } -int APS5_VABI scePthreadBarrierWait(void** barrier) { +int APS5_VABI scePthreadBarrierWait(PthreadBarrierPrivate** barrier) { const int result = pthread_barrier_wait_nid_postfix(barrier); return result > 0 ? SceKernelError(result) : result; } -int APS5_VABI scePthreadBarrierattrDestroy(void** attr) { +int APS5_VABI scePthreadBarrierattrDestroy(PthreadBarrierattrPrivate** attr) { return SceResult(pthread_barrierattr_destroy_nid_postfix(attr)); } -int APS5_VABI scePthreadBarrierattrGetpshared(void* const* attr, int* pshared) { +int APS5_VABI scePthreadBarrierattrGetpshared(PthreadBarrierattrPrivate* const* attr, int* pshared) { return SceResult(pthread_barrierattr_getpshared_nid_postfix(attr, pshared)); } -int APS5_VABI scePthreadBarrierattrInit(void** attr) { +int APS5_VABI scePthreadBarrierattrInit(PthreadBarrierattrPrivate** attr) { return SceResult(pthread_barrierattr_init_nid_postfix(attr)); } -int APS5_VABI scePthreadBarrierattrSetpshared(void** attr, int pshared) { +int APS5_VABI scePthreadBarrierattrSetpshared(PthreadBarrierattrPrivate** attr, int pshared) { return SceResult(pthread_barrierattr_setpshared_nid_postfix(attr, pshared)); } @@ -2201,7 +2162,7 @@ int APS5_VABI scePthreadGetconcurrency(void) { return pthread_getconcurrency_nid_postfix(); } -int APS5_VABI scePthreadGetcpuclockid(void* thread, int* clockId) { +int APS5_VABI scePthreadGetcpuclockid(Pthread thread, int* clockId) { return SceResult(pthread_getcpuclockid_nid_postfix(thread, clockId)); } @@ -2354,11 +2315,6 @@ int APS5_VABI statfs_nid_postfix(void) { return 0; } -int APS5_VABI swapcontext_nid_postfix(void) { - NotImplemented_nid_no_patch(__func__); - return 0; -} - int APS5_VABI swapon_nid_postfix(void) { NotImplemented_nid_no_patch(__func__); return 0; diff --git a/core/libs/prx/libkernel_sys/Export.cpp b/core/libs/prx/libkernel_sys/Export.cpp index 9710b77ff0..d14112e151 100644 --- a/core/libs/prx/libkernel_sys/Export.cpp +++ b/core/libs/prx/libkernel_sys/Export.cpp @@ -1,3 +1,6 @@ +#include "prx/libkernel_sys/include/Api.hpp" +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include #include #include @@ -30,7 +33,7 @@ #include "prx/libc/include/CreationMask.hpp" #include "prx/libkernel/File/include/FileFlags.hpp" #include "prx/libkernel/File/include/File.hpp" -extern "C" int APS5_VABI getpid_nid_postfix(void); + #ifdef _WIN32 #ifndef NOMINMAX #define NOMINMAX @@ -44,9 +47,6 @@ extern "C" int APS5_VABI getpid_nid_postfix(void); #endif #endif -extern "C" int* APS5_VABI __error_nid_postfix(); -extern "C" int APS5_VABI getpid_nid_postfix(); - namespace { #ifdef _WIN32 extern "C" _invalid_parameter_handler _set_thread_local_invalid_parameter_handler(_invalid_parameter_handler); @@ -163,6 +163,12 @@ std::int64_t PathConfigurationValue(int name, const char* function) { } } +int CopyPath(const char*& path, std::string& copy) { + if (const int error = CopyGuestPath_nid_no_patch(path, copy)) return error; + path = copy.c_str(); + return copy.empty() ? GuestEnoent : 0; +} + int GuestError(const std::error_code& error) { const auto condition = error.default_error_condition(); if (condition == std::errc::resource_unavailable_try_again) return GuestEagain; @@ -336,14 +342,11 @@ std::int64_t APS5_VABI pwrite_nid_postfix(int d, const void* buf, std::size_t nb return PosixPwrite_nid_no_patch(d, buf, nbytes, offset); } -int APS5_VABI _fstatfs_nid_postfix(int d, void* buf); - -int APS5_VABI fstatfs_nid_postfix(int d, void* buf) { +int APS5_VABI fstatfs_nid_postfix(int d, KernelStatfs* buf) { return _fstatfs_nid_postfix(d, buf); } int GetModuleInfoExByHandle_nid_no_patch(KernelModule handle, ModuleInfoEx* info); -int APS5_VABI sceKernelGetModuleList(KernelModule* handles, std::size_t count, std::size_t* actual); int APS5_VABI sceKernelGetModuleInfoInternal(KernelModule handle, ModuleInfoEx* info) { return GetModuleInfoExByHandle_nid_no_patch(handle, info); @@ -353,16 +356,14 @@ int APS5_VABI sceKernelGetModuleListInternal(KernelModule* handles, std::size_t return sceKernelGetModuleList(handles, count, actual); } -std::int64_t APS5_VABI _fstat_nid_postfix(int d, FileStat* sb); - int APS5_VABI fstat_nid_postfix(int d, FileStat* sb) { return static_cast(_fstat_nid_postfix(d, sb)); } std::int64_t APS5_VABI readlink_nid_postfix(const char* path, char* buffer, std::size_t size) { if (size > static_cast(std::numeric_limits::max())) return Fail(GuestEinval); - if (path == nullptr) return Fail(GuestEfault); - if (*path == '\0') return Fail(GuestEnoent); + std::string copy; + if (const int error = CopyPath(path, copy)) return Fail(error); std::filesystem::path native; if (const int error = ResolvePathError_nid_no_patch(path, native)) return Fail(error); return ReadNativeLink(native, buffer, size); @@ -370,8 +371,8 @@ std::int64_t APS5_VABI readlink_nid_postfix(const char* path, char* buffer, std: std::int64_t APS5_VABI readlinkat_nid_postfix(int fd, const char* path, char* buffer, std::size_t size) { if (size > static_cast(std::numeric_limits::max())) return Fail(GuestEinval); - if (path == nullptr) return Fail(GuestEfault); - if (*path == '\0') return Fail(GuestEnoent); + std::string copy; + if (const int error = CopyPath(path, copy)) return Fail(error); if (fd == GuestAtFdcwd || *path == '/') return readlink_nid_postfix(path, buffer, size); int error = 0; const char* base = GetDirectoryDescriptorPath_nid_no_patch(fd, &error); @@ -381,8 +382,8 @@ std::int64_t APS5_VABI readlinkat_nid_postfix(int fd, const char* path, char* bu } std::int64_t APS5_VABI pathconf_nid_postfix(const char* path, int name) { - if (path == nullptr) return Fail(GuestEfault); - if (*path == '\0') return Fail(GuestEnoent); + std::string copy; + if (const int error = CopyPath(path, copy)) return Fail(error); if (std::strlen(path) >= GuestPathMax || HasLongComponent(path)) return Fail(GuestEnametoolong); std::filesystem::path native; if (const int error = ResolvePathError_nid_no_patch(path, native)) return Fail(error); @@ -441,22 +442,21 @@ static int FollowLinkPath(const std::filesystem::path& source, std::filesystem:: } #endif -int APS5_VABI link_nid_postfix(const char* existing, const char* created) { - if (existing == nullptr || created == nullptr) return static_cast(Fail(GuestEfault)); - if (*existing == '\0' || *created == '\0') return static_cast(Fail(GuestEnoent)); - std::filesystem::path source, destination; - if (const int error = ResolvePathError_nid_no_patch(existing, source)) return static_cast(Fail(error)); - if (const int error = ResolvePathError_nid_no_patch(created, destination)) return static_cast(Fail(error)); +static int LinkSourceError(const std::filesystem::path& source) { std::error_code error; const auto status = std::filesystem::status(source, error); if (!std::filesystem::exists(status)) { #ifdef _WIN32 std::filesystem::path target; - if (const int followError = FollowLinkPath(source, target)) return static_cast(Fail(followError)); + if (const int followError = FollowLinkPath(source, target)) return followError; #endif - return static_cast(Fail(HasNonDirectoryPrefix(source) ? GuestEnotdir : GuestEnoent)); + return HasNonDirectoryPrefix(source) ? GuestEnotdir : GuestEnoent; } - if (std::filesystem::is_directory(status)) return static_cast(Fail(GuestEperm)); + return std::filesystem::is_directory(status) ? GuestEperm : 0; +} + +static int LinkNative(const std::filesystem::path& source, const std::filesystem::path& destination) { + std::error_code error; if (std::filesystem::exists(std::filesystem::symlink_status(destination, error))) return static_cast(Fail(GuestEexist)); if (!std::filesystem::is_directory(destination.parent_path(), error)) return static_cast(Fail(HasNonDirectoryPrefix(destination) ? GuestEnotdir : GuestEnoent)); #ifdef _WIN32 @@ -473,15 +473,38 @@ int APS5_VABI link_nid_postfix(const char* existing, const char* created) { return 0; } +int APS5_VABI link_nid_postfix(const char* existing, const char* created) { + std::string existingCopy, createdCopy; + if (const int error = CopyPath(existing, existingCopy)) return static_cast(Fail(error)); + std::filesystem::path source, destination; + if (const int error = ResolvePathError_nid_no_patch(existing, source)) return static_cast(Fail(error)); + if (const int error = LinkSourceError(source)) return static_cast(Fail(error)); + if (const int error = CopyPath(created, createdCopy)) return static_cast(Fail(error)); + if (const int error = ResolvePathError_nid_no_patch(created, destination)) return static_cast(Fail(error)); + return LinkNative(source, destination); +} + +static int ResolveAtPath(int fd, const char* path, std::filesystem::path& native) { + if (fd == GuestAtFdcwd || *path == '/') return ResolvePathError_nid_no_patch(path, native); + if (std::strlen(path) >= GuestPathMax || HasLongComponent(path)) return GuestEnametoolong; + int error = 0; + const char* base = GetDirectoryDescriptorPath_nid_no_patch(fd, &error); + if (base == nullptr) return error; + native = std::filesystem::path(reinterpret_cast(base)) / std::filesystem::path(reinterpret_cast(path)); + return 0; +} + int APS5_VABI linkat_nid_postfix(int fd1, const char* path1, int fd2, const char* path2, int flag) { if (flag & ~GuestAtSymlinkFollow) return static_cast(Fail(GuestEinval)); - if (path1 == nullptr || path2 == nullptr) return static_cast(Fail(GuestEfault)); - if ((fd1 != GuestAtFdcwd && *path1 != '/') || (fd2 != GuestAtFdcwd && *path2 != '/')) - NotImplemented_nid_no_patch("linkat: a relative path with a directory descriptor"); - std::filesystem::path source; - if (flag == 0 && *path1 != '\0' && ResolvePathError_nid_no_patch(path1, source) == 0 && IsSymbolicLink(source)) - NotImplemented_nid_no_patch("linkat: a hard link to a symbolic link itself"); - return link_nid_postfix(path1, path2); + std::string copy1, copy2; + if (const int error = CopyPath(path1, copy1)) return static_cast(Fail(error)); + std::filesystem::path source, destination; + if (const int error = ResolveAtPath(fd1, path1, source)) return static_cast(Fail(error)); + if (flag == 0 && IsSymbolicLink(source)) NotImplemented_nid_no_patch("linkat: a hard link to a symbolic link itself"); + if (const int error = LinkSourceError(source)) return static_cast(Fail(error)); + if (const int error = CopyPath(path2, copy2)) return static_cast(Fail(error)); + if (const int error = ResolveAtPath(fd2, path2, destination)) return static_cast(Fail(error)); + return LinkNative(source, destination); } int APS5_VABI fchdir_nid_postfix(int fd) { @@ -498,8 +521,8 @@ int APS5_VABI fchdir_nid_postfix(int fd) { } int APS5_VABI chroot_nid_postfix(const char* path) { - if (path == nullptr) return static_cast(Fail(GuestEfault)); - if (*path == '\0') return static_cast(Fail(GuestEnoent)); + std::string copy; + if (const int error = CopyPath(path, copy)) return static_cast(Fail(error)); if (std::strlen(path) >= GuestPathMax || HasLongComponent(path)) return static_cast(Fail(GuestEnametoolong)); std::filesystem::path native; if (const int error = ResolvePathError_nid_no_patch(path, native)) return static_cast(Fail(error)); @@ -515,9 +538,9 @@ int APS5_VABI chroot_nid_postfix(const char* path) { } int APS5_VABI symlink_nid_postfix(const char* target, const char* created) { - if (target == nullptr || created == nullptr) return static_cast(Fail(GuestEfault)); - if (std::strlen(target) >= GuestPathMax) return static_cast(Fail(GuestEnametoolong)); - if (*target == '\0' || *created == '\0') return static_cast(Fail(GuestEnoent)); + std::string targetCopy, createdCopy; + if (const int error = CopyPath(target, targetCopy)) return static_cast(Fail(error)); + if (const int error = CopyPath(created, createdCopy)) return static_cast(Fail(error)); const std::filesystem::path contents(target); if (contents.has_root_name() || contents.has_root_directory()) { NotImplemented_nid_no_patch("symlink: absolute targets"); @@ -560,8 +583,6 @@ int APS5_VABI symlink_nid_postfix(const char* target, const char* created) { return 0; } -int APS5_VABI open_nid_postfix(const char* path, int flags, int mode); - int APS5_VABI openat_nid_postfix(int fd, const char* path, int flags, ...) { int mode = 0; if (flags & SCE_KERNEL_O_CREAT) { @@ -578,8 +599,8 @@ int APS5_VABI openat_nid_postfix(int fd, const char* path, int flags, ...) { #endif } if (File::InvalidOpenFlags(flags)) return static_cast(Fail(GuestEinval)); - if (path == nullptr) return static_cast(Fail(GuestEfault)); - if (*path == '\0') return static_cast(Fail(GuestEnoent)); + std::string copy; + if (const int error = CopyPath(path, copy)) return static_cast(Fail(error)); if (fd == GuestAtFdcwd || *path == '/') return open_nid_postfix(path, flags, mode); const int result = OpenInDirectory_nid_no_patch(fd, path, flags, static_cast(mode)); if (result < 0) return static_cast(Fail(result & 0xffff)); @@ -604,11 +625,10 @@ int APS5_VABI _openat_nid_postfix(int fd, const char* path, int flags, ...) { return openat_nid_postfix(fd, path, flags, mode); } -int APS5_VABI mkdir_nid_postfix(const char* path, std::uint16_t mode); int APS5_VABI mkdirat_nid_postfix(int fd, const char* path, std::uint16_t mode) { - if (path == nullptr) return static_cast(Fail(GuestEfault)); - if (*path == '\0') return static_cast(Fail(GuestEnoent)); + std::string copy; + if (const int error = CopyPath(path, copy)) return static_cast(Fail(error)); if (fd == GuestAtFdcwd || *path == '/') return mkdir_nid_postfix(path, mode); if (std::strlen(path) >= GuestPathMax || HasLongComponent(path)) return static_cast(Fail(GuestEnametoolong)); int error = 0; @@ -644,8 +664,8 @@ int APS5_VABI mkdirat_nid_postfix(int fd, const char* path, std::uint16_t mode) int APS5_VABI fchmodat_nid_postfix(int fd, const char* path, int mode, int flag) { if (flag != 0 && flag != GuestAtSymlinkNofollow) return static_cast(Fail(GuestEinval)); - if (path == nullptr) return static_cast(Fail(GuestEfault)); - if (*path == '\0') return static_cast(Fail(GuestEnoent)); + std::string copy; + if (const int error = CopyPath(path, copy)) return static_cast(Fail(error)); std::filesystem::path native; if (fd == GuestAtFdcwd || *path == '/') { if (const int error = ResolvePathError_nid_no_patch(path, native)) return static_cast(Fail(error)); @@ -683,9 +703,13 @@ int APS5_VABI fchmodat_nid_postfix(int fd, const char* path, int mode, int flag) } int APS5_VABI lchmod_nid_postfix(const char* path, std::uint16_t mode) { + std::string copy; + if (path != nullptr) { + if (const int error = CopyPath(path, copy)) return static_cast(Fail(error)); + } #ifndef __APPLE__ std::filesystem::path native; - if (path != nullptr && *path != '\0' && ResolvePathError_nid_no_patch(path, native) == 0) { + if (path != nullptr && ResolvePathError_nid_no_patch(path, native) == 0) { #ifdef _WIN32 const DWORD attributes = GetFileAttributesW(native.wstring().c_str()); const bool symbolic = attributes != INVALID_FILE_ATTRIBUTES && (attributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0; @@ -722,10 +746,6 @@ int APS5_VABI sched_rr_get_interval_nid_postfix(int pid, KernelTimespec* interva return 0; } -int APS5_VABI stat_nid_postfix(const char* path, FileStat* sb); -int APS5_VABI lstat_nid_postfix(const char* path, FileStat* sb); -int APS5_VABI fstatat_nid_postfix(int fd, const char* path, FileStat* sb, int flag); - int APS5_VABI chown_nid_postfix(const char* path, std::uint32_t uid, std::uint32_t gid) { FileStat status{}; if (stat_nid_postfix(path, &status) != 0) return -1; @@ -750,21 +770,18 @@ int APS5_VABI fchownat_nid_postfix(int fd, const char* path, std::uint32_t uid, int APS5_VABI fstatat_nid_postfix(int fd, const char* path, FileStat* sb, int flag) { if (flag & ~GuestAtSymlinkNofollow) return static_cast(Fail(GuestEinval)); - if (path == nullptr) return static_cast(Fail(GuestEfault)); - if (*path == '\0') return static_cast(Fail(GuestEnoent)); + std::string copy; + if (const int error = CopyPath(path, copy)) return static_cast(Fail(error)); if (fd == GuestAtFdcwd || *path == '/') return flag ? lstat_nid_postfix(path, sb) : stat_nid_postfix(path, sb); const int result = StatInDirectory_nid_no_patch(fd, path, sb, flag == 0); if (result < 0) return static_cast(Fail(result & 0xffff)); return 0; } -int APS5_VABI unlink_nid_postfix(const char* path); -int APS5_VABI rmdir_nid_postfix(const char* path); - int APS5_VABI unlinkat_nid_postfix(int fd, const char* path, int flag) { if (flag & ~GuestAtRemovedir) return static_cast(Fail(GuestEinval)); - if (path == nullptr) return static_cast(Fail(GuestEfault)); - if (*path == '\0') return static_cast(Fail(GuestEnoent)); + std::string copy; + if (const int error = CopyPath(path, copy)) return static_cast(Fail(error)); if (fd == GuestAtFdcwd || *path == '/') return (flag & GuestAtRemovedir) ? rmdir_nid_postfix(path) : unlink_nid_postfix(path); if (std::strlen(path) >= GuestPathMax || HasLongComponent(path)) return static_cast(Fail(GuestEnametoolong)); int error = 0; @@ -840,14 +857,13 @@ int APS5_VABI scePthreadCondattrGetclock(const PthreadCondattr* attr, KernelCloc } int APS5_VABI renameat_nid_postfix(int oldfd, const char* from, int newfd, const char* to) { - if (from == nullptr || to == nullptr) return static_cast(Fail(GuestEfault)); - if (*from == '\0' || *to == '\0') return static_cast(Fail(GuestEnoent)); - if ((oldfd == GuestAtFdcwd || *from == '/') && (newfd == GuestAtFdcwd || *to == '/')) + std::string fromCopy, toCopy; + if (const int error = CopyPath(from, fromCopy)) return static_cast(Fail(error)); + if ((oldfd == GuestAtFdcwd || *from == '/') && newfd == GuestAtFdcwd) return RenameGuestPath_nid_no_patch(from, to); - if (std::strlen(from) >= GuestPathMax || HasLongComponent(from) || - std::strlen(to) >= GuestPathMax || HasLongComponent(to)) + if (std::strlen(from) >= GuestPathMax || HasLongComponent(from)) return static_cast(Fail(GuestEnametoolong)); - if (IsDotOrDotDot(from) || IsDotOrDotDot(to)) return static_cast(Fail(GuestEinval)); + if (IsDotOrDotDot(from)) return static_cast(Fail(GuestEinval)); std::filesystem::path source; if (oldfd == GuestAtFdcwd || *from == '/') { @@ -859,6 +875,20 @@ int APS5_VABI renameat_nid_postfix(int oldfd, const char* from, int newfd, const source = std::filesystem::path(reinterpret_cast(base)) / std::filesystem::path(reinterpret_cast(from)); } + const std::string_view fromView(from); + const bool oldTrailingSlash = !fromView.empty() && fromView.back() == '/'; + while (!source.has_filename() && source.has_relative_path()) source = source.parent_path(); + std::error_code statusError; + const auto sourceStatus = std::filesystem::symlink_status(source, statusError); + if (statusError && statusError != std::errc::no_such_file_or_directory) + return static_cast(Fail(FilesystemError(statusError))); + if (sourceStatus.type() == std::filesystem::file_type::not_found) + return static_cast(Fail(HasNonDirectoryPrefix(source) ? GuestEnotdir : GuestEnoent)); + if (oldTrailingSlash && !std::filesystem::is_directory(sourceStatus)) return static_cast(Fail(GuestEnotdir)); + + if (const int error = CopyPath(to, toCopy)) return static_cast(Fail(error)); + if (std::strlen(to) >= GuestPathMax || HasLongComponent(to)) return static_cast(Fail(GuestEnametoolong)); + if (IsDotOrDotDot(to)) return static_cast(Fail(GuestEinval)); std::filesystem::path destination; if (newfd == GuestAtFdcwd || *to == '/') { @@ -871,21 +901,11 @@ int APS5_VABI renameat_nid_postfix(int oldfd, const char* from, int newfd, const std::filesystem::path(reinterpret_cast(to)); } - const std::string_view fromView(from); const std::string_view toView(to); - const bool oldTrailingSlash = !fromView.empty() && fromView.back() == '/'; const bool newTrailingSlash = !toView.empty() && toView.back() == '/'; - while (!source.has_filename() && source.has_relative_path()) source = source.parent_path(); while (!destination.has_filename() && destination.has_relative_path()) destination = destination.parent_path(); - std::error_code statusError; - const auto sourceStatus = std::filesystem::symlink_status(source, statusError); - if (oldTrailingSlash) { - if (sourceStatus.type() == std::filesystem::file_type::not_found) - return static_cast(Fail(HasNonDirectoryPrefix(source) ? GuestEnotdir : GuestEnoent)); - if (!std::filesystem::is_directory(sourceStatus)) return static_cast(Fail(GuestEnotdir)); - } if (newTrailingSlash && sourceStatus.type() != std::filesystem::file_type::not_found && !std::filesystem::is_directory(sourceStatus)) return static_cast(Fail(GuestEnotdir)); @@ -897,9 +917,7 @@ int APS5_VABI renameat_nid_postfix(int oldfd, const char* from, int newfd, const return 0; } - bool SetDefaultStackSize_nid_no_patch(std::size_t size); -void APS5_VABI pthread_set_name_np_nid_postfix(void* thread, const char* name); int APS5_VABI pthread_set_defaultstacksize_np_nid_postfix(std::size_t size) { return SetDefaultStackSize_nid_no_patch(size) ? 0 : GuestEinval; @@ -909,15 +927,10 @@ int APS5_VABI scePthreadSetDefaultstacksize(std::size_t size) { return SetDefaultStackSize_nid_no_patch(size) ? 0 : SceKernelError(GuestEinval); } -void APS5_VABI scePthreadSetName(void* thread, const char* name) { +void APS5_VABI scePthreadSetName(Pthread thread, const char* name) { pthread_set_name_np_nid_postfix(thread, name); -} -struct KernelTitleWorkaround { - std::int32_t version; - std::int32_t align; - std::uint64_t ids[2]; -}; +} int APS5_VABI sceKernelTitleWorkaroundIsEnabled(const KernelTitleWorkaround* workaround, std::int32_t bit, std::int32_t* enabled) { if (!workaround || !enabled) return static_cast(0x8002000E); diff --git a/core/libs/prx/libkernel_sys/ThreadQueries.cpp b/core/libs/prx/libkernel_sys/ThreadQueries.cpp new file mode 100644 index 0000000000..6bdc835871 --- /dev/null +++ b/core/libs/prx/libkernel_sys/ThreadQueries.cpp @@ -0,0 +1,10 @@ +#include "prx/libc/include/general/VabiMacros.hpp" + +extern "C" { +bool IsInitialPthread_nid_no_patch(); + +int APS5_VABI pthread_main_np_nid_postfix() { + return IsInitialPthread_nid_no_patch() ? 1 : 0; +} + +} diff --git a/core/libs/prx/libkernel_sys/include/Api.hpp b/core/libs/prx/libkernel_sys/include/Api.hpp new file mode 100644 index 0000000000..2ae044df95 --- /dev/null +++ b/core/libs/prx/libkernel_sys/include/Api.hpp @@ -0,0 +1,561 @@ +#pragma once + +#include "prx/libkernel/include/Api.hpp" +#include "SceTypes.hpp" + +struct GuestAiocb { + int fildes; + std::int64_t offset; + void* buf; + std::uint64_t nbytes; + int spare[2]; + void* spare2; + int lioOpcode; + int reqprio; + std::int64_t status; + std::int64_t error; + void* kernelinfo; + GuestSigevent sigevent; +}; + +struct KernelTitleWorkaround { + std::int32_t version; + std::int32_t align; + std::uint64_t ids[2]; +}; + +extern "C" { + +int APS5_VABI aio_read_nid_postfix(GuestAiocb* aiocb); +int APS5_VABI aio_write_nid_postfix(GuestAiocb* aiocb); +int APS5_VABI aio_fsync_nid_postfix(int operation, GuestAiocb* aiocb); +int APS5_VABI aio_error_nid_postfix(const GuestAiocb* aiocb); +std::int64_t APS5_VABI aio_return_nid_postfix(GuestAiocb* aiocb); +int APS5_VABI aio_suspend_nid_postfix(const GuestAiocb* const* list, int count, const KernelTimespec* timeout); +std::int64_t APS5_VABI aio_waitcomplete_nid_postfix(GuestAiocb** result, const KernelTimespec* timeout); +int APS5_VABI aio_cancel_nid_postfix(int descriptor, GuestAiocb* aiocb); +int APS5_VABI sceKernelGetCompiledSdkVersion(std::int32_t* version); +int APS5_VABI fork_nid_postfix(void); +int APS5_VABI setsid_nid_postfix(void); +std::uint16_t APS5_VABI umask_nid_postfix(std::uint16_t mask); +int APS5_VABI fstatfs_nid_postfix(int d, KernelStatfs* buf); +int APS5_VABI sceKernelGetModuleInfoInternal(KernelModule handle, ModuleInfoEx* info); +int APS5_VABI sceKernelGetModuleListInternal(KernelModule* handles, std::size_t count, std::size_t* actual); +int APS5_VABI fstat_nid_postfix(int d, FileStat* sb); +std::int64_t APS5_VABI readlink_nid_postfix(const char* path, char* buffer, std::size_t size); +std::int64_t APS5_VABI readlinkat_nid_postfix(int fd, const char* path, char* buffer, std::size_t size); +std::int64_t APS5_VABI pathconf_nid_postfix(const char* path, int name); +std::int64_t APS5_VABI _fpathconf_nid_postfix(int fd, int name); +std::int64_t APS5_VABI fpathconf_nid_postfix(int fd, int name); +int APS5_VABI link_nid_postfix(const char* existing, const char* created); +int APS5_VABI linkat_nid_postfix(int fd1, const char* path1, int fd2, const char* path2, int flag); +int APS5_VABI fchdir_nid_postfix(int fd); +int APS5_VABI chroot_nid_postfix(const char* path); +int APS5_VABI symlink_nid_postfix(const char* target, const char* created); +int APS5_VABI openat_nid_postfix(int fd, const char* path, int flags, ...); +int APS5_VABI mkdirat_nid_postfix(int fd, const char* path, std::uint16_t mode); +int APS5_VABI fchmodat_nid_postfix(int fd, const char* path, int mode, int flag); +int APS5_VABI lchmod_nid_postfix(const char* path, std::uint16_t mode); +int APS5_VABI fchown_nid_postfix(int fd, std::uint32_t uid, std::uint32_t gid); +int APS5_VABI sched_rr_get_interval_nid_postfix(int pid, KernelTimespec* interval); +int APS5_VABI chown_nid_postfix(const char* path, std::uint32_t uid, std::uint32_t gid); +int APS5_VABI lchown_nid_postfix(const char* path, std::uint32_t uid, std::uint32_t gid); +int APS5_VABI fchownat_nid_postfix(int fd, const char* path, std::uint32_t uid, std::uint32_t gid, int flag); +int APS5_VABI fstatat_nid_postfix(int fd, const char* path, FileStat* sb, int flag); +int APS5_VABI unlinkat_nid_postfix(int fd, const char* path, int flag); +int APS5_VABI scePthreadCondattrGetclock(const PthreadCondattr* attr, KernelClockid* clockId); +int APS5_VABI renameat_nid_postfix(int oldfd, const char* from, int newfd, const char* to); +int APS5_VABI pthread_set_defaultstacksize_np_nid_postfix(std::size_t size); +int APS5_VABI scePthreadSetDefaultstacksize(std::size_t size); +void APS5_VABI scePthreadSetName(Pthread thread, const char* name); +int APS5_VABI sceKernelTitleWorkaroundIsEnabled(const KernelTitleWorkaround* workaround, std::int32_t bit, std::int32_t* enabled); +int APS5_VABI sceKernelGetProcessType(int pid); +int APS5_VABI amd64_set_fsbase_nid_postfix(void); +int APS5_VABI blockpool_batch_nid_postfix(void); +int APS5_VABI blockpool_map_nid_postfix(void); +int APS5_VABI blockpool_open_nid_postfix(void); +int APS5_VABI blockpool_unmap_nid_postfix(void); +int APS5_VABI cpuset_nid_postfix(void); +int APS5_VABI cpuset_getid_nid_postfix(void); +int APS5_VABI cpuset_setid_nid_postfix(void); +int APS5_VABI dynlib_get_obj_member_nid_postfix(void); +int APS5_VABI futimesat_nid_postfix(void); +int APS5_VABI get_authinfo_nid_postfix(void); +int APS5_VABI get_module_info_list_nid_postfix(void); +int APS5_VABI get_page_table_stats_nid_postfix(void); +int APS5_VABI get_sdk_compiled_version_nid_postfix(void); +int APS5_VABI get_self_auth_info_nid_postfix(void); +int APS5_VABI get_vm_map_timestamp_nid_postfix(void); +int APS5_VABI getfsstat_nid_postfix(void); +int APS5_VABI getlogin_nid_postfix(void); +int APS5_VABI ipmimgr_call_nid_postfix(void); +int APS5_VABI is_in_sandbox_nid_postfix(void); +int APS5_VABI kenv_nid_postfix(void); +int APS5_VABI kldfind_nid_postfix(void); +int APS5_VABI kldfirstmod_nid_postfix(void); +int APS5_VABI kldload_nid_postfix(void); +int APS5_VABI kldnext_nid_postfix(void); +int APS5_VABI kldstat_nid_postfix(void); +int APS5_VABI kldsym_nid_postfix(void); +int APS5_VABI kldunload_nid_postfix(void); +int APS5_VABI kmq_notify_nid_postfix(void); +int APS5_VABI kmq_open_nid_postfix(void); +int APS5_VABI kmq_setattr_nid_postfix(void); +int APS5_VABI kmq_timedreceive_nid_postfix(void); +int APS5_VABI kmq_timedsend_nid_postfix(void); +int APS5_VABI kmq_unlink_nid_postfix(void); +int APS5_VABI ksem_close_nid_postfix(void); +int APS5_VABI ksem_destroy_nid_postfix(void); +int APS5_VABI ksem_getvalue_nid_postfix(void); +int APS5_VABI ksem_init_nid_postfix(void); +int APS5_VABI ksem_open_nid_postfix(void); +int APS5_VABI ksem_post_nid_postfix(void); +int APS5_VABI ksem_timedwait_nid_postfix(void); +int APS5_VABI ksem_trywait_nid_postfix(void); +int APS5_VABI ksem_unlink_nid_postfix(void); +int APS5_VABI ksem_wait_nid_postfix(void); +int APS5_VABI ktrace_nid_postfix(void); +int APS5_VABI lchflags_nid_postfix(void); +int APS5_VABI mdbg_call_nid_postfix(void); +int APS5_VABI mdbg_service_nid_postfix(void); +int APS5_VABI mount_nid_postfix(void); +int APS5_VABI openintr_nid_postfix(void); +int APS5_VABI profil_nid_postfix(void); +int APS5_VABI pthread_attr_getaffinity_np_nid_postfix(void); +int APS5_VABI pthread_attr_getsolosched_np_nid_postfix(void); +int APS5_VABI pthread_attr_setaffinity_np_nid_postfix(void); +int APS5_VABI pthread_attr_setcreatesuspend_np_nid_postfix(void); +int APS5_VABI pthread_attr_setstackaddr_nid_postfix(void); +int APS5_VABI pthread_barrier_setname_np_nid_postfix(void); +int APS5_VABI pthread_cond_setname_np_nid_postfix(void); +int APS5_VABI pthread_get_specificarray_np_nid_postfix(void); +int APS5_VABI pthread_get_user_context_np_nid_postfix(void); +int APS5_VABI pthread_getstack_np_nid_postfix(void); +int APS5_VABI pthread_main_np_nid_postfix(void); +int APS5_VABI pthread_multi_np_nid_postfix(void); +int APS5_VABI pthread_mutex_getprioceiling_nid_postfix(void); +int APS5_VABI pthread_mutex_init_for_mono_nid_postfix(void); +int APS5_VABI pthread_mutex_setname_np_nid_postfix(void); +int APS5_VABI pthread_mutex_setprioceiling_nid_postfix(void); +int APS5_VABI pthread_mutexattr_getgen_np_nid_postfix(void); +int APS5_VABI pthread_mutexattr_setgen_np_nid_postfix(void); +int APS5_VABI pthread_resume_all_np_nid_postfix(void); +int APS5_VABI pthread_resume_np_nid_postfix(void); +int APS5_VABI pthread_resume_user_context_np_nid_postfix(void); +int APS5_VABI pthread_rwlock_setname_np_nid_postfix(void); +int APS5_VABI pthread_rwlockattr_settype_np_nid_postfix(void); +int APS5_VABI pthread_set_user_context_np_nid_postfix(void); +int APS5_VABI pthread_single_np_nid_postfix(void); +int APS5_VABI pthread_suspend_all_np_nid_postfix(void); +int APS5_VABI pthread_suspend_np_nid_postfix(void); +int APS5_VABI pthread_suspend_user_context_np_nid_postfix(void); +int APS5_VABI pthread_switch_add_np_nid_postfix(void); +int APS5_VABI pthread_switch_delete_np_nid_postfix(void); +int APS5_VABI ptrace_nid_postfix(void); +std::int64_t APS5_VABI pwrite_nid_postfix(int d, const void* buf, std::size_t nbytes, std::int64_t offset); +int APS5_VABI reboot_nid_postfix(void); +int APS5_VABI revoke_nid_postfix(void); +int APS5_VABI rfork_thread_nid_postfix(void); +int APS5_VABI rtld_printf_nid_postfix(void); +int APS5_VABI sceCoredumpDebugForceCoredumpOnAppClose(void); +int APS5_VABI sceCoredumpDebugTriggerCoredump(void); +int APS5_VABI sceCoredumpGetStopInfoGpu(void); +int APS5_VABI sceCoredumpInternalGetThreadContextInfo(void); +int APS5_VABI sceKernelAddACInfo(void); +int APS5_VABI sceKernelAddCpumodeEvent(void); +int APS5_VABI sceKernelAddGpuExceptionEvent(void); +int APS5_VABI sceKernelAddProcessToCanvasMap(void); +int APS5_VABI sceKernelAddResource(void); +int APS5_VABI sceKernelAllocateDirectMemory2(void); +int APS5_VABI sceKernelAllocateDirectMemoryForApp(void); +int APS5_VABI sceKernelAllocateDirectMemoryForMiniApp(void); +int APS5_VABI sceKernelAllocateToolMemory(void); +int APS5_VABI sceKernelAllocateTraceDirectMemory(void); +int APS5_VABI sceKernelAprCtrl(void); +int APS5_VABI sceKernelAprSubmitCommandBufferAndGetResult_TEST(void); +int APS5_VABI sceKernelAprSubmitCommandBuffer_TEST(void); +int APS5_VABI sceKernelAvailableToolMemorySize(void); +int APS5_VABI sceKernelBacktraceSelf(void); +int APS5_VABI sceKernelBeginAppMount(void); +int APS5_VABI sceKernelBeginAppMount2(void); +int APS5_VABI sceKernelCallIndirectBuffer(void); +int APS5_VABI sceKernelCallIndirectBuffer2(void); +int APS5_VABI sceKernelClearBootReqNotifyCount(void); +int APS5_VABI sceKernelClearGameDirectMemory(void); +int APS5_VABI sceKernelCloseEport(void); +int APS5_VABI sceKernelCloseSema(void); +int APS5_VABI sceKernelCreateBudget(void); +int APS5_VABI sceKernelCreateEport(void); +int APS5_VABI sceKernelDebugAcquireAndUpdateDebugRegister(void); +int APS5_VABI sceKernelDebugGetAppStatus(void); +int APS5_VABI sceKernelDebugGetPauseCount(void); +int APS5_VABI sceKernelDebugGetPrivateLogText(void); +int APS5_VABI sceKernelDebugGetSchedLockMode(void); +int APS5_VABI sceKernelDebugGetSdkLogText(void); +int APS5_VABI sceKernelDebugGpuPaDebugIsInProgress(void); +int APS5_VABI sceKernelDebugInjectProcessEvent(void); +int APS5_VABI sceKernelDebugPackageCorrupted(void); +int APS5_VABI sceKernelDebugRaiseExceptionWithContext(void); +int APS5_VABI sceKernelDebugRaiseExceptionWithInfo(void); +int APS5_VABI sceKernelDebugReleaseDebugContext(void); +int APS5_VABI sceKernelDeleteACInfo(void); +int APS5_VABI sceKernelDeleteBudget(void); +int APS5_VABI sceKernelDeleteCpumodeEvent(void); +int APS5_VABI sceKernelDeleteEport(void); +int APS5_VABI sceKernelDeleteGpuExceptionEvent(void); +int APS5_VABI sceKernelDeleteProcessFromCanvasMap(void); +int APS5_VABI sceKernelDeleteSavedApp(void); +int APS5_VABI sceKernelDirectMemoryQueryForId(void); +int APS5_VABI sceKernelEnableDmemAliasing2(void); +int APS5_VABI sceKernelEnablePthreadObjectCheck(void); +int APS5_VABI sceKernelEndAppMount(void); +int APS5_VABI sceKernelEndAppMount2(void); +int APS5_VABI sceKernelEventLogInit(void); +int APS5_VABI sceKernelEventLogPread(void); +int APS5_VABI sceKernelEventLogRead(void); +int APS5_VABI sceKernelEventLogWrite(void); +int APS5_VABI sceKernelExpectedHddFormat(void); +int APS5_VABI sceKernelFlock(void); +int APS5_VABI sceKernelGetACInfoAllForCoredump(void); +int APS5_VABI sceKernelGetAppCategoryType(void); +int APS5_VABI sceKernelGetAppInfoByAppId(void); +int APS5_VABI sceKernelGetAppState(void); +int APS5_VABI sceKernelGetAslrStatus(void); +int APS5_VABI sceKernelGetAutoUpdateVersion(void); +int APS5_VABI sceKernelGetBackupRestoreMode(void); +int APS5_VABI sceKernelGetBackupRestoreModeOfNextBoot(void); +int APS5_VABI sceKernelGetBasicProductShape(void); +int APS5_VABI sceKernelGetBetaUpdateTestForRcmgr(void); +int APS5_VABI sceKernelGetBioUsageAll(void); +int APS5_VABI sceKernelGetBootReqNotifyCount(void); +int APS5_VABI sceKernelGetBudget(void); +int APS5_VABI sceKernelGetBuildNumber(void); +int APS5_VABI sceKernelGetCallRecord(void); +int APS5_VABI sceKernelGetChildApp(void); +int APS5_VABI sceKernelGetCompiledSdkVersionByPath(void); +int APS5_VABI sceKernelGetCompiledSdkVersionByPid(void); +int APS5_VABI sceKernelGetCoredumpAppInfo(void); +int APS5_VABI sceKernelGetCpuUsage(void); +int APS5_VABI sceKernelGetCpuUsageAll(void); +int APS5_VABI sceKernelGetCpuUsageProc(void); +int APS5_VABI sceKernelGetCpuUsageProc2(void); +int APS5_VABI sceKernelGetCpuUsageThread(void); +int APS5_VABI sceKernelGetCpumodeGame(void); +int APS5_VABI sceKernelGetCurrentFanDuty(void); +int APS5_VABI sceKernelGetDataTransferMode(void); +int APS5_VABI sceKernelGetDebugMenuMiniModeForRcmgr(void); +int APS5_VABI sceKernelGetDebugMenuModeForPsmForRcmgr(void); +int APS5_VABI sceKernelGetDebugMenuModeForRcmgr(void); +int APS5_VABI sceKernelGetDefaultToolMemorySize(void); +int APS5_VABI sceKernelGetEmergencyErrorLog(void); +int APS5_VABI sceKernelGetExecutableModuleHandle(void); +int APS5_VABI sceKernelGetExtLibcHandle(void); +int APS5_VABI sceKernelGetFakeFinalizeMenuForRcmgr(void); +int APS5_VABI sceKernelGetFirstImageAddr(void); +int APS5_VABI sceKernelGetFlagedUpdaterForRcmgr(void); +int APS5_VABI sceKernelGetForceUpdateModeForRcmgr(void); +int APS5_VABI sceKernelGetGPO(void); +int APS5_VABI sceKernelGetHwFeatureInfoForDecid(void); +int APS5_VABI sceKernelGetHwModelName(void); +int APS5_VABI sceKernelGetHwSerialNumber(void); +int APS5_VABI sceKernelGetIdPs(void); +int APS5_VABI sceKernelGetIdTableCurrentCount(void); +int APS5_VABI sceKernelGetIoreq(void); +int APS5_VABI sceKernelGetIpcPath(void); +int APS5_VABI sceKernelGetKnobs(void); +int APS5_VABI sceKernelGetKqueueFromEqueue(void); +int APS5_VABI sceKernelGetMemoryPstate(void); +int APS5_VABI sceKernelGetOpenPsIdForSystem(void); +int APS5_VABI sceKernelGetPagingStatsOfAllObjects(void); +int APS5_VABI sceKernelGetPagingStatsOfAllThreads(void); +int APS5_VABI sceKernelGetParentApp(void); +int APS5_VABI sceKernelGetPhysPageSize(void); +int APS5_VABI sceKernelGetProcessName(void); +int APS5_VABI sceKernelGetProcessTypeOfBudget(void); +int APS5_VABI sceKernelGetProductCode(void); +int APS5_VABI sceKernelGetProductStr(void); +int APS5_VABI sceKernelGetPs4SystemSwVersion(void); +int APS5_VABI sceKernelGetPsmIntdevModeForRcmgr(void); +int APS5_VABI sceKernelGetPsnAccessTraceLogForRcmgr(void); +int APS5_VABI sceKernelGetQafExpirationTimeNotafterForRcmgr(void); +int APS5_VABI sceKernelGetQafExpirationTimeNotbeforeForRcmgr(void); +int APS5_VABI sceKernelGetQafGenerationForRcmgr(void); +int APS5_VABI sceKernelGetQafNameForRcmgr(void); +int APS5_VABI sceKernelGetRenderingMode(void); +int APS5_VABI sceKernelGetResidentCount(void); +int APS5_VABI sceKernelGetResidentFmemCount(void); +int APS5_VABI sceKernelGetResource(void); +int APS5_VABI sceKernelGetResourceLimit(void); +int APS5_VABI sceKernelGetResourceOne(void); +int APS5_VABI sceKernelGetSafemode(void); +int APS5_VABI sceKernelGetSanitizerMallocReplace(void); +int APS5_VABI sceKernelGetSanitizerNewReplace(void); +int APS5_VABI sceKernelGetSocClock(void); +int APS5_VABI sceKernelGetSpecialIForRcmgr(void); +int APS5_VABI sceKernelGetSubsysId(void); +int APS5_VABI sceKernelGetSubsysSubId(void); +int APS5_VABI sceKernelGetSystemLevelDebuggerModeForRcmgr(void); +int APS5_VABI sceKernelGetSystemSwBeta(void); +int APS5_VABI sceKernelGetThreadName(void); +int APS5_VABI sceKernelGetUniversalMode(void); +int APS5_VABI sceKernelGetUpdVersion(void); +int APS5_VABI sceKernelGetUtokenDataExecutionForRcmgr(void); +int APS5_VABI sceKernelGetUtokenExpirationTimeNotafterForRcmgr(void); +int APS5_VABI sceKernelGetUtokenExpirationTimeNotbeforeForRcmgr(void); +int APS5_VABI sceKernelGetUtokenFakeSharefactoryForRcmgr(void); +int APS5_VABI sceKernelGetUtokenFlagedUpdaterForRcmgr(void); +int APS5_VABI sceKernelGetUtokenNpEnvSwitchingForRcmgr(void); +int APS5_VABI sceKernelGetUtokenSaveDataRepairForRcmgr(void); +int APS5_VABI sceKernelGetUtokenStoreModeForRcmgr(void); +int APS5_VABI sceKernelGetUtokenUseSoftwagnerForAcmgr(void); +int APS5_VABI sceKernelGetUtokenUseSoftwagnerForRcmgr(void); +int APS5_VABI sceKernelGetUtokenWeakenedPortRestrictionForRcmgr(void); +int APS5_VABI sceKernelGetVrCaptureSize(void); +int APS5_VABI sceKernelGiveDirectMemoryToMapper(void); +int APS5_VABI sceKernelHasNeoMode(void); +int APS5_VABI sceKernelHwGetBdDriveInfo(void); +int APS5_VABI sceKernelHwHasOpticalOut(void); +int APS5_VABI sceKernelHwHasWlanBt(void); +int APS5_VABI sceKernelIccControlBDPowerState(void); +int APS5_VABI sceKernelIccControlUSBPowerState(void); +int APS5_VABI sceKernelIccGetBDPowerState(void); +int APS5_VABI sceKernelIccGetBootTimestamp(void); +int APS5_VABI sceKernelIccGetCPMode(void); +int APS5_VABI sceKernelIccGetCountTime(void); +int APS5_VABI sceKernelIccGetCpuInfoBit(void); +int APS5_VABI sceKernelIccGetErrLog(void); +int APS5_VABI sceKernelIccGetHwInfo(void); +int APS5_VABI sceKernelIccGetPowerNumberOfBootShutdown(void); +int APS5_VABI sceKernelIccGetPowerOperatingTime(void); +int APS5_VABI sceKernelIccGetPowerUpCause(void); +int APS5_VABI sceKernelIccGetSysEventLog(void); +int APS5_VABI sceKernelIccGetUSBPowerState(void); +int APS5_VABI sceKernelIccIndicatorBootDone(void); +int APS5_VABI sceKernelIccIndicatorShutdown(void); +int APS5_VABI sceKernelIccIndicatorStandby(void); +int APS5_VABI sceKernelIccIndicatorStandbyBoot(void); +int APS5_VABI sceKernelIccIndicatorStandbyShutdown(void); +int APS5_VABI sceKernelIccNotifyBootStatus(void); +int APS5_VABI sceKernelIccNvsFlush(void); +int APS5_VABI sceKernelIccReadPowerBootMessage(void); +int APS5_VABI sceKernelIccSetBuzzer(void); +int APS5_VABI sceKernelIccSetCPMode(void); +int APS5_VABI sceKernelIccSetCpuInfoBit(void); +int APS5_VABI sceKernelIccSetDownloadMode(void); +int APS5_VABI sceKernelInternalGetKmemStatistics(void); +int APS5_VABI sceKernelInternalGetMapStatistics(void); +int APS5_VABI sceKernelInternalHeapPrintBacktraceWithModuleInfo(void); +int APS5_VABI sceKernelInternalMapDirectMemory(void); +int APS5_VABI sceKernelInternalMapNamedDirectMemory(void); +int APS5_VABI sceKernelInternalResumeDirectMemoryRelease(void); +int APS5_VABI sceKernelInternalSuspendDirectMemoryRelease(void); +int APS5_VABI sceKernelIsAllowedToSelectDvdRegion(void); +int APS5_VABI sceKernelIsAuthenticNeo(void); +int APS5_VABI sceKernelIsCEX(void); +int APS5_VABI sceKernelIsDebuggerAttached(void); +int APS5_VABI sceKernelIsDevKit(void); +int APS5_VABI sceKernelIsExperimentalBeta(void); +int APS5_VABI sceKernelIsGenuineCEX(void); +int APS5_VABI sceKernelIsGenuineDevKit(void); +int APS5_VABI sceKernelIsGenuineKratosCex(void); +int APS5_VABI sceKernelIsGenuineN(void); +int APS5_VABI sceKernelIsGenuineTestKit(void); +int APS5_VABI sceKernelIsInSandbox(void); +int APS5_VABI sceKernelIsKratos(void); +int APS5_VABI sceKernelIsM2DeviceAttached(void); +int APS5_VABI sceKernelIsMainOnStanbyMode(void); +int APS5_VABI sceKernelIsMainOnStandbyMode(void); +int APS5_VABI sceKernelIsModuleLoaded(void); +int APS5_VABI sceKernelIsNeoMode(void); +int APS5_VABI sceKernelIsProspero(void); +int APS5_VABI sceKernelIsPs4Process(void); +int APS5_VABI sceKernelIsTestKit(void); +int APS5_VABI sceKernelJitGetSharedMemoryInfo(void); +int APS5_VABI sceKernelKernelHeapUsage(void); +int APS5_VABI sceKernelLoadStartModuleForSysmodule(void); +int APS5_VABI sceKernelLoadStartModuleInternalForMono(void); +int APS5_VABI sceKernelLwfsAllocateBlock(void); +int APS5_VABI sceKernelLwfsLseek(void); +int APS5_VABI sceKernelLwfsSetAttribute(void); +int APS5_VABI sceKernelLwfsTrimBlock(void); +int APS5_VABI sceKernelLwfsWrite(void); +int APS5_VABI sceKernelMapNamedSystemFlexibleMemory(void); +int APS5_VABI sceKernelMapSanitizerShadowMemory(void); +int APS5_VABI sceKernelMapToolMemory(void); +int APS5_VABI sceKernelMapTraceMemory(void); +int APS5_VABI sceKernelMapperGetParam(void); +int APS5_VABI sceKernelMemoryPoolMove(void); +int APS5_VABI sceKernelMlockall(void); +int APS5_VABI sceKernelMsync(void* address, std::size_t length, int flags); +int APS5_VABI sceKernelNormalizePath(void); +int APS5_VABI sceKernelNotifyAppEvent(void); +int APS5_VABI sceKernelNotifyAppStateChanged(void); +int APS5_VABI sceKernelNotifySystemSuspendResumeProgress(void); +int APS5_VABI sceKernelNotifySystemSuspendStart(void); +int APS5_VABI sceKernelOpenEport(void); +int APS5_VABI sceKernelOpenInternal(void); +int APS5_VABI sceKernelOpenSema(void); +int APS5_VABI sceKernelPrepareDirectMemorySwap(void); +int APS5_VABI sceKernelPrepareToResumeProcess(void); +int APS5_VABI sceKernelPrepareToSuspendProcess(void); +int APS5_VABI sceKernelProtectDirectMemory(void); +int APS5_VABI sceKernelProtectDirectMemoryForPID(void); +int APS5_VABI sceKernelQueryToolMemory(void); +int APS5_VABI sceKernelQueryTraceMemory(void); +int APS5_VABI sceKernelRandomizedPath(void); +int APS5_VABI sceKernelRdup(void); +int APS5_VABI sceKernelReboot(void); +int APS5_VABI sceKernelReleaseToolMemory(void); +int APS5_VABI sceKernelReleaseTraceDirectMemory(void); +int APS5_VABI sceKernelReportUnpatchedFunctionCall(void); +int APS5_VABI sceKernelReserve2mbPage(void); +int APS5_VABI sceKernelReserveSystemDirectMemory(void); +int APS5_VABI sceKernelRestoreApp(void); +int APS5_VABI sceKernelResumeDirectMemoryRelease(void); +int APS5_VABI sceKernelResumeProcess(void); +int APS5_VABI sceKernelRtldControl(void); +int APS5_VABI sceKernelSandboxPath(void); +int APS5_VABI sceKernelSaveApp(void); +int APS5_VABI sceKernelSetAppInfo(void); +int APS5_VABI sceKernelSetAppState(void); +int APS5_VABI sceKernelSetBackupRestoreMode(void); +int APS5_VABI sceKernelSetBaseModeClock(void); +int APS5_VABI sceKernelSetBesteffort(void); +int APS5_VABI sceKernelSetBootReqNotify(void); +int APS5_VABI sceKernelSetBudget(void); +int APS5_VABI sceKernelSetCallRecord(void); +int APS5_VABI sceKernelSetCompressionAttribute(void); +int APS5_VABI sceKernelSetCoredumpAppInfo(void); +int APS5_VABI sceKernelSetCpumodeGame(void); +int APS5_VABI sceKernelSetDataTransferMode(void); +int APS5_VABI sceKernelSetEmergencyErrorLog(void); +int APS5_VABI sceKernelSetFsstParam(void); +int APS5_VABI sceKernelSetGPI(void); +int APS5_VABI sceKernelSetGameDirectMemoryLimit(void); +int APS5_VABI sceKernelSetGpuCu(void); +int APS5_VABI sceKernelSetIoreq(void); +int APS5_VABI sceKernelSetKnobs(void); +int APS5_VABI sceKernelSetMemoryPstate(void); +int APS5_VABI sceKernelSetNeoModeClock(void); +int APS5_VABI sceKernelSetPackageInfo(void); +int APS5_VABI sceKernelSetPhysFmemLimit(void); +int APS5_VABI sceKernelSetProcessName(void); +int APS5_VABI sceKernelSetProcessProperty(void); +int APS5_VABI sceKernelSetProcessPropertyString(void); +int APS5_VABI sceKernelSetSafemode(void); +int APS5_VABI sceKernelSetSafemodeDirect(void); +int APS5_VABI sceKernelSetSuspendState(void); +int APS5_VABI sceKernelSetTimezoneInfo(void); +int APS5_VABI sceKernelSetUpdatemode(void); +int APS5_VABI sceKernelSetVmContainer(void); +int APS5_VABI sceKernelSettimeofday(void); +int APS5_VABI sceKernelSflashGetWritePrio(void); +int APS5_VABI sceKernelSflashSetWritePrio(void); +int APS5_VABI sceKernelSlvNotifyError(void); +int APS5_VABI sceKernelSpawn(void); +int APS5_VABI sceKernelStreamWriteActivate(void); +int APS5_VABI sceKernelStreamWriteCreate(void); +int APS5_VABI sceKernelStreamWriteDeactivate(void); +int APS5_VABI sceKernelStreamWriteDelete(void); +int APS5_VABI sceKernelStreamWriteRead(void); +int APS5_VABI sceKernelStreamWriteStat(void); +int APS5_VABI sceKernelStreamWriteWrite(void); +int APS5_VABI sceKernelSuspendDirectMemoryRelease(void); +int APS5_VABI sceKernelSuspendProcess(void); +int APS5_VABI sceKernelSuspendSystem(void); +int APS5_VABI sceKernelSwitchToBaseMode(void); +int APS5_VABI sceKernelSwitchToNativeMode(void); +int APS5_VABI sceKernelSwitchToNeoMode(void); +int APS5_VABI sceKernelTerminateProcess(void); +int APS5_VABI sceKernelTerminateSysCore(void); +int APS5_VABI sceKernelTitleWorkdaroundIsEnabled(void); +int APS5_VABI sceKernelTraceMemoryTypeProtect(void); +int APS5_VABI sceKernelTriggerEport(void); +int APS5_VABI sceKernelVirtualQueryAll(void); +int APS5_VABI sceKernelWaitCommandBufferCompletion(void); +int APS5_VABI sceKernelWriteEventQueueOnCompletionCommand(void); +int APS5_VABI sceKernelWriteMapCommand(void); +int APS5_VABI sceKernelWriteMapCommand2(void); +int APS5_VABI sceKernelWriteMapDirectCommand(void); +int APS5_VABI sceKernelWriteMapDirectWithGpuMaskIdCommand(void); +int APS5_VABI sceKernelWriteMapWithGpuMaskIdCommand(void); +int APS5_VABI sceKernelWriteModifyMtypeProtectWithGpuMaskIdCommand(void); +int APS5_VABI sceKernelWriteModifyProtectCommand(void); +int APS5_VABI sceKernelWriteModifyProtectWithGpuMaskIdCommand(void); +int APS5_VABI sceKernelWriteMultiMapCommand(void); +int APS5_VABI sceKernelWriteMultiMapWithGpuMaskIdCommand(void); +int APS5_VABI sceKernelWriteRemapCommand(void); +int APS5_VABI sceKernelWriteRemapWithGpuMaskIdCommand(void); +int APS5_VABI sceKernelWriteSdkEventLog(void); +int APS5_VABI sceKernelWriteSdkEventLogV(void); +int APS5_VABI sceKernelWriteUnmapCommand(void); +int APS5_VABI sceKernelWriteWaitOnAddressCommand(void); +int APS5_VABI sceKernelWriteWaitOnCounterCommand(void); +int APS5_VABI sceKernelWriteWriteAddressCommand(void); +int APS5_VABI sceKernelWriteWriteCounterCommand(void); +int APS5_VABI sceKernelYieldCpumode(void); +int APS5_VABI sceLibcMspaceCreateForMonoMutex(void); +int APS5_VABI scePthreadAtfork(void (APS5_VABI* prepare)(), void (APS5_VABI* parent)(), void (APS5_VABI* child)()); +int APS5_VABI scePthreadAttrGetscope(const PthreadAttr* attr, int* scope); +int APS5_VABI scePthreadAttrSetcreatesuspend(void); +int APS5_VABI scePthreadAttrSetscope(PthreadAttr* attr, int scope); +int APS5_VABI scePthreadBarrierDestroy(PthreadBarrierPrivate** barrier); +int APS5_VABI scePthreadBarrierInit(PthreadBarrierPrivate** barrier, PthreadBarrierattrPrivate* const* attr, unsigned count, const char* name); +int APS5_VABI scePthreadBarrierWait(PthreadBarrierPrivate** barrier); +int APS5_VABI scePthreadBarrierattrDestroy(PthreadBarrierattrPrivate** attr); +int APS5_VABI scePthreadBarrierattrGetpshared(PthreadBarrierattrPrivate* const* attr, int* pshared); +int APS5_VABI scePthreadBarrierattrInit(PthreadBarrierattrPrivate** attr); +int APS5_VABI scePthreadBarrierattrSetpshared(PthreadBarrierattrPrivate** attr, int pshared); +int APS5_VABI scePthreadGetconcurrency(void); +int APS5_VABI scePthreadGetcpuclockid(Pthread thread, int* clockId); +int APS5_VABI scePthreadMain(void); +int APS5_VABI scePthreadMulti(void); +int APS5_VABI scePthreadMutexGetprioceiling(void); +int APS5_VABI scePthreadMutexInitForInternalLibc(void); +int APS5_VABI scePthreadMutexIsowned(void); +int APS5_VABI scePthreadMutexSetprioceiling(void); +int APS5_VABI scePthreadMutexattrGetgen(void); +int APS5_VABI scePthreadMutexattrGetkind(void); +int APS5_VABI scePthreadMutexattrInitForInternalLibc(void); +int APS5_VABI scePthreadMutexattrSetgen(void); +int APS5_VABI scePthreadMutexattrSetkind(void); +int APS5_VABI scePthreadResume(void); +int APS5_VABI scePthreadResumeAll(void); +int APS5_VABI scePthreadSetBesteffort(void); +int APS5_VABI scePthreadSetconcurrency(int level); +int APS5_VABI scePthreadSingle(void); +int APS5_VABI scePthreadSuspend(void); +int APS5_VABI scePthreadSuspendAll(void); +int APS5_VABI scePthreadTimedjoin(void); +int APS5_VABI sched_getparam_nid_postfix(void); +int APS5_VABI sched_getscheduler_nid_postfix(void); +int APS5_VABI sched_setparam_nid_postfix(void); +int APS5_VABI sched_setscheduler_nid_postfix(void); +int APS5_VABI sem_setname_nid_postfix(void); +int APS5_VABI set_phys_fmem_limit_nid_postfix(void); +int APS5_VABI setlogin_nid_postfix(void); +int APS5_VABI settimeofday_nid_postfix(void); +int APS5_VABI sigqueue_nid_postfix(void); +int APS5_VABI sigreturn_nid_postfix(void); +int APS5_VABI statfs_nid_postfix(void); +int APS5_VABI swapon_nid_postfix(void); +int APS5_VABI symlinkat_nid_postfix(void); +int APS5_VABI sysKernelGetIntdevModeForInternalLibc_nid_postfix(void); +int APS5_VABI sysKernelGetIntdevModeForRcmgr_nid_postfix(void); +int APS5_VABI sysKernelGetManufacturingMode_nid_postfix(void); +int APS5_VABI sysKernelGetUpdVersion_nid_postfix(void); +int APS5_VABI sysc_e00_nid_postfix(void); +int APS5_VABI sysc_m00_nid_postfix(void); +int APS5_VABI sysc_s00_nid_postfix(void); +int APS5_VABI tcgetsid_nid_postfix(void); +int APS5_VABI tcsetsid_nid_postfix(void); +int APS5_VABI unmount_nid_postfix(void); +int APS5_VABI utrace_nid_postfix(void); +int APS5_VABI uuidgen_nid_postfix(void); +int APS5_VABI vfork_nid_postfix(void); +int APS5_VABI wait3_nid_postfix(void); +int APS5_VABI wait4_nid_postfix(void); + +int APS5_VABI _openat_nid_postfix(int fd, const char* path, int flags, ...); + +} diff --git a/core/libs/prx/libkernel_sys/libkernel_sys.hpp b/core/libs/prx/libkernel_sys/libkernel_sys.hpp new file mode 100644 index 0000000000..d1700db775 --- /dev/null +++ b/core/libs/prx/libkernel_sys/libkernel_sys.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libkernel_sys/include/Api.hpp" diff --git a/core/libs/prx/libkernel_web/libkernel_web.hpp b/core/libs/prx/libkernel_web/libkernel_web.hpp new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/core/libs/prx/libkernel_web/libkernel_web.hpp @@ -0,0 +1 @@ +#pragma once diff --git a/core/libs/prx/libmdbg_syscore/Export.cpp b/core/libs/prx/libmdbg_syscore/Export.cpp index 195bb3c119..77409149dd 100644 --- a/core/libs/prx/libmdbg_syscore/Export.cpp +++ b/core/libs/prx/libmdbg_syscore/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/libmdbg_syscore/include/Api.hpp" #include #include #include "SceTypes.hpp" diff --git a/core/libs/prx/libmdbg_syscore/include/Api.hpp b/core/libs/prx/libmdbg_syscore/include/Api.hpp new file mode 100644 index 0000000000..9008d00bb7 --- /dev/null +++ b/core/libs/prx/libmdbg_syscore/include/Api.hpp @@ -0,0 +1,151 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI sceDebugAcquireAndUpdateDebugRegister(); +int APS5_VABI sceDebugAttachProcess(); +int APS5_VABI sceDebugCancelCoredump(); +int APS5_VABI sceDebugClearStepThread(); +int APS5_VABI sceDebugCreatePerfScratchDataArea(); +int APS5_VABI sceDebugCreatePerfScratchExecutableArea(); +int APS5_VABI sceDebugCreateScratchDataArea(); +int APS5_VABI sceDebugCreateScratchDataAreaForPrx(); +int APS5_VABI sceDebugCreateScratchExecutableArea(); +int APS5_VABI sceDebugCreateScratchExecutableAreaForPrx(); +int APS5_VABI sceDebugDestroyPerfScratchDataArea(); +int APS5_VABI sceDebugDestroyPerfScratchExecutableArea(); +int APS5_VABI sceDebugDestroyScratchDataArea(); +int APS5_VABI sceDebugDestroyScratchExecutableArea(); +int APS5_VABI sceDebugDetachProcess(); +int APS5_VABI sceDebugGetApplicationIdByTitleId(); +int APS5_VABI sceDebugGetApplicationInfo(); +int APS5_VABI sceDebugGetApplicationList(); +int APS5_VABI sceDebugGetCrashInfoDetailForCoredump(); +int APS5_VABI sceDebugGetCrashInfoForCoredump(); +int APS5_VABI sceDebugGetDLLoadFlag(); +int APS5_VABI sceDebugGetDataListOfUltQueue(); +int APS5_VABI sceDebugGetDebugRegisterStatusMap(); +int APS5_VABI sceDebugGetEventList(); +int APS5_VABI sceDebugGetEventListForEQueueFd(); +int APS5_VABI sceDebugGetEventSubscriptionList(); +int APS5_VABI sceDebugGetEventSubscriptionListForEQueueFd(); +int APS5_VABI sceDebugGetFiberInfo(); +int APS5_VABI sceDebugGetFileInfo(); +int APS5_VABI sceDebugGetFileInfoForCoredump(); +int APS5_VABI sceDebugGetFileList(); +int APS5_VABI sceDebugGetFileListForCoredump(); +int APS5_VABI sceDebugGetGpuInfoArea(); +int APS5_VABI sceDebugGetJobManagerInfo(); +int APS5_VABI sceDebugGetJobManagerSequenceInfo(); +int APS5_VABI sceDebugGetJobManagerSequenceList(); +int APS5_VABI sceDebugGetModuleInfo(); +int APS5_VABI sceDebugGetModuleList(); +int APS5_VABI sceDebugGetModuleMetaData(); +int APS5_VABI sceDebugGetMonoVMInfo(); +int APS5_VABI sceDebugGetMonoVMList(); +int APS5_VABI sceDebugGetProcessCoredumpHandlerEventBlob(); +int APS5_VABI sceDebugGetProcessCoredumpHandlerEventInfo(); +int APS5_VABI sceDebugGetProcessCoredumpHandlerResult(); +int APS5_VABI sceDebugGetProcessEventCntlFlag(); +int APS5_VABI sceDebugGetProcessInfo(); +int APS5_VABI sceDebugGetProcessList(); +int APS5_VABI sceDebugGetProcessPropertyForCoredump(); +int APS5_VABI sceDebugGetProcessResourceStatCount(); +int APS5_VABI sceDebugGetProcessResourceStatData(); +int APS5_VABI sceDebugGetProcessTime(); +int APS5_VABI sceDebugGetProcessTimeCounter(); +int APS5_VABI sceDebugGetSyncExclusiveWaiterList(); +int APS5_VABI sceDebugGetSyncObjectData(); +int APS5_VABI sceDebugGetSyncObjectList(); +int APS5_VABI sceDebugGetSyncWaiterList(); +int APS5_VABI sceDebugGetSyncWaiterListForEQueueFd(); +int APS5_VABI sceDebugGetSystemStatusBlob(); +int APS5_VABI sceDebugGetSystemStatusCount(); +int APS5_VABI sceDebugGetThreadInfo(); +int APS5_VABI sceDebugGetThreadInfoByIdent(); +int APS5_VABI sceDebugGetThreadList(); +int APS5_VABI sceDebugGetThreadListAsIdent(); +int APS5_VABI sceDebugGetUlObjectList(); +int APS5_VABI sceDebugGetUltCondvarInfo(); +int APS5_VABI sceDebugGetUltInfo(); +int APS5_VABI sceDebugGetUltListOfUltRuntime(); +int APS5_VABI sceDebugGetUltMutexInfo(); +int APS5_VABI sceDebugGetUltQueueDataResourcePoolInfo(); +int APS5_VABI sceDebugGetUltQueueInfo(); +int APS5_VABI sceDebugGetUltRuntimeInfo(); +int APS5_VABI sceDebugGetUltRwlockInfo(); +int APS5_VABI sceDebugGetUltSemaphoreInfo(); +int APS5_VABI sceDebugGetUltWaitingQueueResourcePoolInfo(); +int APS5_VABI sceDebugGetVirtualMemoryDetailInfoForCoredump(); +int APS5_VABI sceDebugGetVirtualMemoryInfo(); +int APS5_VABI sceDebugGetVirtualMemoryInfoForCoredump(); +int APS5_VABI sceDebugGetWaitingListOfUltCondvar(); +int APS5_VABI sceDebugGetWaitingListOfUltMutex(); +int APS5_VABI sceDebugGetWaitingListOfUltQueue(); +int APS5_VABI sceDebugGetWaitingListOfUltRwlock(); +int APS5_VABI sceDebugGetWaitingListOfUltSemaphore(); +int APS5_VABI sceDebugGetWorkerThreadListOfUltRuntime(); +int APS5_VABI sceDebugInit(); +int APS5_VABI sceDebugInitForCoredump(); +int APS5_VABI sceDebugInitForTest(); +int APS5_VABI sceDebugIpmiGetBlockTimeInfoList(); +int APS5_VABI sceDebugIpmiGetBlockedIpcInfo(); +int APS5_VABI sceDebugIpmiGetChannelInfo(); +int APS5_VABI sceDebugIpmiGetChannelKidList(); +int APS5_VABI sceDebugIpmiGetChannelWaitingThreadList(); +int APS5_VABI sceDebugIpmiGetClientInfo(); +int APS5_VABI sceDebugIpmiGetClientKidList(); +int APS5_VABI sceDebugIpmiGetClientKidListByDump(); +int APS5_VABI sceDebugIpmiGetClientKidListByServerKid(); +int APS5_VABI sceDebugIpmiGetConnectRequestInfoList(); +int APS5_VABI sceDebugIpmiGetConnectionInfoList(); +int APS5_VABI sceDebugIpmiGetConnectionWaitingThreadListByClientKid(); +int APS5_VABI sceDebugIpmiGetConnectionWaitingThreadListBySessionKid(); +int APS5_VABI sceDebugIpmiGetDump(); +int APS5_VABI sceDebugIpmiGetEncryptedInfoAllForCoredump(); +int APS5_VABI sceDebugIpmiGetKidInfoListForCoredump(); +int APS5_VABI sceDebugIpmiGetServerDispatchInfo(); +int APS5_VABI sceDebugIpmiGetServerInfo(); +int APS5_VABI sceDebugIpmiGetServerKidList(); +int APS5_VABI sceDebugIpmiGetServerKidListByDump(); +int APS5_VABI sceDebugIpmiGetServerWaitingThreadList(); +int APS5_VABI sceDebugIpmiGetSessionInfo(); +int APS5_VABI sceDebugIpmiGetSessionKidList(); +int APS5_VABI sceDebugIpmiGetSessionKidListByServerKid(); +int APS5_VABI sceDebugIpmiGetTidListByDump(); +int APS5_VABI sceDebugKillApplication(); +int APS5_VABI sceDebugKillProcess(); +int APS5_VABI sceDebugNoStopChildProcesses(); +int APS5_VABI sceDebugNoStopOnDLLoad(); +int APS5_VABI sceDebugProcessSpawn(); +int APS5_VABI sceDebugReadEvent(); +int APS5_VABI sceDebugReadEventForTest(); +int APS5_VABI sceDebugReadProcessMemory(); +int APS5_VABI sceDebugReadProcessMemoryForSDBGP(); +int APS5_VABI sceDebugReadProcessRegister(); +int APS5_VABI sceDebugReadProcessRegisterForSDBGP(); +int APS5_VABI sceDebugReadProcessResourceStatData(); +int APS5_VABI sceDebugReadThreadRegister(); +int APS5_VABI sceDebugReadThreadRegisterForSDBGP(); +int APS5_VABI sceDebugReleaseDebugRegister(); +int APS5_VABI sceDebugResumeApplication(); +int APS5_VABI sceDebugResumeProcess(); +int APS5_VABI sceDebugResumeThread(); +int APS5_VABI sceDebugSetProcessEventCntlFlag(); +int APS5_VABI sceDebugSetStepThread(); +int APS5_VABI sceDebugSpawnApplication(); +int APS5_VABI sceDebugStopChildProcesses(); +int APS5_VABI sceDebugStopOnDLLoad(); +int APS5_VABI sceDebugSuspendApplication(); +int APS5_VABI sceDebugSuspendProcess(); +int APS5_VABI sceDebugSuspendThread(); +int APS5_VABI sceDebugTriggerCoredump(); +int APS5_VABI sceDebugTriggerCoredumpForSystem(); +int APS5_VABI sceDebugTriggerVrCaptureDump(); +int APS5_VABI sceDebugWriteProcessMemory(); +int APS5_VABI sceDebugWriteProcessRegister(); +int APS5_VABI sceDebugWriteThreadRegister(); + +} diff --git a/core/libs/prx/libmdbg_syscore/libmdbg_syscore.hpp b/core/libs/prx/libmdbg_syscore/libmdbg_syscore.hpp new file mode 100644 index 0000000000..8a0fe08e5f --- /dev/null +++ b/core/libs/prx/libmdbg_syscore/libmdbg_syscore.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/libmdbg_syscore/include/Api.hpp" diff --git a/core/libs/prx/ulobjmgr/Export.cpp b/core/libs/prx/ulobjmgr/Export.cpp index 25b7f547b2..31328f15db 100644 --- a/core/libs/prx/ulobjmgr/Export.cpp +++ b/core/libs/prx/ulobjmgr/Export.cpp @@ -1,3 +1,4 @@ +#include "prx/ulobjmgr/include/Api.hpp" #include #include #include "SceTypes.hpp" @@ -23,4 +24,12 @@ int APS5_VABI _sceUlobjmgrUnregisterObject(std::uint32_t id) { return 0; } +int APS5_VABI _sceUlobjmgrRegisterObject_nid_postfix(std::uint64_t object, std::int32_t kind, std::uint32_t* id) { + return _sceUlobjmgrRegisterObject(object, kind, id); +} + +int APS5_VABI _sceUlobjmgrUnregisterObject_nid_postfix(std::uint32_t id) { + return _sceUlobjmgrUnregisterObject(id); +} + } diff --git a/core/libs/prx/ulobjmgr/include/Api.hpp b/core/libs/prx/ulobjmgr/include/Api.hpp new file mode 100644 index 0000000000..f551d92f17 --- /dev/null +++ b/core/libs/prx/ulobjmgr/include/Api.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include "SceTypes.hpp" + +extern "C" { + +int APS5_VABI _sceUlobjmgrRegisterObject(std::uint64_t object, std::int32_t kind, std::uint32_t* id); +int APS5_VABI _sceUlobjmgrUnregisterObject(std::uint32_t id); + +int APS5_VABI _sceUlobjmgrRegisterObject_nid_postfix(std::uint64_t object, std::int32_t kind, std::uint32_t* id); +int APS5_VABI _sceUlobjmgrUnregisterObject_nid_postfix(std::uint32_t id); + +} diff --git a/core/libs/prx/ulobjmgr/ulobjmgr.hpp b/core/libs/prx/ulobjmgr/ulobjmgr.hpp new file mode 100644 index 0000000000..3a6f8594df --- /dev/null +++ b/core/libs/prx/ulobjmgr/ulobjmgr.hpp @@ -0,0 +1,3 @@ +#pragma once + +#include "prx/ulobjmgr/include/Api.hpp" diff --git a/core/libs/tests/ApplicationHeap.cpp b/core/libs/tests/ApplicationHeap.cpp index a563e69556..8c02b16146 100644 --- a/core/libs/tests/ApplicationHeap.cpp +++ b/core/libs/tests/ApplicationHeap.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/ApplicationHeap.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -22,24 +23,9 @@ #endif extern "C" { -void APS5_VABI _init_env_nid_postfix(); -int APS5_VABI posix_memalign_nid_postfix(void**, std::size_t, std::size_t); -void* APS5_VABI reallocf_nid_postfix(void*, std::size_t); -void* APS5_VABI _Znwm_nid_postfix(std::size_t); -void* APS5_VABI _ZnwmRKSt9nothrow_t_nid_postfix(std::size_t, const void*) noexcept; -void* APS5_VABI _ZnamRKSt9nothrow_t_nid_postfix(std::size_t, const void*) noexcept; -void APS5_VABI _ZdlPv_nid_postfix(void*); -void APS5_VABI _ZdaPv_nid_postfix(void*); -void APS5_VABI _ZdlPvSt11align_val_t_nid_postfix(void*, std::size_t); -void APS5_VABI _ZdlPvmSt11align_val_t_nid_postfix(void*, std::size_t, std::size_t); + void* ApplicationHeapRealign_nid_no_patch(void*, std::size_t, std::size_t); -char* APS5_VABI strdup_nid_postfix(const char*); -char* APS5_VABI strndup_nid_postfix(const char*, std::size_t); -char* APS5_VABI getcwd_nid_postfix(char*, std::size_t); -int* APS5_VABI __error_nid_postfix(); -int APS5_VABI atexit_nid_postfix(void (APS5_VABI*)()); -void* APS5_VABI scriptingGetMem_nid_postfix(std::size_t, std::size_t); -void APS5_VABI scriptingFreeMem_nid_postfix(void*); + } namespace { @@ -256,8 +242,10 @@ int main(int argc, char** argv) { require(initializes == 0); require(_Znwm_nid_postfix(40) == storage.data() && lastSize == 40 && initializes == 1); _ZdlPv_nid_postfix(storage.data()); + require(frees == 1); _init_env_nid_postfix(); + require(initializes == 1); return 0; } @@ -275,11 +263,14 @@ int main(int argc, char** argv) { require(first[blockBytes - 1] == std::byte{0x5a} && second[0] == std::byte{0xa5}); scriptingFreeMem_nid_postfix(first); scriptingFreeMem_nid_postfix(second); + require(initializes == 0 && frees == 0); _init_env_nid_postfix(); + require(initializes == 1); require(_Znwm_nid_postfix(40) == storage.data() && lastSize == 40); _ZdlPv_nid_postfix(storage.data()); + require(frees == 1); return 0; } @@ -342,6 +333,7 @@ int main(int argc, char** argv) { auto* aligned = ApplicationHeapAlign_nid_no_patch(alignment, 37); require(reinterpret_cast(aligned) % alignment == 0); _ZdlPvSt11align_val_t_nid_postfix(aligned, alignment); + } void* aligned = nullptr; require(ApplicationHeapPosixAlign_nid_no_patch(&aligned, 256, 99) == 0); @@ -385,21 +377,27 @@ int main(int argc, char** argv) { require(_Znwm_nid_postfix(0) == storage.data() && lastSize == 1); _ZdlPv_nid_postfix(storage.data()); _ZdlPv_nid_postfix(nullptr); + require(frees == 3); require(_ZnamRKSt9nothrow_t_nid_postfix(24, nullptr) == storage.data() && lastSize == 24); _ZdaPv_nid_postfix(storage.data()); + require(frees == 4); require(ApplicationHeapRealign_nid_no_patch(storage.data(), 48, 32) == storage.data() && lastSize == 48 && lastAlignment == 32); reject([] { ApplicationHeapRealign_nid_no_patch(storage.data(), 16, 4096); }); pointer = ApplicationHeapAlign_nid_no_patch(64, 37); _ZdlPvSt11align_val_t_nid_postfix(pointer, 64); + require(frees == 5); _ZdlPvSt11align_val_t_nid_postfix(nullptr, 64); + require(frees == 5); pointer = ApplicationHeapAlign_nid_no_patch(64, 37); _ZdlPvmSt11align_val_t_nid_postfix(pointer, 37, 64); + require(frees == 6); _ZdlPvmSt11align_val_t_nid_postfix(nullptr, 37, 64); + require(frees == 6); require(reallocf_nid_postfix(storage.data(), 80) == storage.data() && lastSize == 80 && frees == 6); require(reallocf_nid_postfix(storage.data(), 16) == storage.data() && lastSize == 16 && frees == 6); @@ -480,6 +478,7 @@ int main(int argc, char** argv) { const auto beforeScripting = frees; const auto sizeBeforeScripting = lastSize; scriptingFreeMem_nid_postfix(nullptr); + auto* small = static_cast(scriptingGetMem_nid_postfix(0, 31)); auto* aligned = static_cast(scriptingGetMem_nid_postfix(64, 37)); require(small != nullptr && small != storage.data() && reinterpret_cast(small) % 16 == 0); @@ -489,12 +488,14 @@ int main(int argc, char** argv) { require(small + 31 <= aligned || aligned + 37 <= small); scriptingFreeMem_nid_postfix(small); scriptingFreeMem_nid_postfix(aligned); + require(scriptingGetMem_nid_postfix(24, 80) == nullptr); require(scriptingGetMem_nid_postfix(16, std::numeric_limits::max()) == nullptr); fail = true; auto* unaffected = scriptingGetMem_nid_postfix(16, 64); require(unaffected != nullptr); scriptingFreeMem_nid_postfix(unaffected); + fail = false; require(frees == beforeScripting && lastSize == sizeBeforeScripting); } diff --git a/core/libs/tests/ApplicationHeapStats.cpp b/core/libs/tests/ApplicationHeapStats.cpp index 1345d218d1..8844a5c835 100644 --- a/core/libs/tests/ApplicationHeapStats.cpp +++ b/core/libs/tests/ApplicationHeapStats.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/ApplicationHeap.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -6,11 +7,6 @@ #include #include -extern "C" { -int APS5_VABI malloc_stats_fast_nid_postfix(void*); -std::size_t APS5_VABI malloc_usable_size_nid_postfix(void*); -} - namespace { alignas(64) std::array storage{}; diff --git a/core/libs/tests/ExceptionCCleanup.cpp b/core/libs/tests/ExceptionCCleanup.cpp index cca7677edb..9612a8aaa3 100644 --- a/core/libs/tests/ExceptionCCleanup.cpp +++ b/core/libs/tests/ExceptionCCleanup.cpp @@ -1,10 +1,10 @@ +#include "prx/libc/include/Api.hpp" #include #include #include extern "C" void CallWithCleanup(void (*function)(), int* count); extern "C" void CallAroundCleanup(void (*before)(), void (*within)(), int* count); -extern "C" void (*_ZSt13set_terminatePFvvE_nid_postfix(void (*)()))(); int cleanups; diff --git a/core/libs/tests/ExceptionRuntime.cpp b/core/libs/tests/ExceptionRuntime.cpp index 8f8b1c41fe..8eb7fde24e 100644 --- a/core/libs/tests/ExceptionRuntime.cpp +++ b/core/libs/tests/ExceptionRuntime.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #undef NDEBUG #include #include @@ -19,30 +20,6 @@ #ifdef __linux__ #include #endif -#include - -extern "C" unsigned __cxa_uncaught_exceptions_nid_postfix(); -extern "C" void* __cxa_current_primary_exception_nid_postfix(); -extern "C" void __cxa_decrement_exception_refcount_nid_postfix(void*); -extern "C" void __cxa_rethrow_primary_exception_nid_postfix(void*); - -extern "C" [[noreturn]] void _ZSt14_Xout_of_rangePKc_nid_postfix(const char*); -extern "C" [[noreturn]] void _ZSt13_Xrange_errorPKc_nid_postfix(const char*); -extern "C" [[noreturn]] void _ZNSt8__sce_v219_Xbad_function_callEv_nid_postfix(); -extern "C" [[noreturn]] void _ZSt19_Xbad_function_callv_nid_postfix(); -extern "C" [[noreturn]] void __cxa_bad_cast_nid_postfix(); -extern "C" [[noreturn]] void _ZSt19_Throw_bad_weak_ptrv_nid_postfix(); -extern "C" [[noreturn]] void _ZSt26__throw_bad_variant_accessv_nid_postfix(); -extern "C" [[noreturn]] void _ZSt26_Throw_bad_optional_accessv_nid_postfix(); -extern "C" [[noreturn]] void _ZNKSt9exception6_RaiseEv_nid_postfix(const void*); -extern "C" [[noreturn]] void _ZNKSt8bad_cast8_DoraiseEv_nid_postfix(const void*); -extern "C" void* __cxa_vec_new3_nid_postfix(std::size_t, std::size_t, std::size_t, void(*)(void*), void(*)(void*), void*(*)(std::size_t), void(*)(void*, std::size_t)); -extern "C" void __cxa_vec_delete3_nid_postfix(void*, std::size_t, std::size_t, void(*)(void*), void(*)(void*, std::size_t)); -extern "C" _Unwind_Reason_Code _Unwind_Backtrace_nid_postfix(_Unwind_Trace_Fn, void*); -extern "C" _Unwind_Reason_Code _Unwind_ForcedUnwind_nid_postfix(_Unwind_Exception*, _Unwind_Stop_Fn, void*); -extern "C" std::uintptr_t _Unwind_GetIP_nid_postfix(_Unwind_Context*); -extern "C" std::uintptr_t _Unwind_GetGR_nid_postfix(_Unwind_Context*, int); -extern "C" void (*_ZSt13set_terminatePFvvE_nid_postfix(void(*)()))(); thread_local int destroyed = 0; struct Guard { @@ -101,7 +78,7 @@ void CheckForeign() { assert(reason == _URC_FOREIGN_EXCEPTION_CAUGHT); ++foreignDeleted; delete p; }; try { - try { _Unwind_RaiseException(exception); assert(false); } + try { _Unwind_RaiseException_nid_postfix(exception); assert(false); } catch (...) { assert(__cxa_current_primary_exception_nid_postfix() == nullptr); throw; } } catch (...) {} assert(foreignDeleted == 1); @@ -136,6 +113,7 @@ void CheckArrays() { failArray = true; try { __cxa_vec_new3_nid_postfix(4, sizeof(int), sizeof(std::size_t), ArrayConstruct, ArrayDestroy, std::malloc, ArrayFree); + assert(false); } catch (int value) { assert(value == 73); } assert(arrayConstructed == 2 && arrayDestroyed == 2 && arrayFreed == 1); @@ -143,6 +121,7 @@ void CheckArrays() { failArray = false; void* array = __cxa_vec_new3_nid_postfix(4, sizeof(int), sizeof(std::size_t), ArrayConstruct, ArrayDestroy, std::malloc, ArrayFree); __cxa_vec_delete3_nid_postfix(array, sizeof(int), sizeof(std::size_t), ArrayDestroy, ArrayFree); + assert(arrayConstructed == 4 && arrayDestroyed == 4 && arrayFreed == 1); } void* ThreadTest(void*) { @@ -228,6 +207,7 @@ int main() { try { __cxa_rethrow_primary_exception_nid_postfix(retained); assert(false); } catch (int value) { assert(value == 27); } __cxa_decrement_exception_refcount_nid_postfix(retained); + { auto made = std::make_exception_ptr(Counted()); try { std::rethrow_exception(made); assert(false); } catch (const Counted&) {} @@ -271,12 +251,17 @@ int main() { catch (const std::bad_optional_access& value) { if (std::strcmp(value.what(), "bad_optional_access") != 0) std::abort(); } try { _ZNKSt9exception6_RaiseEv_nid_postfix(nullptr); assert(false); } catch (const std::invalid_argument&) {} - try { _ZNKSt9exception6_RaiseEv_nid_postfix(&object); assert(false); } + LibcException::ExceptionObject exceptionObject {}; + _ZNSt9exceptionC1Ev_nid_postfix(&exceptionObject); + try { _ZNKSt9exception6_RaiseEv_nid_postfix(&exceptionObject); assert(false); } catch (const std::exception& value) { assert(std::strcmp(value.what(), "std::exception") == 0); } + _ZNSt9exceptionD1Ev_nid_postfix(&exceptionObject); try { _ZNKSt8bad_cast8_DoraiseEv_nid_postfix(nullptr); assert(false); } catch (const std::invalid_argument&) {} - try { _ZNKSt8bad_cast8_DoraiseEv_nid_postfix(&object); assert(false); } + _ZNSt8bad_castC1Ev_nid_postfix(&exceptionObject); + try { _ZNKSt8bad_cast8_DoraiseEv_nid_postfix(&exceptionObject); assert(false); } catch (const std::bad_cast&) {} + _ZNSt8bad_castD1Ev_nid_postfix(&exceptionObject); CheckRtti(); CheckForeign(); CheckStaticInitialization(); diff --git a/core/libs/tests/Fiber.cpp b/core/libs/tests/Fiber.cpp index f6b532900b..9f77bd063e 100644 --- a/core/libs/tests/Fiber.cpp +++ b/core/libs/tests/Fiber.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceFiber/include/Api.hpp" #include "SceTypes.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -12,23 +13,6 @@ using Entry = void (APS5_VABI*)(std::uint64_t, std::uint64_t); -extern "C" { -std::int32_t APS5_VABI _sceFiberInitializeImpl_nid_postfix(FiberObject*, const char*, Entry, std::uint64_t, void*, std::uint64_t, const void*, std::uint32_t); -std::int32_t APS5_VABI sceFiberFinalize(FiberObject*); -std::int32_t APS5_VABI sceFiberRun_nid_postfix(FiberObject*, std::uint64_t, std::uint64_t*); -std::int32_t APS5_VABI sceFiberSwitch(FiberObject*, std::uint64_t, std::uint64_t*); -std::int32_t APS5_VABI sceFiberReturnToThread(std::uint64_t, std::uint64_t*); -std::int32_t APS5_VABI sceFiberGetSelf(FiberObject**); -std::int32_t APS5_VABI sceFiberGetInfo(FiberObject*, FiberInfo*); -std::int32_t APS5_VABI sceFiberGetThreadFramePointerAddress(std::uint64_t*); -std::int32_t APS5_VABI _sceFiberGetThreadFramePointerAddress(std::uint64_t*); -std::int32_t APS5_VABI sceFiberStartContextSizeCheck(std::uint32_t); -std::int32_t APS5_VABI sceFiberStopContextSizeCheck(void); -std::int32_t APS5_VABI _sceFiberAttachContextAndRun(FiberObject*, void*, std::uint64_t, std::uint64_t, std::uint64_t*); -std::int32_t APS5_VABI _sceFiberAttachContextAndSwitch(FiberObject*, void*, std::uint64_t, std::uint64_t, std::uint64_t*); -std::int32_t APS5_VABI _sceFiberInitializeWithInternalOptionImpl(FiberObject*, const char*, Entry, std::uint64_t, void*, std::uint64_t, const void*, std::uint32_t, std::uint32_t); -} - static void Require(bool value, const char* what) { if (!value) { std::fprintf(stderr, "Fiber check failed: %s\n", what); std::abort(); } } @@ -230,6 +214,7 @@ void APS5_VABI LargeContextEntry(std::uint64_t, std::uint64_t) { const auto* address = const_cast(&local); g_largeOnContext = address >= g_largeContext.data() && address < g_largeContext.data() + g_largeContext.size(); sceFiberReturnToThread(0, nullptr); + } void RunOnLargeContext() { diff --git a/core/libs/tests/FilePosition.cpp b/core/libs/tests/FilePosition.cpp index 0337c58932..9bd695cc15 100644 --- a/core/libs/tests/FilePosition.cpp +++ b/core/libs/tests/FilePosition.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/FileStream.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -12,12 +13,6 @@ #include #endif -extern "C" { -int APS5_VABI fgetpos_nid_postfix(FileStream*, std::int64_t*); -int APS5_VABI fsetpos_nid_postfix(FileStream*, const std::int64_t*); -std::int64_t APS5_VABI ftello_nid_postfix(FileStream*); -} - static void Check(bool value, int line) { if (!value) { std::fprintf(stderr, "File position check failed at line %d\n", line); diff --git a/core/libs/tests/FileStreams.cpp b/core/libs/tests/FileStreams.cpp index 2e11f4dfb2..fc8af8e721 100644 --- a/core/libs/tests/FileStreams.cpp +++ b/core/libs/tests/FileStreams.cpp @@ -1,8 +1,10 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/FileStream.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include #include +#include #include #include #include @@ -22,29 +24,6 @@ #include #endif -extern "C" { -FileStream* APS5_VABI fopen_nid_postfix(const char* filename, const char* mode); -FileStream* APS5_VABI _ZSt7_FiopenPKcNSt5_IosbIiE9_OpenmodeEi_nid_postfix(const char*, int, int); -FileStream* APS5_VABI freopen_nid_postfix(const char* filename, const char* mode, FileStream* stream); -int APS5_VABI fclose_nid_postfix(FileStream* stream); -std::size_t APS5_VABI fread_nid_postfix(void* buffer, std::size_t size, std::size_t count, FileStream* stream); -std::size_t APS5_VABI fwrite_nid_postfix(const void* buffer, std::size_t size, std::size_t count, FileStream* stream); -int APS5_VABI fseek_nid_postfix(FileStream* stream, std::int64_t offset, int origin); -std::int64_t APS5_VABI ftell_nid_postfix(FileStream* stream); -int APS5_VABI fputs_nid_postfix(const char* str, FileStream* stream); -int APS5_VABI fflush_nid_postfix(FileStream* stream); -int APS5_VABI remove_nid_postfix(const char* path); -int APS5_VABI rename_nid_postfix(const char* from, const char* to); -int APS5_VABI ferror_nid_postfix(FileStream* stream); -int APS5_VABI feof_nid_postfix(FileStream* stream); -void APS5_VABI clearerr_nid_postfix(FileStream* stream); -int APS5_VABI fgetc_nid_postfix(FileStream* stream); -int APS5_VABI getc_unlocked_nid_postfix(FileStream* stream); -char* APS5_VABI fgets_nid_postfix(char* buffer, int size, FileStream* stream); -int APS5_VABI ungetc_nid_postfix(int value, FileStream* stream); -int APS5_VABI fscanf_nid_postfix(FileStream* stream, const char* format, ...); -} - static void Require(bool condition, const char* message = "File stream check failed") { if (!condition) throw std::runtime_error(message); } @@ -124,6 +103,23 @@ static void CheckExclusiveCppOpen(const std::string& base) { } } +static int APS5_VABI ScanList(FileStream* stream, const char* format, ...) { +#ifdef _WIN32 + __builtin_sysv_va_list args; + __builtin_sysv_va_start(args, format); +#else + std::va_list args; + va_start(args, format); +#endif + const int result = vfscanf_nid_postfix(stream, format, reinterpret_cast(args)); +#ifdef _WIN32 + __builtin_sysv_va_end(args); +#else + va_end(args); +#endif + return result; +} + static std::string ReadWhole(const std::string& path) { auto* stream = fopen_nid_postfix(path.c_str(), "rb"); Require(stream != nullptr); @@ -180,6 +176,11 @@ static void CheckUpdateStreamReadsAfterWrites(const std::string& base) { Require(fscanf_nid_postfix(stream, "%3s", buffer.data()) == 1, "fscanf after fwrite on an r+ stream"); Require(std::strcmp(buffer.data(), "234") == 0, "fscanf after fwrite on an r+ stream read other bytes"); }); + CheckReadAfterWrite(path, "r+b", overwritten, [](FileStream* stream) { + std::array buffer{}; + Require(ScanList(stream, "%3s", buffer.data()) == 1, "vfscanf after fwrite on an r+ stream"); + Require(std::strcmp(buffer.data(), "234") == 0, "vfscanf after fwrite on an r+ stream read other bytes"); + }); CheckReadAfterWrite(path, "w+b", "AB", [](FileStream* stream) { std::array buffer{}; Require(fread_nid_postfix(buffer.data(), 1, buffer.size(), stream) == 0 && feof_nid_postfix(stream) != 0, "fread after fwrite on a w+ stream"); diff --git a/core/libs/tests/Formatting.cpp b/core/libs/tests/Formatting.cpp index ea4b2ecaa8..92b799e92f 100644 --- a/core/libs/tests/Formatting.cpp +++ b/core/libs/tests/Formatting.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "SceTypes.hpp" #include "prx/libc/include/ApplicationHeap.hpp" #include "prx/libc/include/GuestHeap.hpp" @@ -19,23 +20,6 @@ #define __builtin_sysv_va_end va_end #endif -extern "C" { -int APS5_VABI snprintf_nid_postfix(char*, size_t, const char*, ...); -int APS5_VABI sprintf_nid_postfix(char*, const char*, ...); -int APS5_VABI printf_nid_postfix(const char*, ...); -int APS5_VABI libc_printf_nid_postfix(const char*, ...); -int APS5_VABI sscanf_nid_postfix(const char*, const char*, ...); -int APS5_VABI vsnprintf_nid_postfix(char*, size_t, const char*, VaList*); -int APS5_VABI vsnprintf_s_nid_postfix(char*, size_t, const char*, VaList*); -int APS5_VABI snprintf_s_nid_postfix(char*, size_t, const char*, ...); -int APS5_VABI vsscanf_s_nid_postfix(const char*, const char*, VaList*); -int APS5_VABI vsscanf_nid_postfix(const char*, const char*, VaList*); -int APS5_VABI vprintf_nid_postfix(const char*, VaList*); -int APS5_VABI asprintf_nid_postfix(char**, const char*, ...); -void APS5_VABI free_nid_postfix(void*); -int* APS5_VABI __error_nid_postfix(); -} - static void Require(bool condition) { if (!condition) throw std::runtime_error("Formatting check failed"); } @@ -209,19 +193,24 @@ __attribute__((noinline)) static void APS5_VABI RunChecks() { Require(std::strcmp(buffer, "Mount requested: 0") == 0); for (int index = 0; index < 10000; ++index) { snprintf_nid_postfix(buffer, sizeof(buffer), "%d %d %d %d %d %d %d %d", 1, 2, 3, 4, 5, 6, 7, 8); + Require(std::strcmp(buffer, "1 2 3 4 5 6 7 8") == 0); FormatList(buffer, sizeof(buffer), "%.1f %.1f %.1f %.1f %.1f %.1f %.1f %.1f %.1f %.1f %d", 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11); Require(std::strcmp(buffer, "1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0 10.0 11") == 0); snprintf_nid_postfix(buffer, sizeof(buffer), "%ld %lu %lld %zu %td %jd", -4294967297LL, 4294967297ULL, -5LL, 7ULL, -8LL, 9LL); + Require(std::strcmp(buffer, "-4294967297 4294967297 -5 7 -8 9") == 0); snprintf_nid_postfix(buffer, sizeof(buffer), "%s:%*.*f:%d", "test", -8, 2, 1.25, 7); + Require(std::strcmp(buffer, "test:1.25 :7") == 0); FormatList(buffer, sizeof(buffer), "%d %d %d %d %d %d %d %.3Lf %.1f", 1, 2, 3, 4, 5, 6, 7, 1.125L, 2.5); Require(std::strcmp(buffer, "1 2 3 4 5 6 7 1.125 2.5") == 0); } snprintf_nid_postfix(buffer, sizeof(buffer), "%.1f %.1f %.1f %.1f %.1f %.1f %.1f %.1f %.1f %.1f", 1., 2., 3., 4., 5., 6., 7., 8., 9., 10.); + Require(std::strcmp(buffer, "1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0 10.0") == 0); snprintf_nid_postfix(buffer, sizeof(buffer), "%.3Lf %d %.1f", 1.125L, 7, 2.5); + Require(std::strcmp(buffer, "1.125 7 2.5") == 0); Require(snprintf_nid_postfix(buffer, sizeof(buffer), "%'d|%'u|%'.2f|%'-8ld|%'+05d|%'g", 1234567, 4000000000u, 1234567.891, 1234567LL, 42, 1e6) == 50); Require(std::strcmp(buffer, "1234567|4000000000|1234567.89|1234567 |+0042|1e+06") == 0); @@ -245,6 +234,7 @@ __attribute__((noinline)) static void APS5_VABI RunChecks() { std::snprintf(expected, sizeof(expected), "%#08x %.3e %a %g %llx", 42u, 1.25, 1.25, 1.25, static_cast(reinterpret_cast(buffer))); snprintf_nid_postfix(buffer, sizeof(buffer), "%#08x %.3e %a %g %p", 42u, 1.25, 1.25, 1.25, static_cast(buffer)); + Require(std::strcmp(buffer, expected) == 0); char pointers[128]; const auto address = [](std::uintptr_t value) { return reinterpret_cast(value); }; @@ -265,6 +255,7 @@ __attribute__((noinline)) static void APS5_VABI RunChecks() { Require(snprintf_nid_postfix(pointers, sizeof(pointers), "%p", address(0xffffffffffffffffull)) == 16 && std::strcmp(pointers, "ffffffffffffffff") == 0); snprintf_nid_postfix(buffer, sizeof(buffer), "%.*s", -1, "unlimited"); + Require(std::strcmp(buffer, "unlimited") == 0); buffer[5] = '!'; Require(snprintf_nid_postfix(buffer, 5, "%s", "abcdef") == 6); @@ -411,6 +402,94 @@ static void CheckAllocatingFormat() { char* allocated = nullptr; Require(asprintf_nid_postfix(&allocated, "%ls:%S:%lc:%d", u"\u00e9", u"ab", 0x20ac, 7) == 11 && std::strcmp(allocated, "\xc3\xa9:ab:\xe2\x82\xac:7") == 0); free_nid_postfix(allocated); + } -int main() { CheckSizeLimits(); RunChecks(); CheckAllocatingFormat(); return CheckWidePrecision() ? 0 : 1; } +static void RequireFloat(const char* format, double value, const char* expected) { + char buffer[64]; + const int written = snprintf_nid_postfix(buffer, sizeof(buffer), format, value); + if (written != static_cast(std::strlen(expected)) || std::strcmp(buffer, expected) != 0) { + std::fprintf(stderr, "%s of %a gave \"%s\", expected \"%s\"\n", format, value, buffer, expected); + Require(false); + } +} + +static void CheckHexFloat() { + RequireFloat("[%-010a]", 1.5, "[0x1.8p+0 ]"); + RequireFloat("[%-0#12A]", 0.75, "[0X1.8P-1 ]"); + RequireFloat("[%0-10.2a]", 1.0, "[0x1.00p+0 ]"); + RequireFloat("[%010a]", -1.5, "[-0x01.8p+0]"); + RequireFloat("[%a]", 0x1p-1074, "[0x1p-1074]"); + RequireFloat("[%a]", 0x0.fffffffffffffp-1022, "[0x1.ffffffffffffep-1023]"); + RequireFloat("[%.3a]", 0x0.fffffffffffffp-1022, "[0x2.000p-1023]"); + RequireFloat("[%A]", 0x0.012688b70e62bp-1022, "[0X1.2688B70E62BP-1030]"); + RequireFloat("[%.0a]", 0x0.012688b70e62bp-1022, "[0x1p-1030]"); + RequireFloat("[%.1a]", 0x1.08p0, "[0x1.1p+0]"); + RequireFloat("[%.0a]", 0x1.8p0, "[0x2p+0]"); + RequireFloat("[%#.0a]", 1.0, "[0x1.p+0]"); + RequireFloat("[%.20a]", 0.1, "[0x1.999999999999a0000000p-4]"); + RequireFloat("[% a]", -0.0, "[-0x0p+0]"); + char buffer[32]; + Require(snprintf_nid_postfix(buffer, sizeof(buffer), "[%*a]", -12, 1.5) == 14 && std::strcmp(buffer, "[0x1.8p+0 ]") == 0); + Require(snprintf_nid_postfix(buffer, 6, "%a", 1.5) == 8 && std::strcmp(buffer, "0x1.8") == 0); +#ifdef _WIN32 + for (const char* format : {"%.2147483648a", "%.2147483649A", "%.9999999999a", + "%.9999999999999999999999999999999999999999A", "%.0002147483648a", "%-+20.2147483648A", + "%2147483648a", "%999999999999999999999999a", "%.2147483647a", "%.2147483641a", "%+.2147483640A", + "x%2147483647a", "xx%.2147483640a", "x%+.2147483639A"}) { + bool rejected = false; + try { + snprintf_nid_postfix(buffer, sizeof(buffer), format, 1.5); + } catch (const std::overflow_error&) { + rejected = true; + } + Require(rejected); + } +#endif +} + +static void CheckDecimalFloat() { + RequireFloat("[%.0f]", 0.5, "[1]"); + RequireFloat("[%.0f]", 2.5, "[3]"); + RequireFloat("[%.0f]", -0.5, "[-1]"); + RequireFloat("[%.1f]", 0.25, "[0.3]"); + RequireFloat("[%#.3g]", 2025.0, "[2.03e+03]"); + RequireFloat("[%.2e]", 1125.0, "[1.13e+03]"); + RequireFloat("[%.2f]", 0.015, "[0.01]"); + RequireFloat("[%.1f]", 99.95, "[100.0]"); + RequireFloat("[%.40e]", 0.1, "[1.0000000000000000555000000000000000000000e-01]"); + RequireFloat("[%.20f]", 0.1, "[0.10000000000000000555]"); + RequireFloat("[%.0f]", 0x1p100, "[1267650600228229401496700000000]"); + RequireFloat("[%.25e]", 0x1p-1074, "[4.9406564584124654417600000e-324]"); + RequireFloat("[%.23e]", 0x1.0f6b8p+1023, "[9.52987754335065669050000e+307]"); + RequireFloat("[%.17e]", -0x1.16a55a5cd7c73p+48, "[-3.06374418159559187e+14]"); + RequireFloat("[%.17g]", 0x1.e5dec6655f463p+50, "[2136879802973464.7]"); + RequireFloat("[%.0f]", 67108865.5, "[67108865]"); + RequireFloat("[%.0f]", 33554433.5, "[33554434]"); + RequireFloat("[%+08.1f]", 2.25, "[+00002.3]"); + RequireFloat("[%#.0e]", 2.5, "[3.e+00]"); + RequireFloat("[%g]", 0.0001, "[0.0001]"); + RequireFloat("[%G]", 0.00001, "[1E-05]"); + RequireFloat("[%.3g]", 999.5, "[1e+03]"); + RequireFloat("[%e]", 0.0, "[0.000000e+00]"); + RequireFloat("[%#g]", 0.0, "[0.00000]"); + RequireFloat("[%.0f]", -0.0, "[-0]"); + RequireFloat("[%-12.3E]", -1.25e-5, "[-1.250E-05 ]"); + char buffer[64]; + Require(snprintf_nid_postfix(buffer, sizeof(buffer), "[%.40Le]", 1.0L / 3) == 48 && std::strcmp(buffer, "[3.3333333333333333334000000000000000000000e-01]") == 0); + Require(snprintf_nid_postfix(buffer, sizeof(buffer), "[%.2Lf]", 0.125L) == 6 && std::strcmp(buffer, "[0.13]") == 0); + Require(snprintf_nid_postfix(buffer, sizeof(buffer), "[%.30Le]", 0x1p-16445L) == 40 && std::strcmp(buffer, "[3.645199531882474602528000000000e-4951]") == 0); + for (const char* format : {"%.2147483647e", "%+.2147483647E", "%.2147483647f", "% .2147483646F", "%#.2147483647g", + "%.2147483643e", "x%.2147483645f", "x%-2147483647e", "%.2147483647Le"}) { + bool rejected = false; + try { + if (std::strstr(format, "L")) snprintf_nid_postfix(buffer, sizeof(buffer), format, 1.5L); + else snprintf_nid_postfix(buffer, sizeof(buffer), format, 1.5); + } catch (const std::overflow_error&) { + rejected = true; + } + Require(rejected); + } +} + +int main() { CheckSizeLimits(); RunChecks(); CheckHexFloat(); CheckDecimalFloat(); CheckAllocatingFormat(); return CheckWidePrecision() ? 0 : 1; } diff --git a/core/libs/tests/GuestAccess.cpp b/core/libs/tests/GuestAccess.cpp index f4fa4fb8e8..f7cd52dcae 100644 --- a/core/libs/tests/GuestAccess.cpp +++ b/core/libs/tests/GuestAccess.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/General.hpp" #include #include @@ -10,12 +11,6 @@ #include #endif -extern "C" { -int APS5_VABI access_nid_postfix(const char*, int); -int APS5_VABI chdir_nid_postfix(const char*); -int* APS5_VABI __error_nid_postfix(); -} - static void Require(bool value) { if (!value) std::abort(); } int main() { diff --git a/core/libs/tests/GuestAcm.cpp b/core/libs/tests/GuestAcm.cpp index 9ba39f03ee..80d918bda6 100644 --- a/core/libs/tests/GuestAcm.cpp +++ b/core/libs/tests/GuestAcm.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceAcm/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -6,17 +7,6 @@ #include #include "SceTypes.hpp" -extern "C" { -int APS5_VABI sceAcmContextCreate(std::uint32_t*); -int APS5_VABI sceAcmContextDestroy(std::uint32_t); -int APS5_VABI sceAcmBatchStartBuffer(std::uint32_t, const void*, std::size_t, void*, std::uint32_t*); -int APS5_VABI sceAcmBatchStartBuffers(std::uint32_t, std::uint32_t, const void* const[], void*, std::uint32_t*); -int APS5_VABI sceAcmBatchWait(std::uint32_t, std::uint32_t, std::uint32_t); -int APS5_VABI sceAcm_ConvReverb_SharedInput(AcmBatchInfo*, std::uint32_t, AcmReverbInput*, std::uint32_t, const AcmReverbFilter* const*, const float*, const AcmReverbOutput* const*); -int APS5_VABI sceAcm_FFT(AcmBatchInfo*, std::int32_t, std::uint32_t, std::int32_t, const void* const*, std::int32_t, void* const*, std::int32_t); -int APS5_VABI sceAcm_Panner(AcmBatchInfo*, std::uint32_t, const void* const*, std::uint32_t, std::uint32_t, std::uint32_t, const void* const*, const void* const*, const void* const*, void* const*); -} - static void Require(bool value) { if (!value) std::abort(); } diff --git a/core/libs/tests/GuestAddressConversion.cpp b/core/libs/tests/GuestAddressConversion.cpp index 4d44b0a41b..4b6b4f252a 100644 --- a/core/libs/tests/GuestAddressConversion.cpp +++ b/core/libs/tests/GuestAddressConversion.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -5,17 +7,6 @@ #include #include -extern "C" { -int APS5_VABI __inet_pton_nid_postfix(int, const char*, void*); -const char* APS5_VABI __inet_ntop_nid_postfix(int, const void*, char*, std::uint32_t); -int APS5_VABI inet_pton_nid_postfix(int, const char*, void*); -const char* APS5_VABI inet_ntop_nid_postfix(int, const void*, char*, std::uint32_t); -int* APS5_VABI __error_nid_postfix(); -std::uint32_t APS5_VABI htonl_nid_postfix(std::uint32_t); -std::uint32_t APS5_VABI ntohl_nid_postfix(std::uint32_t); -std::uint16_t APS5_VABI htons_nid_postfix(std::uint16_t); -std::uint16_t APS5_VABI ntohs_nid_postfix(std::uint16_t); -} static void Require(bool value) { if (!value) std::abort(); } using Ntop = const char* (APS5_VABI *)(int, const void*, char*, std::uint32_t); @@ -470,6 +461,7 @@ static void CheckConsolePton() { *__error_nid_postfix() = 0; const int result = sample.plain ? inet_pton_nid_postfix(sample.family, sample.text, destination) : __inet_pton_nid_postfix(sample.family, sample.text, destination); + Require(result == sample.result); Require(*__error_nid_postfix() == sample.error); Require(SameBytes(destination, sample.bytes)); @@ -484,6 +476,7 @@ static void CheckConsoleNtop() { *__error_nid_postfix() = 0; const char* result = sample.plain ? inet_ntop_nid_postfix(sample.family, source, Wide, sample.size) : __inet_ntop_nid_postfix(sample.family, source, Wide, sample.size); + Require(result == (sample.succeeds ? Wide : nullptr)); Require(*__error_nid_postfix() == sample.error); Require(SameBytes(Wide, sample.bytes)); diff --git a/core/libs/tests/GuestAgcDriverDebugUnavailable.cpp b/core/libs/tests/GuestAgcDriverDebugUnavailable.cpp index 72b97bd56f..8e807d6996 100644 --- a/core/libs/tests/GuestAgcDriverDebugUnavailable.cpp +++ b/core/libs/tests/GuestAgcDriverDebugUnavailable.cpp @@ -1,38 +1,9 @@ +#include "prx/libSceAgcDriver/include/AgcDriver.hpp" #include "SceTypes.hpp" #include #include #include -extern "C" { -int APS5_VABI sceAgcDriverGetShaderDebuggingStatus(); -int APS5_VABI sceAgcDriverSetValidationErrorOutputFrequency(std::uint32_t); -int APS5_VABI sceAgcDriverSetSubmitValidationMode(std::uint32_t); -int APS5_VABI sceAgcDriverGetSubmitValidationMode(std::uint32_t*); -int APS5_VABI sceAgcDriverSetSubmitValidationConfig(const void*); -int APS5_VABI sceAgcDriverGetSubmitValidationConfig(void*); -int APS5_VABI sceAgcDriverSetValidationDisabled(); -int APS5_VABI sceAgcDriverGetCaptureConfig(); -int APS5_VABI sceAgcDriverSetCaptureConfig(); -int APS5_VABI sceAgcDriverGetGpuPrintfWorkArea(); -int APS5_VABI sceAgcDriverSetGpuPrintfEnabled(); -int APS5_VABI sceAgcDriverDbgReadRegister(); -int APS5_VABI sceAgcDriverDbgWriteRegister(); -int APS5_VABI sceAgcDriverGetGpuRefClks(); -int APS5_VABI sceAgcDriverIsSuspendPointInFlight(); -int APS5_VABI sceAgcDriverIsPaDebug(); -int APS5_VABI sceAgcDriverGetExceptionStatus(); -int APS5_VABI sceAgcDriverGetTraceInitiator(); -int APS5_VABI sceAgcDriverRegisterGpuResetCallbacks(); -int APS5_VABI sceAgcDriverUnregisterGpuResetCallbacks(); -int APS5_VABI sceAgdResetGpu(); -int APS5_VABI sceAgcDriverSysSubmitFlipHandleProxy(); -int APS5_VABI sceAgcDriverUserDataImmediateWrite(); -int APS5_VABI sceAgcDriverUserDataImmediateWritePacket(); -int APS5_VABI sceAgcDriverGetCoredumpMode(std::uint32_t*); -int APS5_VABI sceAgcDriverAllocateToolMemoryForGpuReset(std::uint64_t, std::uint64_t, std::uint64_t, void*); -int APS5_VABI sceAgcDriverGetAllocatedToolMemoryForGpuReset(std::uint64_t, void*); -} - static constexpr int DebugUnavailable = static_cast(0x8A6C1000); static constexpr int FeatureUnavailable = static_cast(0x8A6D0001); static void Require(bool value) { if (!value) std::abort(); } diff --git a/core/libs/tests/GuestAgcDriverResources.cpp b/core/libs/tests/GuestAgcDriverResources.cpp index 5ee342a763..eafe67b86e 100644 --- a/core/libs/tests/GuestAgcDriverResources.cpp +++ b/core/libs/tests/GuestAgcDriverResources.cpp @@ -1,3 +1,6 @@ +#include "prx/libSceAgcDriver/State/include/Status.hpp" +#include "prx/libSceAgcDriver/Resource/include/Registration.hpp" +#include "prx/libSceAgcDriver/include/AgcDriver.hpp" #include "SceTypes.hpp" #include #include @@ -6,33 +9,6 @@ #include #include -extern "C" { -int APS5_VABI sceAgcDriverRegisterDefaultOwner(std::uint32_t); -int APS5_VABI sceAgcDriverRegisterOwner(std::uint32_t*, const char*); -int APS5_VABI sceAgcDriverRegisterResource(std::uint32_t*, std::uint32_t, const void*, std::size_t, const char*, std::uint32_t, std::uint64_t); -int APS5_VABI sceAgcDriverRegisterMultipleResources(std::uint32_t*, std::uint32_t, const void*, std::uint32_t); -int APS5_VABI sceAgcDriverRegisterGdsResource(std::uint32_t*, std::uint32_t, std::uint32_t, std::uint32_t, const char*, std::uint32_t, std::uint64_t); -int APS5_VABI sceAgcDriverUnregisterAllResourcesForOwner(std::uint32_t); -int APS5_VABI sceAgcDriverRegisterWorkloadStream(std::uint32_t, const void*); -int APS5_VABI sceAgcDriverUnregisterWorkloadStream(std::uint32_t); -int APS5_VABI sceAgcDriverGetDefaultOwner(std::uint32_t*); -int APS5_VABI sceAgcDriverGetResourceRegistrationMaxNameLength(std::uint32_t*); -int APS5_VABI sceAgcDriverGetOwnerName(std::uint32_t, const char**); -int APS5_VABI sceAgcDriverGetResourceName(std::uint32_t, const char**); -int APS5_VABI sceAgcDriverGetResourceType(std::uint32_t, std::uint32_t*); -int APS5_VABI sceAgcDriverGetResourceUserData(std::uint32_t, std::uint64_t*); -int APS5_VABI sceAgcDriverSetResourceUserData(std::uint32_t, std::uint64_t); -int APS5_VABI sceAgcDriverGetResourceBaseAddressAndSizeInBytes(std::uint32_t, void**, std::size_t*); -int APS5_VABI sceAgcDriverGetResourceShaderGuid(std::uint32_t, void*); -int APS5_VABI sceAgcDriverFindResourcesPublic(const void*, void*); -bool APS5_VABI sceAgcDriverIsCaptureInProgress(void); -bool APS5_VABI sceAgcDriverIsTraceInProgress(void); -bool APS5_VABI sceAgcDriverIsSubmitValidationEnabled(void); -int APS5_VABI sceAgcDriverRegisterOwnerForSystem(); -int APS5_VABI sceAgcDriverInitResourceRegistrationInterface(); -int APS5_VABI sceAgcDriverSetResourceRegistrationInfo(); -} - static constexpr int Unavailable = static_cast(0x8A6C9018); static void Require(bool value) { if (!value) std::abort(); } diff --git a/core/libs/tests/GuestAio.cpp b/core/libs/tests/GuestAio.cpp index 616f141ce4..79dfd69a61 100644 --- a/core/libs/tests/GuestAio.cpp +++ b/core/libs/tests/GuestAio.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libkernel/File/include/File.hpp" #include "SceTypes.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libkernel/File/include/FileFlags.hpp" @@ -19,28 +21,7 @@ #include extern "C" _invalid_parameter_handler _set_thread_local_invalid_parameter_handler(_invalid_parameter_handler); #endif -extern "C" { -int APS5_VABI sceKernelOpen(const char* path, int flags, std::uint16_t mode); -int APS5_VABI sceKernelClose(int d); -std::int64_t APS5_VABI sceKernelPread(int, void*, std::size_t, std::int64_t); -std::int64_t APS5_VABI sceKernelPwrite(int, const void*, std::size_t, std::int64_t); -std::int64_t APS5_VABI sceKernelLseek(int d, std::int64_t offset, int whence); -int APS5_VABI sceKernelAioDeleteRequest(std::int32_t id, std::int32_t* ret); -int APS5_VABI sceKernelAioInitializeImpl(void* param, std::int32_t size); -void APS5_VABI sceKernelAioInitializeParam(void* param); -int APS5_VABI sceKernelAioSetParam(KernelAioSchedulingParam* param, std::int32_t schedulingWindowSize, std::int32_t delayedCountLimit, std::uint32_t enableSplit, std::uint32_t splitSize, std::uint32_t splitChunkSize); -int APS5_VABI sceKernelAioSubmitReadCommands(KernelAioRwRequest* req, std::int32_t size, std::int32_t prio, std::int32_t* id); -int APS5_VABI sceKernelAioSubmitWriteCommands(KernelAioRwRequest* req, std::int32_t size, std::int32_t prio, std::int32_t* id); -int APS5_VABI sceKernelAioPollRequest(std::int32_t id, std::int32_t* state); -int APS5_VABI sceKernelAioWaitRequest(std::int32_t id, std::int32_t* state, std::uint32_t* usec); -int APS5_VABI sceKernelAioSubmitReadCommandsMultiple(KernelAioRwRequest* req, std::int32_t size, std::int32_t prio, std::int32_t* id); -int APS5_VABI sceKernelAioSubmitWriteCommandsMultiple(KernelAioRwRequest* req, std::int32_t size, std::int32_t prio, std::int32_t* id); -int APS5_VABI sceKernelAioWaitRequests(std::int32_t* id, std::int32_t num, std::int32_t* state, std::uint32_t mode, std::uint32_t* usec); -int APS5_VABI sceKernelAioPollRequests(std::int32_t* id, std::int32_t num, std::int32_t* state); -int APS5_VABI sceKernelAioCancelRequest(std::int32_t id, std::int32_t* state); -int APS5_VABI sceKernelAioCancelRequests(std::int32_t* id, std::int32_t num, std::int32_t* state); -int APS5_VABI sceKernelAioDeleteRequests(std::int32_t* id, std::int32_t num, std::int32_t* ret); -} + static void Require(bool value, int line) { if (!value) { std::fprintf(stderr, "Aio check failed at line %d\n", line); diff --git a/core/libs/tests/GuestAjm.cpp b/core/libs/tests/GuestAjm.cpp index 4fca98867a..c7780f5f65 100644 --- a/core/libs/tests/GuestAjm.cpp +++ b/core/libs/tests/GuestAjm.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceAjm.native/include/Api.hpp" #include "SceTypes.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -16,34 +17,6 @@ #include #endif -extern "C" { -int APS5_VABI sceAjmInitialize(std::int64_t, std::uint32_t*); -int APS5_VABI sceAjmFinalize(std::uint32_t); -int APS5_VABI sceAjmDecAt9ParseConfigData(const void*, AjmDecAt9ConfigDataInfo*); -int APS5_VABI sceAjmDecMp3ParseFrame(const std::uint8_t*, std::uint32_t, int, AjmDecMp3ParseFrame*); -int APS5_VABI sceAjmInstanceCreate(std::uint32_t, std::uint32_t, std::uint64_t, std::uint32_t*); -int APS5_VABI sceAjmInstanceDestroy(std::uint32_t, std::uint32_t); -int APS5_VABI sceAjmBatchInitialize(void*, std::size_t, AjmBatchInfo*); -int APS5_VABI sceAjmBatchJobInitialize(AjmBatchInfo*, std::uint32_t, const void*, std::size_t, void*); -int APS5_VABI sceAjmBatchJobDecode(AjmBatchInfo*, std::uint32_t, const void*, std::size_t, void*, std::size_t, void*); -int APS5_VABI sceAjmBatchJobDecodeSingle(AjmBatchInfo*, std::uint32_t, const void*, std::size_t, void*, std::size_t, void*); -int APS5_VABI sceAjmBatchJobRun(AjmBatchInfo*, std::uint32_t, std::uint64_t, const void*, std::size_t, void*, std::size_t, void*, std::size_t); -int APS5_VABI sceAjmBatchJobRunSplit(AjmBatchInfo*, std::uint32_t, std::uint64_t, const AjmBuffer*, std::size_t, const AjmBuffer*, std::size_t, void*, std::size_t); -int APS5_VABI sceAjmBatchJobSetGaplessDecode(AjmBatchInfo*, std::uint32_t, const void*, int, void*); -int APS5_VABI sceAjmBatchJobControl(AjmBatchInfo*, std::uint32_t, std::uint64_t, const void*, std::size_t, void*, std::size_t); -int APS5_VABI sceAjmBatchJobGetGaplessDecode(AjmBatchInfo*, std::uint32_t, void*); -int APS5_VABI sceAjmBatchJobGetCodecInfo(AjmBatchInfo*, std::uint32_t, void*, std::size_t); -int APS5_VABI sceAjmBatchJobGetInfo(AjmBatchInfo*, std::uint32_t, void*); -int APS5_VABI sceAjmBatchStart(std::uint32_t, const AjmBatchInfo*, int, AjmBatchError*, std::uint32_t*); -int APS5_VABI sceAjmBatchWait(std::uint32_t, std::uint32_t, std::uint32_t, AjmBatchError*); -int APS5_VABI sceAjmBatchCancel(std::uint32_t, std::uint32_t); -int APS5_VABI sceAjmBatchJobClearContext(AjmBatchInfo*, std::uint32_t, void*); -int APS5_VABI sceAjmBatchJobSetResampleParameters(AjmBatchInfo*, std::uint32_t, float, std::uint32_t, void*); -int APS5_VABI sceAjmBatchJobGetResampleInfo(AjmBatchInfo*, std::uint32_t, void*); -int APS5_VABI sceAjmBatchJobSetResampleParametersEx(AjmBatchInfo*, std::uint32_t, float, float, std::uint32_t, void*); -int APS5_VABI sceAjmBatchJobDecodeSplit(AjmBatchInfo*, std::uint32_t, const AjmBuffer*, std::size_t, const AjmBuffer*, std::size_t, void*); -} - static void Require(bool value) { if (!value) std::abort(); } namespace { @@ -1999,6 +1972,7 @@ int main() { bool nullBuffersThrow = false; try { sceAjmBatchJobRunSplit(&batchInfo, 0, 0, nullptr, 1, nullptr, 0, nullptr, 0); + } catch (const std::runtime_error&) { nullBuffersThrow = true; } diff --git a/core/libs/tests/GuestAjmVibration.cpp b/core/libs/tests/GuestAjmVibration.cpp index 11351dcb6f..b130f5fbd2 100644 --- a/core/libs/tests/GuestAjmVibration.cpp +++ b/core/libs/tests/GuestAjmVibration.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceAjm.native/include/Api.hpp" #include "SceTypes.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -8,19 +9,6 @@ #include #include -extern "C" { -int APS5_VABI sceAjmInitialize(std::int64_t, std::uint32_t*); -int APS5_VABI sceAjmFinalize(std::uint32_t); -int APS5_VABI sceAjmDecAt9ParseConfigData(const void*, AjmDecAt9ConfigDataInfo*); -int APS5_VABI sceAjmInstanceCreate(std::uint32_t, std::uint32_t, std::uint64_t, std::uint32_t*); -int APS5_VABI sceAjmInstanceDestroy(std::uint32_t, std::uint32_t); -int APS5_VABI sceAjmBatchInitialize(void*, std::size_t, AjmBatchInfo*); -int APS5_VABI sceAjmBatchJobInitialize(AjmBatchInfo*, std::uint32_t, const void*, std::size_t, void*); -int APS5_VABI sceAjmBatchJobRun(AjmBatchInfo*, std::uint32_t, std::uint64_t, const void*, std::size_t, void*, std::size_t, void*, std::size_t); -int APS5_VABI sceAjmBatchStart(std::uint32_t, const AjmBatchInfo*, int, AjmBatchError*, std::uint32_t*); -int APS5_VABI sceAjmBatchWait(std::uint32_t, std::uint32_t, std::uint32_t, AjmBatchError*); -} - namespace { void Require(bool value, const char* message) { if (!value) throw std::runtime_error(message); diff --git a/core/libs/tests/GuestAjmWVorbis.cpp b/core/libs/tests/GuestAjmWVorbis.cpp index 4344e98e00..b017065e10 100644 --- a/core/libs/tests/GuestAjmWVorbis.cpp +++ b/core/libs/tests/GuestAjmWVorbis.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceAjm.native/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -7,23 +8,7 @@ #include #include -struct HeaderPacketParam { - std::uint64_t size; - std::uint32_t channels; - std::uint32_t sampleRate; - std::int32_t bytesPerSecond; - std::int32_t blockSize0Log2; - std::int32_t blockSize1Log2; - std::uint32_t reserved; - const std::uint8_t* setupPacket; - std::uint64_t setupPacketSize; - std::uint8_t* output; - std::uint64_t outputSize; - std::uint64_t writtenSize; -}; -static_assert(sizeof(HeaderPacketParam) == 0x48); - -extern "C" int APS5_VABI sceAjmDecWVorbisCreateHeaderPacket(HeaderPacketParam* param); +static_assert(sizeof(WVorbisHeaderPacketParameter) == 0x48); namespace { @@ -40,11 +25,11 @@ void Require(bool value, const char* message) { constexpr std::array Setup {5, 'v', 'o', 'r', 'b', 'i', 's', 9, 0, 0xAA, 0xBB, 0xCC}; -HeaderPacketParam Valid(std::uint8_t* output, std::size_t outputSize) { - return {sizeof(HeaderPacketParam), 2, 48000, 16000, 8, 11, 0, Setup.data(), Setup.size(), output, outputSize, 0}; +WVorbisHeaderPacketParameter Valid(std::uint8_t* output, std::size_t outputSize) { + return {sizeof(WVorbisHeaderPacketParameter), 2, 48000, 16000, 8, 11, 0, Setup.data(), Setup.size(), output, outputSize, 0}; } -int Create(HeaderPacketParam param) { return sceAjmDecWVorbisCreateHeaderPacket(¶m); } +int Create(WVorbisHeaderPacketParameter param) { return sceAjmDecWVorbisCreateHeaderPacket(¶m); } void TestValidation() { std::array output {}; @@ -56,15 +41,15 @@ void TestValidation() { param.bytesPerSecond = -1; Require(Create(param) == InvalidParameter, "a negative byte rate is refused"); param = Valid(output.data(), output.size()); - param.blockSize0Log2 = 5; + param.shortBlockExponent = 5; Require(Create(param) == InvalidParameter, "a block size below 64 is refused"); - param.blockSize0Log2 = 38; - param.blockSize1Log2 = 38; + param.shortBlockExponent = 38; + param.longBlockExponent = 38; Require(Create(param) == 0, "block size exponents are taken modulo 32 as the console's shift does"); param = Valid(output.data(), output.size()); - param.blockSize1Log2 = 7; + param.longBlockExponent = 7; Require(Create(param) == InvalidParameter, "block size 1 below block size 0 is refused"); - param.blockSize1Log2 = 14; + param.longBlockExponent = 14; Require(Create(param) == InvalidParameter, "a block size above 8192 is refused"); param = Valid(output.data(), output.size()); param.setupPacket = nullptr; @@ -86,7 +71,7 @@ void TestPacket() { output.fill(0xEE); auto param = Valid(output.data(), output.size()); Require(sceAjmDecWVorbisCreateHeaderPacket(¶m) == 0, "a valid header packet is built"); - Require(param.writtenSize == 56 + Setup.size(), "the written size covers the table, both headers and the setup packet"); + Require(param.outputSize == 56 + Setup.size(), "the written size covers the table, both headers and the setup packet"); constexpr std::uint8_t Expected[] { 0, 0, 30, 0, 16, 0, 9, 0, 3, 0, 1, 'v', 'o', 'r', 'b', 'i', 's', 0, 0, 0, 0, 2, 0x80, 0xBB, 0, 0, 0, 0, 0, 0, 0x00, 0xF4, 0x01, 0x00, 0, 0, 0, 0, 0xB8, 1, diff --git a/core/libs/tests/GuestAllocatingStrings.cpp b/core/libs/tests/GuestAllocatingStrings.cpp index 8bf053914b..9bcaf27685 100644 --- a/core/libs/tests/GuestAllocatingStrings.cpp +++ b/core/libs/tests/GuestAllocatingStrings.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/ApplicationHeap.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "SceTypes.hpp" @@ -8,15 +9,6 @@ #include #include -extern "C" { -char* APS5_VABI strndup_nid_postfix(const char*, std::size_t); -char* APS5_VABI strdup_nid_postfix(const char*); -int APS5_VABI asprintf_nid_postfix(char**, const char*, ...); -int APS5_VABI vasprintf_nid_postfix(char**, const char*, VaList*); -void APS5_VABI free_nid_postfix(void*); -int* APS5_VABI __error_nid_postfix(); -} - namespace { void Require(bool value) { diff --git a/core/libs/tests/GuestAllocatorFailures.cpp b/core/libs/tests/GuestAllocatorFailures.cpp index ef2ae3d380..f38e1a1e2d 100644 --- a/core/libs/tests/GuestAllocatorFailures.cpp +++ b/core/libs/tests/GuestAllocatorFailures.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/ApplicationHeap.hpp" #include "prx/libc/include/GuestArena.hpp" #include "prx/libc/include/general/VabiMacros.hpp" @@ -12,18 +13,6 @@ #include #endif -extern "C" { -void* APS5_VABI malloc_nid_postfix(std::size_t); -void* APS5_VABI calloc_nid_postfix(std::size_t, std::size_t); -void* APS5_VABI realloc_nid_postfix(void*, std::size_t); -void* APS5_VABI memalign_nid_postfix(std::size_t, std::size_t); -void* APS5_VABI aligned_alloc_nid_postfix(std::size_t, std::size_t); -int APS5_VABI posix_memalign_nid_postfix(void**, std::size_t, std::size_t); -std::size_t APS5_VABI malloc_usable_size_nid_postfix(void*); -void APS5_VABI free_nid_postfix(void*); -int* APS5_VABI __error_nid_postfix(); -} - namespace { constexpr int NoMemory = 12; @@ -68,6 +57,7 @@ void expectNull(const char* what, int expectedError, TCall call) { if (result != nullptr) { report(what, "returned a block"); free_nid_postfix(result); + return; } if (*__error_nid_postfix() != expectedError) { @@ -133,6 +123,7 @@ int main() { void* aligned = expectBlock("memalign with an alignment that is not a power of two", [&alignment] { return memalign_nid_postfix(alignment.requested, 40); }); if (aligned != nullptr && reinterpret_cast(aligned) % alignment.guaranteed != 0) report("memalign", "did not round the alignment up to a power of two"); free_nid_postfix(aligned); + } auto* block = static_cast(expectBlock("malloc(40)", [] { return malloc_nid_postfix(40); })); @@ -149,6 +140,7 @@ int main() { void* regrown = expectBlock("realloc(emptied, 64)", [emptied] { return realloc_nid_postfix(emptied, 64); }); if (regrown != nullptr && malloc_usable_size_nid_postfix(regrown) != 64) report("realloc(emptied, 64)", "did not hold 64 bytes"); free_nid_postfix(regrown); + } #ifdef ANYPS5_ENABLE_ASAN @@ -186,6 +178,7 @@ int main() { } if (huge != nullptr) { free_nid_postfix(huge); + committed = true; } else if (*__error_nid_postfix() != InvalidArgument) { report("malloc(300 GiB)", "returned NULL without EINVAL"); @@ -225,9 +218,11 @@ int main() { void* small = malloc_nid_postfix(100); if (small == nullptr) report("malloc(100) after a failed huge malloc", "returned NULL"); free_nid_postfix(small); + void* large = malloc_nid_postfix(std::size_t{1} << 20); if (large == nullptr) report("malloc(1 MiB) after a failed huge malloc", "returned NULL"); free_nid_postfix(large); + } #endif diff --git a/core/libs/tests/GuestAmmPlacement.cpp b/core/libs/tests/GuestAmmPlacement.cpp index db65b897bf..9c05f42929 100644 --- a/core/libs/tests/GuestAmmPlacement.cpp +++ b/core/libs/tests/GuestAmmPlacement.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceAmpr/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libc/include/GuestArena.hpp" #include @@ -5,10 +6,6 @@ #include #include -extern "C" { -int APS5_VABI sceAmprAmmGetVirtualAddressRanges(std::uint64_t*, std::uint64_t*, std::uint64_t*, std::uint64_t*); -} - static void Require(bool condition, const char* message) { if (!condition) throw std::runtime_error(message); } diff --git a/core/libs/tests/GuestAmpr.cpp b/core/libs/tests/GuestAmpr.cpp index b17776bcd9..7b5bc20439 100644 --- a/core/libs/tests/GuestAmpr.cpp +++ b/core/libs/tests/GuestAmpr.cpp @@ -1,3 +1,6 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" +#include "prx/libSceAmpr/include/Api.hpp" #include "SceTypes.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libc/include/GuestArena.hpp" @@ -20,136 +23,6 @@ #include #endif -extern "C" { -int APS5_VABI sceAmprCommandBufferConstructor(Apr::CommandBufferObject*); -int APS5_VABI sceAmprAprCommandBufferConstructor(Apr::CommandBufferObject*, std::uint64_t*, std::uint64_t*); -int APS5_VABI sceAmprCommandBufferSetBuffer(Apr::CommandBufferObject*, void*, std::uint32_t); -int APS5_VABI sceAmprCommandBufferReset(Apr::CommandBufferObject*); -void* APS5_VABI sceAmprCommandBufferClearBuffer(Apr::CommandBufferObject*); -std::uint32_t APS5_VABI sceAmprCommandBufferGetCurrentOffset(const Apr::CommandBufferObject*); -std::uint32_t APS5_VABI sceAmprCommandBufferGetNumCommands(const Apr::CommandBufferObject*); -int APS5_VABI sceAmprCommandBufferWriteAddressOnCompletion(Apr::CommandBufferObject*, volatile std::uint64_t*, std::uint64_t); -int APS5_VABI sceAmprCommandBufferPushMarker(Apr::CommandBufferObject*, const char*); -int APS5_VABI sceAmprCommandBufferPushMarkerWithColor(Apr::CommandBufferObject*, const char*, std::uint32_t); -int APS5_VABI sceAmprCommandBufferPopMarker(Apr::CommandBufferObject*); -int APS5_VABI sceAmprCommandBufferSetMarker(Apr::CommandBufferObject*, const char*); -int APS5_VABI sceAmprCommandBufferSetMarkerWithColor(Apr::CommandBufferObject*, const char*, const std::uint32_t*); -std::uint64_t APS5_VABI sceAmprMeasureCommandSizePushMarker(const char*); -std::uint64_t APS5_VABI sceAmprMeasureCommandSizePushMarkerWithColor(const char*, std::uint32_t); -std::uint64_t APS5_VABI sceAmprMeasureCommandSizePopMarker(); -std::uint64_t APS5_VABI sceAmprMeasureCommandSizeWriteAddressOnCompletion(); -std::uint64_t APS5_VABI sceAmprMeasureCommandSizeWriteCounterOnCompletion(); -std::uint64_t APS5_VABI sceAmprMeasureCommandSizeWriteKernelEventQueueOnCompletion(); -void* APS5_VABI sceAmprCommandBufferGetBufferBaseAddress(const Apr::CommandBufferObject*); -std::uint64_t APS5_VABI sceAmprMeasureCommandSizeSetMarker(const char*); -std::uint64_t APS5_VABI sceAmprMeasureCommandSizeSetMarkerWithColor(const char*, std::uint32_t); -int APS5_VABI sceKernelAprSubmitCommandBuffer(const Apr::CommandBufferObject*, std::uint32_t); -int APS5_VABI sceKernelAprSubmitCommandBufferAndGetId(const Apr::CommandBufferObject*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceKernelAprWaitCommandBuffer(std::uint32_t); -int APS5_VABI sceAmprCommandBufferWaitOnAddress(Apr::CommandBufferObject*, volatile std::uint64_t*, std::uint64_t, std::uint8_t, std::uint8_t); -int APS5_VABI sceAmprCommandBufferWaitOnCounter(Apr::CommandBufferObject*, std::uint8_t, std::uint32_t, std::uint8_t, std::uint8_t); -int APS5_VABI sceAmprCommandBufferWriteCounterOnCompletion(Apr::CommandBufferObject*, std::uint8_t, std::uint32_t); -int APS5_VABI sceAmprCommandBufferWriteAddressFromTimeCounterOnCompletion(Apr::CommandBufferObject*, volatile std::uint64_t*); -int APS5_VABI sceAmprCommandBufferWriteAddressFromCounterOnCompletion(Apr::CommandBufferObject*, volatile std::uint64_t*, std::uint8_t); -int APS5_VABI sceAmprCommandBufferWriteAddressFromCounterPairOnCompletion(Apr::CommandBufferObject*, volatile std::uint64_t*, std::uint8_t); -int APS5_VABI sceAmprCommandBufferWriteKernelEventQueueOnCompletion(Apr::CommandBufferObject*, std::uint64_t, std::int32_t, std::uint64_t); -int APS5_VABI sceAmprCommandBufferNop(Apr::CommandBufferObject*, std::uint32_t); -int APS5_VABI sceAmprCommandBufferNopWithData(Apr::CommandBufferObject*, std::uint32_t, const std::uint32_t*); -std::uint64_t APS5_VABI sceAmprMeasureCommandSizeNop(std::uint32_t); -std::uint64_t APS5_VABI sceAmprMeasureCommandSizeNopWithData(std::uint32_t); -int APS5_VABI sceAmprCommandBufferWaitOnAddress_04_00(Apr::CommandBufferObject*, volatile std::uint64_t*, std::uint64_t, std::uint8_t, std::uint8_t); -std::uint64_t APS5_VABI sceAmprMeasureCommandSizeWaitOnAddress_04_00(volatile std::uint64_t*, std::uint64_t, std::uint8_t, std::uint8_t); -int APS5_VABI sceAmprCommandBufferWriteAddressFromTimeCounter_04_00(Apr::CommandBufferObject*, volatile std::uint64_t*, std::uint64_t); -int APS5_VABI sceAmprCommandBufferWriteAddressFromCounter_04_00(Apr::CommandBufferObject*, volatile std::uint64_t*, std::uint8_t, std::uint64_t); -int APS5_VABI sceAmprCommandBufferWriteAddressFromCounterPair_04_00(Apr::CommandBufferObject*, volatile std::uint64_t*, std::uint8_t, std::uint64_t); -int APS5_VABI sceAmprCommandBufferWriteKernelEventQueue_04_00(Apr::CommandBufferObject*, std::uint64_t, std::int32_t, std::uint64_t, std::uint64_t); -std::uint64_t APS5_VABI sceAmprMeasureCommandSizeWriteAddressFromTimeCounter_04_00(volatile std::uint64_t*); -std::uint64_t APS5_VABI sceAmprMeasureCommandSizeWriteAddressFromCounter_04_00(volatile std::uint64_t*, std::uint8_t); -std::uint64_t APS5_VABI sceAmprMeasureCommandSizeWriteAddressFromCounterPair_04_00(volatile std::uint64_t*, std::uint8_t); -int APS5_VABI sceAmprCommandBufferWaitOnCounter_04_00(Apr::CommandBufferObject*, std::uint8_t, std::uint8_t, std::uint64_t, std::uint8_t, std::uint8_t, std::uint64_t, std::uint8_t); -int APS5_VABI sceAmprCommandBufferWriteCounter_04_00(Apr::CommandBufferObject*, std::uint8_t, std::uint8_t, std::uint64_t, std::uint8_t, std::uint8_t); -std::uint64_t APS5_VABI sceAmprMeasureCommandSizeWaitOnCounter_04_00(std::uint8_t, std::uint8_t, std::uint64_t, std::uint8_t, std::uint8_t, std::uint64_t, std::uint8_t); -std::uint64_t APS5_VABI sceAmprMeasureCommandSizeWriteCounter_04_00(std::uint8_t, std::uint8_t, std::uint64_t, std::uint8_t); -int APS5_VABI sceAmprCommandBufferConstructNop(Apr::CommandBufferObject*, std::int16_t, const void*, std::uint32_t, const std::uint32_t*); -int APS5_VABI sceAmprCommandBufferConstructMarker(Apr::CommandBufferObject*, std::uint32_t, const char*, const std::uint32_t*); -int APS5_VABI sceKernelAprResolveFilepathsToIds(const char**, std::uint32_t, std::uint32_t*, std::uint32_t*); -int APS5_VABI sceKernelAprResolveFilepathsToIdsAndFileSizes(const char**, std::uint32_t, std::uint32_t*, std::uint64_t*, std::uint32_t*); -int APS5_VABI sceKernelAprResolveFilepathsToIdsAndFileSizesForEach(const char**, std::uint32_t, std::uint32_t*, std::uint64_t*, int*); -int* APS5_VABI __error_nid_postfix(); -int APS5_VABI sceAmprAprCommandBufferReadFile(Apr::CommandBufferObject*, std::uint64_t*, std::uint64_t*, std::uint32_t, void*, std::uint64_t, std::uint64_t); -std::uint32_t APS5_VABI sceAmprMeasureCommandSizeReadFile(); -int APS5_VABI sceAmprAprCommandBufferReadFileGather(Apr::CommandBufferObject*, std::uint64_t*, std::uint64_t*, std::uint64_t, std::uint64_t); -int APS5_VABI sceAmprAprCommandBufferReadFileScatter(Apr::CommandBufferObject*, std::uint64_t*, std::uint64_t*, void*, std::uint64_t); -int APS5_VABI sceAmprAprCommandBufferReadFileGatherScatter(Apr::CommandBufferObject*, std::uint64_t*, std::uint64_t*, void*, std::uint64_t, std::uint64_t); -int APS5_VABI sceAmprAprCommandBufferResetGatherScatterState(Apr::CommandBufferObject*); -std::uint64_t APS5_VABI sceAmprMeasureCommandSizeReadFileGather(std::uint64_t, std::uint64_t); -std::uint64_t APS5_VABI sceAmprMeasureCommandSizeReadFileScatter(void*, std::uint64_t); -std::uint64_t APS5_VABI sceAmprMeasureCommandSizeReadFileGatherScatter(void*, std::uint64_t, std::uint64_t); -std::uint64_t APS5_VABI sceAmprMeasureCommandSizeResetGatherScatterState(); -std::size_t APS5_VABI sceKernelGetDirectMemorySize(); -int APS5_VABI sceAmprAmmGetUsageStatsData(void*); -int APS5_VABI sceAmprAmmCommandBufferConstructor(Apr::CommandBufferObject*); -int APS5_VABI sceAmprAmmCommandBufferMap(Apr::CommandBufferObject*, std::uint64_t, std::uint64_t, std::int32_t, std::int32_t); -int APS5_VABI sceAmprAmmCommandBufferMapWithGpuMaskId(Apr::CommandBufferObject*, std::uint64_t, std::uint64_t, std::int32_t, std::int32_t, std::uint8_t); -int APS5_VABI sceAmprAmmCommandBufferMapDirect(Apr::CommandBufferObject*, std::uint64_t, std::uint64_t, std::uint64_t, std::int32_t, std::int32_t); -int APS5_VABI sceAmprAmmCommandBufferMapDirectWithGpuMaskId(Apr::CommandBufferObject*, std::uint64_t, std::uint64_t, std::uint64_t, std::int32_t, std::int32_t, std::uint8_t); -int APS5_VABI sceAmprAmmCommandBufferUnmap(Apr::CommandBufferObject*, std::uint64_t, std::uint64_t); -std::int64_t APS5_VABI sceAmprAmmMeasureAmmCommandSizeMap(std::uint64_t, std::uint64_t, std::int32_t, std::int32_t); -std::int64_t APS5_VABI sceAmprAmmMeasureAmmCommandSizeMapWithGpuMaskId(std::uint64_t, std::uint64_t, std::int32_t, std::int32_t, std::uint8_t); -std::int64_t APS5_VABI sceAmprAmmMeasureAmmCommandSizeMapDirect(std::uint64_t, std::uint64_t, std::uint64_t, std::int32_t, std::int32_t); -std::int64_t APS5_VABI sceAmprAmmMeasureAmmCommandSizeMapDirectWithGpuMaskId(std::uint64_t, std::uint64_t, std::uint64_t, std::int32_t, std::int32_t, std::uint8_t); -std::int64_t APS5_VABI sceAmprAmmMeasureAmmCommandSizeUnmap(std::uint64_t, std::uint64_t); -int APS5_VABI sceAmprAmmGiveDirectMemory(std::int64_t, std::int64_t, std::size_t, std::size_t, int, std::int64_t*); -int APS5_VABI sceAmprAmmGetVirtualAddressRanges(std::uint64_t*, std::uint64_t*, std::uint64_t*, std::uint64_t*); -int APS5_VABI sceAmprAmmSubmitCommandBuffer(void*, std::uint32_t, std::uint32_t); -int APS5_VABI sceAmprAmmSubmitCommandBuffer2(void*, std::uint32_t, std::uint32_t, std::uint64_t*, std::uint32_t*); -int APS5_VABI sceAmprAmmSubmitCommandBuffer3(void*, std::uint32_t, std::uint32_t, std::uint32_t*); -int APS5_VABI sceAmprAmmWaitCommandBufferCompletion(std::uint32_t); -int APS5_VABI sceAmprAprCommandBufferMapBegin(Apr::CommandBufferObject*, std::uint64_t, std::uint64_t, std::int32_t, std::int32_t); -int APS5_VABI sceAmprAprCommandBufferMapDirectBegin(Apr::CommandBufferObject*, std::uint64_t, std::uint64_t, std::uint64_t, std::int32_t, std::int32_t); -int APS5_VABI sceAmprAprCommandBufferMapEnd(Apr::CommandBufferObject*); -std::uint64_t APS5_VABI sceAmprMeasureCommandSizeMapBegin(std::uint64_t, std::uint64_t, std::uint32_t, std::uint32_t); -std::uint64_t APS5_VABI sceAmprMeasureCommandSizeMapDirectBegin(std::uint64_t, std::uint64_t, std::uint64_t, std::uint32_t, std::uint32_t); -std::uint64_t APS5_VABI sceAmprMeasureCommandSizeMapEnd(); -int APS5_VABI sceKernelQueryMemoryProtection(void*, void**, void**, int*); -int APS5_VABI sceKernelReserveVirtualRange(void**, std::size_t, int, std::size_t); -int APS5_VABI sceKernelMapFlexibleMemory(void**, std::size_t, int, int); -int APS5_VABI sceKernelMunmap(void*, std::size_t); -int APS5_VABI sceAmprAmmCommandBufferMapAsPrt(Apr::CommandBufferObject*, std::uint64_t, std::uint64_t); -int APS5_VABI sceAmprAmmCommandBufferAllocatePaForPrt(Apr::CommandBufferObject*, std::uint64_t, std::uint64_t, std::int32_t, std::int32_t); -int APS5_VABI sceAmprAmmCommandBufferRemapIntoPrt(Apr::CommandBufferObject*, std::uint64_t, std::uint64_t, std::uint64_t, std::int32_t, std::uint32_t); -int APS5_VABI sceKernelWriteModifyMtypeProtectCommand(void*, std::uint64_t, std::uint64_t, std::uint64_t, std::uint64_t, std::uint64_t, std::uint64_t*); -int APS5_VABI sceKernelWriteRemapIntoPrtCommand(std::uint32_t*, std::uint64_t, std::uint64_t, std::uint64_t, int, int, std::uint64_t*); -int APS5_VABI sceAmprAmmCommandBufferUnmapToPrt(Apr::CommandBufferObject*, std::uint64_t, std::uint64_t); -std::int64_t APS5_VABI sceAmprAmmMeasureAmmCommandSizeMapAsPrt(std::uint64_t, std::uint64_t); -std::int64_t APS5_VABI sceAmprAmmMeasureAmmCommandSizeAllocatePaForPrt(std::uint64_t, std::uint64_t, std::int32_t, std::int32_t); -int APS5_VABI sceAmprAmmCommandBufferRemap(Apr::CommandBufferObject*, std::uint64_t, std::uint64_t, std::uint64_t, std::int32_t); -int APS5_VABI sceAmprAmmCommandBufferRemapWithGpuMaskId(Apr::CommandBufferObject*, std::uint64_t, std::uint64_t, std::uint64_t, std::int32_t, std::uint8_t); -int APS5_VABI sceAmprAmmCommandBufferMultiMap(Apr::CommandBufferObject*, std::uint64_t, std::uint64_t, std::uint64_t, std::int32_t); -int APS5_VABI sceAmprAmmCommandBufferMultiMapWithGpuMaskId(Apr::CommandBufferObject*, std::uint64_t, std::uint64_t, std::uint64_t, std::int32_t, std::uint8_t); -int APS5_VABI sceAmprAmmCommandBufferModifyProtect(Apr::CommandBufferObject*, std::uint64_t, std::uint64_t, std::int32_t, std::int32_t); -int APS5_VABI sceAmprAmmCommandBufferModifyProtectWithGpuMaskId(Apr::CommandBufferObject*, std::uint64_t, std::uint64_t, std::int32_t, std::int32_t, std::uint8_t); -int APS5_VABI sceAmprAmmCommandBufferModifyMtypeProtect(Apr::CommandBufferObject*, std::uint64_t, std::uint64_t, std::int32_t, std::int32_t, std::int32_t); -int APS5_VABI sceAmprAmmCommandBufferModifyMtypeProtectWithGpuMaskId(Apr::CommandBufferObject*, std::uint64_t, std::uint64_t, std::int32_t, std::int32_t, std::int32_t, std::uint8_t); -std::int64_t APS5_VABI sceAmprAmmMeasureAmmCommandSizeRemap(std::uint64_t, std::uint64_t, std::uint64_t, std::int32_t); -std::int64_t APS5_VABI sceAmprAmmMeasureAmmCommandSizeRemapWithGpuMaskId(std::uint64_t, std::uint64_t, std::uint64_t, std::int32_t, std::uint8_t); -std::int64_t APS5_VABI sceAmprAmmMeasureAmmCommandSizeMultiMap(std::uint64_t, std::uint64_t, std::uint64_t, std::int32_t); -std::int64_t APS5_VABI sceAmprAmmMeasureAmmCommandSizeMultiMapWithGpuMaskId(std::uint64_t, std::uint64_t, std::uint64_t, std::int32_t, std::uint8_t); -std::int64_t APS5_VABI sceAmprAmmMeasureAmmCommandSizeModifyProtect(std::uint64_t, std::uint64_t, std::int32_t, std::int32_t); -std::int64_t APS5_VABI sceAmprAmmMeasureAmmCommandSizeModifyProtectWithGpuMaskId(std::uint64_t, std::uint64_t, std::int32_t, std::int32_t, std::uint8_t); -std::int64_t APS5_VABI sceAmprAmmMeasureAmmCommandSizeModifyMtypeProtect(std::uint64_t, std::uint64_t, std::int32_t, std::int32_t, std::int32_t); -std::int64_t APS5_VABI sceAmprAmmMeasureAmmCommandSizeModifyMtypeProtectWithGpuMaskId(std::uint64_t, std::uint64_t, std::int32_t, std::int32_t, std::int32_t, std::uint8_t); -int APS5_VABI sceKernelCreateEqueue(KernelEqueue*, const char*); -int APS5_VABI sceKernelDeleteEqueue(KernelEqueue); -int APS5_VABI sceKernelWaitEqueue(KernelEqueue, KernelEvent*, int, int*, const KernelUseconds*); -int APS5_VABI sceKernelAddAmprEvent(KernelEqueue, int, void*); -int APS5_VABI sceKernelDeleteAmprEvent(KernelEqueue, int); -int APS5_VABI sceKernelGetEventFilter(const KernelEvent*); -std::uintptr_t APS5_VABI sceKernelGetEventId(const KernelEvent*); -std::intptr_t APS5_VABI sceKernelGetEventData(const KernelEvent*); -void* APS5_VABI sceKernelGetEventUserData(const KernelEvent*); -} - static void RequireAt(bool value, int line) { if (value) return; std::fprintf(stderr, "GuestAmpr.cpp:%d: requirement failed\n", line); @@ -749,6 +622,7 @@ void TestReadAtUnseekableOffsetThrows() { bool rejected = false; try { sceKernelAprSubmitCommandBuffer(&buffer, 0); + } catch (const std::runtime_error& error) { rejected = std::string(error.what()).find("returned 0 of 4 bytes") != std::string::npos; } @@ -786,6 +660,7 @@ void TestMalformedCommandSizes() { bool rejected = false; try { sceKernelAprSubmitCommandBuffer(&buffer, 0); + } catch (const std::runtime_error& error) { rejected = std::string(error.what()).starts_with(expected); } @@ -805,6 +680,7 @@ void TestMalformedCommandSizes() { bool rejected = false; try { sceKernelAprSubmitCommandBuffer(&buffer, 0); + } catch (const std::runtime_error& error) { rejected = std::string(error.what()).starts_with("APR: malformed command"); } @@ -932,7 +808,7 @@ void TestAmmRangesAboveHintedMaps() { constexpr std::uint64_t step = 0x400000; void* span = nullptr; Require(sceKernelReserveVirtualRange(&span, 4 * step, 0, 0) == 0); - Require(sceKernelMunmap(span, 4 * step) == 0); + Require(sceKernelMunmap(reinterpret_cast(span), 4 * step) == 0); const auto heap = reinterpret_cast(span); void* placed = span; Require(sceKernelMapFlexibleMemory(&placed, page, 3, 0) == 0 && placed == span); @@ -952,26 +828,26 @@ void TestAmmRangesAboveHintedMaps() { Require(sceKernelMapFlexibleMemory(&mapped, page, 3, 0) == 0); Require(reinterpret_cast(mapped) == hint); Require(hint + page <= start || hint >= multimapEnd); - Require(sceKernelMunmap(mapped, page) == 0); + Require(sceKernelMunmap(reinterpret_cast(mapped), page) == 0); } - Require(sceKernelMunmap(span, page) == 0); + Require(sceKernelMunmap(reinterpret_cast(span), page) == 0); } void TestAmmUsageStats() { std::array stats{}; Require(sceAmprAmmGetUsageStatsData(nullptr) == static_cast(0x80020016)); stats[0] = 0x19; - Require(sceAmprAmmGetUsageStatsData(stats.data()) == static_cast(0x80020016)); + Require(sceAmprAmmGetUsageStatsData(reinterpret_cast(stats.data())) == static_cast(0x80020016)); stats = {0x18, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef}; - Require(sceAmprAmmGetUsageStatsData(stats.data()) == 0); + Require(sceAmprAmmGetUsageStatsData(reinterpret_cast(stats.data())) == 0); Require(stats[0] == 0x18); Require((stats[1] & 0xffffu) == 512u && (stats[1] >> 16u) == 0u); Require((stats[2] & 0xffffffffu) == 7u && (stats[2] >> 32u) == 0u); stats = {0x8, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef}; - Require(sceAmprAmmGetUsageStatsData(stats.data()) == 0); + Require(sceAmprAmmGetUsageStatsData(reinterpret_cast(stats.data())) == 0); Require(stats[0] == 0x8 && stats[1] == 0xdeadbeef && stats[2] == 0xdeadbeef); stats = {0x0, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef}; - Require(sceAmprAmmGetUsageStatsData(stats.data()) == 0); + Require(sceAmprAmmGetUsageStatsData(reinterpret_cast(stats.data())) == 0); Require(stats[0] == 0 && stats[1] == 0xdeadbeef); } @@ -1029,7 +905,7 @@ void TestAmm() { RequireAppended(remaps, offset, commands, Apr::Opcode::AmmUnmap, sceAmprAmmMeasureAmmCommandSizeUnmap(automatic, 2 * page)); Require(sceAmprAmmCommandBufferMapWithGpuMaskId(&remaps.buffer, reused, 6 * page, 0, cpuReadWrite, 1) == 0); std::uint64_t result = ~0ull; - Require(sceAmprAmmSubmitCommandBuffer2(remaps.memory.data(), remaps.Offset(), 0, &result, &id) == 0 && result == 0); + Require(sceAmprAmmSubmitCommandBuffer2(remaps.memory.data(), remaps.Offset(), 0, reinterpret_cast(&result), &id) == 0 && result == 0); Require(sceAmprAmmWaitCommandBufferCompletion(id) == 0); At(reused + 6 * page - 8) = 0x5555; Require(At(reused + 6 * page - 8) == 0x5555); diff --git a/core/libs/tests/GuestAmprCppError.cpp b/core/libs/tests/GuestAmprCppError.cpp index 2cd8eceea5..62d9843363 100644 --- a/core/libs/tests/GuestAmprCppError.cpp +++ b/core/libs/tests/GuestAmprCppError.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libc/include/GuestLocale.hpp" #include "prx/libc/include/ApplicationHeap.hpp" @@ -11,18 +12,16 @@ #include struct TypeRecord { const void* vtable; const char* name; const TypeRecord* base; }; -struct Category { const void* const* vtable; }; -struct ErrorCode { int reserved; int value; const Category* category; }; -struct SystemError { const void* const* vtable; const char* message; ErrorCode code; }; -static_assert(sizeof(SystemError) == 32 && offsetof(SystemError, code) == 16); -using GuestWhat = const char* (APS5_VABI *)(const SystemError*); -using CategoryDelete = void (APS5_VABI *)(const Category*); -using CategoryName = const char* (APS5_VABI *)(const Category*); -using CategoryMessage = void* (APS5_VABI *)(void*, const Category*, int); -using CategoryCondition = ErrorCode (APS5_VABI *)(const Category*, int); -using CategoryEquivalentCondition = bool (APS5_VABI *)(const Category*, int, const ErrorCode*); -using CategoryEquivalentCode = bool (APS5_VABI *)(const Category*, const ErrorCode*, int); +static_assert(sizeof(LibcException::SystemErrorObject) == 32 && offsetof(LibcException::SystemErrorObject, code) == 16); + +using GuestWhat = const char* (APS5_VABI *)(const LibcException::SystemErrorObject*); +using CategoryDelete = void (APS5_VABI *)(const LibcException::CategoryObject*); +using CategoryName = const char* (APS5_VABI *)(const LibcException::CategoryObject*); +using CategoryMessage = void* (APS5_VABI *)(void*, const LibcException::CategoryObject*, int); +using CategoryCondition = LibcException::ErrorCode (APS5_VABI *)(const LibcException::CategoryObject*, int); +using CategoryEquivalentCondition = bool (APS5_VABI *)(const LibcException::CategoryObject*, int, const LibcException::ErrorCode*); +using CategoryEquivalentCode = bool (APS5_VABI *)(const LibcException::CategoryObject*, const LibcException::ErrorCode*, int); struct Expected { int value; const char* what; }; static constexpr Expected Errors[] { @@ -40,11 +39,7 @@ extern const unsigned char _ZTISt9exception_nid_postfix[]; extern const unsigned char _ZTISt11logic_error_nid_postfix[]; extern const unsigned char _ZTISt13runtime_error_nid_postfix[]; extern const unsigned char _ZTISt12system_error_nid_postfix[]; -[[noreturn]] void APS5_VABI _ZSt16_Throw_Cpp_errori_nid_postfix(int code); -void APS5_VABI _ZNSt12system_errorC1ERKS__nid_postfix(SystemError* self, const SystemError* source); -SystemError* APS5_VABI _ZNSt12system_erroraSERKS__nid_postfix(SystemError* self, const SystemError* source); -void APS5_VABI _ZNSt12system_errorD1Ev_nid_postfix(SystemError* self); -void APS5_VABI _ZdlPv_nid_postfix(void* pointer); + void APS5_VABI GuestCatch(int code); const void* FixtureCatchType = nullptr; @@ -71,58 +66,61 @@ static const TypeRecord* TypeOf(const void* const* vtable, int destroySlot) { return static_cast(vtable[destroySlot - 1]); } -static void CheckCategory(const SystemError& error) { - const Category* category = error.code.category; +static void CheckCategory(const LibcException::SystemErrorObject& error) { + const LibcException::CategoryObject* category = error.code.category; Require(category != nullptr, 20); - const TypeRecord* type = TypeOf(category->vtable, 0); + const TypeRecord* type = TypeOf(static_cast(category->vtable), 0); Require(std::strcmp(type->name, "St23_Generic_error_category") == 0, 21); Require(type->base && std::strcmp(type->base->name, "St14error_category") == 0, 22); - Require(std::strcmp(Slot(category->vtable, 2)(category), "generic") == 0, 23); - const ErrorCode condition = Slot(category->vtable, 4)(category, error.code.value); + Require(std::strcmp(Slot(reinterpret_cast(category->vtable), 2)(category), "generic") == 0, 23); + const LibcException::ErrorCode condition = Slot(reinterpret_cast(category->vtable), 4)(category, error.code.value); Require(condition.value == error.code.value && condition.category == category, 24); - const ErrorCode other {0, error.code.value + 1, category}; - const ErrorCode foreign {0, error.code.value, nullptr}; - auto equivalentCondition = Slot(category->vtable, 5); + const LibcException::ErrorCode other {0, error.code.value + 1, category}; + const LibcException::ErrorCode foreign {0, error.code.value, nullptr}; + auto equivalentCondition = Slot(reinterpret_cast(category->vtable), 5); Require(equivalentCondition(category, error.code.value, &condition), 25); Require(!equivalentCondition(category, error.code.value, &other), 26); Require(!equivalentCondition(category, error.code.value, &foreign), 27); - auto equivalentCode = Slot(category->vtable, 6); + auto equivalentCode = Slot(reinterpret_cast(category->vtable), 6); Require(equivalentCode(category, &error.code, error.code.value), 28); Require(!equivalentCode(category, &error.code, error.code.value + 1), 29); Require(!equivalentCode(category, &foreign, error.code.value), 30); GuestLocale::String result {}; - Require(Slot(category->vtable, 3)(&result, category, error.code.value) == &result, 33); + Require(Slot(reinterpret_cast(category->vtable), 3)(&result, category, error.code.value) == &result, 33); const char* data = result.capacity <= 15 ? result.buffer : result.pointer; Require(std::strcmp(data, std::strstr(FixtureExpected->what, ": ") + 2) == 0, 34); if (result.capacity > 15) _ZdlPv_nid_postfix(result.pointer); bool deleteThrew = false; try { - Slot(category->vtable, 1)(category); + Slot(reinterpret_cast(category->vtable), 1)(category); } catch (const std::invalid_argument&) { deleteThrew = true; } Require(deleteThrew, 32); } -static void CheckCopies(const SystemError& error) { - SystemError copy {}; +static void CheckCopies(const LibcException::SystemErrorObject& error) { + LibcException::SystemErrorObject copy {}; _ZNSt12system_errorC1ERKS__nid_postfix(©, &error); - Require(copy.vtable == error.vtable && copy.message == error.message, 40); + + Require(copy.base.vtable == error.base.vtable && copy.base.message == error.base.message, 40); Require(copy.code.value == error.code.value && copy.code.category == error.code.category, 41); - SystemError assigned {}; + LibcException::SystemErrorObject assigned {}; _ZNSt12system_errorC1ERKS__nid_postfix(&assigned, &error); + assigned.code = {0, 0, nullptr}; Require(_ZNSt12system_erroraSERKS__nid_postfix(&assigned, &error) == &assigned, 42); Require(assigned.code.value == error.code.value && assigned.code.category == error.code.category, 43); - _ZNSt12system_errorD1Ev_nid_postfix(&assigned); - _ZNSt12system_errorD1Ev_nid_postfix(©); - Require(copy.message == nullptr && assigned.message == nullptr, 44); + _ZNSt12system_errorD1Ev_nid_postfix(&assigned.base); + _ZNSt12system_errorD1Ev_nid_postfix(©.base); + + Require(copy.base.message == nullptr && assigned.base.message == nullptr, 44); } extern "C" void APS5_VABI FixtureInspect(void* object) { - const auto& error = *static_cast(object); - Require(std::strcmp(TypeOf(error.vtable, 0)->name, "St12system_error") == 0, 10); - const char* what = Slot(error.vtable, 2)(&error); + const auto& error = *static_cast(object); + Require(std::strcmp(TypeOf(static_cast(error.base.vtable), 0)->name, "St12system_error") == 0, 10); + const char* what = Slot(reinterpret_cast(error.base.vtable), 2)(&error); Require(what && std::strcmp(what, FixtureExpected->what) == 0, 11); Require(error.code.value == FixtureExpected->value, 12); CheckCategory(error); @@ -142,6 +140,7 @@ static void CheckOutOfRange(int code) { bool threw = false; try { _ZSt16_Throw_Cpp_errori_nid_postfix(code); + } catch (const std::out_of_range& error) { threw = std::string(error.what()).find(std::to_string(code)) != std::string::npos; } diff --git a/core/libs/tests/GuestAmprThreads.cpp b/core/libs/tests/GuestAmprThreads.cpp index 5e0bddb739..653c2cb941 100644 --- a/core/libs/tests/GuestAmprThreads.cpp +++ b/core/libs/tests/GuestAmprThreads.cpp @@ -1,3 +1,7 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libkernel/Time/include/Time.hpp" +#include "prx/libc/include/Api.hpp" +#include "prx/libSceAmpr/include/Api.hpp" #include "SceTypes.hpp" #include "prx/libc/include/exceptions/Runtime.hpp" #include "prx/libc/include/general/VabiMacros.hpp" @@ -17,11 +21,6 @@ #include #endif -struct GuestXtime { - std::int64_t sec; - std::int64_t nsec; -}; - struct PadTarget { std::atomic* order; std::atomic* destroyed; @@ -43,44 +42,14 @@ struct GuestSystemError { const void* category; }; -using GuestTerminate = void (APS5_VABI*)(); - -struct TestPad { - unsigned (APS5_VABI* const* vtable)(TestPad*); - void* condition; - void* mutex; - bool started; +struct TestPad : GuestPad { PadTarget target; }; +using GuestTerminate = void (APS5_VABI*)(); + extern "C" { -void APS5_VABI _ZNSt4_PadC2Ev_nid_postfix(TestPad* pad); -void APS5_VABI _ZNSt4_PadD2Ev_nid_postfix(TestPad* pad); -void APS5_VABI _ZNSt4_Pad7_LaunchEPP7pthread_nid_postfix(TestPad* pad, Pthread* thread); -void APS5_VABI _ZNSt4_Pad8_ReleaseEv_nid_postfix(TestPad* pad); -int APS5_VABI _Thrd_join_nid_postfix(Pthread thread, int* code); -int APS5_VABI _Thrd_sleep_nid_postfix(const GuestXtime* target, GuestXtime* remaining); -void APS5_VABI _Lock_shared_ptr_spin_lock_nid_postfix(void); -void APS5_VABI _Unlock_shared_ptr_spin_lock_nid_postfix(void); -int APS5_VABI sceAmprWcstombsS(std::size_t* result, char* destination, std::size_t capacity, const std::uint16_t* source, std::size_t limit); -int APS5_VABI scePthreadCreate(Pthread* thread, const PthreadAttr* attr, PthreadEntry entry, void* arg, const char* name); -int APS5_VABI pthread_detach_nid_postfix(Pthread thread); -int APS5_VABI clock_gettime_nid_postfix(int clockId, KernelTimespec* tp); -int APS5_VABI _Cnd_signal_nid_postfix(void** handle); -int APS5_VABI _Cnd_init_with_name_nid_postfix(void** handle, const char* name); -int APS5_VABI _Cnd_init_nid_postfix(void** handle); -void APS5_VABI _Cnd_destroy_nid_postfix(void** handle); -int APS5_VABI _Cnd_wait_nid_postfix(void** condition, void** mutex); -int APS5_VABI _Cnd_broadcast_nid_postfix(void** handle); -int APS5_VABI _Mtx_init_nid_postfix(void** handle, int type); -void APS5_VABI _Mtx_destroy_nid_postfix(void** handle); -int APS5_VABI _Mtx_lock_nid_postfix(void** handle); -int APS5_VABI _Mtx_unlock_nid_postfix(void** handle); -GuestTerminate APS5_VABI _ZSt13set_terminatePFvvE_nid_postfix(GuestTerminate handler); -const GuestTypeInfo* APS5_VABI __cxa_current_exception_type_nid_postfix(); -void* APS5_VABI __cxa_current_primary_exception_nid_postfix(); -LibcException::Header* APS5_VABI __cxa_init_primary_exception_nid_postfix(void* object, std::type_info* type, void (*destructor)(void*)); -[[noreturn]] void APS5_VABI __cxa_call_unexpected_nid_postfix(void* unwindException); + extern const unsigned char _ZTVN10__cxxabiv117__class_type_infoE_nid_postfix[]; } @@ -107,7 +76,7 @@ static std::int64_t RealtimeNanos() { return now.tv_sec * NanosPerSecond + now.tv_nsec; } -static GuestXtime XtimeAfter(std::int64_t nanos) { +static Xtime XtimeAfter(std::int64_t nanos) { const auto target = RealtimeNanos() + nanos; return {target / NanosPerSecond, target % NanosPerSecond}; } @@ -135,10 +104,12 @@ static void* APS5_VABI SpinWorker(void* arg) { auto& context = *static_cast(arg); for (int iteration = 0; iteration < SpinIterations; ++iteration) { _Lock_shared_ptr_spin_lock_nid_postfix(); + if (context.inside.fetch_add(1) != 0) context.overlapped = true; ++context.counter; context.inside.fetch_sub(1); _Unlock_shared_ptr_spin_lock_nid_postfix(); + } return nullptr; } @@ -181,12 +152,12 @@ static void TestThreadSleep() { Require(RealtimeNanos() - before < NanosPerSecond / 2); const auto carried = XtimeAfter(30000000); - const GuestXtime unnormalized{carried.sec - 2, carried.nsec + 2 * NanosPerSecond}; + const Xtime unnormalized{carried.sec - 2, carried.nsec + 2 * NanosPerSecond}; Require(_Thrd_sleep_nid_postfix(&unnormalized, nullptr) == 0); Require(RealtimeNanos() >= carried.sec * NanosPerSecond + carried.nsec); const auto borrowed = XtimeAfter(20000000); - const GuestXtime negative{borrowed.sec + 1, borrowed.nsec - NanosPerSecond}; + const Xtime negative{borrowed.sec + 1, borrowed.nsec - NanosPerSecond}; Require(_Thrd_sleep_nid_postfix(&negative, nullptr) == 0); Require(RealtimeNanos() >= borrowed.sec * NanosPerSecond + borrowed.nsec); @@ -210,6 +181,7 @@ static void TestThreadSleep() { bool rejected = false; try { _Thrd_sleep_nid_postfix(nullptr, nullptr); + } catch (const std::invalid_argument&) { rejected = true; } @@ -225,6 +197,7 @@ static void TestSpinLock() { Require(context.counter == SpinThreads * SpinIterations); _Lock_shared_ptr_spin_lock_nid_postfix(); _Unlock_shared_ptr_spin_lock_nid_postfix(); + } static void TestWcstombs() { @@ -367,6 +340,7 @@ static void TestConditionSignal() { RequireThrows([&] { _Cnd_signal_nid_postfix(&context.mutex); }); RequireThrows([] { _Cnd_init_with_name_nid_postfix(nullptr, "AmprSignal"); }); _Cnd_destroy_nid_postfix(&context.condition); + Require(context.condition == nullptr); RequireThrows([&] { _Cnd_signal_nid_postfix(&context.condition); }); @@ -374,24 +348,28 @@ static void TestConditionSignal() { Require(_Cnd_init_with_name_nid_postfix(&unnamed, nullptr) == ThrdSuccess && unnamed != nullptr); Require(_Cnd_signal_nid_postfix(&unnamed) == ThrdSuccess); _Cnd_destroy_nid_postfix(&unnamed); + void* plain = nullptr; Require(_Cnd_init_nid_postfix(&plain) == ThrdSuccess); Require(_Cnd_signal_nid_postfix(&plain) == ThrdSuccess); _Cnd_destroy_nid_postfix(&plain); _Mtx_destroy_nid_postfix(&context.mutex); + } -static unsigned APS5_VABI PadGo(TestPad* pad) { +static unsigned APS5_VABI PadGo(GuestPad* base) { + auto* pad = static_cast(base); const auto local = pad->target; std::this_thread::sleep_for(std::chrono::milliseconds(20)); local.order->store(local.beforeRelease); _ZNSt4_Pad8_ReleaseEv_nid_postfix(pad); + while (!local.destroyed->load()) std::this_thread::yield(); local.order->store(local.afterRelease); return local.exitCode; } -static constexpr std::array PadVtable{PadGo}; +static constexpr std::array PadVtable{PadGo}; template static bool Throws(TCall call) { @@ -407,6 +385,7 @@ static void ConstructPad(TestPad& pad, std::atomic& order, std::atomic(&thread)); + Require(thread != nullptr); Require(pad.started); Require(order.load() == 1); _ZNSt4_PadD2Ev_nid_postfix(&pad); + Require(!pad.condition && !pad.mutex); Require(order.load() == 1); destroyed = true; @@ -440,9 +421,11 @@ static void TestPadLaunchMany() { std::array threads{}; for (int index = 0; index < Count; ++index) { ConstructPad(pads[index], orders[index], destroyed, index, 100u + index); - _ZNSt4_Pad7_LaunchEPP7pthread_nid_postfix(&pads[index], &threads[index]); + _ZNSt4_Pad7_LaunchEPP7pthread_nid_postfix(&pads[index], reinterpret_cast(&threads[index])); + Require(orders[index].load() == 2 * index + 1); _ZNSt4_PadD2Ev_nid_postfix(&pads[index]); + } destroyed = true; for (int index = 0; index < Count; ++index) { @@ -453,10 +436,12 @@ static void TestPadLaunchMany() { } } -static unsigned APS5_VABI PadGoImmediate(TestPad* pad) { +static unsigned APS5_VABI PadGoImmediate(GuestPad* base) { + auto* pad = static_cast(base); const auto local = pad->target; local.order->store(local.beforeRelease); _ZNSt4_Pad8_ReleaseEv_nid_postfix(pad); + while (!local.destroyed->load()) std::this_thread::yield(); local.order->store(local.afterRelease); return local.exitCode; @@ -464,7 +449,7 @@ static unsigned APS5_VABI PadGoImmediate(TestPad* pad) { static void TestPadConcurrentLaunch() { constexpr int Count = 4; - constexpr std::array immediateVtable{PadGoImmediate}; + constexpr std::array immediateVtable{PadGoImmediate}; std::atomic ready{0}; std::array parents; for (int index = 0; index < Count; ++index) { @@ -477,9 +462,11 @@ static void TestPadConcurrentLaunch() { ready.fetch_add(1); while (ready.load() != Count) std::this_thread::yield(); Pthread thread = nullptr; - _ZNSt4_Pad7_LaunchEPP7pthread_nid_postfix(&pad, &thread); + _ZNSt4_Pad7_LaunchEPP7pthread_nid_postfix(&pad, reinterpret_cast(&thread)); + Require(thread != nullptr && pad.started && order.load() == 2 * index + 1); _ZNSt4_PadD2Ev_nid_postfix(&pad); + std::memset(&pad, 0xcd, sizeof(pad)); destroyed = true; int code = 0; @@ -506,7 +493,7 @@ static void* APS5_VABI DestroyPad(void* arg) { static void APS5_VABI ExitWithSystemErrorCode() { const auto* type = __cxa_current_exception_type_nid_postfix(); const auto* error = static_cast(__cxa_current_primary_exception_nid_postfix()); - _exit(type && error && std::strcmp(type->name, "St12system_error") == 0 ? error->code : 1); + _exit(type && error && std::strcmp(type->name(), "St12system_error") == 0 ? error->code : 1); } template @@ -515,6 +502,7 @@ static int TerminateExitCode(GuestTerminate handler, TCall call) { Require(child >= 0); if (child == 0) { _ZSt13set_terminatePFvvE_nid_postfix(handler); + call(); _exit(2); } @@ -527,7 +515,7 @@ static const GuestTypeInfo UnexpectedType{_ZTVN10__cxxabiv117__class_type_infoE_ static void APS5_VABI ExitWithCaughtType() { const auto* type = __cxa_current_exception_type_nid_postfix(); - _exit(type == &UnexpectedType ? 42 : type == nullptr ? 43 : 1); + _exit(type == reinterpret_cast(&UnexpectedType) ? 42 : type == nullptr ? 43 : 1); } static void TestCallUnexpected() { @@ -536,6 +524,7 @@ static void TestCallUnexpected() { auto* type = reinterpret_cast(const_cast(&UnexpectedType)); LibcException::Header* header = __cxa_init_primary_exception_nid_postfix(object, type, nullptr); __cxa_call_unexpected_nid_postfix(&header->unwind); + }) == 42); Require(TerminateExitCode(ExitWithCaughtType, [] { __cxa_call_unexpected_nid_postfix(nullptr); }) == 43); } @@ -546,7 +535,7 @@ static void TestPadErrors() { Require(Throws([] { _ZNSt4_PadD2Ev_nid_postfix(nullptr); })); Require(Throws([] { _ZNSt4_Pad8_ReleaseEv_nid_postfix(nullptr); })); Pthread thread = nullptr; - Require(Throws([&] { _ZNSt4_Pad7_LaunchEPP7pthread_nid_postfix(nullptr, &thread); })); + Require(Throws([&] { _ZNSt4_Pad7_LaunchEPP7pthread_nid_postfix(nullptr, reinterpret_cast(&thread)); })); std::atomic order{0}; std::atomic destroyed{true}; @@ -564,6 +553,7 @@ static void TestPadErrors() { Require(context.rejected); Require(pad.condition && pad.mutex); _ZNSt4_PadD2Ev_nid_postfix(&pad); + Require(!pad.condition && !pad.mutex); Require(Throws([&] { _ZNSt4_PadD2Ev_nid_postfix(&pad); })); } diff --git a/core/libs/tests/GuestAppContent.cpp b/core/libs/tests/GuestAppContent.cpp index 42be4b89b2..876515f966 100644 --- a/core/libs/tests/GuestAppContent.cpp +++ b/core/libs/tests/GuestAppContent.cpp @@ -1,3 +1,5 @@ +#include "prx/libc/include/Api.hpp" +#include "prx/libSceAppContent/include/Api.hpp" #include "SceTypes.hpp" #include "prx/libc/include/General.hpp" #include @@ -8,27 +10,6 @@ #include #include "ProcessParametersFixture.hpp" -extern "C" { -int APS5_VABI sceAppContentInitialize(const AppContentInitParam*, AppContentBootParam*); -int APS5_VABI sceAppContentAddcontMount(uint32_t, const NpUnifiedEntitlementLabel*, AppContentMountPoint*); -int APS5_VABI sceAppContentAddcontUnmount(const AppContentMountPoint*); -int APS5_VABI sceAppContentAddcontEnqueueDownload(uint32_t, const NpUnifiedEntitlementLabel*); -int APS5_VABI sceAppContentAddcontDelete(uint32_t, const NpUnifiedEntitlementLabel*); -int APS5_VABI sceAppContentGetAddcontDownloadProgress(uint32_t, const NpUnifiedEntitlementLabel*, void*); -int APS5_VABI sceAppContentTemporaryDataMount(AppContentMountPoint*); -int APS5_VABI sceAppContentTemporaryDataMount2(uint32_t, AppContentMountPoint*); -int APS5_VABI sceAppContentTemporaryDataUnmount(const AppContentMountPoint*); -int APS5_VABI sceAppContentTemporaryDataFormat(const AppContentMountPoint*); -int APS5_VABI sceAppContentTemporaryDataGetAvailableSpaceKb(const AppContentMountPoint*, size_t*); -int APS5_VABI access_nid_postfix(const char*, int); -int* APS5_VABI __error_nid_postfix(); -int APS5_VABI sceAppContentGetAddcontInfo(uint32_t, const NpUnifiedEntitlementLabel*, void*); -int APS5_VABI sceAppContentGetAddcontInfoList(uint32_t, void*, uint32_t, uint32_t*); -int APS5_VABI sceAppContentDownloadDataGetAvailableSpaceKb(const AppContentMountPoint*, size_t*); -int APS5_VABI sceAppContentDownloadDataFormat(const AppContentMountPoint*); -int APS5_VABI sceAppContentAppParamGetInt(uint32_t, int32_t*); -} - static constexpr int ErrorParameter = static_cast(0x80D90002); static constexpr int ErrorNotFound = static_cast(0x80D90005); static constexpr int ErrorDrmNoEntitlement = static_cast(0x80D90007); @@ -207,9 +188,9 @@ int main() { std::memset(info, 0x5a, sizeof(info)); unsigned char untouchedInfo[24]; std::memcpy(untouchedInfo, info, sizeof(info)); - Require(sceAppContentGetAddcontInfo(0, &label, info) == ErrorDrmNoEntitlement); + Require(sceAppContentGetAddcontInfo(0, &label, reinterpret_cast(info)) == ErrorDrmNoEntitlement); Require(std::memcmp(info, untouchedInfo, sizeof(info)) == 0); - Require(sceAppContentGetAddcontInfo(0, nullptr, info) == ErrorParameter); + Require(sceAppContentGetAddcontInfo(0, nullptr, reinterpret_cast(info)) == ErrorParameter); Require(sceAppContentGetAddcontInfo(0, &label, nullptr) == ErrorParameter); for (const std::uint32_t version : {0x014fffffu, 0x01500000u, 0x034fffffu, 0x03500000u}) { @@ -220,7 +201,7 @@ int main() { const int infoError = version >= 0x01500000 ? ErrorParameter : ErrorDrmNoEntitlement; const int lateError = version >= 0x03500000 ? ErrorParameter : ErrorNotFound; Require(sceAppContentAddcontMount(0, &label, &mountPoint) == earlyError); - Require(sceAppContentGetAddcontInfo(0, &label, info) == infoError); + Require(sceAppContentGetAddcontInfo(0, &label, reinterpret_cast(info)) == infoError); Require(sceAppContentAddcontEnqueueDownload(0, &label) == earlyError); Require(sceAppContentAddcontDelete(0, &label) == lateError); Require(sceAppContentGetAddcontDownloadProgress(0, &label, progress) == lateError); @@ -234,18 +215,18 @@ int main() { Require(sceAppContentGetAddcontInfoList(0, nullptr, 0, &hitNum) == 0); Require(hitNum == 0); hitNum = 0x5a5a5a5a; - Require(sceAppContentGetAddcontInfoList(0, info, 0, &hitNum) == 0); + Require(sceAppContentGetAddcontInfoList(0, reinterpret_cast(info), 0, &hitNum) == 0); Require(hitNum == 0); hitNum = 0x5a5a5a5a; Require(sceAppContentGetAddcontInfoList(0, nullptr, 1, &hitNum) == 0); Require(hitNum == 0); hitNum = 0x5a5a5a5a; - Require(sceAppContentGetAddcontInfoList(0, info, 1, &hitNum) == 0); + Require(sceAppContentGetAddcontInfoList(0, reinterpret_cast(info), 1, &hitNum) == 0); Require(hitNum == 0); Require(std::memcmp(info, untouchedInfo, sizeof(info)) == 0); - Require(sceAppContentGetAddcontInfoList(0, info, 1, nullptr) == ErrorParameter); + Require(sceAppContentGetAddcontInfoList(0, reinterpret_cast(info), 1, nullptr) == ErrorParameter); Require(sceAppContentGetAddcontInfoList(0, nullptr, 0, nullptr) == ErrorParameter); - Require(sceAppContentGetAddcontInfoList(0, info, 0, nullptr) == ErrorParameter); + Require(sceAppContentGetAddcontInfoList(0, reinterpret_cast(info), 0, nullptr) == ErrorParameter); Require(sceAppContentGetAddcontInfoList(0, nullptr, 1, nullptr) == ErrorParameter); std::filesystem::current_path(original); std::filesystem::remove_all(directory); diff --git a/core/libs/tests/GuestAppInfo.cpp b/core/libs/tests/GuestAppInfo.cpp index 860ff13718..e1220222b5 100644 --- a/core/libs/tests/GuestAppInfo.cpp +++ b/core/libs/tests/GuestAppInfo.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/KernelErrors.hpp" +#include "prx/libkernel/include/Api.hpp" #include "SceTypes.hpp" #include #include @@ -8,16 +10,6 @@ #include #include -extern "C" { -int APS5_VABI sceKernelGetAppInfo(int pid, void* info); -int APS5_VABI getpid_nid_postfix(void); -int APS5_VABI sceKernelUuidCreate(std::uint32_t* uuid); -int APS5_VABI sceKernelCreateUuidV4(std::uint8_t* uuid); -} - -static constexpr int SCE_KERNEL_ERROR_EPERM = static_cast(0x80020001); -static constexpr int SCE_KERNEL_ERROR_EINVAL = static_cast(0x80020016); - static void Require(bool value) { if (!value) std::abort(); } struct AppInfo { diff --git a/core/libs/tests/GuestAppendStreams.cpp b/core/libs/tests/GuestAppendStreams.cpp index 2fb3939330..ee44d84e7f 100644 --- a/core/libs/tests/GuestAppendStreams.cpp +++ b/core/libs/tests/GuestAppendStreams.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/FileStream.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -13,21 +15,6 @@ #include #include -extern "C" { -FileStream* APS5_VABI fopen_nid_postfix(const char*, const char*); -FileStream* APS5_VABI freopen_nid_postfix(const char*, const char*, FileStream*); -std::size_t APS5_VABI fwrite_nid_postfix(const void*, std::size_t, std::size_t, FileStream*); -std::size_t APS5_VABI fread_nid_postfix(void*, std::size_t, std::size_t, FileStream*); -int APS5_VABI fseek_nid_postfix(FileStream*, std::int64_t, int); -std::int64_t APS5_VABI ftell_nid_postfix(FileStream*); -int APS5_VABI fflush_nid_postfix(FileStream*); -int APS5_VABI fclose_nid_postfix(FileStream*); -int APS5_VABI fileno_nid_postfix(FileStream*); -int APS5_VABI ftruncate_nid_postfix(int, std::int64_t); -int APS5_VABI flock_nid_postfix(int, int); -int* APS5_VABI __error_nid_postfix(); -} - static void Check(bool condition, int line) { if (!condition) { std::fprintf(stderr, "append stream check failed at line %d\n", line); diff --git a/core/libs/tests/GuestAppendWrites.cpp b/core/libs/tests/GuestAppendWrites.cpp index 7184c45d5a..806611cae1 100644 --- a/core/libs/tests/GuestAppendWrites.cpp +++ b/core/libs/tests/GuestAppendWrites.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libkernel/File/include/File.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -12,23 +14,6 @@ #include #include -struct GuestIovec { - const void* base; - std::size_t length; -}; - -extern "C" { -int APS5_VABI sceKernelOpen(const char*, int, std::uint16_t); -int APS5_VABI sceKernelClose(int); -std::int64_t APS5_VABI sceKernelWrite(int, const void*, std::size_t); -std::int64_t APS5_VABI sceKernelLseek(int, std::int64_t, int); -std::int64_t APS5_VABI sceKernelPwrite(int, const void*, std::size_t, std::int64_t); -std::int64_t APS5_VABI write_nid_postfix(int, const char*, std::int64_t); -std::int64_t APS5_VABI writev_nid_postfix(int, const GuestIovec*, int); -std::int64_t APS5_VABI pwritev_nid_postfix(int, const GuestIovec*, int, std::int64_t); -int APS5_VABI dup_nid_postfix(int); -} - static void Check(bool condition, int line) { if (!condition) { std::fprintf(stderr, "append check failed at line %d\n", line); @@ -54,17 +39,17 @@ static std::string Line(int writer, int index) { static void WriteLines(int fd, int writer) { for (int index = 0; index < LinesPerWriter; ++index) { - const std::string line = Line(writer, index); + std::string line = Line(writer, index); std::int64_t written = -1; if (writer == 0 || writer == 2) { written = sceKernelWrite(fd, line.data(), line.size()); } else if (writer == 1) { written = write_nid_postfix(fd, line.data(), static_cast(line.size())); } else if (writer == 3) { - const GuestIovec parts[2]{{line.data(), 7}, {line.data() + 7, line.size() - 7}}; + const KernelIovec parts[2]{{line.data(), 7}, {line.data() + 7, line.size() - 7}}; written = writev_nid_postfix(fd, parts, 2); } else { - const GuestIovec parts[2]{{line.data(), 7}, {line.data() + 7, line.size() - 7}}; + const KernelIovec parts[2]{{line.data(), 7}, {line.data() + 7, line.size() - 7}}; written = pwritev_nid_postfix(fd, parts, 2, 0); } Require(written == static_cast(LineLength)); @@ -94,7 +79,7 @@ int main() { Require(contents.size() == static_cast(Writers) * LinesPerWriter * LineLength); std::set> seen; for (std::size_t offset = 0; offset < contents.size(); offset += LineLength) { - const std::string line = contents.substr(offset, LineLength); + std::string line = contents.substr(offset, LineLength); int writer = -1; int index = -1; Require(std::sscanf(line.c_str(), "w%d %d ", &writer, &index) == 2); @@ -116,8 +101,8 @@ int main() { Require(sceKernelLseek(first, 0, FromStart) == 0); Require(sceKernelPwrite(first, positioned.data(), positioned.size(), 0) == static_cast(LineLength)); Require(sceKernelLseek(first, 0, FromCurrent) == 0); - const std::string gathered = Line(9, 2); - const GuestIovec pieces[2]{{gathered.data(), 7}, {gathered.data() + 7, gathered.size() - 7}}; + std::string gathered = Line(9, 2); + const KernelIovec pieces[2]{{gathered.data(), 7}, {gathered.data() + 7, gathered.size() - 7}}; Require(pwritev_nid_postfix(first, pieces, 2, static_cast(LineLength)) == static_cast(LineLength)); Require(sceKernelLseek(first, 0, FromCurrent) == 0); const std::string appended = Contents(); diff --git a/core/libs/tests/GuestAprRead.cpp b/core/libs/tests/GuestAprRead.cpp index a8ba636dc3..004346dbcd 100644 --- a/core/libs/tests/GuestAprRead.cpp +++ b/core/libs/tests/GuestAprRead.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libkernel/Apr/include/AprCommandBuffer.hpp" #include @@ -14,18 +16,6 @@ #include #endif -extern "C" { -int APS5_VABI sceKernelAprResolveFilepathsToIds(const char**, std::uint32_t, std::uint32_t*, std::uint32_t*); -int APS5_VABI sceKernelAprSubmitCommandBuffer(const Apr::CommandBufferObject*, std::uint32_t); -int APS5_VABI sceKernelAllocateDirectMemory(std::int64_t, std::int64_t, std::size_t, std::size_t, int, std::int64_t*); -int APS5_VABI sceKernelMapDirectMemory(void**, std::size_t, int, int, std::int64_t, std::size_t); -int APS5_VABI sceKernelMunmap(void*, std::size_t); -int APS5_VABI sceKernelMprotect(const void*, std::size_t, int); -int APS5_VABI sceKernelReleaseDirectMemory(std::int64_t, std::size_t); -void* APS5_VABI fopen_nid_postfix(const char*, const char*); -int APS5_VABI fclose_nid_postfix(void*); -} - namespace { constexpr std::size_t FileBytes = (16u << 20u) + 257u; @@ -81,13 +71,15 @@ public: Require(sceKernelAllocateDirectMemory(0, 13824ll << 20, MappingBytes, 0x4000, 0, &physical) == 0, "cannot allocate direct memory"); if (sceKernelMapDirectMemory(&pointer, MappingBytes, 0x33, 0, physical, 0x4000) != 0) { sceKernelReleaseDirectMemory(physical, MappingBytes); + throw std::runtime_error("cannot map direct memory"); } } ~DirectBuffer() { - sceKernelMunmap(pointer, MappingBytes); + sceKernelMunmap(reinterpret_cast(pointer), MappingBytes); sceKernelReleaseDirectMemory(physical, MappingBytes); + } std::uint8_t* Data() const { return static_cast(pointer); } @@ -161,9 +153,9 @@ void TestErrors(const Fixture& fixture) { void TestStreams(const Fixture& fixture) { constexpr int StreamCount = 600; - std::vector streams; + std::vector streams; for (int index = 0; index < StreamCount; ++index) { - void* stream = fopen_nid_postfix(("apr_stream_" + std::to_string(index) + ".tmp").c_str(), "w"); + FileStream* stream = fopen_nid_postfix(("apr_stream_" + std::to_string(index) + ".tmp").c_str(), "w"); if (stream == nullptr) break; streams.push_back(stream); } @@ -175,7 +167,7 @@ void TestStreams(const Fixture& fixture) { } catch (const std::runtime_error& failure) { error = failure.what(); } - for (void* stream : streams) fclose_nid_postfix(stream); + for (FileStream* stream : streams) fclose_nid_postfix(stream); for (int index = 0; index < StreamCount; ++index) std::filesystem::remove("apr_stream_" + std::to_string(index) + ".tmp"); Require(error.empty(), ("APR read failed while " + std::to_string(streams.size()) + " guest streams were open: " + error).c_str()); Require(held, "cannot hold 600 guest fopen streams"); diff --git a/core/libs/tests/GuestArrayCallbacks.cpp b/core/libs/tests/GuestArrayCallbacks.cpp index 92bfdfdef7..cdb9079455 100644 --- a/core/libs/tests/GuestArrayCallbacks.cpp +++ b/core/libs/tests/GuestArrayCallbacks.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -11,19 +12,6 @@ using AllocateCallback = void* (APS5_VABI *)(std::size_t); using FreeCallback = void (APS5_VABI *)(void*); using SizedFreeCallback = void (APS5_VABI *)(void*, std::size_t); -extern "C" { -void APS5_VABI __cxa_vec_ctor_nid_postfix(void*, std::size_t, std::size_t, ElementCallback, ElementCallback); -void APS5_VABI __cxa_vec_cctor_nid_postfix(void*, void*, std::size_t, std::size_t, CopyCallback, ElementCallback); -void APS5_VABI __cxa_vec_dtor_nid_postfix(void*, std::size_t, std::size_t, ElementCallback); -void APS5_VABI __cxa_vec_cleanup_nid_postfix(void*, std::size_t, std::size_t, ElementCallback); -void* APS5_VABI __cxa_vec_new_nid_postfix(std::size_t, std::size_t, std::size_t, ElementCallback, ElementCallback); -void* APS5_VABI __cxa_vec_new2_nid_postfix(std::size_t, std::size_t, std::size_t, ElementCallback, ElementCallback, AllocateCallback, FreeCallback); -void* APS5_VABI __cxa_vec_new3_nid_postfix(std::size_t, std::size_t, std::size_t, ElementCallback, ElementCallback, AllocateCallback, SizedFreeCallback); -void APS5_VABI __cxa_vec_delete_nid_postfix(void*, std::size_t, std::size_t, ElementCallback); -void APS5_VABI __cxa_vec_delete2_nid_postfix(void*, std::size_t, std::size_t, ElementCallback, FreeCallback); -void APS5_VABI __cxa_vec_delete3_nid_postfix(void*, std::size_t, std::size_t, ElementCallback, SizedFreeCallback); -} - namespace { constexpr std::size_t Count = 4; @@ -104,18 +92,23 @@ void checkCookie(const void* array) { void checkElements() { reset(source.data()); __cxa_vec_ctor_nid_postfix(source.data(), Count, ElementBytes, construct, destroy); + require(constructed == Count, "constructor count is wrong"); __cxa_vec_dtor_nid_postfix(source.data(), Count, ElementBytes, destroy); + require(destroyed == Count, "destructor count is wrong"); reset(storage.data()); __cxa_vec_cctor_nid_postfix(storage.data(), source.data(), Count, ElementBytes, copy, destroy); + require(copied == Count && std::memcmp(storage.data(), source.data(), source.size()) == 0, "copy construction failed"); __cxa_vec_cleanup_nid_postfix(storage.data(), Count, ElementBytes, destroy); + require(destroyed == Count, "cleanup count is wrong"); __cxa_vec_ctor_nid_postfix(nullptr, Count, ElementBytes, nullptr, nullptr); __cxa_vec_cctor_nid_postfix(nullptr, nullptr, Count, ElementBytes, nullptr, nullptr); __cxa_vec_dtor_nid_postfix(nullptr, Count, ElementBytes, nullptr); __cxa_vec_cleanup_nid_postfix(nullptr, Count, ElementBytes, nullptr); + } void checkAllocation(bool sized) { @@ -123,6 +116,7 @@ void checkAllocation(bool sized) { void* array = sized ? __cxa_vec_new3_nid_postfix(Count, ElementBytes, Padding, construct, destroy, allocate, releaseSized) : __cxa_vec_new2_nid_postfix(Count, ElementBytes, Padding, construct, destroy, allocate, release); + require(array == destination && constructed == Count && allocated == 1, "array allocation failed"); checkCookie(array); if (sized) __cxa_vec_delete3_nid_postfix(array, ElementBytes, Padding, destroy, releaseSized); @@ -133,6 +127,7 @@ void checkAllocation(bool sized) { array = sized ? __cxa_vec_new3_nid_postfix(Count, ElementBytes, Padding, construct, destroy, allocate, releaseSized) : __cxa_vec_new2_nid_postfix(Count, ElementBytes, Padding, construct, destroy, allocate, release); + require(array == nullptr && allocated == 1 && constructed == 0 && freed == 0, "failed allocation invoked element callbacks"); if (sized) __cxa_vec_delete3_nid_postfix(nullptr, ElementBytes, Padding, destroy, releaseSized); else __cxa_vec_delete2_nid_postfix(nullptr, ElementBytes, Padding, destroy, release); @@ -146,8 +141,10 @@ void checkDefaultAllocation() { reset(static_cast(array)); __cxa_vec_ctor_nid_postfix(array, Count, ElementBytes, construct, destroy); __cxa_vec_delete_nid_postfix(array, ElementBytes, Padding, destroy); + require(constructed == Count && destroyed == Count, "default array deletion failed"); __cxa_vec_delete_nid_postfix(nullptr, ElementBytes, Padding, destroy); + } template @@ -170,6 +167,7 @@ void checkRollback(bool sized) { void* array = sized ? __cxa_vec_new3_nid_postfix(Count, ElementBytes, Padding, construct, destroy, allocate, releaseSized) : __cxa_vec_new2_nid_postfix(Count, ElementBytes, Padding, construct, destroy, allocate, release); + failDestroy = true; expectException([&] { if (sized) __cxa_vec_delete3_nid_postfix(array, ElementBytes, Padding, destroy, releaseSized); @@ -183,6 +181,7 @@ void checkCopyRollback() { failCopy = true; expectException([] { __cxa_vec_cctor_nid_postfix(storage.data(), source.data(), Count, ElementBytes, copy, destroy); + }); require(copied == 2 && destroyed == 2, "copy constructor rollback failed"); } diff --git a/core/libs/tests/GuestAt9Enc.cpp b/core/libs/tests/GuestAt9Enc.cpp index 2da60d41b3..470baa0b57 100644 --- a/core/libs/tests/GuestAt9Enc.cpp +++ b/core/libs/tests/GuestAt9Enc.cpp @@ -1,16 +1,9 @@ +#include "prx/libSceAt9Enc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include #include -extern "C" { -int32_t APS5_VABI sceAt9EncClearContext(void* pAt9EncWorkArea, int32_t* pInternalResult); -int32_t APS5_VABI sceAt9EncCreateEncoder(void* pAt9EncWorkArea, void* pAt9EncParam, int32_t memSize, int32_t* pInternalResult); -int32_t APS5_VABI sceAt9EncEncode(void* pAt9EncWorkArea, const void* pInputBuf, void* pOutputBuf, uint32_t inputBufSize, uint32_t outputBufSize, uint32_t* pOutputDataByte, uint32_t* pUsedBufSize, int32_t* pInternalResult); -int32_t APS5_VABI sceAt9EncFlush(void* pAt9EncWorkArea, void* pOutputBuf, uint32_t outputBufSize, uint32_t* pOutputDataByte, int32_t* pInternalResult); -int32_t APS5_VABI sceAt9EncQueryMemSize(void* pAt9EncParam, int32_t* pMemSize, int32_t* pInternalResult); -} - namespace { void Require(bool value) { if (!value) std::abort(); } diff --git a/core/libs/tests/GuestAtoi.cpp b/core/libs/tests/GuestAtoi.cpp index 31d63e6ccd..0d7be20f60 100644 --- a/core/libs/tests/GuestAtoi.cpp +++ b/core/libs/tests/GuestAtoi.cpp @@ -1,12 +1,8 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include -extern "C" { -int APS5_VABI atoi_nid_postfix(const char*); -int* APS5_VABI __error_nid_postfix(); -} - int main() { struct Case { const char* text; diff --git a/core/libs/tests/GuestAtomicBuiltins.cpp b/core/libs/tests/GuestAtomicBuiltins.cpp index 43d9a0f010..7ac75e5ea4 100644 --- a/core/libs/tests/GuestAtomicBuiltins.cpp +++ b/core/libs/tests/GuestAtomicBuiltins.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -5,22 +6,6 @@ #include #include -using Uint128 = unsigned __int128; - -extern "C" { -void APS5_VABI __atomic_load_nid_postfix(std::size_t, void*, void*, int); -void APS5_VABI __atomic_store_nid_postfix(std::size_t, void*, void*, int); -void APS5_VABI __atomic_exchange_nid_postfix(std::size_t, void*, void*, void*, int); -bool APS5_VABI __atomic_compare_exchange_nid_postfix(std::size_t, void*, void*, void*, int, int); -bool APS5_VABI __atomic_is_lock_free_nid_postfix(std::size_t, const void*); -Uint128 APS5_VABI __sync_fetch_and_add_16_nid_postfix(Uint128*, Uint128); -Uint128 APS5_VABI __sync_fetch_and_sub_16_nid_postfix(Uint128*, Uint128); -Uint128 APS5_VABI __sync_fetch_and_and_16_nid_postfix(Uint128*, Uint128); -Uint128 APS5_VABI __sync_fetch_and_or_16_nid_postfix(Uint128*, Uint128); -Uint128 APS5_VABI __sync_fetch_and_xor_16_nid_postfix(Uint128*, Uint128); -Uint128 APS5_VABI __sync_lock_test_and_set_16_nid_postfix(Uint128*, Uint128); -} - static void Require(bool value) { if (!value) std::abort(); } template diff --git a/core/libs/tests/GuestAudio3dParameters.cpp b/core/libs/tests/GuestAudio3dParameters.cpp index dc4e19688a..8382df155a 100644 --- a/core/libs/tests/GuestAudio3dParameters.cpp +++ b/core/libs/tests/GuestAudio3dParameters.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceAudio3d/include/Audio3d.hpp" #include "SceTypes.hpp" #include #include @@ -5,9 +6,6 @@ #include #include -extern "C" void APS5_VABI sceAudio3dGetDefaultOpenParameters(Audio3dOpenParameters* parameters); -extern "C" int APS5_VABI sceAudio3dInitialize(std::int64_t reserved); - static_assert(sizeof(Audio3dOpenParameters) == 0x28); static_assert(offsetof(Audio3dOpenParameters, num_beds) == 0x20); diff --git a/core/libs/tests/GuestAudio3dPort.cpp b/core/libs/tests/GuestAudio3dPort.cpp index 7adbb92ede..5833c4a051 100644 --- a/core/libs/tests/GuestAudio3dPort.cpp +++ b/core/libs/tests/GuestAudio3dPort.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceAudio3d/include/Audio3d.hpp" #include "SceTypes.hpp" #include #include @@ -9,29 +10,6 @@ #include #include -extern "C" { -void APS5_VABI sceAudio3dGetDefaultOpenParameters(Audio3dOpenParameters* parameters); -int APS5_VABI sceAudio3dInitialize(std::int64_t reserved); -int APS5_VABI sceAudio3dTerminate(); -int APS5_VABI sceAudio3dPortOpen(int user_id, const Audio3dOpenParameters* parameters, std::uint32_t* id); -int APS5_VABI sceAudio3dPortClose(std::uint32_t port_id); -int APS5_VABI sceAudio3dPortSetAttribute(std::uint32_t port_id, std::uint32_t attribute_id, const void* attribute, std::size_t attribute_size); -int APS5_VABI sceAudio3dPortGetAttributesSupported(std::uint32_t port_id, std::uint32_t* attributes, std::uint32_t* num_attributes); -int APS5_VABI sceAudio3dPortGetQueueLevel(std::uint32_t port_id, std::uint32_t* queue_level, std::uint32_t* queue_available); -int APS5_VABI sceAudio3dPortAdvance(std::uint32_t port_id); -int APS5_VABI sceAudio3dPortPush(std::uint32_t port_id, std::uint32_t blocking); -int APS5_VABI sceAudio3dPortFlush(std::uint32_t port_id); -int APS5_VABI sceAudio3dObjectReserve(std::uint32_t port_id, std::uint32_t* object_id); -int APS5_VABI sceAudio3dObjectUnreserve(std::uint32_t port_id, std::uint32_t object_id); -int APS5_VABI sceAudio3dObjectSetAttributes(std::uint32_t port_id, std::uint32_t object_id, std::uint64_t num_attributes, const Audio3dAttribute* attribute_array); -int APS5_VABI sceAudio3dBedWrite(std::uint32_t port_id, std::uint32_t num_channels, std::uint32_t format, const void* buffer, std::uint32_t num_samples); -int APS5_VABI sceAudio3dBedWrite2(std::uint32_t port_id, std::uint32_t num_channels, std::uint32_t format, const void* buffer, std::uint32_t num_samples, std::uint32_t output_route, bool restricted); -int APS5_VABI sceAudio3dAudioOutOpen(std::uint32_t port_id, int user_id, std::int32_t type, std::int32_t index, std::uint32_t len, std::uint32_t freq, std::uint32_t param); -int APS5_VABI sceAudio3dAudioOutClose(std::int32_t handle); -int APS5_VABI sceAudio3dAudioOutOutput(std::int32_t handle, const void* ptr); -int APS5_VABI sceAudio3dAudioOutOutputs(AudioOutOutputParam* param, std::uint32_t num); -} - namespace { constexpr int INVALID_PORT = static_cast(0x80EA0002); diff --git a/core/libs/tests/GuestAudio3dSpeakerArray.cpp b/core/libs/tests/GuestAudio3dSpeakerArray.cpp index 4f188b37c4..4a70481074 100644 --- a/core/libs/tests/GuestAudio3dSpeakerArray.cpp +++ b/core/libs/tests/GuestAudio3dSpeakerArray.cpp @@ -1,3 +1,5 @@ +#include "prx/libSceAudioOut/include/AudioOut2.hpp" +#include "prx/libSceAudio3d/include/Audio3d.hpp" #include "SceTypes.hpp" #include #include @@ -5,23 +7,6 @@ #include #include -struct Audio3dSpeakerArrayParameters { - const AudioOut2Position* positions; - std::uint32_t numSpeakers; - std::uint8_t is3d; - void* memory; - std::size_t memorySize; -}; - -extern "C" { -size_t APS5_VABI sceAudio3dGetSpeakerArrayMemorySize(std::uint32_t num_speakers, std::uint8_t is_3d); -int APS5_VABI sceAudio3dCreateSpeakerArray(AudioOut2SpeakerArrayHandle* handle, const Audio3dSpeakerArrayParameters* parameters); -int APS5_VABI sceAudio3dDeleteSpeakerArray(AudioOut2SpeakerArrayHandle handle); -int APS5_VABI sceAudio3dGetSpeakerArrayMixCoefficients(AudioOut2SpeakerArrayHandle handle, AudioOut2Position pos, float spread, float* coefficients, std::uint32_t num_coefficients); -int APS5_VABI sceAudio3dGetSpeakerArrayMixCoefficients2(AudioOut2SpeakerArrayHandle handle, AudioOut2Position pos, float spread, float* coefficients, std::uint32_t num_coefficients, std::uint8_t height_aware, float downmix_spread_radius); -size_t APS5_VABI sceAudioOut2GetSpeakerArrayMemorySize(std::uint32_t num_speakers, std::uint8_t is_3d, std::uint8_t is_ambisonics); -} - namespace { constexpr int INVALID_PARAMETER = static_cast(0x80EA0004); diff --git a/core/libs/tests/GuestAudioIn.cpp b/core/libs/tests/GuestAudioIn.cpp index 15caefd1ec..f968624ea3 100644 --- a/core/libs/tests/GuestAudioIn.cpp +++ b/core/libs/tests/GuestAudioIn.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceAudioIn/include/AudioIn.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -11,23 +12,6 @@ #include #include -extern "C" { -int APS5_VABI sceAudioInInit(); -int APS5_VABI sceAudioInOpen(int, std::uint32_t, std::uint32_t, std::uint32_t, std::uint32_t, std::uint32_t); -int APS5_VABI sceAudioInHqOpen(int, std::uint32_t, std::uint32_t, std::uint32_t, std::uint32_t, std::uint32_t); -int APS5_VABI sceAudioInAsyncOpen(int, std::uint32_t, std::uint32_t, std::uint32_t, std::uint32_t, std::uint32_t); -int APS5_VABI sceAudioInOpenEx(int, std::uint32_t, std::uint32_t, std::uint32_t, std::uint32_t, std::uint32_t, std::uint32_t); -int APS5_VABI sceAudioInHqOpenEx(int, std::uint32_t, std::uint32_t, std::uint32_t, std::uint32_t, std::uint32_t, std::uint32_t); -int APS5_VABI sceAudioInSetCompressorPreGain(); -int APS5_VABI sceAudioInSetNoiseGateThreshold(); -int32_t APS5_VABI sceAudioInIsPadEmbeddedMic(int32_t); -int32_t APS5_VABI sceAudioInGetGain(int32_t, float*); -int32_t APS5_VABI sceAudioInGetRerouteCount(int32_t); -int APS5_VABI sceAudioInInput(int, void*); -int APS5_VABI sceAudioInGetSilentState(int); -int APS5_VABI sceAudioInClose(int); -} - static void Require(bool value) { if (!value) std::abort(); } template diff --git a/core/libs/tests/GuestAudioPropagation.cpp b/core/libs/tests/GuestAudioPropagation.cpp index 65815b617a..b1435209ae 100644 --- a/core/libs/tests/GuestAudioPropagation.cpp +++ b/core/libs/tests/GuestAudioPropagation.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceAudioPropagation/include/Api.hpp" #include "prx/libSceAudioPropagation/AudioPropagation.hpp" #include @@ -14,10 +15,6 @@ #include #endif -extern "C" { -int APS5_VABI sceAudioPropagationSystemLock(); -} - namespace { void Require(bool condition, const char* message) { @@ -386,7 +383,7 @@ int main() { Require(sceAudioPropagationSystemCreate(&options, &memory, &system) == 0, "memory reuse after destroy failed"); Require(sceAudioPropagationSystemDestroy(system) == 0, "second destroy failed"); - RequireThrows([&] { sceAudioPropagationSystemLock(); }, "system lock throw"); + RequireThrows([&] { sceAudioPropagationSystemLock(0); }, "system lock throw"); Require(Resolve("sceAudioPropagationSystemCreate") != nullptr && Resolve("sceAudioPropagationSourceSetAudioPath") != nullptr, "export lookup"); for (const char* name : {"sceAudioPropagationAudioPathInit", "sceAudioPropagationAudioPathPointInit", "sceAudioPropagationMaterialInit", "sceAudioPropagationPortalSettingsInit", "sceAudioPropagationRayInit", "sceAudioPropagationSourceRenderInfoInit", "sceAudioPropagationSourceSetAudioPathsParamInit", "sceAudioPropagationSystemMemoryInit", "sceAudioPropagationSystemOptionInit", "sceAudioPropagationSystem"}) { diff --git a/core/libs/tests/GuestAudiodec.cpp b/core/libs/tests/GuestAudiodec.cpp index 3eb7a370db..ed04f8ee5d 100644 --- a/core/libs/tests/GuestAudiodec.cpp +++ b/core/libs/tests/GuestAudiodec.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceAudiodec/include/Api.hpp" #include "SceTypes.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -8,15 +9,6 @@ #include #include -extern "C" { -std::int32_t APS5_VABI sceAudiodecInitLibrary(std::uint32_t); -std::int32_t APS5_VABI sceAudiodecTermLibrary(std::uint32_t); -std::int32_t APS5_VABI sceAudiodecCreateDecoder(AudiodecCtrl*, std::uint32_t); -std::int32_t APS5_VABI sceAudiodecDeleteDecoder(std::int32_t); -std::int32_t APS5_VABI sceAudiodecDecode(std::int32_t, AudiodecCtrl*); -std::int32_t APS5_VABI sceAudiodecClearContext(std::int32_t); -} - static void Require(bool value) { if (!value) std::abort(); } namespace { diff --git a/core/libs/tests/GuestAvPlayer.cpp b/core/libs/tests/GuestAvPlayer.cpp index 29977f4a42..a784e37263 100644 --- a/core/libs/tests/GuestAvPlayer.cpp +++ b/core/libs/tests/GuestAvPlayer.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceAvPlayer/include/Api.hpp" #include #include #include @@ -25,37 +26,6 @@ #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libSceAvPlayer/include/AvPlayer.hpp" -extern "C" { -AvPlayerInternal* APS5_VABI sceAvPlayerInit(AvPlayerInitData*); -int APS5_VABI sceAvPlayerInitEx(const AvPlayerInitDataEx*, AvPlayerInternal**); -int APS5_VABI sceAvPlayerPostInit(AvPlayerInternal*, const AvPlayerPostInitData*); -int APS5_VABI sceAvPlayerSetLogCallback(void*, void*); -int APS5_VABI sceAvPlayerAddSource(AvPlayerInternal*, const char*); -int APS5_VABI sceAvPlayerStreamCount(AvPlayerInternal*); -int APS5_VABI sceAvPlayerGetStreamInfo(AvPlayerInternal*, std::uint32_t, AvPlayerStreamInfo*); -int APS5_VABI sceAvPlayerGetStreamInfoEx(AvPlayerInternal*, std::uint32_t, AvPlayerStreamInfoEx*); -int APS5_VABI sceAvPlayerEnableStream(AvPlayerInternal*, std::uint32_t); -int APS5_VABI sceAvPlayerChangeStream(AvPlayerInternal*, std::uint32_t, std::uint32_t); -int APS5_VABI sceAvPlayerSetAvailableBandwidth(AvPlayerInternal*, std::uint32_t, std::uint32_t, std::uint32_t); -int APS5_VABI sceAvPlayerStart(AvPlayerInternal*); -int APS5_VABI sceAvPlayerStartEx(AvPlayerInternal*, const AvPlayer::StartInfo*); -int APS5_VABI sceAvPlayerAddSourceEx(AvPlayerInternal*, std::uint32_t, const void*); -int APS5_VABI sceAvPlayerDisableStream(AvPlayerInternal*, std::uint32_t); -int APS5_VABI sceAvPlayerStop(AvPlayerInternal*); -int APS5_VABI sceAvPlayerPause(AvPlayerInternal*); -int APS5_VABI sceAvPlayerResume(AvPlayerInternal*); -int APS5_VABI sceAvPlayerJumpToTime(AvPlayerInternal*, std::uint64_t); -int APS5_VABI sceAvPlayerSetLooping(AvPlayerInternal*, Bool); -int APS5_VABI sceAvPlayerSetAvSyncMode(AvPlayerInternal*, std::uint32_t); -int APS5_VABI sceAvPlayerSetTrickSpeed(AvPlayerInternal*, std::int32_t); -Bool APS5_VABI sceAvPlayerGetVideoDataEx(AvPlayerInternal*, AvPlayerFrameInfoEx*); -Bool APS5_VABI sceAvPlayerGetVideoData(AvPlayerInternal*, AvPlayerFrameInfo*); -Bool APS5_VABI sceAvPlayerGetAudioData(AvPlayerInternal*, AvPlayerFrameInfo*); -Bool APS5_VABI sceAvPlayerIsActive(AvPlayerInternal*); -std::uint64_t APS5_VABI sceAvPlayerCurrentTime(AvPlayerInternal*); -int APS5_VABI sceAvPlayerClose(AvPlayerInternal*); -} - namespace { constexpr int Width = 100; diff --git a/core/libs/tests/GuestAvailableCpumask.cpp b/core/libs/tests/GuestAvailableCpumask.cpp index 31775180e5..1450a36bce 100644 --- a/core/libs/tests/GuestAvailableCpumask.cpp +++ b/core/libs/tests/GuestAvailableCpumask.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "SceTypes.hpp" #include #include @@ -9,28 +11,6 @@ #include #include -extern "C" { -KernelCpumask APS5_VABI sceKernelGetAvailableCpumask(void); -int APS5_VABI scePthreadCreate(Pthread* thread, const PthreadAttr* attr, PthreadEntry entry, void* arg, const char* name); -int APS5_VABI scePthreadJoin(Pthread thread, void** retval); -Pthread APS5_VABI scePthreadSelf(); -int APS5_VABI scePthreadGetaffinity(Pthread thread, KernelCpumask* mask); -int APS5_VABI scePthreadSetaffinity(Pthread thread, KernelCpumask mask); -int APS5_VABI scePthreadAttrInit(PthreadAttr* attr); -int APS5_VABI scePthreadAttrDestroy(PthreadAttr* attr); -int APS5_VABI scePthreadAttrGetaffinity(const PthreadAttr* attr, KernelCpumask* mask); -int APS5_VABI scePthreadAttrSetaffinity(PthreadAttr* attr, KernelCpumask mask); -int APS5_VABI cpuset_getaffinity_nid_postfix(int level, int which, std::int64_t id, std::size_t size, void* mask); -int APS5_VABI cpuset_setaffinity_nid_postfix(int level, int which, std::int64_t id, std::size_t size, const void* mask); -int APS5_VABI getpid_nid_postfix(void); -int* APS5_VABI __error_nid_postfix(); -Pthread APS5_VABI pthread_self_nid_postfix(void); -int APS5_VABI pthread_getaffinity_np_nid_postfix(Pthread thread, std::size_t cpusetSize, void* cpuset); -int APS5_VABI pthread_setaffinity_np_nid_postfix(Pthread thread, std::size_t cpusetSize, const void* cpuset); -int APS5_VABI scePthreadGetthreadid(void); -int APS5_VABI sceKernelGetCurrentCpu(void); -} - static constexpr int SCE_OK = 0; static constexpr int PS5_LOGICAL_CPUS = 16; @@ -120,6 +100,7 @@ static void* APS5_VABI SetCpuset(void* arg) { std::uint64_t set[4] = {cpu | (1ull << 40), 0, 0, 0}; result->results[0] = cpuset_setaffinity_nid_postfix(3, 1, -1, 8, set); scePthreadGetaffinity(scePthreadSelf(), &result->affinity[0]); + set[1] = 1; result->results[1] = cpuset_setaffinity_nid_postfix(3, 1, -1, 16, set) == -1 && *__error_nid_postfix() == 22; set[1] = 0; @@ -130,9 +111,11 @@ static void* APS5_VABI SetCpuset(void* arg) { const std::uint64_t unavailable[1] = {1ull << 40}; result->results[6] = cpuset_setaffinity_nid_postfix(3, 1, -1, 8, unavailable) == -1 && *__error_nid_postfix() == 11; scePthreadGetaffinity(scePthreadSelf(), &result->affinity[1]); + const std::uint64_t process[1] = {cpu}; result->results[7] = cpuset_setaffinity_nid_postfix(3, 2, getpid_nid_postfix(), 8, process); scePthreadGetaffinity(scePthreadSelf(), &result->affinity[2]); + return nullptr; } diff --git a/core/libs/tests/GuestBacktrace.cpp b/core/libs/tests/GuestBacktrace.cpp index 7ae55383e3..8d3f597480 100644 --- a/core/libs/tests/GuestBacktrace.cpp +++ b/core/libs/tests/GuestBacktrace.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -13,8 +14,7 @@ #include extern "C" { -int APS5_VABI sceLibcBacktraceGetBufferSize_nid_postfix(int, int*, std::size_t*); -int APS5_VABI sceLibcBacktraceSelf_nid_postfix(int, void*, std::size_t, int*); + #if defined(_WIN32) std::string BacktraceModulePath_nid_no_patch(HMODULE, std::size_t); #endif diff --git a/core/libs/tests/GuestBadOptionalAccess.cpp b/core/libs/tests/GuestBadOptionalAccess.cpp index a4280e3ef5..0b9d8edfe9 100644 --- a/core/libs/tests/GuestBadOptionalAccess.cpp +++ b/core/libs/tests/GuestBadOptionalAccess.cpp @@ -1,19 +1,18 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include #include struct TypeRecord { const void* const* vtable; const char* name; const TypeRecord* base; }; -struct Object { const void* vtable; const char* message; }; -struct Vtable { std::ptrdiff_t offset; const TypeRecord* type; const void* destroy; const void* deleteObject; const char* (APS5_VABI *what)(const Object*); }; + +struct Vtable { std::ptrdiff_t offset; const TypeRecord* type; const void* destroy; const void* deleteObject; const char* (APS5_VABI *what)(const LibcException::ExceptionObject*); }; extern "C" { extern const TypeRecord _ZTISt9exception_nid_postfix; extern const TypeRecord _ZTISt19bad_optional_access_nid_postfix; extern const Vtable _ZTVSt19bad_optional_access_nid_postfix; -void APS5_VABI _ZNSt19bad_optional_accessC1Ev_nid_postfix(Object*); -void APS5_VABI _ZNSt19bad_optional_accessD1Ev_nid_postfix(Object*); -[[noreturn]] void APS5_VABI _ZSt26_Throw_bad_optional_accessv_nid_postfix(); + } static void Require(bool value) { if (!value) std::abort(); } @@ -24,14 +23,17 @@ int main() { Require(type.base == &_ZTISt9exception_nid_postfix); const auto& table = _ZTVSt19bad_optional_access_nid_postfix; Require(table.offset == 0 && table.type == &type && table.what != nullptr); - Object object{}; + LibcException::ExceptionObject object{}; _ZNSt19bad_optional_accessC1Ev_nid_postfix(&object); + Require(object.vtable == &table.destroy); Require(std::strcmp(table.what(&object), "bad_optional_access") == 0); _ZNSt19bad_optional_accessD1Ev_nid_postfix(&object); + bool thrown = false; try { _ZSt26_Throw_bad_optional_accessv_nid_postfix(); + } catch (...) { thrown = true; } diff --git a/core/libs/tests/GuestBessel.cpp b/core/libs/tests/GuestBessel.cpp index 6650201428..4ff093ad18 100644 --- a/core/libs/tests/GuestBessel.cpp +++ b/core/libs/tests/GuestBessel.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -10,19 +11,6 @@ #include #include -extern "C" { -double APS5_VABI j0_nid_postfix(double); -double APS5_VABI j1_nid_postfix(double); -double APS5_VABI jn_nid_postfix(int, double); -double APS5_VABI y0_nid_postfix(double); -double APS5_VABI y1_nid_postfix(double); -double APS5_VABI yn_nid_postfix(int, double); -float APS5_VABI y0f_nid_postfix(float); -float APS5_VABI y1f_nid_postfix(float); -float APS5_VABI ynf_nid_postfix(int, float); -int* APS5_VABI __error_nid_postfix(); -} - static void Require(bool value) { if (!value) std::abort(); } static double Value(std::uint64_t bits) { return std::bit_cast(bits); } @@ -99,6 +87,7 @@ static void CheckSecondKind() { y0_nid_postfix(input); y1_nid_postfix(input); yn_nid_postfix(3, input); + Require(std::fetestexcept(FE_DIVBYZERO | FE_INVALID) == 0); } } diff --git a/core/libs/tests/GuestBinaryWord.cpp b/core/libs/tests/GuestBinaryWord.cpp index 2720a1f894..cfb2f004f0 100644 --- a/core/libs/tests/GuestBinaryWord.cpp +++ b/core/libs/tests/GuestBinaryWord.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/FileStream.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -10,22 +11,6 @@ #include #include -extern "C" { -int APS5_VABI getw_nid_postfix(FileStream*); -int APS5_VABI putw_nid_postfix(int, FileStream*); -FileStream* APS5_VABI fopen_nid_postfix(const char*, const char*); -int APS5_VABI fclose_nid_postfix(FileStream*); -std::size_t APS5_VABI fread_nid_postfix(void*, std::size_t, std::size_t, FileStream*); -std::size_t APS5_VABI fwrite_nid_postfix(const void*, std::size_t, std::size_t, FileStream*); -int APS5_VABI fseek_nid_postfix(FileStream*, std::int64_t, int); -std::int64_t APS5_VABI ftell_nid_postfix(FileStream*); -int APS5_VABI ungetc_nid_postfix(int, FileStream*); -int APS5_VABI fgetc_nid_postfix(FileStream*); -void APS5_VABI clearerr_nid_postfix(FileStream*); -void APS5_VABI flockfile_nid_postfix(FileStream*); -void APS5_VABI funlockfile_nid_postfix(FileStream*); -} - namespace { void Require(bool condition, const char* message) { @@ -75,6 +60,7 @@ void CheckShortReads(const char* path) { Require((stream->GuestState().flags & 0x60) == 0x20, "short-read EOF flag"); Require(ftell_nid_postfix(stream) == static_cast(length), "consume incomplete word bytes"); clearerr_nid_postfix(stream); + Require((stream->GuestState().flags & 0x60) == 0, "clear short-read status"); Require(fclose_nid_postfix(stream) == 0, "close incomplete word"); } @@ -107,8 +93,10 @@ void CheckConcurrentWrites(const char* path) { auto* stream = fopen_nid_postfix(path, "w+b"); Require(stream != nullptr, "open shared stream"); flockfile_nid_postfix(stream); + Require(putw_nid_postfix(0, stream) == 0, "putw accepts a lock held by its caller"); funlockfile_nid_postfix(stream); + const auto writer = [stream](int value) { for (int count = 0; count < 256; ++count) Require(putw_nid_postfix(value, stream) == 0, "concurrent word write"); diff --git a/core/libs/tests/GuestBluetoothHid.cpp b/core/libs/tests/GuestBluetoothHid.cpp index fb37aa3c23..fbc4db06e2 100644 --- a/core/libs/tests/GuestBluetoothHid.cpp +++ b/core/libs/tests/GuestBluetoothHid.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceBluetoothHid/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -6,36 +7,6 @@ #include #include -struct BluetoothHidEvent; -struct BluetoothHidDeviceInfo; -struct BluetoothHidThreadParam { - std::int32_t priority; - std::uint32_t padding; - std::uint64_t affinityMask; - std::uint32_t reserved; - std::uint32_t tailPadding; -}; -struct BluetoothHidParam { - const BluetoothHidThreadParam* threadParam; - std::uint32_t reserved; - std::uint32_t padding; -}; -using BluetoothHidCallback = void (APS5_VABI *)(const BluetoothHidEvent*, std::int32_t, void*); - -extern "C" { -std::int32_t APS5_VABI sceBluetoothHidInit(); -std::int32_t APS5_VABI sceBluetoothHidRegisterCallback(BluetoothHidCallback callback, void* userData, const BluetoothHidParam* param); -std::int32_t APS5_VABI sceBluetoothHidUnregisterCallback(); -std::int32_t APS5_VABI sceBluetoothHidRegisterDevice(std::uint16_t vendorId, std::uint16_t productId); -std::int32_t APS5_VABI sceBluetoothHidUnregisterDevice(std::uint16_t vendorId, std::uint16_t productId); -int APS5_VABI sceBluetoothHidGetInputReport(std::uint64_t, std::uint8_t); -int APS5_VABI sceBluetoothHidDebugGetVersion(); -int APS5_VABI sceBluetoothHidGetDeviceInfo(std::int32_t, BluetoothHidDeviceInfo*); -int APS5_VABI sceBluetoothHidDisconnectDevice(std::int32_t); -int APS5_VABI sceBluetoothHidGetFeatureReport(std::uint64_t, std::uint8_t); -int APS5_VABI sceBluetoothHidSetFeatureReport(std::uint64_t, std::uint8_t, const void*, std::size_t); -} - namespace { int callbackCalls = 0; @@ -82,6 +53,7 @@ int main() { threw = false; try { sceBluetoothHidGetInputReport(0, 0); + } catch (const std::runtime_error&) { threw = true; } @@ -90,6 +62,7 @@ int main() { threw = false; try { sceBluetoothHidGetDeviceInfo(0, nullptr); + } catch (const std::runtime_error&) { threw = true; } @@ -97,6 +70,7 @@ int main() { threw = false; try { sceBluetoothHidDisconnectDevice(0); + } catch (const std::runtime_error&) { threw = true; } @@ -104,6 +78,7 @@ int main() { threw = false; try { sceBluetoothHidGetFeatureReport(0, 0); + } catch (const std::runtime_error&) { threw = true; } @@ -111,6 +86,7 @@ int main() { threw = false; try { sceBluetoothHidSetFeatureReport(0, 0, nullptr, 0); + } catch (const std::runtime_error&) { threw = true; } diff --git a/core/libs/tests/GuestBoundsChecking.cpp b/core/libs/tests/GuestBoundsChecking.cpp index 2fe88a5685..fb7977eaa8 100644 --- a/core/libs/tests/GuestBoundsChecking.cpp +++ b/core/libs/tests/GuestBoundsChecking.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/FileStream.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -8,19 +9,8 @@ #include #include -using GuestContextCompare = int (APS5_VABI*)(const void*, const void*, void*); - extern "C" { -void* APS5_VABI set_constraint_handler_s_nid_postfix(void*); -void* APS5_VABI bsearch_s_nid_postfix(const void*, const void*, std::size_t, std::size_t, GuestContextCompare, void*); -std::uint16_t* APS5_VABI wcstok_s_nid_postfix(std::uint16_t*, std::size_t*, const std::uint16_t*, std::uint16_t**); -int APS5_VABI wctomb_s_nid_postfix(int*, char*, std::size_t, std::uint16_t); -int APS5_VABI wcrtomb_s_nid_postfix(std::size_t*, char*, std::size_t, std::uint16_t, void*); -int APS5_VABI mbstowcs_s_nid_postfix(std::size_t*, std::uint16_t*, std::size_t, const char*, std::size_t); -int APS5_VABI mbsrtowcs_s_nid_postfix(std::size_t*, std::uint16_t*, std::size_t, const char**, std::size_t, void*); -char* APS5_VABI gets_s_nid_postfix(char*, std::size_t); -FileStream* APS5_VABI fopen_nid_postfix(const char*, const char*); -int APS5_VABI fclose_nid_postfix(FileStream*); + extern FileStream* __stdinp_nid_postfix; } @@ -238,6 +228,7 @@ void CheckGets(const char* path) { RequireViolation(before, "gets_s: bad argument", 22); __stdinp_nid_postfix = saved; fclose_nid_postfix(stream); + std::remove(path); } @@ -246,6 +237,7 @@ void CheckGets(const char* path) { int main(int argc, char** argv) { Require(argc > 1, "usage: guest_bounds_checking_tests "); set_constraint_handler_s_nid_postfix(reinterpret_cast(RecordConstraint)); + CheckBsearch(); CheckWcstok(); CheckWideToMultibyte(); diff --git a/core/libs/tests/GuestCamera.cpp b/core/libs/tests/GuestCamera.cpp index 95647e9a97..c074795e23 100644 --- a/core/libs/tests/GuestCamera.cpp +++ b/core/libs/tests/GuestCamera.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceCamera/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -5,20 +6,6 @@ #include #include -extern "C" { -int APS5_VABI sceCameraIsAttached(std::int32_t index); -int APS5_VABI sceCameraOpen(void); -int APS5_VABI sceCameraClose(void); -int APS5_VABI sceCameraStart(void); -int APS5_VABI sceCameraStop(void); -int APS5_VABI sceCameraGetConfig(void); -int APS5_VABI sceCameraSetConfig(void); -int APS5_VABI sceCameraSetAttribute(void); -int APS5_VABI sceCameraGetDeviceInfo(void); -int APS5_VABI sceCameraGetFrameData(void); -int APS5_VABI sceCameraIsValidFrameData(void); -} - namespace { constexpr int ErrorParam = static_cast(0x802E0000u); diff --git a/core/libs/tests/GuestCes.cpp b/core/libs/tests/GuestCes.cpp index de0903e090..b978d9f935 100644 --- a/core/libs/tests/GuestCes.cpp +++ b/core/libs/tests/GuestCes.cpp @@ -1,57 +1,12 @@ +#include "prx/libSceCesCs/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" +#include #include #include #include #include #include -extern "C" { -const std::uint8_t* APS5_VABI sceCesRefersUcsProfileCp1252(void); -const std::uint8_t* APS5_VABI sceCesRefersUcsProfileCp1251(void); -const std::uint8_t* APS5_VABI sceCesRefersUcsProfileCp1250(void); -const std::uint8_t* APS5_VABI sceCesRefersUcsProfileIso8859_1(void); -const std::uint8_t* APS5_VABI sceCesRefersUcsProfileIso8859_2(void); -const std::uint8_t* APS5_VABI sceCesRefersUcsProfileIso8859_4(void); -const std::uint8_t* APS5_VABI sceCesRefersUcsProfileIso8859_5(void); -const std::uint8_t* APS5_VABI sceCesRefersUcsProfileIso8859_9(void); -const std::uint8_t* APS5_VABI sceCesRefersUcsProfileIso8859_10(void); -const std::uint8_t* APS5_VABI sceCesRefersUcsProfileIso8859_13(void); -const std::uint8_t* APS5_VABI sceCesRefersUcsProfileIso8859_14(void); -const std::uint8_t* APS5_VABI sceCesRefersUcsProfileIso8859_15(void); -const std::uint8_t* APS5_VABI sceCesRefersUcsProfileIso8859_16(void); -const std::uint8_t* APS5_VABI sceCesRefersUcsProfileCp437(void); -const std::uint8_t* APS5_VABI sceCesRefersUcsProfileCp737(void); -const std::uint8_t* APS5_VABI sceCesRefersUcsProfileCp775(void); -const std::uint8_t* APS5_VABI sceCesRefersUcsProfileCp850(void); -const std::uint8_t* APS5_VABI sceCesRefersUcsProfileCp852(void); -const std::uint8_t* APS5_VABI sceCesRefersUcsProfileCp855(void); -const std::uint8_t* APS5_VABI sceCesRefersUcsProfileCp860(void); -const std::uint8_t* APS5_VABI sceCesRefersUcsProfileCp861(void); -const std::uint8_t* APS5_VABI sceCesRefersUcsProfileCp862(void); -const std::uint8_t* APS5_VABI sceCesRefersUcsProfileCp863(void); -const std::uint8_t* APS5_VABI sceCesRefersUcsProfileCp865(void); -const std::uint8_t* APS5_VABI sceCesRefersUcsProfileCp866(void); -const std::uint8_t* APS5_VABI sceCesRefersUcsProfileKoi8R(void); -const std::uint8_t* APS5_VABI sceCesRefersUcsProfileKoi8U(void); -const std::uint8_t* APS5_VABI sceCesRefersUcsProfileCp1254(void); -const std::uint8_t* APS5_VABI sceCesRefersUcsProfileCp1256(void); -const std::uint8_t* APS5_VABI sceCesRefersUcsProfileCp1258(void); -int APS5_VABI sceCesMbcsUcsContextInit(void*, const void*); -void* APS5_VABI sceCesUcsProfileInitEucJpCp51932(void*); -int APS5_VABI sceCesUtf8StrToMbcsStr(void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint8_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesUtf8StrGetMbcsLen(void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint32_t*); -int APS5_VABI sceCesMbcsStrToUtf8Str(void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint8_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesMbcsStrGetUtf8Len(void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint32_t*); -int APS5_VABI sceCesUcs2StrToMbcsStr(void*, const std::uint16_t*, std::uint32_t, std::uint32_t*, std::uint8_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesUcs2StrGetMbcsLen(void*, const std::uint16_t*, std::uint32_t, std::uint32_t*, std::uint32_t*); -int APS5_VABI sceCesMbcsStrToUcs2Str(void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint16_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesMbcsStrGetUcs2Len(void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint32_t*); -int APS5_VABI sceCesEucJpToUcs2(const void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint16_t*); -int APS5_VABI sceCesSbcToUtf8(const std::uint8_t*, std::uint8_t, std::uint8_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesUtf8ToSbc(const std::uint8_t*, std::uint32_t, std::uint32_t*, const std::uint8_t*, std::uint8_t*); -void* APS5_VABI sceCesUcsProfileInitSJis1997Cp932(void*); -} - static void Require(bool value) { if (!value) std::abort(); } static void RequireSbcToUtf8(const std::uint8_t* profile, std::uint8_t sbc, const char* expected) { @@ -75,6 +30,320 @@ static int Utf8ToSbc(const std::uint8_t* profile, const char* utf8, std::uint32_ return sceCesUtf8ToSbc(reinterpret_cast(utf8), utf8max, &length, profile, &sbc); } +static void RequireSbcRoundTrip(const std::uint8_t* profile, std::initializer_list unassigned) { + constexpr int unassignedCode = static_cast(0x805C0020); + for (int sbc = 1; sbc < 256; ++sbc) { + std::uint8_t utf8[4] = {}; + std::uint32_t length = 7; + std::uint8_t back = 0; + if (std::find(unassigned.begin(), unassigned.end(), sbc) != unassigned.end()) { + Require(sceCesSbcToUtf8(profile, static_cast(sbc), utf8, sizeof(utf8), &length) == unassignedCode && length == 0); + continue; + } + Require(sceCesSbcToUtf8(profile, static_cast(sbc), utf8, sizeof(utf8), &length) == 0); + Require(sceCesUtf8ToSbc(utf8, length, &length, profile, &back) == 0 && back == sbc); + } +} + +struct MeasuredUtf8 { + const char* bytes; + std::uint32_t available; + int result; + std::uint32_t length; +}; + +static void RequireMeasuredUtf8ToSbc(const std::uint8_t* profile) { + constexpr MeasuredUtf8 cases[] = { + {"\xE2\x41", 1, static_cast(0x805C0011), 3}, + {"\xE2\x41", 2, static_cast(0x805C0014), 2}, + {"\xE2\x41\xAC", 3, static_cast(0x805C0014), 1}, + {"\xE2\x82\x41", 3, static_cast(0x805C0014), 2}, + {"\xE2\x82", 2, static_cast(0x805C0011), 3}, + {"\xE2\xC0", 2, static_cast(0x805C0014), 2}, + {"\xF0\x41\x98", 3, static_cast(0x805C0014), 2}, + {"\xF0\x9F\x41", 3, static_cast(0x805C0014), 3}, + {"\xF0\x41\x98\x80", 4, static_cast(0x805C0014), 1}, + {"\xF0\x9F\x98\x41", 4, static_cast(0x805C0014), 3}, + {"\xF0\x9F\x98", 3, static_cast(0x805C0011), 4}, + {"\xC3\x41", 2, static_cast(0x805C0014), 1}, + {"\xC3", 1, static_cast(0x805C0011), 2}, + {"\x80", 1, static_cast(0x805C0014), 0}, + {"\xFE", 1, static_cast(0x805C0014), 0}, + {"\xFF", 1, static_cast(0x805C0014), 0}, + {"\xC0\x80", 2, static_cast(0x805C0015), 2}, + {"\xC1\xBF", 2, static_cast(0x805C0015), 2}, + {"\xE0\x80\x80", 3, static_cast(0x805C0015), 3}, + {"\xE0\x9F\xBF", 3, static_cast(0x805C0015), 3}, + {"\xED\xA0\x80", 3, static_cast(0x805C0015), 3}, + {"\xF0\x8F\xBF\xBF", 4, static_cast(0x805C0015), 4}, + {"\xF8\x80\x80\x80\x80", 5, static_cast(0x805C0015), 5}, + {"\xFC\x80\x80\x80\x80\x80", 6, static_cast(0x805C0015), 6}, + {"\xE0\xA0\x80", 3, static_cast(0x805C0020), 3}, + {"\xED\x9F\xBF", 3, static_cast(0x805C0020), 3}, + {"\xEF\xBF\xBF", 3, static_cast(0x805C0020), 3}, + {"\xF0\x90\x80\x80", 4, static_cast(0x805C0020), 4}, + {"\xF4\x90\x80\x80", 4, static_cast(0x805C0020), 4}, + {"\xF5\x80\x80\x80", 4, static_cast(0x805C0020), 4}, + {"\xF7\xBF\xBF\xBF", 4, static_cast(0x805C0020), 4}, + {"\xF8\x88\x80\x80\x80", 4, static_cast(0x805C0011), 5}, + {"\xF8\x88\x80\x80\x80", 5, static_cast(0x805C0020), 5}, + {"\xFB\xBF\xBF\xBF\xBF", 5, static_cast(0x805C0020), 5}, + {"\xFC\x84\x80", 3, static_cast(0x805C0011), 6}, + {"\xFC\x84\x80\x80\x80\x80", 6, static_cast(0x805C0020), 6}, + {"\xFD\xBF\xBF\xBF\xBF\xBF", 6, static_cast(0x805C0020), 6}, + {"\xC2\x80", 2, static_cast(0x805C0020), 2}, + {"\xC2\x81", 2, static_cast(0x805C0020), 2}, + {"\xC2\x8D", 2, static_cast(0x805C0020), 2}, + {"\xC2\xA0", 2, 0, 2}, + {"\xC5\x92", 2, 0, 2}, + }; + for (const MeasuredUtf8& measured : cases) { + std::uint32_t length = 0xAAAAAAAA; + std::uint8_t sbc = 0xBB; + Require(sceCesUtf8ToSbc(reinterpret_cast(measured.bytes), measured.available, &length, profile, &sbc) == measured.result); + Require(length == measured.length); + Require(measured.result != 0 ? sbc == 0 : sbc != 0); + } +} + +constexpr std::uint32_t MeasuredEucJpPairs = 0x9295D4B1; +constexpr std::uint32_t MeasuredEucJpSupplementary = 0x75256134; + +struct MeasuredString { + const char* source; + std::uint32_t available; + std::uint32_t capacity; + int result; + std::uint32_t read; + std::uint32_t written; + const char* output; +}; + +static void RequireMeasuredStrings(void* latin, void* eucJp) { + constexpr int dstBufferEnd = static_cast(0x805C0031); + constexpr int invalidEncode = static_cast(0x805C0014); + constexpr int unassignedCode = static_cast(0x805C0020); + constexpr MeasuredString toUtf8[] = { + {"ABC", 3, 16, 0, 3, 3, "ABC"}, + {"ABC\0D", 5, 16, 0, 3, 3, "ABC"}, + {"ABC", 0, 16, 0, 3, 3, "ABC"}, + {"ABC", 3, 4, 0, 3, 3, "ABC"}, + {"ABC", 3, 3, dstBufferEnd, 2, 2, "AB"}, + {"ABC", 3, 2, dstBufferEnd, 1, 1, "A"}, + {"A\xE9" "B", 3, 16, 0, 3, 4, "A\xC3\xA9" "B"}, + {"A\xE9" "B", 3, 3, dstBufferEnd, 1, 1, "A"}, + {"\x80\x80\x80", 3, 7, dstBufferEnd, 2, 6, "\xE2\x82\xAC\xE2\x82\xAC"}, + {"A\x81" "B", 3, 16, unassignedCode, 1, 1, "A"}, + {"", 2, 16, 0, 0, 0, ""}, + }; + for (const MeasuredString& measured : toUtf8) { + std::uint8_t output[16]; + std::memset(output, 0xBB, sizeof(output)); + std::uint32_t read = 0xAAAAAAAA; + std::uint32_t written = 0xCCCCCCCC; + Require(sceCesMbcsStrToUtf8Str(latin, reinterpret_cast(measured.source), measured.available, &read, output, measured.capacity, &written) == measured.result); + Require(read == measured.read && written == measured.written); + Require(std::memcmp(output, measured.output, measured.written + 1) == 0 && output[measured.written + 1] == 0xBB); + Require(sceCesMbcsStrGetUtf8Len(latin, reinterpret_cast(measured.source), measured.available, &read, &written) == (measured.result == dstBufferEnd ? 0 : measured.result)); + } + constexpr MeasuredString fromUtf8[] = { + {"ABC", 3, 3, dstBufferEnd, 2, 2, "AB"}, + {"A\xC3\xA9" "B", 4, 16, 0, 4, 3, "A\xE9" "B"}, + {"A\xE4\xB8\x80" "B", 5, 16, unassignedCode, 1, 1, "A"}, + {"A\xC3", 2, 16, static_cast(0x805C0011), 1, 1, "A"}, + {"A\xFF" "B", 3, 16, invalidEncode, 1, 1, "A"}, + {"A\xC3\0B", 0, 16, invalidEncode, 1, 1, "A"}, + {"A\xC0\x80" "B", 4, 16, static_cast(0x805C0015), 1, 1, "A"}, + {"A\xED\xA0\x80" "B", 5, 16, static_cast(0x805C0015), 1, 1, "A"}, + {"A\xC2\x81" "B", 4, 16, unassignedCode, 1, 1, "A"}, + {"A\xF8\x88\x80\x80\x80" "B", 7, 16, unassignedCode, 1, 1, "A"}, + {"A\xE2\x41\xAC" "B", 5, 16, invalidEncode, 1, 1, "A"}, + {"ABC", 0, 16, 0, 3, 3, "ABC"}, + }; + for (const MeasuredString& measured : fromUtf8) { + std::uint8_t output[16]; + std::memset(output, 0xBB, sizeof(output)); + std::uint32_t read = 0xAAAAAAAA; + std::uint32_t written = 0xCCCCCCCC; + Require(sceCesUtf8StrToMbcsStr(latin, reinterpret_cast(measured.source), measured.available, &read, output, measured.capacity, &written) == measured.result); + Require(read == measured.read && written == measured.written); + Require(std::memcmp(output, measured.output, measured.written + 1) == 0 && output[measured.written + 1] == 0xBB); + } + constexpr MeasuredString eucToUtf8[] = { + {"A\xA4\xA2" "B", 0, 16, 0, 4, 5, "A\xE3\x81\x82" "B"}, + {"A\xA4\xA2" "B", 0, 4, dstBufferEnd, 1, 1, "A"}, + {"A\xA4\xA2" "B", 0, 5, dstBufferEnd, 3, 4, "A\xE3\x81\x82"}, + {"A\xA4", 2, 16, static_cast(0x805C0011), 1, 1, "A"}, + {"A\x0E" "B", 3, 16, invalidEncode, 1, 1, "A"}, + {"A\x80" "B", 0, 16, 0, 3, 4, "A\xC2\x80" "B"}, + {"A\xA4\0B", 0, 16, invalidEncode, 1, 1, "A"}, + }; + for (const MeasuredString& measured : eucToUtf8) { + std::uint8_t output[16]; + std::memset(output, 0xBB, sizeof(output)); + std::uint32_t read = 0xAAAAAAAA; + std::uint32_t written = 0xCCCCCCCC; + Require(sceCesMbcsStrToUtf8Str(eucJp, reinterpret_cast(measured.source), measured.available, &read, output, measured.capacity, &written) == measured.result); + Require(read == measured.read && written == measured.written); + Require(std::memcmp(output, measured.output, measured.written + 1) == 0 && output[measured.written + 1] == 0xBB); + } + + const auto* letters = reinterpret_cast("ABC"); + std::uint8_t output[4] = {0xBB, 0xBB, 0xBB, 0xBB}; + std::uint32_t read = 7; + std::uint32_t written = 7; + Require(sceCesMbcsStrToUtf8Str(latin, letters, 3, &read, output, 0, &written) == dstBufferEnd && read == 0 && written == 0 && output[0] == 0xBB); + Require(sceCesMbcsStrToUtf8Str(latin, letters, 3, &read, nullptr, 16, &written) == static_cast(0x805C0030) && read == 0 && written == 0); + Require(sceCesMbcsStrToUtf8Str(nullptr, letters, 3, &read, nullptr, 16, &written) == static_cast(0x805C0001)); + Require(sceCesMbcsStrToUtf8Str(latin, nullptr, 3, &read, nullptr, 16, &written) == static_cast(0x805C0010)); + Require(sceCesMbcsStrToUtf8Str(nullptr, letters, 3, &read, output, sizeof(output), &written) == static_cast(0x805C0001) && output[0] == 0 && output[1] == 0xBB); + output[0] = 0xBB; + Require(sceCesMbcsStrToUtf8Str(latin, nullptr, 3, &read, output, sizeof(output), &written) == static_cast(0x805C0010) && output[0] == 0 && read == 0 && written == 0); + output[0] = 0xBB; + Require(sceCesMbcsStrToUtf8Str(latin, nullptr, 3, &read, output, 0, &written) == static_cast(0x805C0010) && output[0] == 0xBB); + Require(sceCesMbcsStrGetUtf8Len(latin, reinterpret_cast("A\x81" "B"), 3, &read, &written) == unassignedCode && read == 1 && written == 1); + Require(sceCesMbcsStrGetUtf8Len(latin, nullptr, 3, &read, &written) == static_cast(0x805C0010) && read == 0 && written == 0); + Require(sceCesUtf8StrGetMbcsLen(latin, reinterpret_cast("A\xE4\xB8\x80" "B"), 5, &read, &written) == unassignedCode && read == 1 && written == 1); + Require(sceCesUtf8StrGetMbcsLen(latin, reinterpret_cast("A\xC3"), 2, &read, &written) == static_cast(0x805C0011) && read == 1 && written == 1); + + std::uint16_t wide[8]; + for (std::uint16_t& unit : wide) unit = 0xBBBB; + Require(sceCesMbcsStrToUcs2Str(latin, letters, 0, &read, wide, 3, &written) == dstBufferEnd && read == 2 && written == 2); + Require(wide[0] == u'A' && wide[1] == u'B' && wide[2] == 0 && wide[3] == 0xBBBB); + Require(sceCesMbcsStrToUcs2Str(latin, reinterpret_cast("A\x81" "B"), 3, &read, wide, 8, &written) == unassignedCode && read == 1 && written == 1 && wide[1] == 0); + const std::uint16_t han[] = {u'A', 0x4E00, u'B', 0}; + const std::uint16_t surrogate[] = {u'A', 0xD800, u'B', 0}; + const std::uint16_t control[] = {u'A', 0x0081, u'B', 0}; + const std::uint16_t plain[] = {u'A', u'B', u'C', 0}; + std::memset(output, 0xBB, sizeof(output)); + Require(sceCesUcs2StrToMbcsStr(latin, plain, 2, &read, output, sizeof(output), &written) == 0 && read == 2 && written == 2 && std::memcmp(output, "AB", 3) == 0); + Require(sceCesUcs2StrToMbcsStr(latin, plain, 0, &read, output, 3, &written) == dstBufferEnd && read == 2 && written == 2); + Require(sceCesUcs2StrToMbcsStr(latin, han, 0, &read, output, sizeof(output), &written) == unassignedCode && read == 1 && written == 1); + Require(sceCesUcs2StrToMbcsStr(latin, surrogate, 0, &read, output, sizeof(output), &written) == static_cast(0x805C0015) && read == 1 && written == 1); + Require(sceCesUcs2StrToMbcsStr(latin, control, 0, &read, output, sizeof(output), &written) == unassignedCode && read == 1 && written == 1); + Require(sceCesUcs2StrGetMbcsLen(latin, han, 0, &read, &written) == unassignedCode && read == 1 && written == 1); +} + +static std::uint32_t Fnv(std::uint32_t hash, std::uint32_t word) { + for (int k = 0; k < 4; ++k) { + hash ^= (word >> (8 * k)) & 0xFFu; + hash *= 16777619u; + } + return hash; +} + +constexpr std::uint32_t MeasuredEucJpEncoder = 0x3AF3CD39; +constexpr std::uint32_t MeasuredSjisEncoder = 0x2FB8906B; + +static std::uint32_t EncoderSweep(void* context) { + std::uint32_t hash = 2166136261u; + for (std::uint32_t value = 0; value <= 0xFFFF; ++value) { + const std::uint16_t source[1] = {static_cast(value)}; + std::uint8_t output[4] = {0xBB, 0xBB, 0xBB, 0xBB}; + std::uint32_t used = 0xAAAAAAAA; + std::uint32_t produced = 0xCCCCCCCC; + const int result = sceCesUcs2StrToMbcsStr(context, source, 1, &used, output, sizeof(output), &produced); + std::uint32_t bytes = 0; + std::memcpy(&bytes, output, sizeof(bytes)); + hash = Fnv(Fnv(Fnv(Fnv(hash, static_cast(result)), produced), bytes), used); + } + return hash; +} + +constexpr std::uint32_t MeasuredSjisDecoder = 0xCA99178C; + +static std::uint32_t SjisDecoderSweep(void* sjis) { + std::uint32_t hash = 2166136261u; + for (std::uint32_t lead = 0; lead < 256; ++lead) { + for (std::uint32_t trail = 0; trail < 256; ++trail) { + const std::uint8_t source[2] = {static_cast(lead), static_cast(trail)}; + std::uint16_t output[3] = {0xBBBB, 0xBBBB, 0xBBBB}; + std::uint32_t used = 0xAAAAAAAA; + std::uint32_t produced = 0xCCCCCCCC; + const int result = sceCesMbcsStrToUcs2Str(sjis, source, 2, &used, output, 3, &produced); + hash = Fnv(Fnv(Fnv(Fnv(Fnv(hash, static_cast(result)), used), produced), static_cast(output[0]) | static_cast(output[1]) << 16), output[2]); + } + } + return hash; +} + +static void RequireMeasuredEncoders(void* eucJp, void* sjis) { + Require(SjisDecoderSweep(sjis) == MeasuredSjisDecoder); + Require(EncoderSweep(eucJp) == MeasuredEucJpEncoder); + Require(EncoderSweep(sjis) == MeasuredSjisEncoder); + const std::uint16_t aliases[] = {0x00A2, 0x00A3, 0x00AC, 0x2014, 0x2016, 0x203E, 0x2212, 0x301C, 0xFEFF, 0x0080, 0}; + std::uint8_t output[32] = {}; + std::uint32_t used = 0; + std::uint32_t produced = 0; + Require(sceCesUcs2StrToMbcsStr(eucJp, aliases, 0, &used, output, sizeof(output), &produced) == 0 && used == 10 && produced == 17); + Require(std::memcmp(output, "\xA1\xF1\xA1\xF2\xA2\xCC\xA1\xBD\xA1\xC2\xA1\xB1\xA1\xDD\xA1\xC1\x80", 18) == 0); + Require(sceCesUcs2StrToMbcsStr(sjis, aliases, 0, &used, output, sizeof(output), &produced) == static_cast(0x805C0024) && used == 9 && produced == 16); + Require(std::memcmp(output, "\x81\x91\x81\x92\x81\xCA\x81\x5C\x81\x61\x81\x50\x81\x7C\x81\x60", 17) == 0); + const std::uint16_t shift[] = {u'A', 0x000E, 0}; + Require(sceCesUcs2StrToMbcsStr(sjis, shift, 0, &used, output, sizeof(output), &produced) == 0 && produced == 2); + Require(sceCesUcs2StrToMbcsStr(eucJp, shift, 0, &used, output, sizeof(output), &produced) == static_cast(0x805C0020) && used == 1 && produced == 1); +} + +static void RequireMeasuredEucJp(void* eucJp) { + constexpr int invalidProfile = static_cast(0x805C0004); + constexpr int invalidSrcBuffer = static_cast(0x805C0010); + constexpr int srcBufferEnd = static_cast(0x805C0011); + constexpr int invalidEncode = static_cast(0x805C0014); + constexpr int unassignedCode = static_cast(0x805C0020); + constexpr int invalidDstBuffer = static_cast(0x805C0030); + constexpr int dstBufferEnd = static_cast(0x805C0031); + std::uint32_t pairs = 2166136261u; + for (int lead = 0; lead < 256; ++lead) { + for (int trail = 0; trail < 256; ++trail) { + const std::uint8_t cell[2] = {static_cast(lead), static_cast(trail)}; + std::uint32_t used = 0xAAAAAAAA; + std::uint16_t code = 0xBBBB; + const int result = sceCesEucJpToUcs2(eucJp, cell, 2, &used, &code); + pairs = Fnv(Fnv(Fnv(Fnv(pairs, static_cast(cell[1])), static_cast(result)), used), code); + } + } + Require(pairs == MeasuredEucJpPairs); + std::uint32_t supplementary = 2166136261u; + for (int second = 0; second < 256; ++second) { + for (int third = 0; third < 256; ++third) { + const std::uint8_t cell[3] = {0x8F, static_cast(second), static_cast(third)}; + std::uint32_t used = 0xAAAAAAAA; + std::uint16_t code = 0xBBBB; + const int result = sceCesEucJpToUcs2(eucJp, cell, 3, &used, &code); + supplementary = Fnv(Fnv(Fnv(Fnv(supplementary, static_cast(third)), static_cast(result)), used), code); + } + } + Require(supplementary == MeasuredEucJpSupplementary); + + const auto* hiragana = reinterpret_cast("\xA4\xA2"); + std::uint32_t used = 7; + std::uint32_t produced = 7; + std::uint16_t code = 0xBBBB; + std::uint8_t utf8[4] = {0xBB, 0xBB, 0xBB, 0xBB}; + Require(sceCesEucJpToUcs2(nullptr, hiragana, 2, &used, &code) == invalidProfile && used == 0 && code == 0); + Require(sceCesEucJpToUcs2(eucJp, nullptr, 2, &used, &code) == invalidSrcBuffer && used == 0); + Require(sceCesEucJpToUcs2(eucJp, hiragana, 0, &used, nullptr) == invalidSrcBuffer && used == 0); + Require(sceCesEucJpToUcs2(eucJp, hiragana, 1, &used, nullptr) == srcBufferEnd && used == 2); + Require(sceCesEucJpToUcs2(eucJp, hiragana, 2, &used, nullptr) == invalidDstBuffer && used == 2); + Require(sceCesEucJpToUcs2(eucJp, hiragana, 2, nullptr, &code) == 0 && code == 0x3042); + Require(sceCesEucJpToUtf8(eucJp, hiragana, 2, &used, utf8, sizeof(utf8), &produced) == 0 && used == 2 && produced == 3 && std::memcmp(utf8, "\xE3\x81\x82", 3) == 0); + Require(sceCesEucJpToUtf8(eucJp, reinterpret_cast("\x8E\xB1"), 2, &used, utf8, sizeof(utf8), &produced) == 0 && used == 2 && produced == 3 && std::memcmp(utf8, "\xEF\xBD\xB1", 3) == 0); + Require(sceCesEucJpToUtf8(eucJp, reinterpret_cast("\x80"), 1, &used, utf8, sizeof(utf8), &produced) == 0 && used == 1 && produced == 2 && std::memcmp(utf8, "\xC2\x80", 2) == 0); + std::memset(utf8, 0xBB, sizeof(utf8)); + Require(sceCesEucJpToUtf8(nullptr, nullptr, 2, &used, utf8, sizeof(utf8), &produced) == invalidProfile && used == 0 && produced == 0); + Require(sceCesEucJpToUtf8(eucJp, nullptr, 0, &used, utf8, sizeof(utf8), &produced) == invalidSrcBuffer && used == 0 && produced == 0); + Require(sceCesEucJpToUtf8(eucJp, hiragana, 1, &used, nullptr, sizeof(utf8), &produced) == srcBufferEnd && used == 2 && produced == 0); + Require(sceCesEucJpToUtf8(eucJp, reinterpret_cast("\xA4\x20"), 2, &used, utf8, sizeof(utf8), &produced) == invalidEncode && used == 2 && produced == 0); + Require(sceCesEucJpToUtf8(eucJp, reinterpret_cast("\x8E\xE0"), 2, &used, utf8, sizeof(utf8), &produced) == unassignedCode && used == 2 && produced == 0); + Require(sceCesEucJpToUtf8(eucJp, reinterpret_cast("\xA9\xA1"), 2, &used, utf8, sizeof(utf8), &produced) == unassignedCode && used == 2 && produced == 0); + Require(sceCesEucJpToUtf8(eucJp, reinterpret_cast("\xFF\xA1"), 2, &used, utf8, sizeof(utf8), &produced) == invalidEncode && used == 1 && produced == 0); + Require(sceCesEucJpToUtf8(eucJp, hiragana, 2, &used, nullptr, sizeof(utf8), &produced) == invalidDstBuffer && used == 2 && produced == 3); + Require(sceCesEucJpToUtf8(eucJp, hiragana, 2, &used, utf8, 2, &produced) == dstBufferEnd && used == 2 && produced == 3); + Require(sceCesEucJpToUtf8(eucJp, hiragana, 2, &used, utf8, 0, &produced) == dstBufferEnd && used == 2 && produced == 3); + Require(utf8[0] == 0xBB); + Require(sceCesEucJpToUtf8(eucJp, hiragana, 2, nullptr, utf8, sizeof(utf8), nullptr) == 0 && std::memcmp(utf8, "\xE3\x81\x82", 3) == 0); +} + static void RequireSbcCode(const std::uint8_t* profile, std::uint8_t sbc, std::uint32_t code) { char expected[4] = {}; if (code < 0x80) { @@ -93,12 +362,12 @@ static void RequireSbcCode(const std::uint8_t* profile, std::uint8_t sbc, std::u static void CheckSingleByteProfiles() { constexpr int unassignedCode = static_cast(0x805C0020); const auto getters = {sceCesRefersUcsProfileIso8859_1, sceCesRefersUcsProfileIso8859_2, sceCesRefersUcsProfileIso8859_4, sceCesRefersUcsProfileIso8859_5, sceCesRefersUcsProfileIso8859_9, sceCesRefersUcsProfileIso8859_10, sceCesRefersUcsProfileIso8859_13, sceCesRefersUcsProfileIso8859_14, sceCesRefersUcsProfileIso8859_15, sceCesRefersUcsProfileIso8859_16, sceCesRefersUcsProfileCp437, sceCesRefersUcsProfileCp737, sceCesRefersUcsProfileCp775, sceCesRefersUcsProfileCp850, sceCesRefersUcsProfileCp852, sceCesRefersUcsProfileCp855, sceCesRefersUcsProfileCp860, sceCesRefersUcsProfileCp861, sceCesRefersUcsProfileCp862, sceCesRefersUcsProfileCp863, sceCesRefersUcsProfileCp865, sceCesRefersUcsProfileCp866, sceCesRefersUcsProfileKoi8R, sceCesRefersUcsProfileKoi8U, sceCesRefersUcsProfileCp1254, sceCesRefersUcsProfileCp1256, sceCesRefersUcsProfileCp1258}; - const std::uint8_t* existing[] = {sceCesRefersUcsProfileCp1252(), sceCesRefersUcsProfileCp1251(), sceCesRefersUcsProfileCp1250()}; + const void* existing[] = {sceCesRefersUcsProfileCp1252(), sceCesRefersUcsProfileCp1251(), sceCesRefersUcsProfileCp1250()}; std::size_t index = 0; for (const auto getter : getters) { const std::uint8_t* profile = getter(); Require(profile != nullptr && profile == getter()); - for (const std::uint8_t* other : existing) Require(profile != other); + for (const void* other : existing) Require(profile != other); std::size_t inner = 0; for (const auto earlier : getters) { if (inner++ == index) break; @@ -260,7 +529,6 @@ int main() { RequireSbcToUtf8(profile, 'A', "A"); RequireSbcToUtf8(profile, 0x80, "\xE2\x82\xAC"); RequireSbcToUtf8(profile, 0x9F, "\xC5\xB8"); - RequireSbcToUtf8(profile, 0x81, "\xC2\x81"); RequireSbcToUtf8(profile, 0xE9, "\xC3\xA9"); RequireSbcToUtf8(profile, 0xFF, "\xC3\xBF"); @@ -268,29 +536,48 @@ int main() { RequireUtf8ToSbc(profile, "\xE2\x82\xAC", 0x80); RequireUtf8ToSbc(profile, "\xE2\x84\xA2", 0x99); RequireUtf8ToSbc(profile, "\xC3\xA9", 0xE9); - RequireUtf8ToSbc(profile, "\xC2\x8D", 0x8D); - for (int sbc = 1; sbc < 256; ++sbc) { - std::uint8_t utf8[4] = {}; - std::uint32_t length = 0; - std::uint8_t back = 0; - Require(sceCesSbcToUtf8(profile, static_cast(sbc), utf8, sizeof(utf8), &length) == 0); - Require(sceCesUtf8ToSbc(utf8, length, &length, profile, &back) == 0 && back == sbc); - } + RequireSbcRoundTrip(profile, {0x81, 0x8D, 0x8F, 0x90, 0x9D}); + RequireMeasuredUtf8ToSbc(profile); std::uint8_t utf8[4] = {}; std::uint32_t length = 0; std::uint8_t sbc = 0; - Require(sceCesSbcToUtf8(nullptr, 'A', utf8, sizeof(utf8), &length) == invalidParameter); - Require(sceCesSbcToUtf8(profile, 'A', nullptr, sizeof(utf8), &length) == invalidDstBuffer); - Require(sceCesSbcToUtf8(profile, 0x80, utf8, 2, &length) == dstBufferEnd); - Require(sceCesUtf8ToSbc(utf8, 1, &length, nullptr, &sbc) == invalidParameter); - Require(sceCesUtf8ToSbc(nullptr, 1, &length, profile, &sbc) == invalidSrcBuffer); - Require(sceCesUtf8ToSbc(utf8, 1, &length, profile, nullptr) == invalidDstBuffer); - Require(Utf8ToSbc(profile, "A", 0) == srcBufferEnd); + constexpr int invalidProfile = static_cast(0x805C0004); + constexpr int illegalCode = static_cast(0x805C0015); + length = 7; + Require(sceCesSbcToUtf8(nullptr, 'A', utf8, sizeof(utf8), &length) == invalidProfile && length == 0); + Require(sceCesSbcToUtf8(nullptr, 0x81, utf8, sizeof(utf8), &length) == invalidProfile && length == 0); + Require(sceCesSbcToUtf8(profile, 0x80, nullptr, sizeof(utf8), &length) == invalidDstBuffer && length == 3); + Require(sceCesSbcToUtf8(profile, 0x81, nullptr, sizeof(utf8), &length) == unassignedCode && length == 0); + Require(sceCesSbcToUtf8(profile, 0x81, utf8, 0, &length) == unassignedCode && length == 0); + utf8[0] = 0xBB; + Require(sceCesSbcToUtf8(profile, 0x80, utf8, 2, &length) == dstBufferEnd && length == 3 && utf8[0] == 0xBB); + Require(sceCesSbcToUtf8(profile, 'A', utf8, 0, &length) == dstBufferEnd && length == 1 && utf8[0] == 0xBB); + Require(sceCesSbcToUtf8(profile, 0xE9, utf8, 1, nullptr) == dstBufferEnd); + const auto* euro = reinterpret_cast("\xE2\x82\xAC"); + const auto* han = reinterpret_cast("\xE4\xB8\x80"); + const auto* letter = reinterpret_cast("A"); + sbc = 0xBB; + Require(sceCesUtf8ToSbc(letter, 1, &length, nullptr, &sbc) == invalidProfile && length == 1 && sbc == 0); + Require(sceCesUtf8ToSbc(letter, 1, &length, nullptr, nullptr) == invalidProfile && length == 1); + Require(sceCesUtf8ToSbc(euro, 3, &length, nullptr, &sbc) == invalidProfile && length == 3); + Require(sceCesUtf8ToSbc(euro, 2, &length, nullptr, &sbc) == srcBufferEnd && length == 3); + Require(sceCesUtf8ToSbc(reinterpret_cast("\xFF"), 1, &length, nullptr, &sbc) == invalidEncode && length == 0); + sbc = 0xBB; + Require(sceCesUtf8ToSbc(nullptr, 1, &length, nullptr, &sbc) == invalidSrcBuffer && length == 0 && sbc == 0); + Require(sceCesUtf8ToSbc(nullptr, 1, &length, profile, nullptr) == invalidSrcBuffer && length == 0); + sbc = 0xBB; + Require(sceCesUtf8ToSbc(letter, 0, &length, profile, &sbc) == invalidSrcBuffer && length == 0 && sbc == 0); + Require(sceCesUtf8ToSbc(euro, 3, &length, profile, nullptr) == invalidDstBuffer && length == 3); + Require(sceCesUtf8ToSbc(han, 3, &length, profile, nullptr) == unassignedCode && length == 3); + sbc = 0xBB; + Require(sceCesUtf8ToSbc(han, 3, &length, profile, &sbc) == unassignedCode && length == 3 && sbc == 0); + Require(sceCesUtf8ToSbc(euro, 3, nullptr, profile, &sbc) == 0 && sbc == 0x80); + Require(Utf8ToSbc(profile, "A", 0) == invalidSrcBuffer); Require(Utf8ToSbc(profile, "\xE2\x82\xAC", 2) == srcBufferEnd); Require(Utf8ToSbc(profile, "\x80", 1) == invalidEncode); - Require(Utf8ToSbc(profile, "\xC0\xAF", 2) == invalidEncode); - Require(Utf8ToSbc(profile, "\xED\xA0\x80", 3) == invalidEncode); + Require(Utf8ToSbc(profile, "\xC0\xAF", 2) == illegalCode); + Require(Utf8ToSbc(profile, "\xED\xA0\x80", 3) == illegalCode); Require(Utf8ToSbc(profile, "\xE3\x81\x82", 3) == unassignedCode); Require(Utf8ToSbc(profile, "\xF0\x9F\x98\x80", 4) == unassignedCode); @@ -304,21 +591,14 @@ int main() { RequireSbcToUtf8(cyrillic, 0xB9, "\xE2\x84\x96"); RequireUtf8ToSbc(cyrillic, "\xD0\x9F", 0xCF); RequireUtf8ToSbc(cyrillic, "\xD1\x91", 0xB8); - for (int sbc = 1; sbc < 256; ++sbc) { - std::uint8_t cp[4] = {}; - std::uint32_t cpLength = 0; - std::uint8_t back = 0; - Require(sceCesSbcToUtf8(cyrillic, static_cast(sbc), cp, sizeof(cp), &cpLength) == 0); - Require(sceCesUtf8ToSbc(cp, cpLength, &cpLength, cyrillic, &back) == 0 && back == sbc); - } + RequireSbcRoundTrip(cyrillic, {0x98}); Require(Utf8ToSbc(cyrillic, "\xC3\xA9", 2) == unassignedCode); Require(Utf8ToSbc(profile, "\xD0\x90", 2) == unassignedCode); - const std::uint8_t* latin2 = sceCesRefersUcsProfileCp1250(); + const auto* latin2 = static_cast(sceCesRefersUcsProfileCp1250()); Require(latin2 != nullptr && latin2 == sceCesRefersUcsProfileCp1250() && latin2 != profile && latin2 != cyrillic); RequireSbcToUtf8(latin2, 'A', "A"); RequireSbcToUtf8(latin2, 0x80, "\xE2\x82\xAC"); - RequireSbcToUtf8(latin2, 0x81, "\xC2\x81"); RequireSbcToUtf8(latin2, 0x8A, "\xC5\xA0"); RequireSbcToUtf8(latin2, 0xA3, "\xC5\x81"); RequireSbcToUtf8(latin2, 0xA5, "\xC4\x84"); @@ -328,13 +608,7 @@ int main() { RequireUtf8ToSbc(latin2, "\xC5\xA0", 0x8A); RequireUtf8ToSbc(latin2, "\xC5\x81", 0xA3); RequireUtf8ToSbc(latin2, "\xC3\xA9", 0xE9); - for (int sbc = 1; sbc < 256; ++sbc) { - std::uint8_t cp[4] = {}; - std::uint32_t cpLength = 0; - std::uint8_t back = 0; - Require(sceCesSbcToUtf8(latin2, static_cast(sbc), cp, sizeof(cp), &cpLength) == 0); - Require(sceCesUtf8ToSbc(cp, cpLength, &cpLength, latin2, &back) == 0 && back == sbc); - } + RequireSbcRoundTrip(latin2, {0x81, 0x83, 0x88, 0x90, 0x98}); Require(Utf8ToSbc(latin2, "\xD0\x90", 2) == unassignedCode); char latin2Context[256] = {}; Require(sceCesMbcsUcsContextInit(latin2Context, latin2) == 0); @@ -355,7 +629,7 @@ int main() { char sjisContext[256] = {}; Require(sceCesMbcsUcsContextInit(sjisContext, sjisSheet) == 0); const auto* eucSource = reinterpret_cast("Go \xEF\xBD\xB1!"); - std::uint8_t mbcs[16] = {}; + std::uint8_t mbcs[32] = {}; std::uint32_t used = 0; std::uint32_t produced = 0; char sheet[1024] = {}; @@ -368,8 +642,12 @@ int main() { Require(used == 7 && produced == 6 && std::memcmp(mbcs, "Go \x8E\xB1!", 6) == 0); Require(sceCesUtf8StrGetMbcsLen(eucContext, eucSource, 16, &used, &produced) == 0 && used == 7 && produced == 6); Require(sceCesUtf8StrToMbcsStr(eucContext, eucSource, 16, &used, mbcs, 4, &produced) == dstBufferEnd); + Require(used == 3 && produced == 3 && std::memcmp(mbcs, "Go ", 4) == 0); + Require(sceCesUtf8StrToMbcsStr(eucContext, eucSource, 16, &used, mbcs, sizeof(mbcs), &produced) == 0); Require(sceCesUtf8StrToMbcsStr(nullptr, eucSource, 16, &used, mbcs, sizeof(mbcs), &produced) == invalidParameter); Require(sceCesUtf8StrToMbcsStr(eucContext, reinterpret_cast("\xF0\x9F\x98\x80"), 4, &used, mbcs, sizeof(mbcs), &produced) == unassignedCode); + Require(used == 0 && produced == 0 && mbcs[0] == 0); + Require(sceCesUtf8StrToMbcsStr(eucContext, eucSource, 16, &used, mbcs, sizeof(mbcs), &produced) == 0); std::uint8_t back[16] = {}; Require(sceCesMbcsStrToUtf8Str(nullptr, mbcs, 6, &used, back, sizeof(back), &produced) == invalidParameter); @@ -384,8 +662,8 @@ int main() { Require(sceCesUcs2StrToMbcsStr(eucContext, ucs2, 4, &used, mbcs, sizeof(mbcs), &produced) == 0); Require(used == 3 && produced == 4 && std::memcmp(mbcs, "OK\x8E\xDF", 4) == 0); Require(sceCesUcs2StrGetMbcsLen(eucContext, ucs2, 4, &used, &produced) == 0 && produced == 4); - std::uint16_t wide[8] = {}; - Require(sceCesMbcsStrToUcs2Str(eucContext, mbcs, 4, &used, wide, 8, &produced) == 0); + std::uint16_t wide[16] = {}; + Require(sceCesMbcsStrToUcs2Str(eucContext, mbcs, 4, &used, wide, 16, &produced) == 0); Require(used == 4 && produced == 3 && wide[0] == u'O' && wide[1] == u'K' && wide[2] == 0xFF9F); Require(sceCesMbcsStrGetUcs2Len(eucContext, mbcs, 4, &used, &produced) == 0 && produced == 3); std::uint16_t single = 0; @@ -397,15 +675,15 @@ int main() { Require(used == 24 && produced == 16 && std::memcmp(mbcs, "\xA4\xB3\xA4\xF3\xA4\xCB\xA4\xC1\xA4\xCF\xC6\xFC\xCB\xDC\xB8\xEC", 16) == 0); std::uint8_t japaneseBack[32] = {}; Require(sceCesMbcsStrToUtf8Str(eucContext, mbcs, 16, &used, japaneseBack, sizeof(japaneseBack), &produced) == 0 && produced == 24 && std::memcmp(japaneseBack, japanese, 24) == 0); - Require(sceCesMbcsStrToUcs2Str(eucContext, mbcs, 16, &used, wide, 8, &produced) == 0 && used == 16 && produced == 8 && wide[0] == 0x3053 && wide[5] == 0x65E5 && wide[7] == 0x8A9E); - Require(sceCesMbcsStrToUcs2Str(eucContext, mbcs, 15, &used, wide, 8, &produced) == srcBufferEnd); + Require(sceCesMbcsStrToUcs2Str(eucContext, mbcs, 16, &used, wide, 16, &produced) == 0 && used == 16 && produced == 8 && wide[0] == 0x3053 && wide[5] == 0x65E5 && wide[7] == 0x8A9E); + Require(sceCesMbcsStrToUcs2Str(eucContext, mbcs, 15, &used, wide, 16, &produced) == srcBufferEnd); const std::uint16_t extensions[] = {0x2460, 0xFF5E, 0x2252, 0}; Require(sceCesUcs2StrToMbcsStr(eucContext, extensions, 4, &used, mbcs, sizeof(mbcs), &produced) == 0 && produced == 6 && std::memcmp(mbcs, "\xAD\xA1\xA1\xC1\xA2\xE2", 6) == 0); - Require(sceCesMbcsStrToUcs2Str(eucContext, reinterpret_cast("\xA9\xA1"), 2, &used, wide, 8, &produced) == unassignedCode); - Require(sceCesMbcsStrToUcs2Str(eucContext, reinterpret_cast("\xA4\x41"), 2, &used, wide, 8, &produced) == invalidEncode); - Require(sceCesMbcsStrToUcs2Str(eucContext, reinterpret_cast("\xA4"), 1, &used, wide, 8, &produced) == srcBufferEnd); + Require(sceCesMbcsStrToUcs2Str(eucContext, reinterpret_cast("\xA9\xA1"), 2, &used, wide, 16, &produced) == unassignedCode); + Require(sceCesMbcsStrToUcs2Str(eucContext, reinterpret_cast("\xA4\x41"), 2, &used, wide, 16, &produced) == invalidEncode); + Require(sceCesMbcsStrToUcs2Str(eucContext, reinterpret_cast("\xA4"), 1, &used, wide, 16, &produced) == srcBufferEnd); const std::uint16_t yen[] = {0x00A5, 0}; - Require(sceCesUcs2StrToMbcsStr(eucContext, yen, 2, &used, mbcs, sizeof(mbcs), &produced) == unassignedCode); + Require(sceCesUcs2StrToMbcsStr(eucContext, yen, 2, &used, mbcs, sizeof(mbcs), &produced) == 0 && used == 1 && produced == 2 && std::memcmp(mbcs, "\xA1\xEF", 3) == 0); std::uint32_t assigned = 0; for (std::uint32_t lead = 0xA1; lead <= 0xFE; ++lead) { for (std::uint32_t trail = 0xA1; trail <= 0xFE; ++trail) { @@ -424,47 +702,36 @@ int main() { Require(assigned == 7336); std::uint16_t supplementary = 0; - Require(sceCesEucJpToUcs2(eucJp, reinterpret_cast("\x8F\xA2\xAF"), 3, &used, &supplementary) == 0 && used == 3 && supplementary == 0x02D8); - Require(sceCesEucJpToUcs2(eucJp, reinterpret_cast("\x8F\xA2"), 2, &used, &supplementary) == srcBufferEnd); + Require(sceCesEucJpToUcs2(eucJp, reinterpret_cast("\x8F\xA2\xAF"), 3, &used, &supplementary) == invalidEncode && used == 3 && supplementary == 0); + Require(sceCesEucJpToUcs2(eucJp, reinterpret_cast("\x8F\xA2"), 2, &used, &supplementary) == srcBufferEnd && used == 3); Require(sceCesEucJpToUcs2(eucJp, reinterpret_cast("\x8F\x41\xA1"), 3, &used, &supplementary) == invalidEncode); Require(sceCesEucJpToUcs2(eucJp, reinterpret_cast("\x8F\xA2\x41"), 3, &used, &supplementary) == invalidEncode); Require(sceCesEucJpToUcs2(eucJp, reinterpret_cast("\x8F\xA1\xA1"), 3, &used, &supplementary) == unassignedCode); Require(sceCesEucJpToUcs2(eucJp, reinterpret_cast("\x8F\xF5\xA1"), 3, &used, &supplementary) == unassignedCode); - const std::uint16_t supplementaryText[] = {0x02D8, 0x0386, 0x0402, 0x6600, 0}; - Require(sceCesUcs2StrToMbcsStr(eucContext, supplementaryText, 5, &used, mbcs, sizeof(mbcs), &produced) == 0); - Require(used == 4 && produced == 11 && std::memcmp(mbcs, "\x8F\xA2\xAF\x8F\xA6\xE1\x8F\xA7\xC2\xFA\xB4", 11) == 0); - Require(sceCesUcs2StrGetMbcsLen(eucContext, supplementaryText, 5, &used, &produced) == 0 && produced == 11); - std::uint16_t supplementaryBack[8] = {}; - Require(sceCesMbcsStrToUcs2Str(eucContext, mbcs, 11, &used, supplementaryBack, 8, &produced) == 0); - Require(used == 11 && produced == 4 && supplementaryBack[0] == 0x02D8 && supplementaryBack[1] == 0x0386 && supplementaryBack[2] == 0x0402 && supplementaryBack[3] == 0x6600); - Require(sceCesMbcsStrGetUcs2Len(eucContext, mbcs, 11, &used, &produced) == 0 && produced == 4); - Require(sceCesMbcsStrToUtf8Str(eucContext, mbcs, 11, &used, japaneseBack, sizeof(japaneseBack), &produced) == 0); - Require(produced == 9 && std::memcmp(japaneseBack, "\xCB\x98\xCE\x86\xD0\x82\xE6\x98\x80", 9) == 0); - Require(sceCesMbcsStrGetUtf8Len(eucContext, mbcs, 11, &used, &produced) == 0 && produced == 9); - Require(sceCesMbcsStrToUcs2Str(eucContext, mbcs, 10, &used, supplementaryBack, 8, &produced) == srcBufferEnd); - std::uint32_t supplementaryAssigned = 0; - for (std::uint32_t lead = 0xA2; lead <= 0xF4; ++lead) { - for (std::uint32_t trail = 0xA1; trail <= 0xFE; ++trail) { - const std::uint8_t cell[3] = {0x8F, static_cast(lead), static_cast(trail)}; - std::uint16_t decoded[2] = {}; - if (sceCesEucJpToUcs2(eucJp, cell, 3, &used, decoded) != 0) continue; - ++supplementaryAssigned; - decoded[1] = 0; - std::uint8_t again[4] = {}; - std::uint16_t second[2] = {}; - Require(sceCesUcs2StrToMbcsStr(eucContext, decoded, 2, &used, again, sizeof(again), &produced) == 0); - if (produced == 3) Require(again[1] == cell[1] && again[2] == cell[2]); - Require(sceCesEucJpToUcs2(eucJp, again, produced, &used, second) == 0 && second[0] == decoded[0]); - } - } - Require(supplementaryAssigned == 6067); + const std::uint16_t supplementaryText[] = {u'A', 0x02D8, 0}; + Require(sceCesUcs2StrToMbcsStr(eucContext, supplementaryText, 0, &used, mbcs, sizeof(mbcs), &produced) == unassignedCode); + Require(used == 1 && produced == 1 && std::memcmp(mbcs, "A", 2) == 0); + const std::uint16_t ibmText[] = {0x6600, 0x2170, 0}; + Require(sceCesUcs2StrToMbcsStr(eucContext, ibmText, 0, &used, mbcs, sizeof(mbcs), &produced) == 0); + Require(used == 2 && produced == 4 && std::memcmp(mbcs, "\xFA\xB4\xFC\xF1", 5) == 0); + Require(sceCesMbcsStrToUtf8Str(eucContext, reinterpret_cast("A\x8F\xA2\xAF" "B"), 0, &used, japaneseBack, sizeof(japaneseBack), &produced) == invalidEncode); + Require(used == 1 && produced == 1 && std::memcmp(japaneseBack, "A", 2) == 0); + RequireMeasuredEucJp(eucJp); + char measuredLatin[256] = {}; + Require(sceCesMbcsUcsContextInit(measuredLatin, profile) == 0); + RequireMeasuredStrings(measuredLatin, eucContext); + Require(sceCesMbcsUcsContextInit(measuredLatin, nullptr) == invalidParameter); const auto* sjisSource = reinterpret_cast("Go \xEF\xBD\xB1!"); Require(sceCesUtf8StrToMbcsStr(sjisContext, sjisSource, 16, &used, mbcs, sizeof(mbcs), &produced) == 0); Require(used == 7 && produced == 5 && std::memcmp(mbcs, "Go \xB1!", 5) == 0); Require(sceCesUtf8StrGetMbcsLen(sjisContext, sjisSource, 16, &used, &produced) == 0 && used == 7 && produced == 5); Require(sceCesUtf8StrToMbcsStr(sjisContext, sjisSource, 16, &used, mbcs, 4, &produced) == dstBufferEnd); + Require(used == 3 && produced == 3 && std::memcmp(mbcs, "Go ", 4) == 0); + Require(sceCesUtf8StrToMbcsStr(sjisContext, sjisSource, 16, &used, mbcs, sizeof(mbcs), &produced) == 0); Require(sceCesUtf8StrToMbcsStr(sjisContext, reinterpret_cast("\xF0\x9F\x98\x80"), 4, &used, mbcs, sizeof(mbcs), &produced) == unassignedCode); + Require(used == 0 && produced == 0 && mbcs[0] == 0); + Require(sceCesUtf8StrToMbcsStr(sjisContext, sjisSource, 16, &used, mbcs, sizeof(mbcs), &produced) == 0); std::uint8_t sjisBack[16] = {}; Require(sceCesMbcsStrToUtf8Str(sjisContext, mbcs, 5, &used, sjisBack, sizeof(sjisBack), &produced) == 0); @@ -478,8 +745,8 @@ int main() { Require(sceCesUcs2StrToMbcsStr(sjisContext, sjisUcs2, 4, &used, mbcs, sizeof(mbcs), &produced) == 0); Require(used == 3 && produced == 3 && std::memcmp(mbcs, "OK\xDF", 3) == 0); Require(sceCesUcs2StrGetMbcsLen(sjisContext, sjisUcs2, 4, &used, &produced) == 0 && produced == 3); - std::uint16_t sjisWide[8] = {}; - Require(sceCesMbcsStrToUcs2Str(sjisContext, mbcs, 3, &used, sjisWide, 8, &produced) == 0); + std::uint16_t sjisWide[16] = {}; + Require(sceCesMbcsStrToUcs2Str(sjisContext, mbcs, 3, &used, sjisWide, 16, &produced) == 0); Require(used == 3 && produced == 3 && sjisWide[0] == u'O' && sjisWide[1] == u'K' && sjisWide[2] == 0xFF9F); Require(sceCesMbcsStrGetUcs2Len(sjisContext, mbcs, 3, &used, &produced) == 0 && produced == 3); @@ -487,19 +754,20 @@ int main() { Require(used == 24 && produced == 16 && std::memcmp(mbcs, "\x82\xB1\x82\xF1\x82\xC9\x82\xBF\x82\xCD\x93\xFA\x96\x7B\x8C\xEA", 16) == 0); std::uint8_t sjisJapaneseBack[32] = {}; Require(sceCesMbcsStrToUtf8Str(sjisContext, mbcs, 16, &used, sjisJapaneseBack, sizeof(sjisJapaneseBack), &produced) == 0 && produced == 24 && std::memcmp(sjisJapaneseBack, japanese, 24) == 0); - Require(sceCesMbcsStrToUcs2Str(sjisContext, mbcs, 16, &used, sjisWide, 8, &produced) == 0 && used == 16 && produced == 8 && sjisWide[0] == 0x3053 && sjisWide[5] == 0x65E5 && sjisWide[7] == 0x8A9E); - Require(sceCesMbcsStrToUcs2Str(sjisContext, mbcs, 15, &used, sjisWide, 8, &produced) == srcBufferEnd); + Require(sceCesMbcsStrToUcs2Str(sjisContext, mbcs, 16, &used, sjisWide, 16, &produced) == 0 && used == 16 && produced == 8 && sjisWide[0] == 0x3053 && sjisWide[5] == 0x65E5 && sjisWide[7] == 0x8A9E); + Require(sceCesMbcsStrToUcs2Str(sjisContext, mbcs, 15, &used, sjisWide, 16, &produced) == srcBufferEnd); const std::uint16_t sjisExtensions[] = {0x2460, 0xFF5E, 0x2252, 0}; Require(sceCesUcs2StrToMbcsStr(sjisContext, sjisExtensions, 4, &used, mbcs, sizeof(mbcs), &produced) == 0 && produced == 6 && std::memcmp(mbcs, "\x87\x40\x81\x60\x81\xE0", 6) == 0); - Require(sceCesMbcsStrToUcs2Str(sjisContext, reinterpret_cast("\x85\x40"), 2, &used, sjisWide, 8, &produced) == unassignedCode); - Require(sceCesMbcsStrToUcs2Str(sjisContext, reinterpret_cast("\x80"), 1, &used, sjisWide, 8, &produced) == invalidEncode); - Require(sceCesMbcsStrToUcs2Str(sjisContext, reinterpret_cast("\xA0"), 1, &used, sjisWide, 8, &produced) == invalidEncode); - Require(sceCesUcs2StrToMbcsStr(sjisContext, yen, 2, &used, mbcs, sizeof(mbcs), &produced) == unassignedCode); - Require(sceCesMbcsStrToUcs2Str(sjisContext, reinterpret_cast("\xFB\xFC"), 2, &used, sjisWide, 8, &produced) == 0 && used == 2 && produced == 1 && sjisWide[0] == 0x9AD9); - Require(sceCesMbcsStrToUcs2Str(sjisContext, reinterpret_cast("\xFA\x40"), 2, &used, sjisWide, 8, &produced) == 0 && used == 2 && produced == 1 && sjisWide[0] == 0x2170); - Require(sceCesMbcsStrToUcs2Str(sjisContext, reinterpret_cast("\xFC\x4B"), 2, &used, sjisWide, 8, &produced) == 0 && used == 2 && produced == 1 && sjisWide[0] == 0x9ED1); - Require(sceCesMbcsStrToUcs2Str(sjisContext, reinterpret_cast("\xFC\x4C"), 2, &used, sjisWide, 8, &produced) == unassignedCode); - Require(sceCesMbcsStrToUcs2Str(sjisContext, reinterpret_cast("\xF0\x40"), 2, &used, sjisWide, 8, &produced) == unassignedCode); + Require(sceCesMbcsStrToUcs2Str(sjisContext, reinterpret_cast("\x85\x40"), 2, &used, sjisWide, 16, &produced) == unassignedCode); + Require(sceCesMbcsStrToUcs2Str(sjisContext, reinterpret_cast("\x80"), 1, &used, sjisWide, 16, &produced) == invalidEncode); + Require(sceCesMbcsStrToUcs2Str(sjisContext, reinterpret_cast("\xA0"), 1, &used, sjisWide, 16, &produced) == invalidEncode); + Require(sceCesUcs2StrToMbcsStr(sjisContext, yen, 2, &used, mbcs, sizeof(mbcs), &produced) == 0 && used == 1 && produced == 2 && std::memcmp(mbcs, "\x81\x8F", 3) == 0); + RequireMeasuredEncoders(eucContext, sjisContext); + Require(sceCesMbcsStrToUcs2Str(sjisContext, reinterpret_cast("\xFB\xFC"), 2, &used, sjisWide, 16, &produced) == 0 && used == 2 && produced == 1 && sjisWide[0] == 0x9AD9); + Require(sceCesMbcsStrToUcs2Str(sjisContext, reinterpret_cast("\xFA\x40"), 2, &used, sjisWide, 16, &produced) == 0 && used == 2 && produced == 1 && sjisWide[0] == 0x2170); + Require(sceCesMbcsStrToUcs2Str(sjisContext, reinterpret_cast("\xFC\x4B"), 2, &used, sjisWide, 16, &produced) == 0 && used == 2 && produced == 1 && sjisWide[0] == 0x9ED1); + Require(sceCesMbcsStrToUcs2Str(sjisContext, reinterpret_cast("\xFC\x4C"), 2, &used, sjisWide, 16, &produced) == unassignedCode); + Require(sceCesMbcsStrToUcs2Str(sjisContext, reinterpret_cast("\xF0\x40"), 2, &used, sjisWide, 16, &produced) == unassignedCode); std::uint32_t sjisAssigned = 0; for (std::uint32_t lead = 0x81; lead <= 0xFC; ++lead) { if (lead > 0x9F && lead < 0xE0) continue; diff --git a/core/libs/tests/GuestCesChinese.cpp b/core/libs/tests/GuestCesChinese.cpp index 5c3b00ea29..fa1490c296 100644 --- a/core/libs/tests/GuestCesChinese.cpp +++ b/core/libs/tests/GuestCesChinese.cpp @@ -1,44 +1,9 @@ +#include "prx/libSceCesCs/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include #include -extern "C" { -void* APS5_VABI sceCesUcsProfileInitEucCnGb2312(void*); -void* APS5_VABI sceCesUcsProfileInitGbkCp936(void*); -void* APS5_VABI sceCesUcsProfileInitSJis1997Cp932(void*); -int APS5_VABI sceCesMbcsUcsContextInit(void*, const void*); -int APS5_VABI sceCesEucCnToUcs2(const void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint16_t*); -int APS5_VABI sceCesEucCnToUtf8(const void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint8_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesEucCnToUtf16be(const void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint16_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesEucCnToUtf32(const void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint32_t*); -int APS5_VABI sceCesGbToUcs2(const void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint16_t*); -int APS5_VABI sceCesGbToUtf8(const void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint8_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesGbToUtf16(const void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint16_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesGbToUtf32le(const void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint32_t*); -int APS5_VABI sceCesUcs2ToEucCn(std::uint16_t, const void*, std::uint8_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesUcs2ToGb(std::uint16_t, const void*, std::uint8_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesUtf8ToEucCn(const std::uint8_t*, std::uint32_t, std::uint32_t*, const void*, std::uint8_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesUtf8ToGb(const std::uint8_t*, std::uint32_t, std::uint32_t*, const void*, std::uint8_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesUtf16leToGb(const std::uint16_t*, std::uint32_t, std::uint32_t*, const void*, std::uint8_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesUtf32ToEucCn(std::uint32_t, const void*, std::uint8_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesUtf32beToGb(const std::uint32_t*, const void*, std::uint8_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesUtf8StrToMbcsStr(void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint8_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesMbcsStrToUtf8Str(void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint8_t*, std::uint32_t, std::uint32_t*); -void* APS5_VABI sceCesUcsProfileInitGb18030_2000(void*); -void* APS5_VABI sceCesUcsProfileInitGb18030_2005(void*); -int APS5_VABI sceCesGbToUtf16be(const void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint16_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesGbToUtf32(const void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint32_t*); -int APS5_VABI sceCesUtf16ToGb(const std::uint16_t*, std::uint32_t, std::uint32_t*, const void*, std::uint8_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesUtf32ToGb(std::uint32_t, const void*, std::uint8_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesMbcToUcs2(const void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint16_t*); -int APS5_VABI sceCesMbcToUtf16le(const void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint16_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesMbcsStrToUcs2Str(void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint16_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesMbcsStrToUtf16Str(void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint16_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesMbcsStrGetUtf16Len(void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint32_t*); -int APS5_VABI sceCesUtf16StrToMbcsStr(void*, const std::uint16_t*, std::uint32_t, std::uint32_t*, std::uint8_t*, std::uint32_t, std::uint32_t*); -} - static void Require(bool value) { if (!value) std::abort(); } static const std::uint8_t* Bytes(const char* text) { return reinterpret_cast(text); } @@ -47,6 +12,7 @@ static constexpr int invalidParameter = static_cast(0x805C0001); static constexpr int invalidSrcBuffer = static_cast(0x805C0010); static constexpr int srcBufferEnd = static_cast(0x805C0011); static constexpr int invalidEncode = static_cast(0x805C0014); + constexpr int outOfCodeSpace = static_cast(0x805C0015); static constexpr int unassignedCode = static_cast(0x805C0020); static constexpr int invalidDstBuffer = static_cast(0x805C0030); static constexpr int dstBufferEnd = static_cast(0x805C0031); @@ -237,8 +203,8 @@ static void CheckGb18030(const void* gb, bool revision2005, std::uint32_t twoByt std::uint8_t mbcs[4] = {1, 2, 3, 4}; produced = 0x55; - Require(sceCesUtf32ToGb(0x10000, gb, mbcs, 3, &produced) == dstBufferEnd && produced == 0x55 && std::memcmp(mbcs, "\x01\x02\x03\x04", 4) == 0); - Require(sceCesUtf32ToGb(0xD800, gb, mbcs, sizeof(mbcs), &produced) == invalidEncode); + Require(sceCesUtf32ToGb(0x10000, gb, mbcs, 3, &produced) == dstBufferEnd && produced == 4 && std::memcmp(mbcs, "\x01\x02\x03\x04", 4) == 0); + Require(sceCesUtf32ToGb(0xD800, gb, mbcs, sizeof(mbcs), &produced) == outOfCodeSpace); Require(sceCesUtf32ToGb(0x110000, gb, mbcs, sizeof(mbcs), &produced) == invalidEncode); Require(sceCesUcs2ToGb(0x80, gb, mbcs, sizeof(mbcs), &produced) == 0 && produced == 4 && std::memcmp(mbcs, "\x81\x30\x81\x30", 4) == 0); Require(sceCesUcs2ToGb(0x20AC, gb, mbcs, sizeof(mbcs), &produced) == 0 && produced == 2 && std::memcmp(mbcs, "\xA2\xE3", 2) == 0); @@ -262,7 +228,8 @@ static void CheckGb18030(const void* gb, bool revision2005, std::uint32_t twoByt std::uint16_t backUtf16[8] = {}; Require(sceCesMbcsStrToUtf16Str(context, text, gbSize, &consumed, backUtf16, 8, &produced) == 0 && consumed == gbSize && produced == 6); Require(backUtf16[0] == 'A' && backUtf16[1] == 0x4E2D && backUtf16[2] == 0x80 && backUtf16[3] == 0xD83D && backUtf16[4] == 0xDE00 && backUtf16[5] == 0xFE10); - Require(sceCesMbcsStrToUtf16Str(context, text, gbSize, &consumed, backUtf16, 4, &produced) == dstBufferEnd); + std::uint16_t shortUtf16[4] = {}; + Require(sceCesMbcsStrToUtf16Str(context, text, gbSize, &consumed, shortUtf16, 4, &produced) == dstBufferEnd); Require(sceCesMbcsStrGetUtf16Len(context, text, gbSize, &consumed, &produced) == 0 && consumed == gbSize && produced == 6); std::uint8_t again[16] = {}; Require(sceCesUtf16StrToMbcsStr(context, backUtf16, 6, &consumed, again, sizeof(again), &produced) == 0 && consumed == 6 && produced == gbSize); @@ -324,7 +291,7 @@ int main() { Require(sceCesUcs2ToEucCn(0x4E02, euc, mbcs, sizeof(mbcs), &produced) == unassignedCode); Require(sceCesUcs2ToEucCn(0x20AC, euc, mbcs, sizeof(mbcs), &produced) == unassignedCode); Require(sceCesUcs2ToEucCn(0x4E2D, euc, mbcs, 1, &produced) == dstBufferEnd); - Require(sceCesUcs2ToEucCn(0xDC00, euc, mbcs, sizeof(mbcs), &produced) == invalidEncode); + Require(sceCesUcs2ToEucCn(0xDC00, euc, mbcs, sizeof(mbcs), &produced) == outOfCodeSpace); Require(sceCesUcs2ToGb(0x4E02, gbk, mbcs, sizeof(mbcs), &produced) == 0 && produced == 2 && std::memcmp(mbcs, "\x81\x40", 2) == 0); Require(sceCesUcs2ToGb(0x20AC, gbk, mbcs, sizeof(mbcs), &produced) == 0 && produced == 1 && mbcs[0] == 0x80); Require(sceCesUcs2ToGb(0x3042, euc, mbcs, sizeof(mbcs), &produced) == invalidParameter); diff --git a/core/libs/tests/GuestCesDbcs.cpp b/core/libs/tests/GuestCesDbcs.cpp index 753c8f5c3e..e8c093f13b 100644 --- a/core/libs/tests/GuestCesDbcs.cpp +++ b/core/libs/tests/GuestCesDbcs.cpp @@ -1,68 +1,9 @@ +#include "prx/libSceCesCs/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include #include -extern "C" { -void* APS5_VABI sceCesUcsProfileInitEucKr(void*); -void* APS5_VABI sceCesUcsProfileInitUhc(void*); -void* APS5_VABI sceCesUcsProfileInitBig5Cp950(void*); -void* APS5_VABI sceCesUcsProfileInitEucJpCp51932(void*); -int APS5_VABI sceCesEucKrToUtf8(const void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint8_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesUhcToUtf8(const void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint8_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesBig5ToUtf8(const void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint8_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesMbcsUcsContextInit(void*, const void*); -int APS5_VABI sceCesUtf8StrToMbcsStr(void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint8_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesMbcsStrToUtf8Str(void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint8_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesUcs2StrToMbcsStr(void*, const std::uint16_t*, std::uint32_t, std::uint32_t*, std::uint8_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesMbcsStrToUcs2Str(void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint16_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesEucKrToUcs2(const void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint16_t*); -int APS5_VABI sceCesEucKrToUtf16(const void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint16_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesEucKrToUtf16be(const void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint16_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesEucKrToUtf16le(const void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint16_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesEucKrToUtf32(const void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint32_t*); -int APS5_VABI sceCesEucKrToUtf32be(const void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint32_t*); -int APS5_VABI sceCesEucKrToUtf32le(const void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint32_t*); -int APS5_VABI sceCesUhcToUcs2(const void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint16_t*); -int APS5_VABI sceCesUhcToUtf16(const void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint16_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesUhcToUtf16be(const void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint16_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesUhcToUtf16le(const void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint16_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesUhcToUtf32(const void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint32_t*); -int APS5_VABI sceCesUhcToUtf32be(const void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint32_t*); -int APS5_VABI sceCesUhcToUtf32le(const void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint32_t*); -int APS5_VABI sceCesBig5ToUcs2(const void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint16_t*); -int APS5_VABI sceCesBig5ToUtf16(const void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint16_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesBig5ToUtf16be(const void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint16_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesBig5ToUtf16le(const void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint16_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesBig5ToUtf32(const void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint32_t*); -int APS5_VABI sceCesBig5ToUtf32be(const void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint32_t*); -int APS5_VABI sceCesBig5ToUtf32le(const void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint32_t*); -int APS5_VABI sceCesUcs2ToEucKr(std::uint16_t, const void*, std::uint8_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesUtf8ToEucKr(const std::uint8_t*, std::uint32_t, std::uint32_t*, const void*, std::uint8_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesUtf16ToEucKr(const std::uint16_t*, std::uint32_t, std::uint32_t*, const void*, std::uint8_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesUtf16beToEucKr(const std::uint16_t*, std::uint32_t, std::uint32_t*, const void*, std::uint8_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesUtf16leToEucKr(const std::uint16_t*, std::uint32_t, std::uint32_t*, const void*, std::uint8_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesUtf32ToEucKr(std::uint32_t, const void*, std::uint8_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesUtf32beToEucKr(const std::uint32_t*, const void*, std::uint8_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesUtf32leToEucKr(const std::uint32_t*, const void*, std::uint8_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesUcs2ToUhc(std::uint16_t, const void*, std::uint8_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesUtf8ToUhc(const std::uint8_t*, std::uint32_t, std::uint32_t*, const void*, std::uint8_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesUtf16ToUhc(const std::uint16_t*, std::uint32_t, std::uint32_t*, const void*, std::uint8_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesUtf16beToUhc(const std::uint16_t*, std::uint32_t, std::uint32_t*, const void*, std::uint8_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesUtf16leToUhc(const std::uint16_t*, std::uint32_t, std::uint32_t*, const void*, std::uint8_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesUtf32ToUhc(std::uint32_t, const void*, std::uint8_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesUtf32beToUhc(const std::uint32_t*, const void*, std::uint8_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesUtf32leToUhc(const std::uint32_t*, const void*, std::uint8_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesUcs2ToBig5(std::uint16_t, const void*, std::uint8_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesUtf8ToBig5(const std::uint8_t*, std::uint32_t, std::uint32_t*, const void*, std::uint8_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesUtf16ToBig5(const std::uint16_t*, std::uint32_t, std::uint32_t*, const void*, std::uint8_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesUtf16beToBig5(const std::uint16_t*, std::uint32_t, std::uint32_t*, const void*, std::uint8_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesUtf16leToBig5(const std::uint16_t*, std::uint32_t, std::uint32_t*, const void*, std::uint8_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesUtf32ToBig5(std::uint32_t, const void*, std::uint8_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesUtf32beToBig5(const std::uint32_t*, const void*, std::uint8_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesUtf32leToBig5(const std::uint32_t*, const void*, std::uint8_t*, std::uint32_t, std::uint32_t*); -} - using ToUtf8 = int (APS5_VABI*)(const void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint8_t*, std::uint32_t, std::uint32_t*); using ToUcs2 = int (APS5_VABI*)(const void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint16_t*); using ToUtf16 = int (APS5_VABI*)(const void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint16_t*, std::uint32_t, std::uint32_t*); @@ -99,6 +40,7 @@ constexpr int invalidParameter = static_cast(0x805C0001); constexpr int invalidSrcBuffer = static_cast(0x805C0010); constexpr int srcBufferEnd = static_cast(0x805C0011); constexpr int invalidEncode = static_cast(0x805C0014); +constexpr int illegalCode = static_cast(0x805C0015); constexpr int unassignedCode = static_cast(0x805C0020); constexpr int invalidDstBuffer = static_cast(0x805C0030); constexpr int dstBufferEnd = static_cast(0x805C0031); @@ -171,15 +113,15 @@ static std::uint32_t RoundTripMismatches(void* context) { for (std::uint32_t lead = 0x81; lead < 0xFF; ++lead) { for (std::uint32_t trail = 0x40; trail < 0xFF; ++trail) { const std::uint8_t source[2] = {static_cast(lead), static_cast(trail)}; - std::uint16_t ucs2 = 0; + std::uint16_t ucs2[2] = {}; std::uint32_t read = 0; std::uint32_t written = 0; - if (sceCesMbcsStrToUcs2Str(context, source, sizeof(source), &read, &ucs2, 1, &written) != 0) continue; - Require(read == 2 && written == 1); - std::uint8_t back[2] = {}; - Require(sceCesUcs2StrToMbcsStr(context, &ucs2, 1, &read, back, sizeof(back), &written) == 0); - Require(read == 1 && written == 2); - if (std::memcmp(source, back, sizeof(back)) != 0) ++mismatches; + if (sceCesMbcsStrToUcs2Str(context, source, sizeof(source), &read, ucs2, 2, &written) != 0) continue; + Require(read == 2 && written == 1 && ucs2[1] == 0); + std::uint8_t back[3] = {}; + Require(sceCesUcs2StrToMbcsStr(context, ucs2, 1, &read, back, sizeof(back), &written) == 0); + Require(read == 1 && written == 2 && back[2] == 0); + if (std::memcmp(source, back, sizeof(source)) != 0) ++mismatches; } } return mismatches; @@ -296,7 +238,7 @@ static void RequireEncode(const Encoders& encoders, const void* profile, std::ui Encoded out; Require(Encode(encoders, form, code, profile, out) == expected); if (expected == 0) Require(out.read == SourceUnits(form, code) && out.size == size && std::memcmp(out.bytes, bytes, size) == 0); - else Require(out.read == 77 && out.size == 77 && out.bytes[0] == 0x55 && out.bytes[1] == 0x55); + else Require(out.read == 77 && out.size == ((form == 0 || form >= 5) && expected != static_cast(0x805C0001) ? 0u : 77u) && out.bytes[0] == 0x55 && out.bytes[1] == 0x55); } } @@ -305,7 +247,7 @@ static void RequireEncoders(const Encoders& encoders, const void* profile, void* for (std::uint32_t code = 1; code < 0x10000; ++code) { if (code >= 0xD800 && code <= 0xDFFF) continue; const auto ucs2 = static_cast(code); - std::uint8_t bytes[2] = {}; + std::uint8_t bytes[3] = {}; std::uint32_t read = 0; std::uint32_t written = 0; const int expected = sceCesUcs2StrToMbcsStr(context, &ucs2, 1, &read, bytes, sizeof(bytes), &written); @@ -434,9 +376,9 @@ int main() { const std::uint32_t big = 0x0000AC00; Require(sceCesUcs2ToEucKr(0xAC00, uhc, nullptr, 0, nullptr) == invalidParameter); Require(sceCesUcs2ToEucKr(0xD800, eucKr, nullptr, 0, nullptr) == invalidDstBuffer); - Require(sceCesUcs2ToEucKr(0xD800, eucKr, out, 2, &size) == invalidEncode); + Require(sceCesUcs2ToEucKr(0xD800, eucKr, out, 2, &size) == illegalCode); Require(sceCesUtf32ToUhc(0x110000, uhc, out, 2, &size) == invalidEncode); - Require(sceCesUtf32ToUhc(0xDFFF, uhc, out, 2, &size) == invalidEncode); + Require(sceCesUtf32ToUhc(0xDFFF, uhc, out, 2, &size) == illegalCode); Require(sceCesUtf32beToBig5(nullptr, eucKr, nullptr, 0, nullptr) == invalidParameter); Require(sceCesUtf32beToBig5(nullptr, big5, nullptr, 0, nullptr) == invalidSrcBuffer); Require(sceCesUtf32leToBig5(&big, big5, nullptr, 0, nullptr) == invalidDstBuffer); @@ -445,14 +387,14 @@ int main() { Require(sceCesUtf8ToEucKr(Bytes("\xEA\xB0\x80"), 0, nullptr, eucKr, nullptr, 0, nullptr) == srcBufferEnd); Require(sceCesUtf8ToEucKr(Bytes("\xEA\xB0\x80"), 3, nullptr, eucKr, nullptr, 0, nullptr) == invalidDstBuffer); Require(sceCesUtf8ToEucKr(Bytes("\xEA\xB0\x80"), 2, &read, eucKr, out, 2, &size) == srcBufferEnd); - Require(sceCesUtf8ToEucKr(Bytes("\xC0\x80"), 2, &read, eucKr, out, 2, &size) == invalidEncode); + Require(sceCesUtf8ToEucKr(Bytes("\xC0\x80"), 2, &read, eucKr, out, 2, &size) == illegalCode); Require(sceCesUtf8ToEucKr(Bytes("\xEA\xB0\x80"), 3, &read, eucKr, out, 1, &size) == dstBufferEnd); const std::uint16_t lowSurrogate[1] = {0xDC00}; const std::uint16_t highSurrogate[2] = {0xD800, 0x0041}; Require(sceCesUtf16ToUhc(lowSurrogate, 1, &read, uhc, out, 2, &size) == invalidEncode); Require(sceCesUtf16ToUhc(highSurrogate, 1, &read, uhc, out, 2, &size) == srcBufferEnd); Require(sceCesUtf16ToUhc(highSurrogate, 2, &read, uhc, out, 2, &size) == invalidEncode); - Require(out[0] == 0x55 && out[1] == 0x55 && size == 77 && read == 77); + Require(out[0] == 0x55 && out[1] == 0x55 && size == 0 && read == 77); std::memcpy(&unit, "\xAC\x00", 2); Require(sceCesUtf16beToEucKr(&unit, 1, &read, eucKr, out, 2, &size) == 0 && read == 1 && size == 2 && std::memcmp(out, "\xB0\xA1", 2) == 0); diff --git a/core/libs/tests/GuestCesJapanese.cpp b/core/libs/tests/GuestCesJapanese.cpp index 754471576e..30bfa8b235 100644 --- a/core/libs/tests/GuestCesJapanese.cpp +++ b/core/libs/tests/GuestCesJapanese.cpp @@ -1,48 +1,13 @@ +#include "prx/libSceCesCs/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" +#include #include #include #include +#include #include #include -extern "C" { -void* APS5_VABI sceCesUcsProfileInitSJis1997Cp932(void*); -void* APS5_VABI sceCesUcsProfileInitEucJpCp51932(void*); -void* APS5_VABI sceCesUcsProfileInitEucJpX0208(void*); -void* APS5_VABI sceCesUcsProfileInitEucJpX0208Ss2(void*); -void* APS5_VABI sceCesUcsProfileInitEucJpX0208Ss2Ss3(void*); -void* APS5_VABI sceCesUcsProfileInitSJis1997X0208(void*); -int APS5_VABI sceCesMbcsUcsContextInit(void*, const void*); -int APS5_VABI sceCesMbcsStrToUcs2Str(void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint16_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesUcs2StrToMbcsStr(void*, const std::uint16_t*, std::uint32_t, std::uint32_t*, std::uint8_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesEucJpToUcs2(const void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint16_t*); -int APS5_VABI sceCesEucJpToUtf8(const void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint8_t*, std::uint32_t, std::uint32_t*); -const std::uint8_t* APS5_VABI sceCesRefersUcsProfileCp1252(void); -int APS5_VABI sceCesSJisToUcs2(const void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint16_t*); -int APS5_VABI sceCesSJisToUtf8(const void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint8_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesSJisToUtf16(const void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint16_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesSJisToUtf16be(const void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint16_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesSJisToUtf16le(const void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint16_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesSJisToUtf32(const void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint32_t*); -int APS5_VABI sceCesSJisToUtf32be(const void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint32_t*); -int APS5_VABI sceCesSJisToUtf32le(const void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint32_t*); -int APS5_VABI sceCesEucJpToUtf16(const void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint16_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesEucJpToUtf16be(const void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint16_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesEucJpToUtf32(const void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint32_t*); -int APS5_VABI sceCesEucJpToUtf32le(const void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint32_t*); -int APS5_VABI sceCesUcs2ToSJis(std::uint16_t, const void*, std::uint8_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesUcs2ToEucJp(std::uint16_t, const void*, std::uint8_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesUtf8ToSJis(const std::uint8_t*, std::uint32_t, std::uint32_t*, const void*, std::uint8_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesUtf8ToEucJp(const std::uint8_t*, std::uint32_t, std::uint32_t*, const void*, std::uint8_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesUtf16ToSJis(const std::uint16_t*, std::uint32_t, std::uint32_t*, const void*, std::uint8_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesUtf16beToEucJp(const std::uint16_t*, std::uint32_t, std::uint32_t*, const void*, std::uint8_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesUtf32ToSJis(std::uint32_t, const void*, std::uint8_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesUtf32beToSJis(const std::uint32_t*, const void*, std::uint8_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesUtf32leToEucJp(const std::uint32_t*, const void*, std::uint8_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesSJisCodeToJisX0208(std::uint16_t, std::uint8_t*, std::uint8_t*); -int APS5_VABI sceCesJisX0208ToSJisCode(std::uint8_t, std::uint8_t, std::uint16_t*); -} - static void Require(bool value) { if (!value) std::abort(); } static const std::uint8_t* Bytes(const char* text) { return reinterpret_cast(text); } @@ -50,6 +15,7 @@ static const std::uint8_t* Bytes(const char* text) { return reinterpret_cast(0x805C0001); constexpr int srcBufferEnd = static_cast(0x805C0011); constexpr int invalidEncode = static_cast(0x805C0014); +constexpr int outOfCodeSpace = static_cast(0x805C0015); constexpr int unassignedCode = static_cast(0x805C0020); constexpr int dstBufferEnd = static_cast(0x805C0031); constexpr std::uint32_t jisX0208Cells = 6878; @@ -100,13 +66,14 @@ static bool EncodeLeavesOutputs(int expected, const void* profile, std::uint16_t std::uint8_t mbcs[4] = {0xEE, 0xEE, 0xEE, 0xEE}; std::uint32_t size = 77; const int result = sjis ? sceCesUcs2ToSJis(ucs2, profile, mbcs, sizeof(mbcs), &size) : sceCesUcs2ToEucJp(ucs2, profile, mbcs, sizeof(mbcs), &size); - return result == expected && size == 77 && mbcs[0] == 0xEE && mbcs[1] == 0xEE && mbcs[2] == 0xEE; + return result == expected && size == (expected == static_cast(0x805C0001) ? 77u : 0u) && mbcs[0] == 0xEE && mbcs[1] == 0xEE && mbcs[2] == 0xEE; } -static bool DecodeLeavesOutputs(int expected, const void* profile, const char* bytes, std::uint32_t size, bool sjis) { +static bool DecodeFails(int expected, const void* profile, const char* bytes, std::uint32_t size, bool sjis) { std::uint32_t used = 77; std::uint16_t ucs2 = 0xEEEE; const int result = sjis ? sceCesSJisToUcs2(profile, Bytes(bytes), size, &used, &ucs2) : sceCesEucJpToUcs2(profile, Bytes(bytes), size, &used, &ucs2); + if (!sjis) return result == expected && ucs2 == 0; return result == expected && used == 77 && ucs2 == 0xEEEE; } @@ -129,7 +96,7 @@ static void SweepEucJisX0208(const void* profile) { std::uint32_t size = 0; Require(sceCesUcs2ToEucJp(ucs2, profile, again, sizeof(again), &size) == 0 && size == 2 && again[0] == lead && again[1] == trail); } else { - Require(result == unassignedCode && used == 77 && ucs2 == 0xEEEE); + Require(result == unassignedCode && used == 2 && ucs2 == 0); } hash = Digest(hash, value); } @@ -193,22 +160,22 @@ static void TestJisX0208Profiles(const void* cp932, const void* cp51932) { Require(EucToUcs2(profile, "\xA2\xCC", 2, ucs2) == 0 && ucs2 == 0x00AC); for (const std::uint16_t cp932Form : {0xFF5E, 0x2225, 0xFF0D, 0xFFE0, 0xFFE1, 0xFFE2, 0x2460, 0x2170}) Require(EncodeLeavesOutputs(unassignedCode, profile, cp932Form, false)); Require(Reports(unsettledCell, [&] { EucEncodes(profile, 0xFF3C, ""); })); - Require(DecodeLeavesOutputs(unassignedCode, profile, "\xAD\xA1", 2, false) && DecodeLeavesOutputs(unassignedCode, profile, "\xF9\xA1", 2, false)); - Require(DecodeLeavesOutputs(unassignedCode, profile, "\xA9\xA1", 2, false) && DecodeLeavesOutputs(unassignedCode, profile, "\xFE\xFE", 2, false)); - Require(DecodeLeavesOutputs(invalidEncode, profile, "\xA4\x41", 2, false) && DecodeLeavesOutputs(invalidEncode, profile, "\xA4\xFF", 2, false)); - Require(DecodeLeavesOutputs(invalidEncode, profile, "\x80", 1, false) && DecodeLeavesOutputs(invalidEncode, profile, "\xFF", 1, false)); - Require(DecodeLeavesOutputs(srcBufferEnd, profile, "\xA4\xA2", 1, false)); + Require(DecodeFails(unassignedCode, profile, "\xAD\xA1", 2, false) && DecodeFails(unassignedCode, profile, "\xF9\xA1", 2, false)); + Require(DecodeFails(unassignedCode, profile, "\xA9\xA1", 2, false) && DecodeFails(unassignedCode, profile, "\xFE\xFE", 2, false)); + Require(DecodeFails(invalidEncode, profile, "\xA4\x41", 2, false) && DecodeFails(invalidEncode, profile, "\xA4\xFF", 2, false)); + Require(DecodeFails(invalidEncode, profile, "\x80", 1, false) && DecodeFails(invalidEncode, profile, "\xFF", 1, false)); + Require(DecodeFails(srcBufferEnd, profile, "\xA4\xA2", 1, false)); std::uint8_t mbcs[4] = {0xEE, 0xEE, 0xEE, 0xEE}; std::uint32_t size = 77; - Require(sceCesUcs2ToEucJp(0x3042, profile, mbcs, 1, &size) == dstBufferEnd && size == 77 && mbcs[0] == 0xEE); + Require(sceCesUcs2ToEucJp(0x3042, profile, mbcs, 1, &size) == dstBufferEnd && size == 2 && mbcs[0] == 0xEE); } Require(EucToUcs2(cp51932, "\xA1\xC0", 2, ucs2) == 0 && ucs2 == 0xFF3C && EucEncodes(cp51932, 0xFF3C, "\xA1\xC0")); Require(EucToUcs2(cp51932, "\xA1\xC1", 2, ucs2) == 0 && ucs2 == 0xFF5E && EucToUcs2(cp51932, "\xAD\xA1", 2, ucs2) == 0 && ucs2 == 0x2460); Require(EucEncodes(cp51932, 0x7E8A, "\xF9\xA1") && EucEncodes(ss3, 0x7E8A, "\x8F\xD4\xE3")); Require(EncodeLeavesOutputs(unassignedCode, euc, 0x7E8A, false) && EncodeLeavesOutputs(unassignedCode, ss2, 0x7E8A, false)); - Require(DecodeLeavesOutputs(invalidEncode, euc, "\x8E\xB1", 2, false) && DecodeLeavesOutputs(invalidEncode, euc, "\x8E", 1, false)); - Require(DecodeLeavesOutputs(invalidEncode, euc, "\x8F\xB0\xA1", 3, false) && DecodeLeavesOutputs(invalidEncode, ss2, "\x8F\xB0\xA1", 3, false)); + Require(DecodeFails(invalidEncode, euc, "\x8E\xB1", 2, false) && DecodeFails(invalidEncode, euc, "\x8E", 1, false)); + Require(DecodeFails(invalidEncode, euc, "\x8F\xB0\xA1", 3, false) && DecodeFails(invalidEncode, ss2, "\x8F\xB0\xA1", 3, false)); Require(EncodeLeavesOutputs(unassignedCode, euc, 0xFF71, false)); Require(EncodeLeavesOutputs(unassignedCode, euc, 0x4E02, false) && EncodeLeavesOutputs(unassignedCode, ss2, 0x4E02, false)); for (const void* profile : {ss2, ss3}) { @@ -216,8 +183,8 @@ static void TestJisX0208Profiles(const void* cp932, const void* cp51932) { const char bytes[3] = {'\x8E', static_cast(kana), 0}; Require(EucToUcs2(profile, bytes, 2, ucs2) == 0 && ucs2 == 0xFF61 + kana - 0xA1 && EucEncodes(profile, ucs2, bytes)); } - Require(DecodeLeavesOutputs(invalidEncode, profile, "\x8E\xE0", 2, false) && DecodeLeavesOutputs(invalidEncode, profile, "\x8E\xA0", 2, false)); - Require(DecodeLeavesOutputs(srcBufferEnd, profile, "\x8E\xB1", 1, false)); + Require(DecodeFails(invalidEncode, profile, "\x8E\xE0", 2, false) && DecodeFails(invalidEncode, profile, "\x8E\xA0", 2, false)); + Require(DecodeFails(srcBufferEnd, profile, "\x8E\xB1", 1, false)); } std::uint32_t supplementary = 0; std::uint32_t hash = 0x811C9DC5u; @@ -236,7 +203,7 @@ static void TestJisX0208Profiles(const void* cp932, const void* cp51932) { } } Require(supplementary == jisX0212Cells && hash == jisX0212Digest); - Require(DecodeLeavesOutputs(srcBufferEnd, ss3, "\x8F\xB0", 2, false) && DecodeLeavesOutputs(invalidEncode, ss3, "\x8F\xB0\x41", 3, false)); + Require(DecodeFails(srcBufferEnd, ss3, "\x8F\xB0", 2, false) && DecodeFails(invalidEncode, ss3, "\x8F\xB0\x41", 3, false)); Require(EucEncodes(ss3, 0x4E02, "\x8F\xB0\xA1") && EucEncodes(ss2, 0xFF71, "\x8E\xB1")); std::uint8_t utf8[4] = {}; @@ -254,11 +221,11 @@ static void TestJisX0208Profiles(const void* cp932, const void* cp51932) { Require(SJisToUcs2(sjis, "\x81\x60", 2, ucs2) == 0 && ucs2 == 0x301C && SJisEncodes(sjis, 0x301C, "\x81\x60")); Require(SJisToUcs2(sjis, "\x81\x91", 2, ucs2) == 0 && ucs2 == 0x00A2 && SJisEncodes(sjis, 0x00AC, "\x81\xCA")); for (const std::uint16_t cp932Form : {0xFF5E, 0x2225, 0xFF0D, 0xFFE0, 0xFFE1, 0xFFE2, 0x2460, 0x2170, 0x7E8A, 0x4E02}) Require(EncodeLeavesOutputs(unassignedCode, sjis, cp932Form, true)); - for (const char* removed : {"\x87\x40", "\xED\x40", "\xEE\xFC", "\xFA\x40", "\xFC\x4B", "\xF0\x40", "\xEF\xFC"}) Require(DecodeLeavesOutputs(unassignedCode, sjis, removed, 2, true)); + for (const char* removed : {"\x87\x40", "\xED\x40", "\xEE\xFC", "\xFA\x40", "\xFC\x4B", "\xF0\x40", "\xEF\xFC"}) Require(DecodeFails(unassignedCode, sjis, removed, 2, true)); Require(SJisToUcs2(cp932, "\x87\x40", 2, ucs2) == 0 && ucs2 == 0x2460 && SJisToUcs2(cp932, "\xFA\x40", 2, ucs2) == 0 && ucs2 == 0x2170); Require(SJisToUcs2(cp932, "\x81\x5F", 2, ucs2) == 0 && ucs2 == 0xFF3C && SJisToUcs2(cp932, "\\", 1, ucs2) == 0 && ucs2 == 0x5C); - Require(DecodeLeavesOutputs(invalidEncode, sjis, "\x82\x7F", 2, true) && DecodeLeavesOutputs(invalidEncode, sjis, "\x82\xFD", 2, true)); - Require(DecodeLeavesOutputs(srcBufferEnd, sjis, "\x82\xA0", 1, true)); + Require(DecodeFails(invalidEncode, sjis, "\x82\x7F", 2, true) && DecodeFails(invalidEncode, sjis, "\x82\xFD", 2, true)); + Require(DecodeFails(srcBufferEnd, sjis, "\x82\xA0", 1, true)); for (std::uint32_t byte = 0; byte <= 0xFF; ++byte) { const char bytes[2] = {static_cast(byte), 0}; if (byte == 0x5C || byte == 0x7E) { @@ -268,7 +235,7 @@ static void TestJisX0208Profiles(const void* cp932, const void* cp51932) { } else if (byte >= 0xA1 && byte <= 0xDF) { Require(SJisToUcs2(sjis, bytes, 1, ucs2) == 0 && ucs2 == 0xFF61 + byte - 0xA1 && SJisEncodes(sjis, ucs2, bytes)); } else { - Require(DecodeLeavesOutputs(byte == 0x80 || byte == 0xA0 || byte >= 0xFD ? invalidEncode : srcBufferEnd, sjis, bytes, 1, true)); + Require(DecodeFails(byte == 0x80 || byte == 0xA0 || byte >= 0xFD ? invalidEncode : srcBufferEnd, sjis, bytes, 1, true)); } } for (const std::uint16_t unsettled : {0x5C, 0x7E, 0xA5, 0x203E}) Require(Reports(unsettledByte, [&] { SJisEncodes(sjis, unsettled, ""); })); @@ -329,7 +296,7 @@ int main() { Require(sceCesEucJpToUtf16(euc, Bytes("\xA4\xA2"), 2, &consumed, &utf16, 1, &produced) == 0 && consumed == 2 && utf16 == 0x3042); Require(sceCesEucJpToUtf16be(euc, Bytes("\x8E\xB1"), 2, &consumed, &utf16, 1, &produced) == 0); Require(std::memcmp(&utf16, "\xFF\x71", 2) == 0); - Require(sceCesEucJpToUtf32(euc, Bytes("\x8F\xB0\xA1"), 3, &consumed, &utf32) == 0 && consumed == 3 && utf32 == 0x4E02); + Require(sceCesEucJpToUtf32(euc, Bytes("\x8F\xB0\xA1"), 3, &consumed, &utf32) == invalidEncode); Require(sceCesEucJpToUtf32le(euc, Bytes("\xA4\xA2"), 2, &consumed, &utf32) == 0); Require(std::memcmp(&utf32, "\x42\x30\x00\x00", 4) == 0); Require(sceCesEucJpToUtf32(sjis, Bytes("\xA4\xA2"), 2, &consumed, &utf32) == invalidParameter); @@ -338,12 +305,12 @@ int main() { Require(sceCesUcs2ToSJis(0x3042, sjis, mbcs, sizeof(mbcs), &produced) == 0 && produced == 2 && std::memcmp(mbcs, "\x82\xA0", 2) == 0); Require(sceCesUcs2ToSJis(0xFF71, sjis, mbcs, sizeof(mbcs), &produced) == 0 && produced == 1 && mbcs[0] == 0xB1); Require(sceCesUcs2ToSJis(0x3042, sjis, mbcs, 1, &produced) == dstBufferEnd); - Require(sceCesUcs2ToSJis(0xD800, sjis, mbcs, sizeof(mbcs), &produced) == invalidEncode); + Require(sceCesUcs2ToSJis(0xD800, sjis, mbcs, sizeof(mbcs), &produced) == outOfCodeSpace); Require(sceCesUcs2ToSJis(0x4E02, sjis, mbcs, sizeof(mbcs), &produced) == unassignedCode); Require(sceCesUcs2ToSJis(0x3042, euc, mbcs, sizeof(mbcs), &produced) == invalidParameter); Require(sceCesUcs2ToSJis(0x3042, sceCesRefersUcsProfileCp1252(), mbcs, sizeof(mbcs), &produced) == invalidParameter); Require(sceCesUcs2ToSJis(0x3042, sjis, nullptr, sizeof(mbcs), &produced) == invalidDstBuffer); - Require(sceCesUcs2ToEucJp(0x4E02, euc, mbcs, sizeof(mbcs), &produced) == 0 && produced == 3 && std::memcmp(mbcs, "\x8F\xB0\xA1", 3) == 0); + Require(sceCesUcs2ToEucJp(0x4E02, euc, mbcs, sizeof(mbcs), &produced) == unassignedCode); Require(sceCesUcs2ToEucJp(0xFF71, euc, mbcs, sizeof(mbcs), &produced) == 0 && produced == 2 && std::memcmp(mbcs, "\x8E\xB1", 2) == 0); Require(sceCesUtf8ToSJis(Bytes("\xE6\x97\xA5"), 3, &consumed, sjis, mbcs, sizeof(mbcs), &produced) == 0); @@ -375,8 +342,10 @@ int main() { std::memcpy(&utf32Le, "\xE5\x65\x00\x00", 4); Require(sceCesUtf32leToEucJp(&utf32Le, euc, mbcs, sizeof(mbcs), &produced) == 0 && std::memcmp(mbcs, "\xC6\xFC", 2) == 0); + constexpr int microsoftForms[] = {0x00A2, 0x00A3, 0x00A5, 0x00AC, 0x2014, 0x2016, 0x203E, 0x2212, 0x301C, 0xFEFF}; for (int code = 1; code < 0x10000; ++code) { if (code >= 0xD800 && code <= 0xDFFF) continue; + if (std::find(std::begin(microsoftForms), std::end(microsoftForms), code) != std::end(microsoftForms)) continue; std::uint8_t encoded[4] = {}; std::uint32_t size = 0; if (sceCesUcs2ToSJis(static_cast(code), sjis, encoded, sizeof(encoded), &size) == 0) { diff --git a/core/libs/tests/GuestCesMbc.cpp b/core/libs/tests/GuestCesMbc.cpp index d586891262..e88d2f94d6 100644 --- a/core/libs/tests/GuestCesMbc.cpp +++ b/core/libs/tests/GuestCesMbc.cpp @@ -1,34 +1,201 @@ +#include "prx/libSceCesCs/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" +#include #include #include #include -extern "C" { -void* APS5_VABI sceCesUcsProfileInitSJis1997Cp932(void*); -void* APS5_VABI sceCesUcsProfileInitEucJpCp51932(void*); -void* APS5_VABI sceCesUcsProfileInitGbkCp936(void*); -const std::uint8_t* APS5_VABI sceCesRefersUcsProfileCp1252(void); -int APS5_VABI sceCesMbcsUcsContextInit(void*, const void*); -int APS5_VABI sceCesMbcsUcsContextInitCopy(void*, const void*); -int APS5_VABI sceCesMbcsStrToUtf8Str(void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint8_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesMbcToUcs2(const void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint16_t*); -int APS5_VABI sceCesMbcToUtf8(const void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint8_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesMbcToUtf16(const void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint16_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesMbcToUtf16be(const void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint16_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesMbcToUtf16le(const void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint16_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesMbcToUtf32(const void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint32_t*); -int APS5_VABI sceCesMbcToUtf32be(const void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint32_t*); -int APS5_VABI sceCesMbcToUtf32le(const void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint32_t*); -int APS5_VABI sceCesSJisGetCode(const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint16_t*); -int APS5_VABI sceCesSJisPutCode(std::uint16_t, std::uint8_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesSJisCodeToJisX0213(std::uint16_t, std::uint8_t*, std::uint8_t*, std::uint8_t*); -int APS5_VABI sceCesJisX0213ToSJisCode(std::uint8_t, std::uint8_t, std::uint8_t, std::uint16_t*); -} +constexpr int invalidParameter = static_cast(0x805C0001); +constexpr int invalidSrcBuffer = static_cast(0x805C0010); +constexpr int srcBufferEnd = static_cast(0x805C0011); +constexpr int invalidEncode = static_cast(0x805C0014); +constexpr int outOfCodeSpace = static_cast(0x805C0015); +constexpr int unassignedCode = static_cast(0x805C0020); +constexpr int unsupported = static_cast(0x805C0024); +constexpr int invalidDstBuffer = static_cast(0x805C0030); +constexpr int dstBufferEnd = static_cast(0x805C0031); +constexpr std::uint32_t untouched = 0xEEEEEEEE; + +enum Form { Ucs2, Utf8, Utf16, Utf16be, Utf16le, Utf32, Utf32be, Utf32le, FormCount }; + +struct Sequence { + std::uint32_t count; + std::uint32_t units[4]; + int expected; +}; static void Require(bool value) { if (!value) std::abort(); } static const std::uint8_t* Bytes(const char* text) { return reinterpret_cast(text); } +static bool IsBuffer(int form) { return form == Utf8 || form == Utf16 || form == Utf16be || form == Utf16le; } + +static std::uint32_t Units(int form, std::uint32_t code, std::uint32_t* units) { + constexpr std::uint32_t leads[5] = {0, 0, 0xC0, 0xE0, 0xF0}; + if (form == Utf8 && code >= 0x80) { + const std::uint32_t count = code < 0x800 ? 2 : code < 0x10000 ? 3 : 4; + for (std::uint32_t i = count - 1; i > 0; --i, code >>= 6) units[i] = 0x80 | (code & 0x3F); + units[0] = leads[count] | code; + return count; + } + if (IsBuffer(form) && code >= 0x10000) { + units[0] = 0xD800 + ((code - 0x10000) >> 10); + units[1] = 0xDC00 + ((code - 0x10000) & 0x3FF); + return 2; + } + units[0] = code; + return 1; +} + +static int Call(int form, const std::uint32_t* units, std::uint32_t count, const void* profile, std::uint8_t* mbc, std::uint32_t mbcMax, std::uint32_t* mbcLen, std::uint32_t* sourceLen) { + const bool bigEndian = form == Utf16be || form == Utf32be || ((form == Utf16 || form == Utf32) && std::endian::native == std::endian::big); + const std::uint32_t width = form == Utf8 ? 1 : form >= Utf32 ? 4 : 2; + alignas(4) std::uint8_t bytes[16] = {}; + for (std::uint32_t i = 0; units && i < count; ++i) { + for (std::uint32_t b = 0; b < width; ++b) bytes[i * width + b] = static_cast(units[i] >> (8 * (bigEndian ? width - 1 - b : b))); + } + const std::uint8_t* utf8 = units ? bytes : nullptr; + const auto* utf16 = reinterpret_cast(utf8); + const auto* utf32 = reinterpret_cast(utf8); + const std::uint32_t value = units ? units[0] : 0; + switch (form) { + case Ucs2: return sceCesUcs2ToMbc(static_cast(value), profile, mbc, mbcMax, mbcLen); + case Utf8: return sceCesUtf8ToMbc(utf8, count, sourceLen, profile, mbc, mbcMax, mbcLen); + case Utf16: return sceCesUtf16ToMbc(utf16, count, sourceLen, profile, mbc, mbcMax, mbcLen); + case Utf16be: return sceCesUtf16beToMbc(utf16, count, sourceLen, profile, mbc, mbcMax, mbcLen); + case Utf16le: return sceCesUtf16leToMbc(utf16, count, sourceLen, profile, mbc, mbcMax, mbcLen); + case Utf32: return sceCesUtf32ToMbc(value, profile, mbc, mbcMax, mbcLen); + case Utf32be: return sceCesUtf32beToMbc(utf32, profile, mbc, mbcMax, mbcLen); + default: return sceCesUtf32leToMbc(utf32, profile, mbc, mbcMax, mbcLen); + } +} + +static void RequireFailure(int form, const std::uint32_t* units, std::uint32_t count, const void* profile, bool target, std::uint32_t mbcMax, int expected) { + std::uint8_t mbc[4] = {0xEE, 0xEE, 0xEE, 0xEE}; + std::uint32_t mbcLen = untouched; + std::uint32_t sourceLen = untouched; + Require(Call(form, units, count, profile, target ? mbc : nullptr, mbcMax, &mbcLen, &sourceLen) == expected); + const bool refused = !IsBuffer(form) && expected != invalidParameter && expected != invalidSrcBuffer && expected != invalidDstBuffer; + Require(mbc[0] == 0xEE && mbc[1] == 0xEE && mbc[2] == 0xEE && mbc[3] == 0xEE && mbcLen == (refused ? 0 : untouched) && sourceLen == untouched); +} + +static void RequireAll(std::uint32_t code, const void* profile, int expected, const std::uint8_t* bytes, std::uint32_t size) { + for (int form = code > 0xFFFF ? Utf8 : Ucs2; form < FormCount; ++form) { + std::uint32_t units[4] = {}; + const std::uint32_t count = Units(form, code, units); + if (expected != 0) { + RequireFailure(form, units, count, profile, true, 4, expected); + continue; + } + std::uint8_t mbc[4] = {0xEE, 0xEE, 0xEE, 0xEE}; + std::uint32_t mbcLen = untouched; + std::uint32_t sourceLen = untouched; + Require(Call(form, units, count, profile, mbc, sizeof(mbc), &mbcLen, &sourceLen) == 0); + Require(mbcLen == size && std::memcmp(mbc, bytes, size) == 0 && sourceLen == (IsBuffer(form) ? count : untouched)); + } +} + +static std::uint32_t SweepCodes(const void* profile) { + constexpr std::uint32_t supplementary[] = {0x10000, 0x1F600, 0x10FFFF}; + std::uint32_t mapped = 0; + for (std::uint32_t code = 0; code < 0x10000; ++code) { + if (code >= 0xD800 && code <= 0xDFFF) continue; + std::uint8_t bytes[4] = {}; + std::uint32_t size = 0; + const int result = sceCesUtf32ToMbc(code, profile, bytes, sizeof(bytes), &size); + Require(result == 0 || result == unassignedCode || result == unsupported); + if (result == 0 && size > 0) { + std::uint32_t consumed = 0; + std::uint32_t back = 0; + Require(sceCesMbcToUtf32(profile, bytes, size, &consumed, &back) == 0 && consumed == size); + if (back == code) ++mapped; + } + RequireAll(code, profile, result, bytes, size); + } + for (const std::uint32_t code : supplementary) RequireAll(code, profile, unassignedCode, nullptr, 0); + return mapped; +} + +static std::uint32_t RoundTrip(const void* profile, const std::uint8_t* source, std::uint32_t size) { + std::uint32_t consumed = 0; + std::uint32_t produced = 0; + std::uint32_t code = 0; + std::uint16_t ucs2 = 0; + std::uint8_t utf8[4] = {}; + std::uint32_t utf8Size = 0; + std::uint16_t utf16[3] = {}; + std::uint32_t utf32[2] = {}; + Require(sceCesMbcToUtf32(profile, source, size, &consumed, &code) == 0 && consumed == size); + Require(sceCesMbcToUcs2(profile, source, size, &consumed, &ucs2) == 0 && consumed == size); + Require(sceCesMbcToUtf8(profile, source, size, &consumed, utf8, sizeof(utf8), &utf8Size) == 0 && consumed == size); + Require(sceCesMbcToUtf16(profile, source, size, &consumed, &utf16[0], 1, &produced) == 0 && consumed == size); + Require(sceCesMbcToUtf16be(profile, source, size, &consumed, &utf16[1], 1, &produced) == 0 && consumed == size); + Require(sceCesMbcToUtf16le(profile, source, size, &consumed, &utf16[2], 1, &produced) == 0 && consumed == size); + Require(sceCesMbcToUtf32be(profile, source, size, &consumed, &utf32[0]) == 0 && consumed == size); + Require(sceCesMbcToUtf32le(profile, source, size, &consumed, &utf32[1]) == 0 && consumed == size); + std::uint8_t mbc[8][4] = {}; + std::uint32_t mbcLen[8] = {}; + std::uint32_t sourceLen[4] = {}; + Require(sceCesUtf32ToMbc(code, profile, mbc[0], 4, &mbcLen[0]) == 0); + Require(sceCesUcs2ToMbc(ucs2, profile, mbc[1], 4, &mbcLen[1]) == 0); + Require(sceCesUtf8ToMbc(utf8, utf8Size, &sourceLen[0], profile, mbc[2], 4, &mbcLen[2]) == 0 && sourceLen[0] == utf8Size); + Require(sceCesUtf16ToMbc(&utf16[0], 1, &sourceLen[1], profile, mbc[3], 4, &mbcLen[3]) == 0 && sourceLen[1] == 1); + Require(sceCesUtf16beToMbc(&utf16[1], 1, &sourceLen[2], profile, mbc[4], 4, &mbcLen[4]) == 0 && sourceLen[2] == 1); + Require(sceCesUtf16leToMbc(&utf16[2], 1, &sourceLen[3], profile, mbc[5], 4, &mbcLen[5]) == 0 && sourceLen[3] == 1); + Require(sceCesUtf32beToMbc(&utf32[0], profile, mbc[6], 4, &mbcLen[6]) == 0); + Require(sceCesUtf32leToMbc(&utf32[1], profile, mbc[7], 4, &mbcLen[7]) == 0); + for (std::uint32_t i = 1; i < 8; ++i) Require(mbcLen[i] == mbcLen[0] && std::memcmp(mbc[i], mbc[0], mbcLen[0]) == 0); + return mbcLen[0] == size && std::memcmp(mbc[0], source, size) == 0 ? 1 : 0; +} + +static std::uint32_t SweepBytes(const void* profile) { + std::uint32_t identical = 0; + std::uint8_t source[3] = {}; + std::uint32_t consumed = 0; + std::uint32_t code = 0; + for (std::uint32_t lead = 0; lead < 256; ++lead) { + source[0] = static_cast(lead); + const int single = sceCesMbcToUtf32(profile, source, 1, &consumed, &code); + if (single == 0) identical += RoundTrip(profile, source, 1); + if (single != srcBufferEnd) continue; + for (std::uint32_t trail = 0; trail < 256; ++trail) { + source[1] = static_cast(trail); + const int pair = sceCesMbcToUtf32(profile, source, 2, &consumed, &code); + if (pair == 0) identical += RoundTrip(profile, source, 2); + for (std::uint32_t third = 0; pair == srcBufferEnd && third < 256; ++third) { + source[2] = static_cast(third); + if (sceCesMbcToUtf32(profile, source, 3, &consumed, &code) == 0) identical += RoundTrip(profile, source, 3); + } + } + } + return identical; +} + +static void RequireInvalid(const void* profile) { + constexpr int scalarForms[] = {Ucs2, Utf32, Utf32be, Utf32le}; + const Sequence utf8[] = { + {2, {0xC0, 0x80}, outOfCodeSpace}, {2, {0xC1, 0xBF}, outOfCodeSpace}, {3, {0xE0, 0x80, 0x80}, outOfCodeSpace}, + {3, {0xE0, 0x9F, 0xBF}, outOfCodeSpace}, {4, {0xF0, 0x80, 0x80, 0x80}, outOfCodeSpace}, {4, {0xF0, 0x8F, 0xBF, 0xBF}, outOfCodeSpace}, + {3, {0xED, 0xA0, 0x80}, outOfCodeSpace}, {3, {0xED, 0xBF, 0xBF}, outOfCodeSpace}, {4, {0xF4, 0x90, 0x80, 0x80}, unassignedCode}, + {4, {0xF7, 0xBF, 0xBF, 0xBF}, unassignedCode}, {1, {0x80}, invalidEncode}, {1, {0xFF}, invalidEncode}, + {3, {0xE3, 0x41, 0x42}, invalidEncode}, {2, {0xE3, 0x81}, srcBufferEnd}, {3, {0xF0, 0x9F, 0x98}, srcBufferEnd}, + }; + const Sequence utf16[] = { + {1, {0xDC00}, invalidEncode}, {1, {0xDFFF}, invalidEncode}, {2, {0xD800, 0x0041}, invalidEncode}, + {2, {0xDBFF, 0xDBFF}, invalidEncode}, {2, {0xDC00, 0xD800}, invalidEncode}, {1, {0xD800}, srcBufferEnd}, + }; + const Sequence utf32[] = {{1, {0xD800}, outOfCodeSpace}, {1, {0xDFFF}, outOfCodeSpace}, {1, {0x110000}, invalidEncode}, {1, {0xFFFFFFFF}, invalidEncode}}; + for (const Sequence& sequence : utf8) RequireFailure(Utf8, sequence.units, sequence.count, profile, true, 4, sequence.expected); + for (const Sequence& sequence : utf16) { + for (int form = Utf16; form <= Utf16le; ++form) RequireFailure(form, sequence.units, sequence.count, profile, true, 4, sequence.expected); + } + for (const Sequence& sequence : utf32) { + for (const int form : scalarForms) { + if (form != Ucs2 || sequence.units[0] <= 0xFFFF) RequireFailure(form, sequence.units, sequence.count, profile, true, 4, sequence.expected); + } + } +} + static void RequireX0213(std::uint16_t sjis, std::uint8_t men, std::uint8_t ku, std::uint8_t ten) { std::uint8_t m = 0; std::uint8_t k = 0; @@ -39,14 +206,6 @@ static void RequireX0213(std::uint16_t sjis, std::uint8_t men, std::uint8_t ku, } int main() { - constexpr int invalidParameter = static_cast(0x805C0001); - constexpr int invalidSrcBuffer = static_cast(0x805C0010); - constexpr int srcBufferEnd = static_cast(0x805C0011); - constexpr int invalidEncode = static_cast(0x805C0014); - constexpr int unassignedCode = static_cast(0x805C0020); - constexpr int invalidDstBuffer = static_cast(0x805C0030); - constexpr int dstBufferEnd = static_cast(0x805C0031); - alignas(8) std::uint8_t sjisSheet[64] = {}; alignas(8) std::uint8_t eucSheet[64] = {}; alignas(8) std::uint8_t gbkSheet[64] = {}; @@ -153,4 +312,80 @@ int main() { Require(std::memcmp(utf8, "\xE4\xB8\xAD", 3) == 0); Require(sceCesMbcsUcsContextInitCopy(nullptr, context) == invalidParameter); Require(sceCesMbcsUcsContextInitCopy(copy, nullptr) == invalidParameter); + + alignas(8) std::uint8_t eucCnSheet[64] = {}; + alignas(8) std::uint8_t eucKrSheet[64] = {}; + alignas(8) std::uint8_t uhcSheet[64] = {}; + alignas(8) std::uint8_t big5Sheet[64] = {}; + const void* eucCn = sceCesUcsProfileInitEucCnGb2312(eucCnSheet); + const void* eucKr = sceCesUcsProfileInitEucKr(eucKrSheet); + const void* uhc = sceCesUcsProfileInitUhc(uhcSheet); + const void* big5 = sceCesUcsProfileInitBig5Cp950(big5Sheet); + const void* cp1251 = sceCesRefersUcsProfileCp1251(); + const void* cp1250 = sceCesRefersUcsProfileCp1250(); + + RequireAll(0x20AC, cp1252, 0, Bytes("\x80"), 1); + RequireAll(0x00E9, cp1252, 0, Bytes("\xE9"), 1); + RequireAll(0x0100, cp1252, unassignedCode, nullptr, 0); + RequireAll(0x0416, cp1251, 0, Bytes("\xC6"), 1); + RequireAll(0x0141, cp1250, 0, Bytes("\xA3"), 1); + RequireAll(0x3042, sjis, 0, Bytes("\x82\xA0"), 2); + RequireAll(0xFF71, sjis, 0, Bytes("\xB1"), 1); + RequireAll(0x4E02, sjis, unassignedCode, nullptr, 0); + RequireAll(0x3042, euc, 0, Bytes("\xA4\xA2"), 2); + RequireAll(0xFF71, euc, 0, Bytes("\x8E\xB1"), 2); + RequireAll(0x4E02, euc, unassignedCode, nullptr, 0); + RequireAll(0x4E2D, gbk, 0, Bytes("\xD6\xD0"), 2); + RequireAll(0x4E02, gbk, 0, Bytes("\x81\x40"), 2); + RequireAll(0x20AC, gbk, 0, Bytes("\x80"), 1); + RequireAll(0x4E2D, eucCn, 0, Bytes("\xD6\xD0"), 2); + RequireAll(0x4E02, eucCn, unassignedCode, nullptr, 0); + RequireAll(0xAC00, eucKr, 0, Bytes("\xB0\xA1"), 2); + RequireAll(0xAC02, eucKr, unassignedCode, nullptr, 0); + RequireAll(0xAC02, uhc, 0, Bytes("\x81\x41"), 2); + RequireAll(0x4E00, big5, 0, Bytes("\xA4\x40"), 2); + + std::uint32_t units[4] = {}; + for (int form = Ucs2; form < FormCount; ++form) { + std::uint32_t count = Units(form, 0xDC00, units); + RequireFailure(form, nullptr, 0, nullptr, false, 0, invalidParameter); + RequireFailure(form, units, count, blankSheet, true, 4, invalidParameter); + if (form != Ucs2 && form != Utf32) RequireFailure(form, nullptr, 0, sjis, false, 0, invalidSrcBuffer); + if (IsBuffer(form)) RequireFailure(form, units, 0, sjis, false, 0, srcBufferEnd); + RequireFailure(form, units, count, sjis, false, 0, invalidDstBuffer); + RequireFailure(form, units, count, sjis, true, 0, IsBuffer(form) && form != Utf8 ? invalidEncode : outOfCodeSpace); + count = Units(form, 0x4E02, units); + RequireFailure(form, units, count, sjis, true, 0, unassignedCode); + count = Units(form, 0x3042, units); + std::uint8_t full[4] = {0xEE, 0xEE, 0xEE, 0xEE}; + std::uint32_t needed = untouched; + std::uint32_t sourceLen = untouched; + Require(Call(form, units, count, sjis, full, 1, &needed, &sourceLen) == dstBufferEnd && needed == (IsBuffer(form) ? untouched : 2) && full[0] == 0xEE && sourceLen == untouched); + std::uint8_t mbc[4] = {}; + Require(Call(form, units, count, sjis, mbc, sizeof(mbc), nullptr, nullptr) == 0 && std::memcmp(mbc, "\x82\xA0", 2) == 0); + } + + std::uint8_t mbc[4] = {}; + std::uint32_t wide = 0; + std::memcpy(&wide, "\x00\x00\x30\x42", 4); + Require(sceCesUtf32beToMbc(&wide, sjis, mbc, sizeof(mbc), &produced) == 0 && produced == 2 && std::memcmp(mbc, "\x82\xA0", 2) == 0); + Require(sceCesUtf32leToMbc(&wide, sjis, mbc, sizeof(mbc), &produced) == invalidEncode); + std::uint16_t narrow = 0; + std::memcpy(&narrow, "\xD8\x00", 2); + Require(sceCesUtf16leToMbc(&narrow, 1, &consumed, cp1252, mbc, sizeof(mbc), &produced) == 0 && consumed == 1 && produced == 1 && mbc[0] == 0xD8); + Require(sceCesUtf16beToMbc(&narrow, 1, &consumed, cp1252, mbc, sizeof(mbc), &produced) == srcBufferEnd); + Require(sceCesUtf8ToMbc(Bytes("A\xE4\xB8\xAD"), 4, &consumed, gbk, mbc, sizeof(mbc), &produced) == 0 && consumed == 1 && produced == 1 && mbc[0] == 'A'); + + const void* singleByte[] = {cp1252, cp1251, cp1250}; + constexpr std::uint32_t singleByteMapped[] = {251, 255, 251}; + const void* multiByte[] = {sjis, euc, eucCn, gbk, eucKr, uhc, big5}; + for (std::size_t index = 0; index < 3; ++index) { + Require(SweepCodes(singleByte[index]) == singleByteMapped[index] && SweepBytes(singleByte[index]) == singleByteMapped[index]); + RequireInvalid(singleByte[index]); + } + for (const void* profile : multiByte) { + const std::uint32_t mapped = SweepCodes(profile); + Require(mapped > 256 && SweepBytes(profile) == mapped); + RequireInvalid(profile); + } } diff --git a/core/libs/tests/GuestCesUnicode.cpp b/core/libs/tests/GuestCesUnicode.cpp index 1603f09810..fa8fee7f88 100644 --- a/core/libs/tests/GuestCesUnicode.cpp +++ b/core/libs/tests/GuestCesUnicode.cpp @@ -1,31 +1,12 @@ +#include "prx/libSceCesCs/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libSceCesCs/JisX0208.hpp" -#include "prx/libSceCesCs/JisX0212.hpp" #include #include #include #include #include -extern "C" { -int APS5_VABI sceCesUcs2ToUtf8(uint16_t, uint8_t*, uint32_t, uint32_t*); -int APS5_VABI sceCesUtf8ToUcs2(const uint8_t*, uint32_t, uint32_t*, uint16_t*); -int APS5_VABI sceCesUtf32ToUtf8(uint32_t, uint8_t*, uint32_t, uint32_t*); -int APS5_VABI sceCesUtf32beToUtf8(const uint32_t*, uint8_t*, uint32_t, uint32_t*); -int APS5_VABI sceCesUtf32leToUtf8(const uint32_t*, uint8_t*, uint32_t, uint32_t*); -int APS5_VABI sceCesUtf8ToUtf32(const uint8_t*, uint32_t, uint32_t*, uint32_t*); -int APS5_VABI sceCesUtf8ToUtf32be(const uint8_t*, uint32_t, uint32_t*, uint32_t*); -int APS5_VABI sceCesUtf8ToUtf32le(const uint8_t*, uint32_t, uint32_t*, uint32_t*); -int APS5_VABI sceCesUtf8ToUtf16(const uint8_t*, uint32_t, uint32_t*, uint16_t*, uint32_t, uint32_t*); -int APS5_VABI sceCesUtf8ToUtf16be(const uint8_t*, uint32_t, uint32_t*, uint16_t*, uint32_t, uint32_t*); -int APS5_VABI sceCesUtf8ToUtf16le(const uint8_t*, uint32_t, uint32_t*, uint16_t*, uint32_t, uint32_t*); -int APS5_VABI sceCesUtf16ToUtf8(const uint16_t*, uint32_t, uint32_t*, uint8_t*, uint32_t, uint32_t*); -int APS5_VABI sceCesUtf16beToUtf8(const uint16_t*, uint32_t, uint32_t*, uint8_t*, uint32_t, uint32_t*); -int APS5_VABI sceCesUtf16leToUtf8(const uint16_t*, uint32_t, uint32_t*, uint8_t*, uint32_t, uint32_t*); -void* APS5_VABI sceCesUcsProfileInitEucJpCp51932(void*); -int APS5_VABI sceCesEucJpToUtf8(const void*, const uint8_t*, uint32_t, uint32_t*, uint8_t*, uint32_t, uint32_t*); -} - namespace { constexpr int INVALID_PARAMETER = static_cast(0x805C0001); @@ -178,6 +159,7 @@ void TestErrors() { } void TestEucJp() { + constexpr int INVALID_PROFILE = static_cast(0x805C0004); std::array sheet{}; const void* profile = sceCesUcsProfileInitEucJpCp51932(sheet.data()); auto check = [&](const uint8_t* source, uint32_t length, uint32_t code) { @@ -195,10 +177,11 @@ void TestEucJp() { output.fill(0xA5); consumed = produced = SENTINEL; Require(sceCesEucJpToUtf8(profile, source, length, &consumed, output.data(), cap, &produced) == DST_BUFFER_END); - Require(consumed == SENTINEL && produced == SENTINEL && output[0] == 0xA5); + Require(consumed == length && produced == expectedLength && output[0] == 0xA5); } }; - for (uint32_t code = 0; code < 128; ++code) { + for (uint32_t code = 0; code < 0xA0; ++code) { + if (code == 0x0E || code == 0x8E || code == 0x8F) continue; const uint8_t source[] = {static_cast(code)}; check(source, 1, code); } @@ -207,39 +190,41 @@ void TestEucJp() { check(source, 2, 0xFF61 + cell); } uint32_t assigned = 0; - for (uint32_t supplementary = 0; supplementary < 2; ++supplementary) { - for (uint32_t cell = 0; cell < 94 * 94; ++cell) { - const uint32_t code = supplementary ? JisX0212::TO_UCS2[cell] : JisX0208::TO_UCS2[cell]; - const uint8_t source[] = {0x8F, static_cast(0xA1 + cell / 94), static_cast(0xA1 + cell % 94)}; - const uint8_t* start = source + (supplementary ? 0 : 1); - const uint32_t length = supplementary ? 3 : 2; - if (code) { check(start, length, code); ++assigned; } - else { - uint8_t output[4] = {0xA5, 0xA5, 0xA5, 0xA5}; - uint32_t consumed = SENTINEL; - uint32_t produced = SENTINEL; - Require(sceCesEucJpToUtf8(profile, start, length, &consumed, output, 4, &produced) == UNASSIGNED_CODE); - Require(consumed == SENTINEL && produced == SENTINEL && output[0] == 0xA5); - } + for (uint32_t cell = 0; cell < 94 * 94; ++cell) { + const uint32_t code = JisX0208::TO_UCS2[cell]; + const uint8_t source[] = {static_cast(0xA1 + cell / 94), static_cast(0xA1 + cell % 94)}; + if (code) { check(source, 2, code); ++assigned; } + else { + uint8_t output[4] = {0xA5, 0xA5, 0xA5, 0xA5}; + uint32_t consumed = SENTINEL; + uint32_t produced = SENTINEL; + Require(sceCesEucJpToUtf8(profile, source, 2, &consumed, output, 4, &produced) == UNASSIGNED_CODE); + Require(consumed == 2 && produced == 0 && output[0] == 0xA5); } } - Require(assigned == 13403); - const uint8_t source[] = {0x8F, 0xA2, 0xAF, 'X'}; + Require(assigned == 7336); + const uint8_t source[] = {0xA4, 0xA2, 'X'}; uint8_t output[4] = {0xA5, 0xA5, 0xA5, 0xA5}; uint32_t consumed = SENTINEL; uint32_t produced = SENTINEL; - Require(sceCesEucJpToUtf8(nullptr, source, 3, &consumed, output, 4, &produced) == INVALID_PARAMETER); + Require(sceCesEucJpToUtf8(nullptr, source, 3, &consumed, output, 4, &produced) == INVALID_PROFILE); + Require(consumed == 0 && produced == 0); Require(sceCesEucJpToUtf8(profile, nullptr, 3, &consumed, output, 4, &produced) == INVALID_SRC_BUFFER); - Require(sceCesEucJpToUtf8(profile, source, 0, &consumed, output, 4, &produced) == SRC_BUFFER_END); + Require(sceCesEucJpToUtf8(profile, source, 0, &consumed, output, 4, &produced) == INVALID_SRC_BUFFER); Require(sceCesEucJpToUtf8(profile, source, 3, &consumed, nullptr, 4, &produced) == INVALID_DST_BUFFER); - for (uint32_t size : {1u, 2u}) Require(sceCesEucJpToUtf8(profile, source, size, &consumed, output, 4, &produced) == SRC_BUFFER_END); + Require(consumed == 2 && produced == 3); + Require(sceCesEucJpToUtf8(profile, source, 1, &consumed, output, 4, &produced) == SRC_BUFFER_END); + Require(consumed == 2 && produced == 0); const uint8_t malformed[] = {0x8E, 0x41}; Require(sceCesEucJpToUtf8(profile, malformed, 2, &consumed, output, 4, &produced) == INVALID_ENCODE); - Require(consumed == SENTINEL && produced == SENTINEL && output[0] == 0xA5); - Require(sceCesEucJpToUtf8(profile, source, 4, &consumed, output, 4, &produced) == 0); - Require(consumed == 3 && produced == 2 && output[0] == 0xCB && output[1] == 0x98 && output[2] == 0xA5); - Require(sceCesEucJpToUtf8(profile, source, 4, nullptr, output, 4, nullptr) == 0); - std::puts("13403 assigned JIS cells plus ASCII, half-width katakana and unassigned cells checked"); + Require(consumed == 2 && produced == 0 && output[0] == 0xA5); + const uint8_t supplementary[] = {0x8F, 0xA2, 0xAF}; + Require(sceCesEucJpToUtf8(profile, supplementary, 3, &consumed, output, 4, &produced) == INVALID_ENCODE); + Require(consumed == 3 && produced == 0 && output[0] == 0xA5); + Require(sceCesEucJpToUtf8(profile, source, 3, &consumed, output, 4, &produced) == 0); + Require(consumed == 2 && produced == 3 && output[0] == 0xE3 && output[1] == 0x81 && output[2] == 0x82 && output[3] == 0xA5); + Require(sceCesEucJpToUtf8(profile, source, 3, nullptr, output, 4, nullptr) == 0); + std::puts("7336 assigned JIS X 0208 cells plus single bytes and half-width katakana checked"); } } diff --git a/core/libs/tests/GuestCesWide.cpp b/core/libs/tests/GuestCesWide.cpp index 5d840cbdfe..e644f825e5 100644 --- a/core/libs/tests/GuestCesWide.cpp +++ b/core/libs/tests/GuestCesWide.cpp @@ -1,38 +1,9 @@ +#include "prx/libSceCesCs/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include #include -extern "C" { -const std::uint8_t* APS5_VABI sceCesRefersUcsProfileCp1252(void); -const std::uint8_t* APS5_VABI sceCesRefersUcsProfileCp1251(void); -void* APS5_VABI sceCesUcsProfileInitSJis1997Cp932(void*); -void* APS5_VABI sceCesUcsProfileInitEucJpCp51932(void*); -int APS5_VABI sceCesMbcsUcsContextInit(void*, const void*); -int APS5_VABI sceCesSbcToUcs2(const std::uint8_t*, std::uint8_t, std::uint16_t*); -int APS5_VABI sceCesSbcToUtf16(const std::uint8_t*, std::uint8_t, std::uint16_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesSbcToUtf16be(const std::uint8_t*, std::uint8_t, std::uint16_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesSbcToUtf16le(const std::uint8_t*, std::uint8_t, std::uint16_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesSbcToUtf32(const std::uint8_t*, std::uint8_t, std::uint32_t*); -int APS5_VABI sceCesSbcToUtf32be(const std::uint8_t*, std::uint8_t, std::uint32_t*); -int APS5_VABI sceCesSbcToUtf32le(const std::uint8_t*, std::uint8_t, std::uint32_t*); -int APS5_VABI sceCesUcs2ToSbc(std::uint16_t, const std::uint8_t*, std::uint8_t*); -int APS5_VABI sceCesUtf16ToSbc(const std::uint16_t*, std::uint32_t, std::uint32_t*, const std::uint8_t*, std::uint8_t*); -int APS5_VABI sceCesUtf16beToSbc(const std::uint16_t*, std::uint32_t, std::uint32_t*, const std::uint8_t*, std::uint8_t*); -int APS5_VABI sceCesUtf16leToSbc(const std::uint16_t*, std::uint32_t, std::uint32_t*, const std::uint8_t*, std::uint8_t*); -int APS5_VABI sceCesUtf32ToSbc(std::uint32_t, const std::uint8_t*, std::uint8_t*); -int APS5_VABI sceCesUtf32beToSbc(const std::uint32_t*, const std::uint8_t*, std::uint8_t*); -int APS5_VABI sceCesUtf32leToSbc(const std::uint32_t*, const std::uint8_t*, std::uint8_t*); -int APS5_VABI sceCesUtf16StrToMbcsStr(void*, const std::uint16_t*, std::uint32_t, std::uint32_t*, std::uint8_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesUtf16StrGetMbcsLen(void*, const std::uint16_t*, std::uint32_t, std::uint32_t*, std::uint32_t*); -int APS5_VABI sceCesUtf32StrToMbcsStr(void*, const std::uint32_t*, std::uint32_t, std::uint32_t*, std::uint8_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesUtf32StrGetMbcsLen(void*, const std::uint32_t*, std::uint32_t, std::uint32_t*, std::uint32_t*); -int APS5_VABI sceCesMbcsStrToUtf16Str(void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint16_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesMbcsStrGetUtf16Len(void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint32_t*); -int APS5_VABI sceCesMbcsStrToUtf32Str(void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint32_t*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceCesMbcsStrGetUtf32Len(void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint32_t*); -} - static void Require(bool value) { if (!value) std::abort(); } static const std::uint8_t* Bytes(const char* text) { return reinterpret_cast(text); } @@ -97,6 +68,10 @@ int main() { Require(sceCesUtf32leToSbc(&yLe, cp1252, &sbc) == 0 && sbc == 0x9F); Require(sceCesUtf32leToSbc(nullptr, cp1252, &sbc) == invalidSrcBuffer); for (int value = 0; value < 256; ++value) { + if (value == 0x98) { + Require(sceCesSbcToUtf32(cp1251, static_cast(value), &utf32) == unassignedCode); + continue; + } Require(sceCesSbcToUtf32(cp1251, static_cast(value), &utf32) == 0); Require(sceCesUtf32ToSbc(utf32, cp1251, &sbc) == 0 && sbc == value); } diff --git a/core/libs/tests/GuestCharacter.cpp b/core/libs/tests/GuestCharacter.cpp index 70615e6c3e..c6fc299ba0 100644 --- a/core/libs/tests/GuestCharacter.cpp +++ b/core/libs/tests/GuestCharacter.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -5,27 +6,7 @@ #include #include #include -extern "C" { -int APS5_VABI isupper_nid_postfix(int); -int APS5_VABI islower_nid_postfix(int); -int APS5_VABI isalpha_nid_postfix(int); -int APS5_VABI isdigit_nid_postfix(int); -int APS5_VABI isalnum_nid_postfix(int); -int APS5_VABI isspace_nid_postfix(int); -int APS5_VABI isblank_nid_postfix(int); -int APS5_VABI iscntrl_nid_postfix(int); -int APS5_VABI isprint_nid_postfix(int); -int APS5_VABI isgraph_nid_postfix(int); -int APS5_VABI ispunct_nid_postfix(int); -int APS5_VABI isxdigit_nid_postfix(int); -int APS5_VABI isascii_nid_postfix(int); -int APS5_VABI toascii_nid_postfix(int); -int APS5_VABI toupper_nid_postfix(int); -int APS5_VABI tolower_nid_postfix(int); -const short* APS5_VABI _Getptolower_nid_postfix(); -const short* APS5_VABI _Getptoupper_nid_postfix(); -const char* APS5_VABI setlocale_nid_postfix(int, const char*); -} + static void Require(bool value) { if (!value) std::abort(); } int main() { Require(std::setlocale(LC_CTYPE, "C") != nullptr); diff --git a/core/libs/tests/GuestClosedStandardDescriptors.cpp b/core/libs/tests/GuestClosedStandardDescriptors.cpp index 4cb0deece1..de4c2500e5 100644 --- a/core/libs/tests/GuestClosedStandardDescriptors.cpp +++ b/core/libs/tests/GuestClosedStandardDescriptors.cpp @@ -1,3 +1,4 @@ +#include "prx/libkernel/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -6,10 +7,6 @@ #include #include -extern "C" { -int APS5_VABI fcntl_nid_postfix(int, int, ...); -} - namespace { constexpr int GuestGetFlags = 3; diff --git a/core/libs/tests/GuestClosedStandardDescriptorsWindows.cpp b/core/libs/tests/GuestClosedStandardDescriptorsWindows.cpp index 77106d6465..b5633d602a 100644 --- a/core/libs/tests/GuestClosedStandardDescriptorsWindows.cpp +++ b/core/libs/tests/GuestClosedStandardDescriptorsWindows.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/FileStream.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -7,17 +9,11 @@ #include extern "C" { -int APS5_VABI fcntl_nid_postfix(int, int, ...); + extern FileStream* __stdinp_nid_postfix; extern FileStream* __stdoutp_nid_postfix; extern FileStream* __stderrp_nid_postfix; -int APS5_VABI fileno_nid_postfix(FileStream*); -int APS5_VABI fputc_nid_postfix(int, FileStream*); -int APS5_VABI fflush_nid_postfix(FileStream*); -int APS5_VABI fgetc_nid_postfix(FileStream*); -int APS5_VABI feof_nid_postfix(FileStream*); -int APS5_VABI ferror_nid_postfix(FileStream*); -void APS5_VABI clearerr_nid_postfix(FileStream*); + } namespace { diff --git a/core/libs/tests/GuestClosedStandardStreamsLoadWindows.cpp b/core/libs/tests/GuestClosedStandardStreamsLoadWindows.cpp index 1bf5e960fc..da5ce1a579 100644 --- a/core/libs/tests/GuestClosedStandardStreamsLoadWindows.cpp +++ b/core/libs/tests/GuestClosedStandardStreamsLoadWindows.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/FileStream.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -11,8 +12,7 @@ extern "C" { _invalid_parameter_handler _set_thread_local_invalid_parameter_handler(_invalid_parameter_handler); -int APS5_VABI fputc_nid_postfix(int, FileStream*); -int APS5_VABI fflush_nid_postfix(FileStream*); + } namespace { diff --git a/core/libs/tests/GuestCollate.cpp b/core/libs/tests/GuestCollate.cpp index 7dec7aabab..f886933573 100644 --- a/core/libs/tests/GuestCollate.cpp +++ b/core/libs/tests/GuestCollate.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/ApplicationHeap.hpp" #include "prx/libc/include/GuestLocale.hpp" #include @@ -10,8 +11,7 @@ extern "C" { extern GuestLocale::Implementation* _ZSt21_sceLibcClassicLocale_nid_postfix; -std::size_t APS5_VABI _ZNSt7collateIcE7_GetcatEPPKNSt6locale5facetEPKS1__nid_postfix(GuestLocale::Facet** facet, const GuestLocale::Implementation* const* locale); -std::size_t APS5_VABI _ZNSt7collateIwE7_GetcatEPPKNSt6locale5facetEPKS1__nid_postfix(GuestLocale::Facet** facet, const GuestLocale::Implementation* const* locale); + } namespace { diff --git a/core/libs/tests/GuestCommonDialog.cpp b/core/libs/tests/GuestCommonDialog.cpp index e5b9cd993b..b0d74a3b47 100644 --- a/core/libs/tests/GuestCommonDialog.cpp +++ b/core/libs/tests/GuestCommonDialog.cpp @@ -1,12 +1,8 @@ +#include "prx/libSceCommonDialog/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libSceCommonDialog/CommonDialog.hpp" #include -extern "C" { -int APS5_VABI sceCommonDialogInitialize(void); -bool APS5_VABI sceCommonDialogIsUsed(void); -} - namespace { void Require(bool value) { diff --git a/core/libs/tests/GuestCompanionHttpd.cpp b/core/libs/tests/GuestCompanionHttpd.cpp index e9f8990365..afe5b08822 100644 --- a/core/libs/tests/GuestCompanionHttpd.cpp +++ b/core/libs/tests/GuestCompanionHttpd.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceCompanionHttpd/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -6,26 +7,6 @@ #include #include -extern "C" { -int APS5_VABI sceCompanionHttpdOptParamInitialize(void* param); -int APS5_VABI sceCompanionHttpdInitialize(const void* param); -int APS5_VABI sceCompanionHttpdTerminate(void); -int APS5_VABI sceCompanionHttpdRegisterRequestCallback(void* function, void* argument); -int APS5_VABI sceCompanionHttpdUnregisterRequestCallback(void); -int APS5_VABI sceCompanionHttpdStart(void); -int APS5_VABI sceCompanionHttpdStop(void); -int APS5_VABI sceCompanionHttpdGetEvent(void* event); -int APS5_VABI sceCompanionHttpdAddHeader(const char* key, const char* value, void* response); -int APS5_VABI sceCompanionHttpdSetStatus(int status, void* response); -int APS5_VABI sceCompanionHttpdSetBody(const char* body, std::uint64_t size, void* response); -int APS5_VABI sceCompanionHttpdGet2ndScreenStatus(void); -int APS5_VABI sceCompanionHttpdGetUserId(void); -int APS5_VABI sceCompanionHttpdInitialize2(void); -int APS5_VABI sceCompanionHttpdRegisterRequestBodyReceptionCallback(void); -int APS5_VABI sceCompanionHttpdRegisterRequestCallback2(void); -int APS5_VABI sceCompanionHttpdUnregisterRequestBodyReceptionCallback(void); -} - namespace { constexpr int InvalidParam = static_cast(0x80E40004u); @@ -63,7 +44,7 @@ void CheckOptionBlock() { unsigned char block[0x70]; std::memset(block, 0x5a, sizeof(block)); Require(sceCompanionHttpdOptParamInitialize(nullptr) == InvalidParam, "a null option block must be rejected"); - Require(sceCompanionHttpdOptParamInitialize(block) == 0, "sceCompanionHttpdOptParamInitialize failed"); + Require(sceCompanionHttpdOptParamInitialize(reinterpret_cast(block)) == 0, "sceCompanionHttpdOptParamInitialize failed"); for (std::size_t index = 0; index < sizeof(block); ++index) { Require(block[index] == (index < 0x60 ? 0u : 0x5au), "the option block must be zeroed over its 0x60 bytes and nothing past them"); } @@ -80,14 +61,14 @@ void CheckStates() { Require(sceCompanionHttpdStart() == NotInitialized, "a start before initialization"); Require(sceCompanionHttpdStop() == NotInitialized, "a stop before initialization"); Require(sceCompanionHttpdTerminate() == NotInitialized, "a termination before initialization"); - Require(sceCompanionHttpdRegisterRequestCallback(callback, nullptr) == NotInitialized, "a callback before initialization"); + Require(sceCompanionHttpdRegisterRequestCallback(reinterpret_cast(callback), nullptr) == NotInitialized, "a callback before initialization"); Require(sceCompanionHttpdUnregisterRequestCallback() == NotInitialized, "an unregistration before initialization"); Require(sceCompanionHttpdInitialize(nullptr) == InvalidParam, "a null parameter must be rejected"); - Require(sceCompanionHttpdInitialize(param) == 0, "sceCompanionHttpdInitialize failed"); - Require(sceCompanionHttpdInitialize(param) == AlreadyInitialized, "a second initialization"); + Require(sceCompanionHttpdInitialize(reinterpret_cast(param)) == 0, "sceCompanionHttpdInitialize failed"); + Require(sceCompanionHttpdInitialize(reinterpret_cast(param)) == AlreadyInitialized, "a second initialization"); Require(sceCompanionHttpdRegisterRequestCallback(nullptr, nullptr) == InvalidParam, "a null callback must be rejected"); - Require(sceCompanionHttpdRegisterRequestCallback(callback, param) == 0, "registering the request callback failed"); - Require(sceCompanionHttpdRegisterRequestCallback(callback, param) == AlreadyRegistered, "a second callback"); + Require(sceCompanionHttpdRegisterRequestCallback(reinterpret_cast(callback), param) == 0, "registering the request callback failed"); + Require(sceCompanionHttpdRegisterRequestCallback(reinterpret_cast(callback), param) == AlreadyRegistered, "a second callback"); Require(sceCompanionHttpdGetEvent(nullptr) == InvalidParam, "a null event must be rejected"); Require(sceCompanionHttpdGetEvent(event) == NoEvent, "no companion device connects before the start"); Require(sceCompanionHttpdStop() == NotStarted, "a stop before the start"); @@ -101,8 +82,8 @@ void CheckStates() { RequireNotImplemented([] { sceCompanionHttpdUnregisterRequestCallback(); }, "sceCompanionHttpdUnregisterRequestCallback"); Require(sceCompanionHttpdTerminate() == 0, "sceCompanionHttpdTerminate failed"); Require(sceCompanionHttpdTerminate() == NotInitialized, "a second termination"); - Require(sceCompanionHttpdInitialize(param) == 0, "initializing again after the termination failed"); - Require(sceCompanionHttpdRegisterRequestCallback(callback, nullptr) == 0, "the termination kept the callback"); + Require(sceCompanionHttpdInitialize(reinterpret_cast(param)) == 0, "initializing again after the termination failed"); + Require(sceCompanionHttpdRegisterRequestCallback(reinterpret_cast(callback), nullptr) == 0, "the termination kept the callback"); Require(sceCompanionHttpdTerminate() == 0, "the last termination failed"); } diff --git a/core/libs/tests/GuestCondRecursiveMutex.cpp b/core/libs/tests/GuestCondRecursiveMutex.cpp index 92f7166071..e21300d818 100644 --- a/core/libs/tests/GuestCondRecursiveMutex.cpp +++ b/core/libs/tests/GuestCondRecursiveMutex.cpp @@ -1,29 +1,12 @@ +#include "prx/libkernel/KernelErrors.hpp" +#include "prx/libkernel/include/Api.hpp" +#include "prx/libkernel/Time/include/Time.hpp" +#include "prx/libkernel/Pthread/include/Mutex.hpp" +#include "prx/libkernel/Pthread/include/Cond.hpp" #include "SceTypes.hpp" #include -extern "C" { -int APS5_VABI scePthreadCreate(Pthread* thread, const PthreadAttr* attr, PthreadEntry entry, void* arg, const char* name); -int APS5_VABI scePthreadJoin(Pthread thread, void** retval); -int APS5_VABI scePthreadMutexattrInit(PthreadMutexattr* attr); -int APS5_VABI scePthreadMutexattrDestroy(PthreadMutexattr* attr); -int APS5_VABI scePthreadMutexattrSettype(PthreadMutexattr* attr, int type); -int APS5_VABI scePthreadMutexInit(PthreadMutex* mutex, const PthreadMutexattr* attr, const char* name); -int APS5_VABI scePthreadMutexDestroy(PthreadMutex* mutex); -int APS5_VABI scePthreadMutexLock(PthreadMutex* mutex); -int APS5_VABI scePthreadMutexUnlock(PthreadMutex* mutex); -int APS5_VABI scePthreadCondInit(PthreadCond* cond, const PthreadCondattr* attr, const char* name); -int APS5_VABI scePthreadCondDestroy(PthreadCond* cond); -int APS5_VABI scePthreadCondSignal(PthreadCond* cond); -int APS5_VABI scePthreadCondWait(PthreadCond* cond, PthreadMutex* mutex); -int APS5_VABI scePthreadCondTimedwait(PthreadCond* cond, PthreadMutex* mutex, unsigned int usec); -int APS5_VABI pthread_cond_wait_nid_postfix(PthreadCond* cond, PthreadMutex* mutex); -int APS5_VABI pthread_cond_timedwait_nid_postfix(PthreadCond* cond, PthreadMutex* mutex, const KernelTimespec* abstime); -int APS5_VABI clock_gettime_nid_postfix(int clockId, KernelTimespec* tp); -} - static constexpr int SCE_OK = 0; -static constexpr int SCE_KERNEL_ERROR_EPERM = static_cast(0x80020001); -static constexpr int SCE_KERNEL_ERROR_ETIMEDOUT = static_cast(0x8002003C); static constexpr int POSIX_ETIMEDOUT = 60; static constexpr int MUTEX_TYPE_RECURSIVE = 2; diff --git a/core/libs/tests/GuestCondTimedwait.cpp b/core/libs/tests/GuestCondTimedwait.cpp index 27a91e95e7..70db4b4e2b 100644 --- a/core/libs/tests/GuestCondTimedwait.cpp +++ b/core/libs/tests/GuestCondTimedwait.cpp @@ -1,38 +1,18 @@ +#include "prx/libkernel/KernelErrors.hpp" +#include "prx/libkernel/include/Api.hpp" +#include "prx/libkernel/Pthread/include/Mutex.hpp" +#include "prx/libkernel/Pthread/include/Cond.hpp" +#include "prx/libc/include/Api.hpp" #include "SceTypes.hpp" #include #include #include #include -extern "C" { -int APS5_VABI scePthreadCreate(Pthread* thread, const PthreadAttr* attr, PthreadEntry entry, void* arg, const char* name); -int APS5_VABI scePthreadJoin(Pthread thread, void** retval); -int APS5_VABI scePthreadMutexInit(PthreadMutex* mutex, const PthreadMutexattr* attr, const char* name); -int APS5_VABI scePthreadMutexDestroy(PthreadMutex* mutex); -int APS5_VABI scePthreadMutexLock(PthreadMutex* mutex); -int APS5_VABI scePthreadMutexUnlock(PthreadMutex* mutex); -int APS5_VABI scePthreadMutexTrylock(PthreadMutex* mutex); -int APS5_VABI scePthreadCondInit(PthreadCond* cond, const PthreadCondattr* attr, const char* name); -int APS5_VABI scePthreadCondDestroy(PthreadCond* cond); -int APS5_VABI scePthreadCondTimedwait(PthreadCond* cond, PthreadMutex* mutex, unsigned int usec); -int APS5_VABI scePthreadCondSignal(PthreadCond* cond); -int APS5_VABI pthread_cond_init_nid_postfix(PthreadCond* cond, const PthreadCondattr* attr); -int APS5_VABI pthread_cond_destroy_nid_postfix(PthreadCond* cond); -int APS5_VABI pthread_cond_timedwait_nid_postfix(PthreadCond* cond, PthreadMutex* mutex, const KernelTimespec* abstime); -int APS5_VABI pthread_cond_reltimedwait_np_nid_postfix(PthreadCond* cond, PthreadMutex* mutex, unsigned int usec); -int APS5_VABI pthread_cond_signalto_np_nid_postfix(PthreadCond* cond, Pthread thread); -Pthread APS5_VABI scePthreadSelf(); -int APS5_VABI __cxa_atexit_nid_postfix(void (APS5_VABI *)(void*), void*, void*); -void APS5_VABI __pthread_cxa_finalize_nid_postfix(void*); -unsigned int APS5_VABI sceKernelSleep(unsigned int seconds); -} - static int cleanupAt = -1; static void APS5_VABI Cleanup(void*) { cleanupAt = 0; } static constexpr int SCE_OK = 0; -static constexpr int SCE_KERNEL_ERROR_ETIMEDOUT = static_cast(0x8002003C); -static constexpr int SCE_KERNEL_ERROR_EBUSY = static_cast(0x80020010); static constexpr int POSIX_EPERM = 1; static constexpr int POSIX_EINVAL = 22; static constexpr int POSIX_ETIMEDOUT = 60; @@ -181,5 +161,6 @@ int main() { void* finalizeHandle = reinterpret_cast(7); Require(__cxa_atexit_nid_postfix(Cleanup, nullptr, finalizeHandle) == SCE_OK); __pthread_cxa_finalize_nid_postfix(finalizeHandle); + Require(cleanupAt == 0); } diff --git a/core/libs/tests/GuestCondUnownedMutex.cpp b/core/libs/tests/GuestCondUnownedMutex.cpp index f68fe17391..124b772719 100644 --- a/core/libs/tests/GuestCondUnownedMutex.cpp +++ b/core/libs/tests/GuestCondUnownedMutex.cpp @@ -1,28 +1,15 @@ +#include "prx/libkernel/KernelErrors.hpp" +#include "prx/libkernel/include/Api.hpp" +#include "prx/libkernel/Time/include/Time.hpp" +#include "prx/libkernel/Pthread/include/Mutex.hpp" +#include "prx/libkernel/Pthread/include/Cond.hpp" #include "SceTypes.hpp" #include #include #include #include -extern "C" { -int APS5_VABI scePthreadCreate(Pthread* thread, const PthreadAttr* attr, PthreadEntry entry, void* arg, const char* name); -int APS5_VABI scePthreadJoin(Pthread thread, void** retval); -int APS5_VABI scePthreadMutexInit(PthreadMutex* mutex, const PthreadMutexattr* attr, const char* name); -int APS5_VABI scePthreadMutexDestroy(PthreadMutex* mutex); -int APS5_VABI scePthreadMutexLock(PthreadMutex* mutex); -int APS5_VABI scePthreadMutexUnlock(PthreadMutex* mutex); -int APS5_VABI scePthreadCondInit(PthreadCond* cond, const PthreadCondattr* attr, const char* name); -int APS5_VABI scePthreadCondDestroy(PthreadCond* cond); -int APS5_VABI scePthreadCondWait(PthreadCond* cond, PthreadMutex* mutex); -int APS5_VABI scePthreadCondTimedwait(PthreadCond* cond, PthreadMutex* mutex, unsigned int usec); -int APS5_VABI pthread_cond_wait_nid_postfix(PthreadCond* cond, PthreadMutex* mutex); -int APS5_VABI pthread_cond_timedwait_nid_postfix(PthreadCond* cond, PthreadMutex* mutex, const KernelTimespec* abstime); -int APS5_VABI clock_gettime_nid_postfix(int clockId, KernelTimespec* tp); -} - static constexpr int SCE_OK = 0; -static constexpr int SCE_KERNEL_ERROR_EPERM = static_cast(0x80020001); -static constexpr int SCE_KERNEL_ERROR_EINVAL = static_cast(0x80020016); static constexpr int POSIX_EPERM = 1; static constexpr int POSIX_EINVAL = 22; static constexpr std::uintptr_t ADAPTIVE_INITIALIZER = 1; diff --git a/core/libs/tests/GuestContentDelete.cpp b/core/libs/tests/GuestContentDelete.cpp index 06cebf5b38..caafe4a5bd 100644 --- a/core/libs/tests/GuestContentDelete.cpp +++ b/core/libs/tests/GuestContentDelete.cpp @@ -1,14 +1,10 @@ +#include "prx/libSceContentDelete/include/Api.hpp" #include "SceTypes.hpp" #include #include #include #include -extern "C" int APS5_VABI sceContentDeleteInitialize(const ContentDeleteInitParam* initParam); -extern "C" int APS5_VABI sceContentDeleteTerminate(void); -extern "C" int APS5_VABI sceContentDeleteById(std::int64_t contentId); -extern "C" int APS5_VABI sceContentDeleteByPath(const char* contentPath); - namespace { void Require(bool value) { if (!value) std::abort(); } diff --git a/core/libs/tests/GuestContentExport.cpp b/core/libs/tests/GuestContentExport.cpp index 4f72b3a7c7..07fa418b6d 100644 --- a/core/libs/tests/GuestContentExport.cpp +++ b/core/libs/tests/GuestContentExport.cpp @@ -1,30 +1,10 @@ +#include "prx/libSceContentExport/include/Api.hpp" #include "SceTypes.hpp" #include #include #include #include -extern "C" int APS5_VABI sceContentExportAddToFavorites(std::int64_t contentId); -extern "C" int APS5_VABI sceContentExportDataProvideFunction(void); -extern "C" int APS5_VABI sceContentExportFree(void); -extern "C" int APS5_VABI sceContentExportFrom(void); -extern "C" int APS5_VABI sceContentExportFromFileForSf(std::int32_t expId, const ContentExportParam* param, const ContentExportSfParam* sfParam, const char* sourcePath, const char* thumbnailPath, char* path, std::size_t pathBufferLength); -extern "C" int APS5_VABI sceContentExportFromFileWithContentIdList(std::int32_t expId, const ContentExportParam* param, const char* sourcePath, const char* thumbnailPath, const std::int64_t* contentIds, std::uint32_t contentCount, char* path, std::size_t pathBufferLength); -extern "C" int APS5_VABI sceContentExportFromFileWithTitleIdList(std::int32_t expId, const ContentExportParam* param, const char* sourcePath, const char* thumbnailPath, const char* titleIdList, char* path, std::size_t pathBufferLength); -extern "C" int APS5_VABI sceContentExportInit(const ContentExportInitParam* param); -extern "C" int APS5_VABI sceContentExportMalloc(void); -extern "C" int APS5_VABI sceContentExportRemoveFromFavorites(std::int64_t contentId); -extern "C" int APS5_VABI sceContentExportRenameContent(std::int64_t contentId, const char* name); -extern "C" int APS5_VABI sceContentExportValidateContents(const std::int64_t* contentIds, std::uint32_t count); - -extern "C" int APS5_VABI sceContentExportInit2(const ContentExportInitParam2* init_param); -extern "C" int APS5_VABI sceContentExportTerm(void); -extern "C" int APS5_VABI sceContentExportStart(void); -extern "C" int APS5_VABI sceContentExportFinish(std::int32_t expId); -extern "C" int APS5_VABI sceContentExportGetProgress(std::int32_t expId); -extern "C" int APS5_VABI sceContentExportCancel(std::int32_t expId); -extern "C" int APS5_VABI sceContentExportFromDataWithThumbnail(std::int32_t expId, const ContentExportParam* param, const ContentExportCallbackParam* contentCallbackParam, const char* thumbnailType, const ContentExportCallbackParam* thumbnailCallbackParam, char* path, std::size_t pathBufferLength); - namespace { void Require(bool value) { if (!value) std::abort(); } @@ -47,6 +27,7 @@ void Export(std::int32_t expId) { ContentExportCallbackParam content{}; ContentExportCallbackParam thumbnail{}; sceContentExportFromDataWithThumbnail(expId, ¶m, &content, "image/png", &thumbnail, path, sizeof(path)); + } } diff --git a/core/libs/tests/GuestContentSearch.cpp b/core/libs/tests/GuestContentSearch.cpp index 5676436c77..c262e8a9df 100644 --- a/core/libs/tests/GuestContentSearch.cpp +++ b/core/libs/tests/GuestContentSearch.cpp @@ -1,34 +1,9 @@ +#include "prx/libSceContentSearch/include/Api.hpp" #include "SceTypes.hpp" #include #include #include -extern "C" { -int APS5_VABI sceContentSearchInit(const ContentSearchInitParam* init_param); -int APS5_VABI sceContentSearchTerm(void); -int APS5_VABI sceContentSearchGetContentLastUpdateId(std::int64_t* lastUpdateId); -int APS5_VABI sceContentSearchGetNumOfContent(const ContentSearchContentColumnSet* columnSet, std::uint32_t columnSetLength, std::int64_t* numOfContent, std::int64_t* lastUpdateId); -int APS5_VABI sceContentSearchGetTotalContentSize(const ContentSearchContentColumnSet* columnSet, std::uint32_t columnSetLength, std::int64_t* size, std::int64_t* lastUpdateId); -int APS5_VABI sceContentSearchSearchContent(const ContentSearchContentColumnSet* columnSet, std::uint32_t columnSetLength, const ContentSearchContentOrderByCondition* orderByConditions, std::uint32_t orderByConditionsLength, std::uint32_t offset, std::uint32_t limit, std::int64_t* numOfContent, void* infos, std::int64_t* lastUpdateId); -int APS5_VABI sceContentSearchOpenMetadata(const char* filePath, std::int32_t* metadataId); -int APS5_VABI sceContentSearchOpenMetadataByContentId(std::int64_t contentId, std::int32_t* metadataId); -int APS5_VABI sceContentSearchCloseMetadata(std::int32_t metadataId); -int APS5_VABI sceContentSearchGetMetadataFieldInfo(std::int32_t metadataId, const char* field, std::int32_t* metadataType, std::int32_t* size); -int APS5_VABI sceContentSearchGetMetadataValue(std::int32_t metadataId, const char* field, void* value); -int APS5_VABI sceContentBinderEnd(void); -int APS5_VABI sceContentBinderGetNumOfDifference(void); -int APS5_VABI sceContentBinderInitialize(void); -int APS5_VABI sceContentBinderIsUpdated(void); -int APS5_VABI sceContentBinderReset(void); -int APS5_VABI sceContentBinderSearchDifference(void); -int APS5_VABI sceContentBinderStart(void); -int APS5_VABI sceContentBinderTerminate(void); -int APS5_VABI sceContentSearchGetApplicationLastUpdateId(void); -int APS5_VABI sceContentSearchGetMyApplicationIndex(void); -int APS5_VABI sceContentSearchGetNumOfApplication(void); -int APS5_VABI sceContentSearchSearchApplication(void); -} - namespace { void Require(bool value) { if (!value) std::abort(); } diff --git a/core/libs/tests/GuestConvertKeycode.cpp b/core/libs/tests/GuestConvertKeycode.cpp index 3bb2493a66..8bf7b815b0 100644 --- a/core/libs/tests/GuestConvertKeycode.cpp +++ b/core/libs/tests/GuestConvertKeycode.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceConvertKeycode/include/Api.hpp" #include "SceTypes.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "ProcessParametersFixture.hpp" @@ -12,12 +13,6 @@ #include #include -extern "C" { -int APS5_VABI sceConvertKeycodeGetVirtualKeycode(std::uint16_t, std::uint32_t, std::uint16_t*); -int APS5_VABI sceConvertKeycodeGetImeKeyboardType(std::int32_t, std::uint32_t*); -int APS5_VABI sceConvertKeycodeGetCharacter(std::uint16_t, std::uint32_t, std::uint32_t, char16_t*); -} - static void Require(bool value) { if (!value) std::abort(); } static void SetLanguage(const char* value) { @@ -146,6 +141,7 @@ int main() { bool rejected = false; try { sceConvertKeycodeGetVirtualKeycode(28, layout, &virtualKey); + } catch (const std::runtime_error&) { rejected = true; } diff --git a/core/libs/tests/GuestConvertKeycodeTitle.cpp b/core/libs/tests/GuestConvertKeycodeTitle.cpp index 6fd7337573..c398ae1ba0 100644 --- a/core/libs/tests/GuestConvertKeycodeTitle.cpp +++ b/core/libs/tests/GuestConvertKeycodeTitle.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceConvertKeycode/include/Api.hpp" #include "SceTypes.hpp" #include "ProcessParametersFixture.hpp" #include @@ -6,10 +7,6 @@ #include #include -extern "C" { -int APS5_VABI sceConvertKeycodeGetImeKeyboardType(std::int32_t, std::uint32_t*); -} - int main() { #ifdef _WIN32 if (_putenv_s("ANYPS5_LANGUAGE", "") != 0) return 2; diff --git a/core/libs/tests/GuestCoredumpAttach.cpp b/core/libs/tests/GuestCoredumpAttach.cpp index 5d3b7ebb5e..e1948026e4 100644 --- a/core/libs/tests/GuestCoredumpAttach.cpp +++ b/core/libs/tests/GuestCoredumpAttach.cpp @@ -1,3 +1,4 @@ +#include "prx/libkernel/include/Api.hpp" #include "ProcessParametersFixture.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -8,18 +9,6 @@ #include #include -extern "C" { -int APS5_VABI sceCoredumpRegisterCoredumpHandler(uint64_t handler, size_t stackSize, uint64_t context); -int APS5_VABI sceCoredumpUnregisterCoredumpHandler(void); -int APS5_VABI sceCoredumpAttachMemoryRegion(uint32_t userValue, const void* mem, std::int32_t size); -int APS5_VABI sceCoredumpAttachUserMemoryFile(uint32_t userValue, const void* mem, std::int32_t size); -int APS5_VABI sceCoredumpGetStopInfoCpu(void* info, size_t size); -int APS5_VABI sceCoredumpGetThreadContextInfo(void* threadContextInfo, size_t threadContextInfoSize); -int APS5_VABI sceCoredumpGetStopInfoGpu_Agc(void* info, size_t size); -int APS5_VABI sceCoredumpWriteUserString(uint32_t first, const char* text, int third); -int APS5_VABI sceCoredumpConfigDumpMode(int mode); -} - namespace { alignas(16) std::array process{}; constexpr int InvalidArgument = static_cast(0x81180000u); diff --git a/core/libs/tests/GuestCoredumpUserData.cpp b/core/libs/tests/GuestCoredumpUserData.cpp index d0baa9fd12..694d076666 100644 --- a/core/libs/tests/GuestCoredumpUserData.cpp +++ b/core/libs/tests/GuestCoredumpUserData.cpp @@ -1,3 +1,4 @@ +#include "prx/libkernel/include/Api.hpp" #include "ProcessParametersFixture.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -8,16 +9,6 @@ #include #include -extern "C" { -int APS5_VABI sceCoredumpRegisterCoredumpHandler(uint64_t handler, size_t stackSize, uint64_t context); -int APS5_VABI sceCoredumpUnregisterCoredumpHandler(void); -int64_t APS5_VABI sceCoredumpWriteUserData(const void* data, size_t size); -void APS5_VABI sceCoredumpDebugTextOut(const char* str, int len); -int APS5_VABI sceCoredumpAttachUserFile(uint32_t userValue, const char* path); -int APS5_VABI sceCoredumpAttachMemoryRegionAsUserFile(uint32_t userValue, const void* mem, std::int32_t size, const char* name); -int APS5_VABI sceCoredumpSetUserDataType(std::int32_t type); -} - namespace { alignas(16) std::array process{}; constexpr int64_t InvalidArgument = static_cast(0x81180000u); @@ -93,6 +84,7 @@ int main() { RequireWritesRefused(region); RequireAttachesRefused(region); sceCoredumpDebugTextOut(text, static_cast(sizeof(text) - 1)); + Require(!handlerRan); Require(sceCoredumpWriteUserData(nullptr, region.size()) == InvalidArgument); diff --git a/core/libs/tests/GuestCpuTimeClocks.cpp b/core/libs/tests/GuestCpuTimeClocks.cpp index cb7405736e..18ae60bb87 100644 --- a/core/libs/tests/GuestCpuTimeClocks.cpp +++ b/core/libs/tests/GuestCpuTimeClocks.cpp @@ -1,19 +1,17 @@ +#include "prx/libkernel/KernelErrors.hpp" +#include "prx/libkernel/include/Api.hpp" +#include "prx/libkernel/Time/include/Time.hpp" #include "SceTypes.hpp" #include #include #include extern "C" { -int APS5_VABI clock_gettime_nid_postfix(int clockId, KernelTimespec* tp); -int APS5_VABI clock_getres_nid_postfix(int clockId, KernelTimespec* res); -int APS5_VABI sceKernelClockGettime(KernelClockid clockId, KernelTimespec* tp); -int APS5_VABI sceKernelClockGetres(KernelClockid clockId, KernelTimespec* tp); + #ifdef _WIN32 int APS5_VABI ClockTimeWin32ErrorToGuestErrno_nid_no_patch(std::uint32_t error); #endif -int APS5_VABI sceKernelUsleep_nid_postfix(KernelUseconds microseconds); -int APS5_VABI scePthreadCreate(Pthread* thread, const PthreadAttr* attr, PthreadEntry entry, void* arg, const char* name); -int APS5_VABI scePthreadJoin(Pthread thread, void** retval); + } #ifdef _WIN32 @@ -23,7 +21,6 @@ static constexpr std::uint32_t WINDOWS_ERROR_INVALID_HANDLE = 6; #endif static constexpr int SCE_OK = 0; -static constexpr int SCE_KERNEL_ERROR_EFAULT = static_cast(0x8002000E); static constexpr int GUEST_CLOCK_MONOTONIC = 4; static constexpr int GUEST_CLOCK_THREAD_CPUTIME_ID = 14; diff --git a/core/libs/tests/GuestCredentials.cpp b/core/libs/tests/GuestCredentials.cpp index ff69af902b..c2bc00310d 100644 --- a/core/libs/tests/GuestCredentials.cpp +++ b/core/libs/tests/GuestCredentials.cpp @@ -1,30 +1,11 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include #include #include -extern "C" { -int APS5_VABI seteuid_nid_postfix(std::uint32_t); -int APS5_VABI setegid_nid_postfix(std::uint32_t); -int APS5_VABI setuid_nid_postfix(std::uint32_t); -int APS5_VABI setgid_nid_postfix(std::uint32_t); -int APS5_VABI setreuid_nid_postfix(std::uint32_t, std::uint32_t); -int APS5_VABI setregid_nid_postfix(std::uint32_t, std::uint32_t); -int APS5_VABI setresuid_nid_postfix(std::uint32_t, std::uint32_t, std::uint32_t); -int APS5_VABI setresgid_nid_postfix(std::uint32_t, std::uint32_t, std::uint32_t); -int APS5_VABI setgroups_nid_postfix(int, const std::uint32_t*); -int APS5_VABI getgroups_nid_postfix(int, std::uint32_t*); -int APS5_VABI getuid_nid_postfix(void); -int APS5_VABI geteuid_nid_postfix(void); -int APS5_VABI getgid_nid_postfix(void); -int APS5_VABI getegid_nid_postfix(void); -int APS5_VABI issetugid_nid_postfix(void); -int APS5_VABI getresuid_nid_postfix(std::uint32_t*, std::uint32_t*, std::uint32_t*); -int APS5_VABI getresgid_nid_postfix(std::uint32_t*, std::uint32_t*, std::uint32_t*); -int* APS5_VABI __error_nid_postfix(); -} - static void Require(bool value) { if (!value) std::abort(); } using SetId = int (APS5_VABI *)(std::uint32_t); using SetReId = int (APS5_VABI *)(std::uint32_t, std::uint32_t); diff --git a/core/libs/tests/GuestCrt.cpp b/core/libs/tests/GuestCrt.cpp index d2fe45d744..1e8f1887f5 100644 --- a/core/libs/tests/GuestCrt.cpp +++ b/core/libs/tests/GuestCrt.cpp @@ -1,3 +1,5 @@ +#include "prx/libc/include/Api.hpp" +#include "prx/libSceAmpr/include/Api.hpp" #include "SceTypes.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libc/include/SonyCrt.hpp" @@ -14,31 +16,6 @@ #include #include -extern "C" { -SonyLconv* APS5_VABI sceAmprLocaleconv(void); -double APS5_VABI sceAmprSinh(double x, double y); -char* APS5_VABI sceAmprStrtokS(char* str, const char* delim, char** context); -int APS5_VABI sceAmprCtimeS(char* buffer, std::size_t size, const std::int64_t* time); -int APS5_VABI sceAmprWcscpyS(std::uint16_t* dest, std::size_t size, const std::uint16_t* src); -void* APS5_VABI sceAmprSetConstraintHandlerS(void* handler); -int APS5_VABI sceAmprFltrounds(void); -void APS5_VABI sceAmprIgnoreHandlerS(const char* message, void* pointer, int error); -std::size_t APS5_VABI sceAmprMbstowcs(std::uint16_t* dest, const char* src, std::size_t size); -int APS5_VABI sceAmprAsctimeS(char* buffer, std::size_t size, const GuestTm* time); -int APS5_VABI ctime_s_nid_postfix(char* buffer, std::size_t size, const std::int64_t* time); -int APS5_VABI asctime_s_nid_postfix(char* buffer, std::size_t size, const GuestTm* time); -std::size_t APS5_VABI mbstowcs_nid_postfix(std::uint16_t* dest, const char* src, std::size_t size); -char* APS5_VABI strtok_s_nid_postfix(char* str, const char* delim, char** context); -int APS5_VABI __fpclassifyd_nid_postfix(double value); -unsigned __int128 APS5_VABI __udivti3_nid_postfix(unsigned __int128 dividend, unsigned __int128 divisor); -__int128 APS5_VABI __divti3_nid_postfix(__int128 dividend, __int128 divisor); -unsigned __int128 APS5_VABI __umodti3_nid_postfix(unsigned __int128 dividend, unsigned __int128 divisor); -__int128 APS5_VABI __modti3_nid_postfix(__int128 dividend, __int128 divisor); -SonyLconv* APS5_VABI localeconv_nid_postfix(void); -int APS5_VABI sceAmprFpclassifyd(double value); -unsigned int APS5_VABI _ZSt14_Random_devicev_nid_postfix(); -} - #define Require(condition) do { if (!(condition)) { std::fprintf(stderr, "guest_crt: line %d: %s\n", __LINE__, #condition); std::abort(); } } while (0) static int g_handlerCalls = 0; @@ -154,6 +131,7 @@ int main() { trapped = false; try { __umodti3_nid_postfix(((unsigned __int128)0x1234 << 64) | 0x5678, 0); + } catch (const std::runtime_error& error) { trapped = std::strcmp(error.what(), "__umodti3: integer divide by zero (0x00000000000012340000000000005678 % 0)") == 0; } @@ -195,6 +173,13 @@ int main() { known.tm_year = 9000; text[0] = 'x'; Require(sceAmprAsctimeS(text, sizeof(text), &known) == EINVAL && text[0] == '\0'); + for (const int year : {INT_MAX, INT_MAX - 1899, INT_MIN}) { + known.tm_year = year; + text[0] = 'x'; + Require(sceAmprAsctimeS(text, sizeof(text), &known) == EINVAL && text[0] == '\0'); + text[0] = 'x'; + Require(asctime_s_nid_postfix(text, sizeof(text), &known) == EINVAL && text[0] == '\0'); + } known.tm_year = 70; known.tm_mday = 32; text[0] = 'x'; diff --git a/core/libs/tests/GuestCryptoMemcmp.cpp b/core/libs/tests/GuestCryptoMemcmp.cpp index 578b4a4645..e23991ed1f 100644 --- a/core/libs/tests/GuestCryptoMemcmp.cpp +++ b/core/libs/tests/GuestCryptoMemcmp.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceLibreSsl3/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -13,8 +14,6 @@ #include #endif -extern "C" int APS5_VABI CRYPTO_memcmp_nid_postfix(const void*, const void*, std::size_t); - namespace { void Require(bool value) { diff --git a/core/libs/tests/GuestCurrentCpu.cpp b/core/libs/tests/GuestCurrentCpu.cpp index 389ad302ff..17cda444cb 100644 --- a/core/libs/tests/GuestCurrentCpu.cpp +++ b/core/libs/tests/GuestCurrentCpu.cpp @@ -1,22 +1,11 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libkernel/Time/include/Time.hpp" #include "SceTypes.hpp" #include "prx/libkernel/Pthread/include/Pthread.hpp" #include #include #include -extern "C" { -int APS5_VABI sceKernelGetCurrentCpu(void); -int APS5_VABI sceKernelGetMainSocId(void); -int APS5_VABI sceKernelGetCpumode(void); -std::int64_t APS5_VABI sceKernelGetCpuFrequency(void); -std::uint64_t APS5_VABI sceKernelGetTscFrequency(void); -KernelCpumask APS5_VABI sceKernelGetAvailableCpumask(void); -Pthread APS5_VABI scePthreadSelf(); -int APS5_VABI scePthreadCreate(Pthread* thread, const PthreadAttr* attr, PthreadEntry entry, void* arg, const char* name); -int APS5_VABI scePthreadJoin(Pthread thread, void** retval); -int APS5_VABI scePthreadSetaffinity(Pthread thread, KernelCpumask mask); -} - static constexpr int SCE_OK = 0; static constexpr unsigned MAX_HOST_CPUS = 256; static constexpr int CALLS_PER_THREAD = 64; diff --git a/core/libs/tests/GuestDaemon.cpp b/core/libs/tests/GuestDaemon.cpp index 0e87384eb6..bec3a6613a 100644 --- a/core/libs/tests/GuestDaemon.cpp +++ b/core/libs/tests/GuestDaemon.cpp @@ -1,12 +1,14 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include #include -extern "C" int APS5_VABI daemon_nid_postfix(int, int); + static void Require(bool value) { if (!value) std::abort(); } static bool ReportsNotImplemented(int noChdir, int noClose) { try { daemon_nid_postfix(noChdir, noClose); + } catch (const std::runtime_error& error) { return std::string(error.what()) == "daemon: forking into the background not implemented"; } diff --git a/core/libs/tests/GuestDatagramReceive.cpp b/core/libs/tests/GuestDatagramReceive.cpp index d719b7719e..d11fe04de6 100644 --- a/core/libs/tests/GuestDatagramReceive.cpp +++ b/core/libs/tests/GuestDatagramReceive.cpp @@ -1,3 +1,6 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" +#include "prx/libSceNet/include/Net.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -8,30 +11,6 @@ #include #include -extern "C" { -int APS5_VABI socket_nid_postfix(int, int, int); -int APS5_VABI bind_nid_postfix(int, const void*, std::uint32_t); -int APS5_VABI connect_nid_postfix(int, const void*, std::uint32_t); -int APS5_VABI getsockname_nid_postfix(int, void*, std::uint32_t*); -int APS5_VABI fcntl_nid_postfix(int, int, ...); -std::int64_t APS5_VABI sendto_nid_postfix(int, const void*, std::uint64_t, int, const void*, std::uint32_t); -std::int64_t APS5_VABI recv_nid_postfix(int, void*, std::uint64_t, int); -std::int64_t APS5_VABI recvfrom_nid_postfix(int, void*, std::uint64_t, int, void*, std::uint32_t*); -int APS5_VABI close_nid_postfix(int); -int* APS5_VABI __error_nid_postfix(); -int APS5_VABI sceNetInit_nid_postfix(); -int APS5_VABI sceNetSocket(const char*, int, int, int); -int APS5_VABI sceNetBind_nid_postfix(int, const void*, std::uint32_t); -int APS5_VABI sceNetConnect(int, const void*, std::uint32_t); -int APS5_VABI sceNetGetsockname(int, void*, std::uint32_t*); -int APS5_VABI sceNetSetsockopt(int, int, int, const void*, std::uint32_t); -std::int64_t APS5_VABI sceNetSendto(int, const void*, std::size_t, int, const void*, std::uint32_t); -std::int64_t APS5_VABI sceNetRecv(int, void*, std::size_t, int); -std::int64_t APS5_VABI sceNetRecvfrom(int, void*, std::size_t, int, void*, std::uint32_t*); -int APS5_VABI sceNetSocketClose(int); -int* APS5_VABI sceNetErrnoLoc(); -} - static void Require(bool condition, const char* message) { if (!condition) { std::fprintf(stderr, "%s\n", message); @@ -56,6 +35,7 @@ static void Check(bool net, bool from, int family) { const auto bind = [&](int descriptor) { return net ? sceNetBind_nid_postfix(descriptor, destination.data(), addressSize) : bind_nid_postfix(descriptor, destination.data(), addressSize); + }; const int bound = bind(receiver); if (bound < 0 && family == 28 && *error == 49) { @@ -80,6 +60,7 @@ static void Check(bool net, bool from, int family) { sceNetRecv(receiver, buffer, length, flags); return from ? recvfrom_nid_postfix(receiver, buffer, length, flags, address, addressLength) : recv_nid_postfix(receiver, buffer, length, flags); + }; const auto send = [&](const char* data, std::size_t length) { Require((net ? sceNetSendto(sender, data, length, 0, destination.data(), addressSize) : diff --git a/core/libs/tests/GuestDeferredModule.cpp b/core/libs/tests/GuestDeferredModule.cpp index 719a68829f..f9e3089049 100644 --- a/core/libs/tests/GuestDeferredModule.cpp +++ b/core/libs/tests/GuestDeferredModule.cpp @@ -1,3 +1,4 @@ +#include "prx/libkernel/include/Api.hpp" #define WIN32_LEAN_AND_MEAN #include "GuestDeferredModule.hpp" #include @@ -6,15 +7,6 @@ #include #include -extern "C" { -void* APS5_VABI dlopen_nid_postfix(const char*, int); -void* APS5_VABI dlsym_nid_postfix(void*, const char*); -int APS5_VABI dlclose_nid_postfix(void*); -char* APS5_VABI dlerror_nid_postfix(); -int APS5_VABI sceKernelLoadStartModule(const char*, std::size_t, const void*, unsigned, const void*, int*); -int APS5_VABI sceKernelStopUnloadModule(int, std::size_t, const void*, unsigned, const void*, int*); -} - static void Require(bool value, const char* what) { if (!value) { std::fprintf(stderr, "%s\n", what); diff --git a/core/libs/tests/GuestDemangle.cpp b/core/libs/tests/GuestDemangle.cpp index ea2f1100cf..b3bc34a66d 100644 --- a/core/libs/tests/GuestDemangle.cpp +++ b/core/libs/tests/GuestDemangle.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/ApplicationHeap.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -9,12 +10,6 @@ #include #include -extern "C" { -char* APS5_VABI __cxa_demangle_nid_postfix(const char*, char*, std::size_t*, int*); -void* APS5_VABI malloc_nid_postfix(std::size_t); -void APS5_VABI free_nid_postfix(void*); -} - namespace { constexpr char MangledName[] = "_ZN3foo3barEi"; @@ -159,12 +154,13 @@ void RegisterAllocator() { void ReleaseIfReturned(void* result, void* original = nullptr) { ForgetIfMoved(original, result); free_nid_postfix(result != nullptr ? result : original); + } void TestNullOutputBuffer() { std::size_t length = 0; int status = 99; - char* result = __cxa_demangle_nid_postfix(MangledName, nullptr, &length, &status); + char* result = reinterpret_cast(__cxa_demangle_nid_postfix(MangledName, nullptr, &length, &status)); Check(result != nullptr, "null output buffer did not demangle"); Check(status == 0, "null output buffer returned the wrong status"); Check(result != nullptr && std::strcmp(result, DemangledName) == 0, "null output buffer returned the wrong string"); @@ -174,7 +170,7 @@ void TestNullOutputBuffer() { } void TestOptionalStatus() { - char* result = __cxa_demangle_nid_postfix(MangledName, nullptr, nullptr, nullptr); + char* result = reinterpret_cast(__cxa_demangle_nid_postfix(MangledName, nullptr, nullptr, nullptr)); Check(result != nullptr && std::strcmp(result, DemangledName) == 0, "optional status output failed"); Check(result != nullptr && Owns(result), "optional status output was not guest-owned"); ReleaseIfReturned(result); @@ -185,7 +181,7 @@ void TestLargeBufferReuse() { const std::size_t originalLength = 128; std::size_t length = originalLength; int status = 99; - char* result = __cxa_demangle_nid_postfix(MangledName, buffer, &length, &status); + char* result = reinterpret_cast(__cxa_demangle_nid_postfix(MangledName, static_cast(buffer), &length, &status)); Check(result == buffer, "sufficient guest buffer was not reused"); Check(status == 0, "sufficient guest buffer returned the wrong status"); Check(result != nullptr && std::strcmp(result, DemangledName) == 0, "sufficient guest buffer returned the wrong string"); @@ -198,7 +194,7 @@ void TestSmallBufferGrowth() { std::size_t length = 1; const std::size_t reallocationsBefore = reallocationCalls; int status = 99; - char* result = __cxa_demangle_nid_postfix(MangledName, buffer, &length, &status); + char* result = reinterpret_cast(__cxa_demangle_nid_postfix(MangledName, static_cast(buffer), &length, &status)); Check(result != nullptr, "too-small guest buffer did not grow"); Check(status == 0, "grown guest buffer returned the wrong status"); Check(result != nullptr && std::strcmp(result, DemangledName) == 0, "grown guest buffer returned the wrong string"); @@ -210,18 +206,19 @@ void TestSmallBufferGrowth() { void TestInvalidInputs() { int status = 99; - char* result = __cxa_demangle_nid_postfix("not_a_mangled_name", nullptr, nullptr, &status); + char* result = reinterpret_cast(__cxa_demangle_nid_postfix("not_a_mangled_name", nullptr, nullptr, &status)); Check(result == nullptr && status == -2, "invalid mangled name did not return status -2"); status = 99; - result = __cxa_demangle_nid_postfix(nullptr, nullptr, nullptr, &status); + result = reinterpret_cast(__cxa_demangle_nid_postfix(nullptr, nullptr, nullptr, &status)); Check(result == nullptr && status == -3, "null mangled name did not return status -3"); auto* buffer = static_cast(malloc_nid_postfix(32)); std::memcpy(buffer, "unchanged", sizeof("unchanged")); - result = __cxa_demangle_nid_postfix(MangledName, buffer, nullptr, &status); + result = reinterpret_cast(__cxa_demangle_nid_postfix(MangledName, static_cast(buffer), nullptr, &status)); Check(result == nullptr && status == -3, "missing length for a supplied buffer did not return status -3"); Check(std::strcmp(buffer, "unchanged") == 0, "invalid supplied-buffer arguments modified the buffer"); free_nid_postfix(buffer); + } void TestAllocationFailure() { @@ -229,7 +226,7 @@ void TestAllocationFailure() { failNextAllocation = true; std::size_t length = 0; int status = 99; - char* result = __cxa_demangle_nid_postfix(MangledName, nullptr, &length, &status); + char* result = reinterpret_cast(__cxa_demangle_nid_postfix(MangledName, nullptr, &length, &status)); Check(result == nullptr, "guest allocation failure returned a buffer"); Check(status == -1, "guest allocation failure did not return status -1"); Check(allocationFailures == failuresBefore + 1, "demangler bypassed failed guest allocation"); @@ -243,7 +240,7 @@ void TestReallocationFailure() { const std::size_t failuresBefore = reallocationFailures; failNextReallocation = true; int status = 99; - char* result = __cxa_demangle_nid_postfix(MangledName, buffer, &length, &status); + char* result = reinterpret_cast(__cxa_demangle_nid_postfix(MangledName, static_cast(buffer), &length, &status)); Check(result == nullptr, "guest reallocation failure returned a buffer"); Check(status == -1, "guest reallocation failure did not return status -1"); Check(reallocationFailures == failuresBefore + 1, "demangler bypassed failed guest reallocation"); @@ -257,7 +254,7 @@ void TestAllocatorDiagnostics() { bool allocationDiagnostic = false; char* result = nullptr; try { - result = __cxa_demangle_nid_postfix(MangledName, nullptr, nullptr, nullptr); + result = reinterpret_cast(__cxa_demangle_nid_postfix(MangledName, nullptr, nullptr, nullptr)); } catch (const std::runtime_error& error) { allocationDiagnostic = std::strcmp(error.what(), "guest allocator callback failure") == 0; } @@ -271,7 +268,7 @@ void TestAllocatorDiagnostics() { bool reallocationDiagnostic = false; result = nullptr; try { - result = __cxa_demangle_nid_postfix(MangledName, buffer, &length, nullptr); + result = reinterpret_cast(__cxa_demangle_nid_postfix(MangledName, static_cast(buffer), &length, nullptr)); } catch (const std::runtime_error& error) { reallocationDiagnostic = std::strcmp(error.what(), "guest reallocator callback failure") == 0; } diff --git a/core/libs/tests/GuestDinkumwareAtomics.cpp b/core/libs/tests/GuestDinkumwareAtomics.cpp index cda03655f0..47765a29c8 100644 --- a/core/libs/tests/GuestDinkumwareAtomics.cpp +++ b/core/libs/tests/GuestDinkumwareAtomics.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -5,46 +6,6 @@ #include #include -extern "C" { -void APS5_VABI _Atomic_store_1_nid_postfix(volatile std::uint8_t*, std::uint8_t, int); -void APS5_VABI _Atomic_store_8_nid_postfix(volatile std::uint64_t*, std::uint64_t, int); -std::uint16_t APS5_VABI _Atomic_load_2_nid_postfix(volatile std::uint16_t*, int); -std::uint64_t APS5_VABI _Atomic_load_8_nid_postfix(volatile std::uint64_t*, int); -std::uint32_t APS5_VABI _Atomic_exchange_4_nid_postfix(volatile std::uint32_t*, std::uint32_t, int); -std::uint64_t APS5_VABI _Atomic_exchange_8_nid_postfix(volatile std::uint64_t*, std::uint64_t, int); -int APS5_VABI _Atomic_compare_exchange_strong_2_nid_postfix(volatile std::uint16_t*, std::uint16_t*, std::uint16_t, int, int); -int APS5_VABI _Atomic_compare_exchange_weak_8_nid_postfix(volatile std::uint64_t*, std::uint64_t*, std::uint64_t, int, int); -std::uint8_t APS5_VABI _Atomic_fetch_add_1_nid_postfix(volatile std::uint8_t*, std::uint8_t, int); -std::uint64_t APS5_VABI _Atomic_fetch_add_8_nid_postfix(volatile std::uint64_t*, std::uint64_t, int); -std::uint16_t APS5_VABI _Atomic_fetch_sub_2_nid_postfix(volatile std::uint16_t*, std::uint16_t, int); -std::uint32_t APS5_VABI _Atomic_fetch_and_4_nid_postfix(volatile std::uint32_t*, std::uint32_t, int); -std::uint8_t APS5_VABI _Atomic_fetch_or_1_nid_postfix(volatile std::uint8_t*, std::uint8_t, int); -std::uint64_t APS5_VABI _Atomic_fetch_xor_8_nid_postfix(volatile std::uint64_t*, std::uint64_t, int); -int APS5_VABI _Atomic_is_lock_free_4_nid_postfix(); -int APS5_VABI _Atomic_flag_test_and_set_nid_postfix(volatile unsigned char*, int); -void APS5_VABI _Atomic_flag_clear_nid_postfix(volatile unsigned char*, int); -void APS5_VABI _Atomic_thread_fence_nid_postfix(int); -void APS5_VABI _Atomic_signal_fence_nid_postfix(int); -void APS5_VABI _Atomic_copy_nid_postfix(volatile unsigned char*, std::size_t, volatile void*, const volatile void*, int); -void APS5_VABI _Atomic_exchange_nid_postfix(volatile unsigned char*, std::size_t, volatile void*, volatile void*, int); -int APS5_VABI _Atomic_compare_exchange_strong_nid_postfix(volatile unsigned char*, std::size_t, volatile void*, void*, const void*, int, int); -int APS5_VABI _Atomic_compare_exchange_weak_nid_postfix(volatile unsigned char*, std::size_t, volatile void*, void*, const void*, int, int); -std::uint8_t APS5_VABI __atomic_load_1_nid_postfix(const volatile std::uint8_t*, int); -std::uint64_t APS5_VABI __atomic_load_8_nid_postfix(const volatile std::uint64_t*, int); -void APS5_VABI __atomic_store_2_nid_postfix(volatile std::uint16_t*, std::uint16_t, int); -void APS5_VABI __atomic_store_8_nid_postfix(volatile std::uint64_t*, std::uint64_t, int); -std::uint32_t APS5_VABI __atomic_exchange_4_nid_postfix(volatile std::uint32_t*, std::uint32_t, int); -int APS5_VABI __atomic_compare_exchange_1_nid_postfix(volatile std::uint8_t*, std::uint8_t*, std::uint8_t, int, int); -int APS5_VABI __atomic_compare_exchange_8_nid_postfix(volatile std::uint64_t*, std::uint64_t*, std::uint64_t, int, int); -std::uint16_t APS5_VABI __atomic_fetch_add_2_nid_postfix(volatile std::uint16_t*, std::uint16_t, int); -std::uint64_t APS5_VABI __atomic_exchange_8_nid_postfix(volatile std::uint64_t*, std::uint64_t, int); -std::uint64_t APS5_VABI __atomic_fetch_add_8_nid_postfix(volatile std::uint64_t*, std::uint64_t, int); -std::uint32_t APS5_VABI __atomic_fetch_sub_4_nid_postfix(volatile std::uint32_t*, std::uint32_t, int); -std::uint8_t APS5_VABI __atomic_fetch_and_1_nid_postfix(volatile std::uint8_t*, std::uint8_t, int); -std::uint16_t APS5_VABI __atomic_fetch_or_2_nid_postfix(volatile std::uint16_t*, std::uint16_t, int); -std::uint64_t APS5_VABI __atomic_fetch_xor_8_nid_postfix(volatile std::uint64_t*, std::uint64_t, int); -} - static void Require(bool value) { if (!value) std::abort(); } constexpr int Relaxed = 0, Acquire = 2, Release = 3, AcqRel = 4, SeqCst = 5; @@ -52,6 +13,7 @@ constexpr int Relaxed = 0, Acquire = 2, Release = 3, AcqRel = 4, SeqCst = 5; static void CheckTyped() { std::uint8_t byte = 0; _Atomic_store_1_nid_postfix(&byte, 7, SeqCst); + Require(byte == 7 && _Atomic_fetch_add_1_nid_postfix(&byte, 250, Relaxed) == 7 && byte == 1); Require(_Atomic_fetch_or_1_nid_postfix(&byte, 0x80, AcqRel) == 1 && byte == 0x81); std::uint16_t half = 5; @@ -64,6 +26,7 @@ static void CheckTyped() { Require(_Atomic_exchange_4_nid_postfix(&word, 9, 6) == 0xf00f && word == 9); std::uint64_t wide = 0; _Atomic_store_8_nid_postfix(&wide, 0x123456789ull, Release); + Require(_Atomic_load_8_nid_postfix(&wide, Acquire) == 0x123456789ull); Require(_Atomic_load_8_nid_postfix(&wide, Release) == 0 && _Atomic_load_8_nid_postfix(&wide, AcqRel) == 0); Require(_Atomic_fetch_add_8_nid_postfix(&wide, 1, SeqCst) == 0x123456789ull && wide == 0x12345678aull); @@ -80,9 +43,11 @@ static void CheckFlagsAndFences() { Require(_Atomic_flag_test_and_set_nid_postfix(&flag, SeqCst) == 0 && flag == 1); Require(_Atomic_flag_test_and_set_nid_postfix(&flag, Relaxed) == 1); _Atomic_flag_clear_nid_postfix(&flag, Release); + Require(flag == 0); _Atomic_thread_fence_nid_postfix(SeqCst); _Atomic_signal_fence_nid_postfix(SeqCst); + } struct Wide { @@ -93,9 +58,11 @@ static void CheckGeneric() { unsigned char lock = 0; Wide target{{1, 2, 3}}, source{{4, 5, 6}}, expected{{1, 2, 3}}; _Atomic_copy_nid_postfix(&lock, sizeof(Wide), &target, &source, SeqCst); + Require(std::memcmp(&target, &source, sizeof(Wide)) == 0 && lock == 0); Wide other{{7, 8, 9}}; _Atomic_exchange_nid_postfix(&lock, sizeof(Wide), &target, &other, SeqCst); + Require(target.parts[0] == 7 && other.parts[0] == 4 && lock == 0); const Wide desired{{10, 11, 12}}; Require(_Atomic_compare_exchange_strong_nid_postfix(&lock, sizeof(Wide), &target, &expected, &desired, SeqCst, SeqCst) == 0); @@ -112,6 +79,7 @@ static void CheckConcurrentGeneric() { for (int i = 0; i < Iterations; ++i) { Wide expected; _Atomic_copy_nid_postfix(&lock, sizeof(Wide), &expected, &counter, SeqCst); + Wide next; do { next = Wide{{expected.parts[0] + 1, expected.parts[1] + 2, expected.parts[2] + 3}}; diff --git a/core/libs/tests/GuestDinkumwareInternals.cpp b/core/libs/tests/GuestDinkumwareInternals.cpp index 563d08d8cc..0ff64c7371 100644 --- a/core/libs/tests/GuestDinkumwareInternals.cpp +++ b/core/libs/tests/GuestDinkumwareInternals.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -6,26 +7,6 @@ #include #include -extern "C" { -int* APS5_VABI __error_nid_postfix(); -double APS5_VABI _Stod_nid_postfix(const char* text, char** end, std::int64_t pten); -long long APS5_VABI _Stoll_nid_postfix(const char* text, char** end, int base); -double APS5_VABI _Stodx_nid_postfix(const char* text, char** end, std::int64_t pten, int* error); -float APS5_VABI _Stofx_nid_postfix(const char* text, char** end, std::int64_t pten, int* error); -long double APS5_VABI _Stoldx_nid_postfix(const char* text, char** end, std::int64_t pten, int* error); -float APS5_VABI _Stof_nid_postfix(const char* text, char** end, std::int64_t pten); -long double APS5_VABI _Stold_nid_postfix(const char* text, char** end, std::int64_t pten); -long long APS5_VABI _Stollx_nid_postfix(const char* text, char** end, int base, int* error); -std::int64_t APS5_VABI _Stolx_nid_postfix(const char* text, char** end, int base, int* error); -std::uint64_t APS5_VABI _Stoulx_nid_postfix(const char* text, char** end, int base, int* error); -unsigned long long APS5_VABI _Stoullx_nid_postfix(const char* text, char** end, int base, int* error); -double APS5_VABI _Sin_nid_postfix(double x, unsigned int quadrant); -float APS5_VABI _FSin_nid_postfix(float x, unsigned int quadrant); -long double APS5_VABI _LSin_nid_postfix(long double x, unsigned int quadrant); -double APS5_VABI _Log_nid_postfix(double x, int base); -float APS5_VABI _FLog_nid_postfix(float x, int base); -} - namespace { constexpr int RangeError = 34; @@ -82,6 +63,30 @@ void TestStoll() { Require(_Stoll_nid_postfix("9223372036854775808", &end, 10) == 9223372036854775807ll && *__error_nid_postfix() == RangeError, "_Stoll saturates"); } +void TestArithmetic() { + Require(_Divide_nid_postfix(3.0, 2.0) == 1.5, "_Divide quotient"); + Require(std::isinf(_Divide_nid_postfix(1.0, 0.0)) && !std::signbit(_Divide_nid_postfix(1.0, 0.0)), "_Divide positive infinity"); + Require(std::isinf(_Divide_nid_postfix(-1.0, 0.0)) && std::signbit(_Divide_nid_postfix(-1.0, 0.0)), "_Divide negative infinity"); + Require(std::isnan(_Divide_nid_postfix(0.0, 0.0)), "_Divide invalid"); + Require(_Divide_nid_postfix(-0.0, 2.0) == 0.0 && std::signbit(_Divide_nid_postfix(-0.0, 2.0)), "_Divide signed zero"); + Require(_Divide_nid_postfix(1.0, INFINITY) == 0.0 && !std::signbit(_Divide_nid_postfix(1.0, INFINITY)), "_Divide finite by infinity"); + Require(std::isnan(_Divide_nid_postfix(INFINITY, INFINITY)), "_Divide infinity by infinity"); + Require(_Recip_nid_postfix(4.0) == 0.25, "_Recip quotient"); + Require(_Recip_nid_postfix(-4.0) == -0.25, "_Recip negative quotient"); + Require(std::isinf(_Recip_nid_postfix(-0.0)) && std::signbit(_Recip_nid_postfix(-0.0)), "_Recip signed infinity"); + Require(_Recip_nid_postfix(INFINITY) == 0.0 && !std::signbit(_Recip_nid_postfix(INFINITY)), "_Recip infinity"); + Require(std::isnan(_Recip_nid_postfix(NAN)), "_Recip NaN"); + Require(_FDivide_nid_postfix(3.0f, 2.0f) == 1.5f, "_FDivide quotient"); + Require(std::isinf(_FDivide_nid_postfix(-1.0f, 0.0f)) && std::signbit(_FDivide_nid_postfix(-1.0f, 0.0f)), "_FDivide negative infinity"); + Require(std::isnan(_FDivide_nid_postfix(0.0f, 0.0f)), "_FDivide invalid"); + Require(_FDivide_nid_postfix(-0.0f, 2.0f) == 0.0f && std::signbit(_FDivide_nid_postfix(-0.0f, 2.0f)), "_FDivide signed zero"); + Require(_FRecip_nid_postfix(4.0f) == 0.25f, "_FRecip quotient"); + Require(_FRecip_nid_postfix(-4.0f) == -0.25f, "_FRecip negative quotient"); + Require(std::isinf(_FRecip_nid_postfix(-0.0f)) && std::signbit(_FRecip_nid_postfix(-0.0f)), "_FRecip signed infinity"); + Require(_FRecip_nid_postfix(INFINITY) == 0.0f && !std::signbit(_FRecip_nid_postfix(INFINITY)), "_FRecip infinity"); + Require(std::isnan(_FRecip_nid_postfix(NAN)), "_FRecip NaN"); +} + void TestFloatErrors() { char* end = nullptr; int error = 99; @@ -185,6 +190,17 @@ void TestDispatch() { Require(_FLog_nid_postfix(8.0f, 0) == std::log(8.0f) && _FLog_nid_postfix(100.0f, 1) == 2.0f && _FLog_nid_postfix(8.0f, -3) == 3.0f, "_FLog"); } +void TestLongDoubleHelpers() { + Require(_LDivide_nid_postfix(3.0L, 2.0L) == 1.5L, "_LDivide quotient"); + Require(std::isinf(_LDivide_nid_postfix(1.0L, 0.0L)), "_LDivide infinity"); + Require(std::isnan(_LDivide_nid_postfix(0.0L, 0.0L)), "_LDivide invalid"); + Require(_LRecip_nid_postfix(4.0L) == 0.25L, "_LRecip quotient"); + Require(std::isinf(_LRecip_nid_postfix(-0.0L)) && std::signbit(_LRecip_nid_postfix(-0.0L)), "_LRecip signed infinity"); + Require(_LLog_nid_postfix(8.0L, 0) == std::log(8.0L), "_LLog natural"); + Require(std::fabs(_LLog_nid_postfix(1000.0L, 1) - 3.0L) <= 1e-17L && std::fabs(_LLog_nid_postfix(1000.0L, 5) - 3.0L) <= 1e-17L, "_LLog base 10"); + Require(_LLog_nid_postfix(8.0L, -1) == 3.0L && _LLog_nid_postfix(8.0L, -3) == 3.0L, "_LLog base 2"); +} + } int main() { @@ -192,5 +208,7 @@ int main() { TestStoll(); TestFloatErrors(); TestIntegerErrors(); + TestArithmetic(); TestDispatch(); + TestLongDoubleHelpers(); } diff --git a/core/libs/tests/GuestDirectory.cpp b/core/libs/tests/GuestDirectory.cpp index 4df4394622..f5646097dc 100644 --- a/core/libs/tests/GuestDirectory.cpp +++ b/core/libs/tests/GuestDirectory.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/GuestDirectory.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "SceTypes.hpp" @@ -15,21 +17,12 @@ #ifdef _WIN32 #include #endif -extern "C" { -void* APS5_VABI opendir_nid_postfix(const char*); -GuestDirectoryEntry* APS5_VABI readdir_nid_postfix(void*); -int APS5_VABI readdir_r_nid_postfix(void*, GuestDirectoryEntry*, GuestDirectoryEntry**); -int APS5_VABI closedir_nid_postfix(void*); -void APS5_VABI rewinddir_nid_postfix(void*); -std::int64_t APS5_VABI telldir_nid_postfix(void*); -void APS5_VABI seekdir_nid_postfix(void*, std::int64_t); -int* APS5_VABI __error_nid_postfix(); -int APS5_VABI lstat_nid_postfix(const char*, FileStat*); -} + static void Require(bool value) { if (!value) std::abort(); } static std::map ReadFileNumbers(void* directory) { std::map numbers; rewinddir_nid_postfix(directory); + while (auto* entry = readdir_nid_postfix(directory)) { Require(entry->fileNumber != 0); numbers[entry->name] = entry->fileNumber; @@ -105,10 +98,12 @@ int main() { Require(entries.at("subdirectory") == 4); Require(entries.at(".") == 4 && entries.at("..") == 4); rewinddir_nid_postfix(directory); + std::size_t count = 0; while (readdir_nid_postfix(directory)) ++count; Require(count == entries.size()); rewinddir_nid_postfix(directory); + std::map copies; GuestDirectoryEntry buffer; GuestDirectoryEntry* result = nullptr; @@ -129,6 +124,7 @@ int main() { result = &buffer; Require(readdir_r_nid_postfix(directory, &buffer, &result) == 0 && result == nullptr); rewinddir_nid_postfix(directory); + *__error_nid_postfix() = 13; auto* first = readdir_nid_postfix(directory); Require(first != nullptr); @@ -141,6 +137,7 @@ int main() { bool nullEntryThrows = false; try { readdir_r_nid_postfix(directory, nullptr, &result); + } catch (const std::invalid_argument&) { nullEntryThrows = true; } @@ -148,11 +145,13 @@ int main() { bool nullResultThrows = false; try { readdir_r_nid_postfix(directory, &buffer, nullptr); + } catch (const std::invalid_argument&) { nullResultThrows = true; } Require(nullResultThrows); rewinddir_nid_postfix(directory); + Require(readdir_nid_postfix(directory) != nullptr); const std::int64_t second = telldir_nid_postfix(directory); Require(second != -1); @@ -161,6 +160,7 @@ int main() { const std::string secondName = entryAfterTell->name; while (readdir_nid_postfix(directory)) {} seekdir_nid_postfix(directory, second); + auto* entryAfterSeek = readdir_nid_postfix(directory); Require(entryAfterSeek != nullptr && secondName == entryAfterSeek->name); Require(entryAfterSeek->fileNumber == fileNumbers.at(secondName)); @@ -168,6 +168,7 @@ int main() { Require(telldir_nid_postfix(nullptr) == -1 && *__error_nid_postfix() == 9); *__error_nid_postfix() = 0; seekdir_nid_postfix(nullptr, second); + Require(*__error_nid_postfix() == 9); Require(closedir_nid_postfix(directory) == 0); Require(opendir_nid_postfix((root / "missing").string().c_str()) == nullptr); diff --git a/core/libs/tests/GuestDirectoryBuffer.cpp b/core/libs/tests/GuestDirectoryBuffer.cpp index e5d0c6c122..02e2ff0246 100644 --- a/core/libs/tests/GuestDirectoryBuffer.cpp +++ b/core/libs/tests/GuestDirectoryBuffer.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libkernel/File/include/File.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libkernel/File/include/FileFlags.hpp" #include "prx/libkernel/KernelErrors.hpp" @@ -13,18 +15,6 @@ #include #include -extern "C" { -int APS5_VABI sceKernelOpen(const char*, int, std::uint16_t); -int APS5_VABI sceKernelClose(int); -int APS5_VABI sceKernelGetdents(int, char*, int); -int APS5_VABI sceKernelGetdirentries(int, char*, int, std::int64_t*); -int APS5_VABI sceKernelAllocateDirectMemory(std::int64_t, std::int64_t, std::size_t, std::size_t, int, std::int64_t*); -int APS5_VABI sceKernelMapDirectMemory(void**, std::size_t, int, int, std::int64_t, std::size_t); -int APS5_VABI sceKernelMprotect(void*, std::size_t, int); -int APS5_VABI sceKernelMunmap(void*, std::size_t); -int APS5_VABI sceKernelReleaseDirectMemory(std::int64_t, std::size_t); -} - static void Check(bool value, int line) { if (!value) { std::fprintf(stderr, "Directory buffer check failed at line %d\n", line); @@ -88,6 +78,7 @@ static void CheckOversizedName() { bool threw = false; try { sceKernelGetdents(directory, buffer.data(), static_cast(buffer.size())); + } catch (const std::runtime_error&) { threw = true; } @@ -121,7 +112,7 @@ static void CheckReadOnlyDestination() { static_cast(mapping)) == SCE_KERNEL_ERROR_EFAULT); Require(sceKernelMprotect(mapping, page, 3) == 0); Require(sceKernelGetdirentries(directory, buffer.data(), static_cast(buffer.size()), &base) > 0); - Require(sceKernelMunmap(mapping, page) == 0); + Require(sceKernelMunmap(reinterpret_cast(mapping), page) == 0); Require(sceKernelReleaseDirectMemory(physical, page) == 0); Require(sceKernelClose(directory) == 0); std::filesystem::remove_all(root); diff --git a/core/libs/tests/GuestDirectoryClose.cpp b/core/libs/tests/GuestDirectoryClose.cpp index 68d3d60176..5a59797a0e 100644 --- a/core/libs/tests/GuestDirectoryClose.cpp +++ b/core/libs/tests/GuestDirectoryClose.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libkernel/File/include/File.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libkernel/File/include/FileFlags.hpp" @@ -10,13 +12,6 @@ #include #include -extern "C" { -int APS5_VABI sceKernelOpen(const char*, int, std::uint16_t); -int APS5_VABI sceKernelGetdents(int, char*, int); -int APS5_VABI close_nid_postfix(int); -int APS5_VABI _close_nid_postfix(int); -} - static void Check(bool value, int line) { if (!value) { std::fprintf(stderr, "Directory close check failed at line %d\n", line); diff --git a/core/libs/tests/GuestDirectoryEntries.cpp b/core/libs/tests/GuestDirectoryEntries.cpp index 35bf2413c9..91b41aea16 100644 --- a/core/libs/tests/GuestDirectoryEntries.cpp +++ b/core/libs/tests/GuestDirectoryEntries.cpp @@ -1,3 +1,6 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libkernel/File/include/File.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libkernel/File/include/FileFlags.hpp" #include @@ -11,20 +14,6 @@ #include #include -extern "C" { -int APS5_VABI sceKernelOpen(const char*, int, std::uint16_t); -int APS5_VABI sceKernelClose(int); -std::int64_t APS5_VABI sceKernelRead(int, void*, std::size_t); -int APS5_VABI sceKernelLseek(int, std::int64_t, int); -int APS5_VABI sceKernelGetdents(int, char*, int); -int APS5_VABI sceKernelGetdirentries(int, char*, int, std::int64_t*); -int APS5_VABI getdents_nid_postfix(int, char*, int); -int APS5_VABI getdirentries_nid_postfix(int, char*, int, std::int64_t*); -int* APS5_VABI __error_nid_postfix(); -std::int64_t APS5_VABI sceKernelPread(int, void*, std::size_t, std::int64_t); -std::int64_t APS5_VABI sceKernelPwrite(int, const void*, std::size_t, std::int64_t); -} - static void Check(bool value, int line) { if (!value) { std::fprintf(stderr, "Directory entry check failed at line %d\n", line); diff --git a/core/libs/tests/GuestDirectoryLinkTypes.cpp b/core/libs/tests/GuestDirectoryLinkTypes.cpp index 344b0c3a1c..fb9b0f0845 100644 --- a/core/libs/tests/GuestDirectoryLinkTypes.cpp +++ b/core/libs/tests/GuestDirectoryLinkTypes.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libkernel/File/include/File.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libkernel/File/include/FileFlags.hpp" #include @@ -11,12 +13,6 @@ #include #include -extern "C" { -int APS5_VABI sceKernelOpen(const char*, int, std::uint16_t); -int APS5_VABI sceKernelClose(int); -int APS5_VABI sceKernelGetdents(int, char*, int); -} - static void Check(bool value, int line) { if (!value) { std::fprintf(stderr, "Directory link type check failed at line %d\n", line); diff --git a/core/libs/tests/GuestDirectoryRewind.cpp b/core/libs/tests/GuestDirectoryRewind.cpp index 00217b646e..424c5bda23 100644 --- a/core/libs/tests/GuestDirectoryRewind.cpp +++ b/core/libs/tests/GuestDirectoryRewind.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libkernel/File/include/File.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libkernel/File/include/DirectoryDescriptor.hpp" #include "prx/libkernel/File/include/FileFlags.hpp" @@ -14,15 +16,6 @@ #include #include -extern "C" { -int APS5_VABI sceKernelOpen(const char*, int, std::uint16_t); -int APS5_VABI sceKernelClose(int); -int APS5_VABI sceKernelGetdents(int, char*, int); -std::int64_t APS5_VABI sceKernelLseek(int, std::int64_t, int); -int APS5_VABI dup_nid_postfix(int); -int APS5_VABI dup2_nid_postfix(int, int); -} - static void Check(bool value, int line) { if (!value) { std::fprintf(stderr, "Directory rewind check failed at line %d\n", line); @@ -31,7 +24,6 @@ static void Check(bool value, int line) { } #define Require(value) Check((value), __LINE__) - static std::set ReadAll(int directory) { std::set names; std::array buffer{}; diff --git a/core/libs/tests/GuestDiscMap.cpp b/core/libs/tests/GuestDiscMap.cpp index 498dc7c443..7c3811f9a5 100644 --- a/core/libs/tests/GuestDiscMap.cpp +++ b/core/libs/tests/GuestDiscMap.cpp @@ -1,14 +1,10 @@ +#include "prx/libSceDiscMap/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include #include -extern "C" { -std::int32_t APS5_VABI sceDiscMapIsRequestOnHDD(const char* path, std::int64_t offset, std::int64_t size, std::int32_t* result); -std::int32_t APS5_VABI sceDiscMapUnknown_ioKMruft1ek(const char* path, std::int64_t offset, std::int64_t size, std::uint64_t* flags, std::uint64_t* out1, std::uint64_t* out2); -} - namespace { constexpr std::int32_t noBitmapInfo = static_cast(0x81100004); diff --git a/core/libs/tests/GuestDup.cpp b/core/libs/tests/GuestDup.cpp index 9d0029e2ca..03db1dcba6 100644 --- a/core/libs/tests/GuestDup.cpp +++ b/core/libs/tests/GuestDup.cpp @@ -1,25 +1,13 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" +#include #include #include #include #include #include -extern "C" { -int APS5_VABI dup_nid_postfix(int); -int APS5_VABI dup2_nid_postfix(int, int); -int APS5_VABI pipe_nid_postfix(int*); -int APS5_VABI close_nid_postfix(int); -std::int64_t APS5_VABI read_nid_postfix(int, void*, std::uint64_t); -std::int64_t APS5_VABI write_nid_postfix(int, const char*, std::int64_t); -int APS5_VABI socketpair_nid_postfix(int, int, int, int*); -std::int64_t APS5_VABI send_nid_postfix(int, const void*, std::uint64_t, int); -std::int64_t APS5_VABI recv_nid_postfix(int, void*, std::uint64_t, int); -int APS5_VABI open_nid_postfix(const char*, int, int); -int APS5_VABI fcntl_nid_postfix(int, int, ...); -int* APS5_VABI __error_nid_postfix(); -} - static void Require(bool value) { if (!value) std::abort(); } constexpr int GuestEbadf = 9; @@ -200,6 +188,8 @@ static void DuplicatesShareStatusFlags() { Require(pipe_nid_postfix(pipe) == 0); Require(pipe_nid_postfix(other) == 0); Require(fcntl_nid_postfix(pipe[0], SetDescriptorFlags, 1) == 0); + *__error_nid_postfix() = 0; + Require(fcntl_nid_postfix(pipe[0], 0, INT_MAX) == -1 && *__error_nid_postfix() == 22); const int duplicate = dup_nid_postfix(pipe[0]); Require(duplicate >= 0); Require(fcntl_nid_postfix(duplicate, GetDescriptorFlags) == 0); diff --git a/core/libs/tests/GuestDynamicCast.cpp b/core/libs/tests/GuestDynamicCast.cpp index c7892a5e96..5a4212d578 100644 --- a/core/libs/tests/GuestDynamicCast.cpp +++ b/core/libs/tests/GuestDynamicCast.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/exceptions/Runtime.hpp" #include #include @@ -11,8 +12,7 @@ struct Object { const void* vtable; }; extern "C" { extern const unsigned char _ZTVN10__cxxabiv117__class_type_infoE_nid_postfix[]; extern const unsigned char _ZTVN10__cxxabiv120__si_class_type_infoE_nid_postfix[]; -void* APS5_VABI __dynamic_cast_nid_postfix(const void*, const void*, const void*, std::ptrdiff_t); -LibcException::Header* APS5_VABI __cxa_init_primary_exception_nid_postfix(void*, std::type_info*, void (*)(void*)); + } namespace { @@ -32,14 +32,15 @@ const Vtable DerivedVtable{0, &DerivedType, nullptr}; int main() { const Object derived{&DerivedVtable.first}; const Object base{&BaseVtable.first}; - Require(__dynamic_cast_nid_postfix(&derived, &BaseType, &DerivedType, 0) == &derived); - Require(__dynamic_cast_nid_postfix(&derived, &BaseType, &OtherType, 0) == nullptr); - Require(__dynamic_cast_nid_postfix(&base, &BaseType, &DerivedType, 0) == nullptr); - Require(__dynamic_cast_nid_postfix(nullptr, &BaseType, &DerivedType, 0) == nullptr); + Require(__dynamic_cast_nid_postfix(&derived, reinterpret_cast(&BaseType), reinterpret_cast(&DerivedType), 0) == &derived); + Require(__dynamic_cast_nid_postfix(&derived, reinterpret_cast(&BaseType), reinterpret_cast(&OtherType), 0) == nullptr); + Require(__dynamic_cast_nid_postfix(&base, reinterpret_cast(&BaseType), reinterpret_cast(&DerivedType), 0) == nullptr); + Require(__dynamic_cast_nid_postfix(nullptr, reinterpret_cast(&BaseType), reinterpret_cast(&DerivedType), 0) == nullptr); void* object = __cxa_allocate_exception_nid_postfix(16); auto* type = reinterpret_cast(const_cast(&DerivedType)); LibcException::Header* header = __cxa_init_primary_exception_nid_postfix(object, type, Destroy); Require(header == LibcException::FromObject(object)); Require(header->type == type && header->destructor == Destroy && header->adjusted == object); __cxa_free_exception_nid_postfix(object); + } diff --git a/core/libs/tests/GuestDynamicLoader.cpp b/core/libs/tests/GuestDynamicLoader.cpp index 1307264c64..b3e9d0b4e9 100644 --- a/core/libs/tests/GuestDynamicLoader.cpp +++ b/core/libs/tests/GuestDynamicLoader.cpp @@ -1,3 +1,4 @@ +#include "prx/libkernel/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -17,17 +18,7 @@ #include #include #include -extern "C" { -int APS5_VABI sceKernelDlsym(std::int32_t, const char*, void**); -void* APS5_VABI dlopen_nid_postfix(const char*, int); -void* APS5_VABI dlsym_nid_postfix(void*, const char*); -int APS5_VABI dlclose_nid_postfix(void*); -char* APS5_VABI dlerror_nid_postfix(); -int APS5_VABI _sceKernelRtldThreadAtexitIncrement_nid_postfix(const void*); -int APS5_VABI _sceKernelRtldThreadAtexitDecrement_nid_postfix(const void*); -int APS5_VABI sceKernelLoadStartModule(const char*, std::size_t, const void*, unsigned, const void*, int*); -int APS5_VABI sceKernelStopUnloadModule(int, std::size_t, const void*, unsigned, const void*, int*); -} + static void Require(bool value, const std::source_location& location = std::source_location::current()) { if (value) return; std::fprintf(stderr, "guest_dynamic_loader: failed at %s:%u\n", location.file_name(), location.line()); @@ -115,6 +106,7 @@ static bool CheckGlobalVisibility(const char* path, bool globalFirst) { std::fprintf(stderr, "RTLD_GLOBAL lost after closing its handle: global_first=%d scope=%s; surviving handle returns %d\n", globalFirst, scope == nullptr ? "NULL" : "-2", add(20, 22)); dlerror_nid_postfix(); + visible = false; } } @@ -146,6 +138,7 @@ int main(int argc, char** argv) { Require(reinterpret_cast(mainSymbol)(6, 7) == 42); Require(sceKernelDlsym(0, "anyps5_missing_main_symbol", &mainSymbol) == static_cast(0x80020003u)); dlerror_nid_postfix(); + void* executable = dlopen_nid_postfix(nullptr, 2); Require(executable != nullptr && dlclose_nid_postfix(executable) == 0); #ifdef _WIN32 diff --git a/core/libs/tests/GuestDynamicLoaderVariants.cpp b/core/libs/tests/GuestDynamicLoaderVariants.cpp index 5dd0f764b8..adeb771494 100644 --- a/core/libs/tests/GuestDynamicLoaderVariants.cpp +++ b/core/libs/tests/GuestDynamicLoaderVariants.cpp @@ -1,12 +1,9 @@ +#include "prx/libkernel/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include #include -extern "C" { -void* APS5_VABI dlopen_nid_postfix(const char*, int); -void* APS5_VABI dlsym_nid_postfix(void*, const char*); -int APS5_VABI dlclose_nid_postfix(void*); -} + static void Require(bool value, const std::source_location& location = std::source_location::current()) { if (value) return; std::fprintf(stderr, "guest_dynamic_loader_variants: failed at %s:%u\n", location.file_name(), location.line()); diff --git a/core/libs/tests/GuestElfPhdrMatch.cpp b/core/libs/tests/GuestElfPhdrMatch.cpp index 3e8d585a70..4d0797a548 100644 --- a/core/libs/tests/GuestElfPhdrMatch.cpp +++ b/core/libs/tests/GuestElfPhdrMatch.cpp @@ -1,3 +1,4 @@ +#include "prx/libkernel/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libc/include/specifics/linux/ElfTypes.hpp" #include "SceTypes.hpp" @@ -5,10 +6,6 @@ #include #include -extern "C" { -int APS5_VABI __elf_phdr_match_addr_nid_postfix(dl_phdr_info*, void*); -} - static void Require(bool condition) { if (!condition) std::abort(); } diff --git a/core/libs/tests/GuestEntitlements.cpp b/core/libs/tests/GuestEntitlements.cpp index 46da7dd6b4..6960f9b349 100644 --- a/core/libs/tests/GuestEntitlements.cpp +++ b/core/libs/tests/GuestEntitlements.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNpEntitlementAccess/include/Api.hpp" #include "SceTypes.hpp" #include @@ -11,15 +12,6 @@ #include #include -extern "C" { -int APS5_VABI sceNpEntitlementAccessGetAddcontEntitlementInfo(std::uint32_t, const NpUnifiedEntitlementLabel*, NpEntitlementAccessAddcontEntitlementInfo*); -int APS5_VABI sceNpEntitlementAccessGetAddcontEntitlementInfoList(std::uint32_t, NpEntitlementAccessAddcontEntitlementInfo*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceNpEntitlementAccessGetSkuFlag(std::uint32_t*); -int APS5_VABI sceNpEntitlementAccessGetPftFlag(std::uint32_t*); -int APS5_VABI sceNpEntitlementAccessGetGameTrialsFlag(std::uint32_t*); -int APS5_VABI sceNpEntitlementAccessGenerateTransactionId(void*); -} - static void Require(bool value) { if (!value) std::abort(); } static void SetEntitlements(const std::filesystem::path& file) { @@ -50,6 +42,7 @@ int main(int argc, char** argv) { bool rejected = false; try { sceNpEntitlementAccessGetAddcontEntitlementInfoList(0, nullptr, 0, &hits); + } catch (const std::runtime_error& error) { rejected = std::string_view(error.what()).starts_with("NpEntitlementAccess: cannot read "); } diff --git a/core/libs/tests/GuestEnvironment.cpp b/core/libs/tests/GuestEnvironment.cpp index 46e2b2b11b..aab45e4742 100644 --- a/core/libs/tests/GuestEnvironment.cpp +++ b/core/libs/tests/GuestEnvironment.cpp @@ -1,14 +1,9 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include #include -extern "C" { -char* APS5_VABI getenv_nid_postfix(const char*); -int APS5_VABI setenv_nid_postfix(const char*, const char*, int); -int APS5_VABI unsetenv_nid_postfix(const char*); -int APS5_VABI putenv_nid_postfix(char*); -int* APS5_VABI __error_nid_postfix(); -} + static void Require(bool value) { if (!value) std::abort(); } int main() { const char* key = "ANYPS5_GUEST_ENV_TEST_4C27"; diff --git a/core/libs/tests/GuestEqueueEvents.cpp b/core/libs/tests/GuestEqueueEvents.cpp index 9a6a6dee78..1a990f8c23 100644 --- a/core/libs/tests/GuestEqueueEvents.cpp +++ b/core/libs/tests/GuestEqueueEvents.cpp @@ -1,3 +1,6 @@ +#include "prx/libkernel/KernelErrors.hpp" +#include "prx/libkernel/include/Api.hpp" +#include "prx/libkernel/Equeue/Equeue.hpp" #include "SceTypes.hpp" #include #include @@ -6,38 +9,7 @@ #include #include -extern "C" { -int APS5_VABI sceKernelCreateEqueue(KernelEqueue* eq, const char* name); -int APS5_VABI sceKernelDeleteEqueue(KernelEqueue eq); -int APS5_VABI sceKernelWaitEqueue(KernelEqueue eq, KernelEvent* ev, int num, int* out, const KernelUseconds* timo); -int APS5_VABI sceKernelAddUserEvent(KernelEqueue eq, int id); -int APS5_VABI sceKernelAddUserEventEdge(KernelEqueue eq, int id); -int APS5_VABI sceKernelTriggerUserEvent(KernelEqueue eq, int id, void* udata); -int APS5_VABI sceKernelDeleteUserEvent(KernelEqueue eq, int id); -int APS5_VABI sceKernelAddAmprEvent(KernelEqueue eq, int id, void* udata); -int APS5_VABI sceKernelDeleteAmprEvent(KernelEqueue eq, int id); -int APS5_VABI EqueueTriggerEvent_nid_postfix(KernelEqueue eq, uintptr_t ident, int16_t filter, void* triggerData); -int APS5_VABI sceKernelAddHRTimerEvent(KernelEqueue eq, int id, const KernelTimespec* ts, void* udata); -int APS5_VABI sceKernelAddTimerEvent(KernelEqueue eq, int id, KernelUseconds usec, void* udata); -int APS5_VABI sceKernelDeleteTimerEvent(KernelEqueue eq, int id); -intptr_t APS5_VABI sceKernelGetEventData(const KernelEvent* ev); -int APS5_VABI sceKernelGetEventError(const KernelEvent* ev); -intptr_t APS5_VABI sceKernelGetEventFflags(const KernelEvent* ev); -int APS5_VABI sceKernelGetEventFilter(const KernelEvent* ev); -uintptr_t APS5_VABI sceKernelGetEventId(const KernelEvent* ev); -void* APS5_VABI sceKernelGetEventUserData(const KernelEvent* ev); -} - static constexpr int SCE_OK = 0; -static constexpr int SCE_KERNEL_ERROR_ENOENT = static_cast(0x80020002); -static constexpr int SCE_KERNEL_ERROR_EBADF = static_cast(0x80020009); -static constexpr int SCE_KERNEL_ERROR_ETIMEDOUT = static_cast(0x8002003c); -static constexpr int EVFILT_TIMER = -7; -static constexpr int EVFILT_USER = -11; -static constexpr int EVFILT_HRTIMER = -15; -static constexpr int EVFILT_AMPR = -25; -static constexpr std::uint16_t EV_ERROR = 0x4000; -static constexpr std::uint16_t EV_EOF = 0x8000; static void Require(bool value) { if (!value) std::abort(); } @@ -54,6 +26,7 @@ static bool RejectsNull(TResult (APS5_VABI *accessor)(const KernelEvent*)) { static bool RejectsWideFflags(const KernelEvent* ev) { try { sceKernelGetEventError(ev); + } catch (const std::runtime_error&) { return true; } diff --git a/core/libs/tests/GuestErr.cpp b/core/libs/tests/GuestErr.cpp index 14c8772bc2..570a1c1d85 100644 --- a/core/libs/tests/GuestErr.cpp +++ b/core/libs/tests/GuestErr.cpp @@ -1,3 +1,5 @@ +#include "prx/libc/include/Api.hpp" +#include "prx/libSceLibcInternal/include/Api.hpp" #include "prx/libc/include/FileStream.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "SceTypes.hpp" @@ -11,29 +13,10 @@ #include #endif -using ErrExit = void (APS5_VABI*)(int); - extern "C" { -void APS5_VABI err_set_file_nid_postfix(FileStream* stream); -void APS5_VABI err_set_exit_nid_postfix(ErrExit function); -void APS5_VABI warn_nid_postfix(const char* format, ...); -void APS5_VABI _warn_nid_postfix(const char* format, ...); -void APS5_VABI warnc_nid_postfix(int code, const char* format, ...); -void APS5_VABI warnx_nid_postfix(const char* format, ...); -[[noreturn]] void APS5_VABI err_nid_postfix(int status, const char* format, ...); -[[noreturn]] void APS5_VABI _err_nid_postfix(int status, const char* format, ...); -[[noreturn]] void APS5_VABI errc_nid_postfix(int status, int code, const char* format, ...); -[[noreturn]] void APS5_VABI errx_nid_postfix(int status, const char* format, ...); -void APS5_VABI vwarn_nid_postfix(const char* format, VaList* args); -void APS5_VABI vwarnc_nid_postfix(int code, const char* format, VaList* args); -void APS5_VABI vwarnx_nid_postfix(const char* format, VaList* args); -[[noreturn]] void APS5_VABI verr_nid_postfix(int status, const char* format, VaList* args); -[[noreturn]] void APS5_VABI verrc_nid_postfix(int status, int code, const char* format, VaList* args); -[[noreturn]] void APS5_VABI verrx_nid_postfix(int status, const char* format, VaList* args); -char* APS5_VABI strerror_nid_postfix(int error); -int* APS5_VABI __error_nid_postfix(); + extern const char* __progname_nid_postfix; -void APS5_VABI psignal_nid_postfix(unsigned int signal, const char* prefix); + extern const char* const sys_signame_nid_postfix[32]; extern const char* const sys_siglist_nid_postfix[32]; } @@ -65,6 +48,7 @@ public: Capture() : stream(std::tmpfile()) { err_set_file_nid_postfix(&stream); } ~Capture() { err_set_file_nid_postfix(nullptr); + stream.Close(); } std::string Take() { @@ -146,18 +130,24 @@ int main() { Capture capture; *__error_nid_postfix() = 2; warn_nid_postfix("open %s", "a.txt"); + Require(capture.Take() == "prog: open a.txt: " + noEntry + "\n", "warn"); *__error_nid_postfix() = 2; warn_nid_postfix(nullptr); + Require(capture.Take() == "prog: " + noEntry + "\n", "warn without format"); *__error_nid_postfix() = 13; _warn_nid_postfix("open %s", "b.txt"); + Require(capture.Take() == "prog: open b.txt: " + denied + "\n", "_warn"); warnc_nid_postfix(13, "%d-%s", 7, "x"); + Require(capture.Take() == "prog: 7-x: " + denied + "\n", "warnc"); warnx_nid_postfix("plain %c", 'q'); + Require(capture.Take() == "prog: plain q\n", "warnx"); warnx_nid_postfix(nullptr); + Require(capture.Take() == "prog: \n", "warnx without format"); err_set_exit_nid_postfix(Hook); @@ -196,6 +186,7 @@ int main() { Require(ExitStatus([] { CallVariant(Variant::Errx, 0, 0, nullptr); }) == 0, "verrx status 0"); Require(capture.Take() == "prog: \n", "verrx without format"); err_set_exit_nid_postfix(nullptr); + } __progname_nid_postfix = savedName; diff --git a/core/libs/tests/GuestErrorDialog.cpp b/core/libs/tests/GuestErrorDialog.cpp index 51779896a1..034eb4e5e0 100644 --- a/core/libs/tests/GuestErrorDialog.cpp +++ b/core/libs/tests/GuestErrorDialog.cpp @@ -1,18 +1,8 @@ +#include "prx/libSceErrorDialog/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include -extern "C" { -int APS5_VABI sceErrorDialogInitialize(void); -int APS5_VABI sceErrorDialogOpen(const void* param); -int APS5_VABI sceErrorDialogUpdateStatus(void); -int APS5_VABI sceErrorDialogGetStatus(void); -int APS5_VABI sceErrorDialogClose(void); -int APS5_VABI sceErrorDialogTerminate(void); -int APS5_VABI sceErrorDialogOpenDetail(void); -int APS5_VABI sceErrorDialogOpenWithReport(void); -} - namespace { void Require(bool value) { if (!value) std::abort(); } diff --git a/core/libs/tests/GuestErrors.cpp b/core/libs/tests/GuestErrors.cpp index 1cf514aaed..1946147d26 100644 --- a/core/libs/tests/GuestErrors.cpp +++ b/core/libs/tests/GuestErrors.cpp @@ -1,3 +1,5 @@ +#include "prx/libc/include/WindowsFormatting.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -5,11 +7,6 @@ #include #include -extern "C" { -char* APS5_VABI strerror_nid_postfix(int); -int APS5_VABI strerror_r_nid_postfix(int, char*, std::size_t); -int* APS5_VABI __error_nid_postfix(); -} static void Require(bool value) { if (!value) std::abort(); } static const char* const freebsd[97] = { "No error: 0", "Operation not permitted", "No such file or directory", diff --git a/core/libs/tests/GuestExceptionHandler.cpp b/core/libs/tests/GuestExceptionHandler.cpp index fbb5dfd8f7..2ad28a7af4 100644 --- a/core/libs/tests/GuestExceptionHandler.cpp +++ b/core/libs/tests/GuestExceptionHandler.cpp @@ -1,15 +1,9 @@ +#include "prx/libkernel/KernelErrors.hpp" +#include "prx/libkernel/include/Api.hpp" #include "SceTypes.hpp" #include #include -extern "C" { -int APS5_VABI sceKernelInstallExceptionHandler(int signum, void* handler); -int APS5_VABI sceKernelRemoveExceptionHandler(int signum); -} - -static constexpr int SCE_KERNEL_ERROR_EINVAL = static_cast(0x80020016); -static constexpr int SCE_KERNEL_ERROR_EAGAIN = static_cast(0x80020023); - static void APS5_VABI Handler(int, void*) {} static void APS5_VABI Other(int, void*) {} diff --git a/core/libs/tests/GuestExecuteOnce.cpp b/core/libs/tests/GuestExecuteOnce.cpp index 327fbe8c32..e58792b37d 100644 --- a/core/libs/tests/GuestExecuteOnce.cpp +++ b/core/libs/tests/GuestExecuteOnce.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -5,7 +6,7 @@ #include using Callback = int (APS5_VABI *)(void*, void*, void**); -extern "C" int APS5_VABI _ZSt13_Execute_onceRSt9once_flagPFiPvS1_PS1_ES1__nid_postfix(int*, Callback, void*); + static int ExecuteOnce(int* flag, Callback callback, void* arg) { return _ZSt13_Execute_onceRSt9once_flagPFiPvS1_PS1_ES1__nid_postfix(flag, callback, arg); } diff --git a/core/libs/tests/GuestExecuteOnceConcurrency.cpp b/core/libs/tests/GuestExecuteOnceConcurrency.cpp index e5fc8f802e..1537ea5887 100644 --- a/core/libs/tests/GuestExecuteOnceConcurrency.cpp +++ b/core/libs/tests/GuestExecuteOnceConcurrency.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -10,10 +11,6 @@ using Callback = int (APS5_VABI *)(void*, void*, void**); using ExecuteFunction = int (APS5_VABI *)(int*, Callback, void*); -extern "C" { -int APS5_VABI _ZSt13_Execute_onceRSt9once_flagPFiPvS1_PS1_ES1__nid_postfix(int*, Callback, void*); -int APS5_VABI std_execute_once_nid_postfix(int*, Callback, void*); -} static void Check(bool value, int line) { if (!value) { diff --git a/core/libs/tests/GuestExecvp.cpp b/core/libs/tests/GuestExecvp.cpp index 24044df2f7..22e67f4d98 100644 --- a/core/libs/tests/GuestExecvp.cpp +++ b/core/libs/tests/GuestExecvp.cpp @@ -1,12 +1,9 @@ +#include "prx/libkernel/include/Api.hpp" #include "prx/libc/include/General.hpp" #include #include #include -extern "C" { -int APS5_VABI execvp_nid_postfix(const char*, char* const*); -int APS5_VABI execv_nid_postfix(const char*, char* const*); -int APS5_VABI execve_nid_postfix(const char*, char* const*, char* const*); -} + template static bool Throws(TCall call, const std::string& message) { try { call(); diff --git a/core/libs/tests/GuestExitOrder.cpp b/core/libs/tests/GuestExitOrder.cpp index 889e6f0f26..af813531ef 100644 --- a/core/libs/tests/GuestExitOrder.cpp +++ b/core/libs/tests/GuestExitOrder.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/Shutdown.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -5,9 +6,6 @@ #include #include -extern "C" int APS5_VABI __cxa_atexit_nid_postfix(void (APS5_VABI *func)(void*), void* arg, void* dsoHandle); -extern "C" int APS5_VABI atexit_nid_postfix(void (APS5_VABI *func)()); - namespace { int events[2]; diff --git a/core/libs/tests/GuestFdopendir.cpp b/core/libs/tests/GuestFdopendir.cpp index 551ad063f0..7dfad311ad 100644 --- a/core/libs/tests/GuestFdopendir.cpp +++ b/core/libs/tests/GuestFdopendir.cpp @@ -1,3 +1,6 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" +#include "prx/libSceLibcInternal/include/Api.hpp" #include "prx/libc/include/GuestDirectory.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libkernel/File/include/File.hpp" @@ -9,16 +12,7 @@ #include #include #include -extern "C" { -void* APS5_VABI fdopendir_nid_postfix(int); -GuestDirectoryEntry* APS5_VABI readdir_nid_postfix(void*); -int APS5_VABI closedir_nid_postfix(void*); -int APS5_VABI open_nid_postfix(const char*, int, int); -int APS5_VABI close_nid_postfix(int); -int APS5_VABI fcntl_nid_postfix(int, int, ...); -std::int64_t APS5_VABI lseek_nid_postfix(int, std::int64_t, int); -int* APS5_VABI __error_nid_postfix(); -} + static void Require(bool value) { if (!value) std::abort(); } int main() { const auto root = std::filesystem::path("anyps5-fdopendir-test-" + diff --git a/core/libs/tests/GuestFileLock.cpp b/core/libs/tests/GuestFileLock.cpp index 16766fef4e..26dd7afae8 100644 --- a/core/libs/tests/GuestFileLock.cpp +++ b/core/libs/tests/GuestFileLock.cpp @@ -1,3 +1,6 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libkernel/File/include/File.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -12,25 +15,6 @@ class FileStream; -extern "C" { -int APS5_VABI open_nid_postfix(const char*, int, int); -int APS5_VABI close_nid_postfix(int); -int APS5_VABI sceKernelClose(int); -int APS5_VABI dup_nid_postfix(int); -int APS5_VABI dup2_nid_postfix(int, int); -int APS5_VABI fcntl_nid_postfix(int, int, ...); -int APS5_VABI flock_nid_postfix(int, int); -std::int64_t APS5_VABI sceKernelWrite(int, const void*, std::size_t); -std::int64_t APS5_VABI sceKernelPread(int, void*, std::size_t, std::int64_t); -std::int64_t APS5_VABI sceKernelPwrite(int, const void*, std::size_t, std::int64_t); -int* APS5_VABI __error_nid_postfix(); -FileStream* APS5_VABI fopen_nid_postfix(const char*, const char*); -FileStream* APS5_VABI fdopen_nid_postfix(int, const char*); -FileStream* APS5_VABI freopen_nid_postfix(const char*, const char*, FileStream*); -int APS5_VABI fclose_nid_postfix(FileStream*); -int APS5_VABI fileno_nid_postfix(FileStream*); -} - static void Require(bool condition) { if (!condition) std::abort(); } diff --git a/core/libs/tests/GuestFileTimestamps.cpp b/core/libs/tests/GuestFileTimestamps.cpp index ec6ac22fe7..983915404c 100644 --- a/core/libs/tests/GuestFileTimestamps.cpp +++ b/core/libs/tests/GuestFileTimestamps.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "SceTypes.hpp" #include #include @@ -10,23 +12,6 @@ #include #endif -extern "C" { -int APS5_VABI utimes_nid_postfix(const char*, const KernelTimeval*); -int APS5_VABI lutimes_nid_postfix(const char*, const KernelTimeval*); -int APS5_VABI futimes_nid_postfix(int, const KernelTimeval*); -int APS5_VABI sceKernelFutimes(int, const KernelTimeval*); -int APS5_VABI sceKernelUtimes_nid_postfix(const char*, const KernelTimeval*); -int APS5_VABI stat_nid_postfix(const char*, FileStat*); -int APS5_VABI lstat_nid_postfix(const char*, FileStat*); -int APS5_VABI sceKernelFstat(int, FileStat*); -std::int64_t APS5_VABI fstat_nid_disambig1_nid_postfix(int, FileStat*); -std::int64_t APS5_VABI _fstat_nid_postfix(int, FileStat*); -int APS5_VABI open_nid_postfix(const char*, int, int); -int APS5_VABI close_nid_postfix(int); -int APS5_VABI pipe_nid_postfix(int*); -int* APS5_VABI __error_nid_postfix(); -} - static void Require(bool value, const char* message) { if (!value) { std::fprintf(stderr, "%s (guest errno %d)\n", message, *__error_nid_postfix()); @@ -61,7 +46,6 @@ static void CheckTimes(const std::string& path, int fd, const KernelTimeval* exp #endif } - #ifdef _WIN32 static std::uint64_t Ticks(const FILETIME& time) { return (static_cast(time.dwHighDateTime) << 32) | time.dwLowDateTime; diff --git a/core/libs/tests/GuestFileVector.cpp b/core/libs/tests/GuestFileVector.cpp index e9e7b46880..72e398204c 100644 --- a/core/libs/tests/GuestFileVector.cpp +++ b/core/libs/tests/GuestFileVector.cpp @@ -1,3 +1,6 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libkernel/File/include/File.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libkernel/File/include/FileFlags.hpp" #include @@ -26,37 +29,6 @@ static int MakePipe(int* ends) { return ::pipe(ends); } static int ClosePipe(int end) { return ::close(end); } #endif -struct GuestIovec { - void* base; - std::size_t length; -}; - -extern "C" { -int APS5_VABI sceKernelOpen(const char*, int, std::uint16_t); -int APS5_VABI sceKernelClose(int); -int APS5_VABI dup_nid_postfix(int); -std::int64_t APS5_VABI sceKernelRead(int, void*, std::size_t); -std::int64_t APS5_VABI sceKernelPread(int, void*, std::size_t, std::int64_t); -int APS5_VABI sceKernelLseek(int, std::int64_t, int); -std::int64_t APS5_VABI sceKernelReadv(int, const GuestIovec*, int); -std::int64_t APS5_VABI readv_nid_postfix(int, const GuestIovec*, int); -std::int64_t APS5_VABI writev_nid_postfix(int, const GuestIovec*, int); -std::int64_t APS5_VABI _readv_nid_postfix(int, const GuestIovec*, int); -std::int64_t APS5_VABI _writev_nid_postfix(int, const GuestIovec*, int); -int* APS5_VABI __error_nid_postfix(); -std::int64_t APS5_VABI sceKernelWritev(int, const GuestIovec*, int); -std::int64_t APS5_VABI sceKernelPreadv(int, const GuestIovec*, int, std::int64_t); -std::int64_t APS5_VABI sceKernelPwritev(int, const GuestIovec*, int, std::int64_t); -std::int64_t APS5_VABI preadv_nid_postfix(int, const GuestIovec*, int, std::int64_t); -std::int64_t APS5_VABI pwritev_nid_postfix(int, const GuestIovec*, int, std::int64_t); -int* APS5_VABI __error_nid_postfix(); -std::int64_t APS5_VABI sceKernelPread(int, void*, std::size_t, std::int64_t); -std::int64_t APS5_VABI sceKernelPwrite(int, const void*, std::size_t, std::int64_t); -std::int64_t APS5_VABI pread_nid_postfix(int, void*, std::size_t, std::int64_t); -std::int64_t APS5_VABI pwrite_nid_disambig1_nid_postfix(int, const void*, std::size_t, std::int64_t); -int APS5_VABI sceKernelFtruncate(int, std::int64_t); -} - static void Check(bool value, int line) { if (!value) { std::fprintf(stderr, "File vector check failed at line %d\n", line); @@ -94,13 +66,14 @@ static void ConcurrentRecords(const std::filesystem::path& path) { for (std::size_t worker = 0; worker < Workers; ++worker) { writers[worker] = std::thread([&, worker] { std::uint16_t label = 0; - std::array pieces; + std::array pieces; pieces.fill({&label, sizeof(label)}); start.arrive_and_wait(); for (std::size_t record = 0; record < Records; ++record) { label = static_cast(worker * Records + record); const auto written = worker % 2 == 0 ? sceKernelWritev(descriptors[worker], pieces.data(), static_cast(pieces.size())) : writev_nid_postfix(descriptors[worker], pieces.data(), static_cast(pieces.size())); + Require(written == RecordBytes); } }); @@ -126,12 +99,13 @@ static void ConcurrentRecords(const std::filesystem::path& path) { for (std::size_t worker = 0; worker < Workers; ++worker) { readers[worker] = std::thread([&, worker] { std::array record{}; - std::array pieces; + std::array pieces; for (std::size_t part = 0; part < Parts; ++part) pieces[part] = {&record[part], sizeof(record[part])}; start.arrive_and_wait(); for (;;) { const auto read = worker % 2 == 0 ? sceKernelReadv(descriptors[worker], pieces.data(), static_cast(pieces.size())) : readv_nid_postfix(descriptors[worker], pieces.data(), static_cast(pieces.size())); + if (read == 0) break; Require(read == RecordBytes); for (const auto label : record) Require(label == record[0]); @@ -152,7 +126,7 @@ static void ConcurrentRecords(const std::filesystem::path& path) { for (std::size_t worker = 0; worker < Workers; ++worker) { positioned[worker] = std::thread([&, worker] { std::array record{}; - std::array pieces; + std::array pieces; for (std::size_t part = 0; part < Parts; ++part) pieces[part] = {&record[part], sizeof(record[part])}; start.arrive_and_wait(); for (std::size_t iteration = 0; iteration < Records; ++iteration) { @@ -161,9 +135,11 @@ static void ConcurrentRecords(const std::filesystem::path& path) { record.fill(static_cast(0x8000 + worker * Records + iteration)); transferred = worker == 0 ? sceKernelPwritev(descriptors[worker], pieces.data(), static_cast(pieces.size()), 0) : pwritev_nid_postfix(descriptors[worker], pieces.data(), static_cast(pieces.size()), 0); + } else { transferred = worker == 1 ? sceKernelPreadv(descriptors[worker], pieces.data(), static_cast(pieces.size()), 0) : preadv_nid_postfix(descriptors[worker], pieces.data(), static_cast(pieces.size()), 0); + for (const auto label : record) Require(label == record[0]); } Require(transferred == RecordBytes); @@ -189,7 +165,7 @@ int main() { char first[3] = {}; char second[4] = {}; - GuestIovec reads[2] = {{first, sizeof(first)}, {second, sizeof(second)}}; + KernelIovec reads[2] = {{first, sizeof(first)}, {second, sizeof(second)}}; Require(sceKernelReadv(file, reads, 2) == 7); Require(std::memcmp(first, "012", 3) == 0 && std::memcmp(second, "3456", 4) == 0); Require(sceKernelLseek(file, 0, 1) == 7); @@ -215,7 +191,7 @@ int main() { char ab[] = "AB"; char cde[] = "CDE"; - GuestIovec writes[2] = {{ab, 2}, {cde, 3}}; + KernelIovec writes[2] = {{ab, 2}, {cde, 3}}; Require(sceKernelPwritev(file, writes, 2, 2) == 5); Require(sceKernelLseek(file, 0, 1) == 10); Require(Contents(path) == "01ABCDE789"); @@ -223,7 +199,7 @@ int main() { Require(sceKernelWritev(file, writes, 2) == 5); Require(sceKernelLseek(file, 0, 1) == 13); Require(Contents(path) == "01ABCDE7ABCDE"); - GuestIovec swapped[2] = {{cde, 3}, {ab, 2}}; + KernelIovec swapped[2] = {{cde, 3}, {ab, 2}}; Require(sceKernelLseek(file, 8, 0) == 8 && writev_nid_postfix(file, swapped, 2) == 5); Require(sceKernelLseek(file, 0, 1) == 13 && Contents(path) == "01ABCDE7CDEAB"); Require(sceKernelLseek(file, 8, 0) == 8 && writev_nid_postfix(file, writes, 2) == 5); @@ -232,7 +208,7 @@ int main() { Require(sceKernelLseek(file, 0, 1) == 13 && Contents(path) == "01ABCDE7CDEAB"); Require(sceKernelLseek(file, 8, 0) == 8 && writev_nid_postfix(file, writes, 2) == 5); - GuestIovec gapped[3] = {{first, 2}, {nullptr, 0}, {second, 3}}; + KernelIovec gapped[3] = {{first, 2}, {nullptr, 0}, {second, 3}}; Require(sceKernelPreadv(file, gapped, 3, 0) == 5); Require(std::memcmp(first, "01", 2) == 0 && std::memcmp(second, "ABC", 3) == 0); Require(sceKernelLseek(file, 2, 0) == 2); @@ -240,7 +216,7 @@ int main() { Require(std::memcmp(first, "AB", 2) == 0 && std::memcmp(second, "CDE", 3) == 0); Require(sceKernelLseek(file, 0, 1) == 7); - GuestIovec empty[1] = {{nullptr, 0}}; + KernelIovec empty[1] = {{nullptr, 0}}; Require(sceKernelReadv(file, empty, 1) == 0); Require(sceKernelReadv(file, reads, 0) == 0); Require(sceKernelWritev(file, nullptr, 0) == 0); @@ -272,12 +248,12 @@ int main() { Require(Contents(path) == "01ABCDE7ABCDE"); char x[] = "X"; char y[] = "Y"; - GuestIovec marks[2] = {{x, 1}, {y, 1}}; + KernelIovec marks[2] = {{x, 1}, {y, 1}}; Require(pwritev_nid_postfix(file, marks, 2, 0) == 2); Require(Contents(path) == "XYABCDE7ABCDE"); char zero[] = "0"; char one[] = "1"; - GuestIovec restore[2] = {{zero, 1}, {one, 1}}; + KernelIovec restore[2] = {{zero, 1}, {one, 1}}; Require(pwritev_nid_postfix(file, restore, 2, 0) == 2); Require(sceKernelLseek(file, 0, 1) == 4); Require(pwritev_nid_postfix(file, writes, 2, -1) == -1 && *__error_nid_postfix() == 22); @@ -326,12 +302,12 @@ int main() { int ends[2] = {}; Require(MakePipe(ends) == 0); char xyz[] = "xyz"; - GuestIovec message[1] = {{xyz, 3}}; + KernelIovec message[1] = {{xyz, 3}}; Require(sceKernelWritev(ends[1], message, 1) == 3); Require(sceKernelReadv(ends[0], reads, 2) == 3); Require(std::memcmp(first, "xyz", 3) == 0); char stuvw[] = "stuvw"; - GuestIovec longer[1] = {{stuvw, 5}}; + KernelIovec longer[1] = {{stuvw, 5}}; Require(sceKernelWritev(ends[1], longer, 1) == 5); Require(sceKernelReadv(ends[0], reads, 2) == 5); Require(std::memcmp(first, "stu", 3) == 0 && std::memcmp(second, "vw", 2) == 0); @@ -351,7 +327,7 @@ int main() { const int random = sceKernelOpen("/dev/urandom", 0, 0); Require(random >= 0); unsigned char noise[48]{}; - GuestIovec pieces[2] = {{noise, 16}, {noise + 16, 16}}; + KernelIovec pieces[2] = {{noise, 16}, {noise + 16, 16}}; Require(sceKernelReadv(random, pieces, 2) == 32); Require(sceKernelPreadv(random, pieces, 1, 1000) == 16); Require(sceKernelPread(random, noise + 32, 16, 1000) == 16); diff --git a/core/libs/tests/GuestFileVectorMemory.cpp b/core/libs/tests/GuestFileVectorMemory.cpp index 58285bbdd7..8bac8775f0 100644 --- a/core/libs/tests/GuestFileVectorMemory.cpp +++ b/core/libs/tests/GuestFileVectorMemory.cpp @@ -1,3 +1,6 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libkernel/File/include/File.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/General.hpp" #include "prx/libc/include/GuestArena.hpp" #include "prx/libkernel/File/include/FileFlags.hpp" @@ -19,28 +22,6 @@ #include #endif -struct GuestIovec { - void* base; - std::size_t length; -}; - -extern "C" { -int APS5_VABI sceKernelOpen(const char*, int, std::uint16_t); -int APS5_VABI sceKernelClose(int); -std::int64_t APS5_VABI sceKernelLseek(int, std::int64_t, int); -std::int64_t APS5_VABI sceKernelReadv(int, const GuestIovec*, int); -std::int64_t APS5_VABI sceKernelWritev(int, const GuestIovec*, int); -std::int64_t APS5_VABI sceKernelPreadv(int, const GuestIovec*, int, std::int64_t); -std::int64_t APS5_VABI sceKernelPwritev(int, const GuestIovec*, int, std::int64_t); -std::int64_t APS5_VABI readv_nid_postfix(int, const GuestIovec*, int); -std::int64_t APS5_VABI writev_nid_postfix(int, const GuestIovec*, int); -std::int64_t APS5_VABI _readv_nid_postfix(int, const GuestIovec*, int); -std::int64_t APS5_VABI _writev_nid_postfix(int, const GuestIovec*, int); -std::int64_t APS5_VABI preadv_nid_postfix(int, const GuestIovec*, int, std::int64_t); -std::int64_t APS5_VABI pwritev_nid_postfix(int, const GuestIovec*, int, std::int64_t); -int* APS5_VABI __error_nid_postfix(); -} - static void Check(bool value, int line) { if (!value) { std::fprintf(stderr, "File vector memory check failed at line %d\n", line); @@ -54,7 +35,7 @@ struct Transfer { bool posix; bool positioned; bool write; - std::function call; + std::function call; }; static std::uintptr_t observedTable = 0; @@ -77,14 +58,14 @@ int main(int argc, char** argv) { const std::array transfers{{ {"readv", true, false, false, readv_nid_postfix}, {"writev", true, false, true, writev_nid_postfix}, - {"preadv", true, true, false, [](int fd, const GuestIovec* iov, int count) { return preadv_nid_postfix(fd, iov, count, 1); }}, - {"pwritev", true, true, true, [](int fd, const GuestIovec* iov, int count) { return pwritev_nid_postfix(fd, iov, count, 1); }}, + {"preadv", true, true, false, [](int fd, const KernelIovec* iov, int count) { return preadv_nid_postfix(fd, iov, count, 1); }}, + {"pwritev", true, true, true, [](int fd, const KernelIovec* iov, int count) { return pwritev_nid_postfix(fd, iov, count, 1); }}, {"_readv", true, false, false, _readv_nid_postfix}, {"_writev", true, false, true, _writev_nid_postfix}, {"sceKernelReadv", false, false, false, sceKernelReadv}, {"sceKernelWritev", false, false, true, sceKernelWritev}, - {"sceKernelPreadv", false, true, false, [](int fd, const GuestIovec* iov, int count) { return sceKernelPreadv(fd, iov, count, 1); }}, - {"sceKernelPwritev", false, true, true, [](int fd, const GuestIovec* iov, int count) { return sceKernelPwritev(fd, iov, count, 1); }}, + {"sceKernelPreadv", false, true, false, [](int fd, const KernelIovec* iov, int count) { return sceKernelPreadv(fd, iov, count, 1); }}, + {"sceKernelPwritev", false, true, true, [](int fd, const KernelIovec* iov, int count) { return sceKernelPwritev(fd, iov, count, 1); }}, }}; #ifdef _WIN32 SYSTEM_INFO system{}; @@ -98,9 +79,9 @@ int main(int argc, char** argv) { Require(memory != MAP_FAILED); #endif std::array bytes{'A', 'B'}; - const std::array vectors{{{bytes.data(), 1}, {bytes.data() + 1, 1}}}; + const std::array vectors{{{bytes.data(), 1}, {bytes.data() + 1, 1}}}; std::memcpy(memory, vectors.data(), sizeof(vectors)); - std::memcpy(memory + page - sizeof(GuestIovec), vectors.data(), sizeof(GuestIovec)); + std::memcpy(memory + page - sizeof(KernelIovec), vectors.data(), sizeof(KernelIovec)); Protect(memory, page, true); Protect(memory + page, page, false); const auto path = std::filesystem::temp_directory_path() / @@ -113,13 +94,13 @@ int main(int argc, char** argv) { { std::ofstream file(path, std::ios::binary); file << "ABCD"; Require(static_cast(file)); } const int fd = sceKernelOpen(guestPath.c_str(), SCE_KERNEL_O_RDWR, 0); Require(fd >= 0); - const std::array invalid{{ + const std::array invalid{{ nullptr, - reinterpret_cast(std::uintptr_t{1}), - reinterpret_cast(memory + page), - reinterpret_cast(memory + page - sizeof(GuestIovec)), - reinterpret_cast(memory + page - sizeof(GuestIovec) / 2), - reinterpret_cast(UINTPTR_MAX - sizeof(GuestIovec) + 1), + reinterpret_cast(std::uintptr_t{1}), + reinterpret_cast(memory + page), + reinterpret_cast(memory + page - sizeof(KernelIovec)), + reinterpret_cast(memory + page - sizeof(KernelIovec) / 2), + reinterpret_cast(UINTPTR_MAX - sizeof(KernelIovec) + 1), }}; for (const auto* table : invalid) { *__error_nid_postfix() = 0; @@ -142,7 +123,7 @@ int main(int argc, char** argv) { observedTable = reinterpret_cast(memory); observedBytes = 0; GuestArena::GuestArenaSetHostReadHook_nid_no_patch(ObserveRead); - Require(transfer.call(fd, reinterpret_cast(memory), 2) == 2); + Require(transfer.call(fd, reinterpret_cast(memory), 2) == 2); GuestArena::GuestArenaSetHostReadHook_nid_no_patch(nullptr); Require(observedBytes == sizeof(vectors)); Require(sceKernelLseek(fd, 0, SEEK_CUR) == (transfer.positioned ? 0 : 2)); @@ -156,10 +137,10 @@ int main(int argc, char** argv) { Require((bytes == (transfer.positioned ? std::array{'B', 'C'} : std::array{'A', 'B'}))); } Require(sceKernelLseek(fd, 0, SEEK_SET) == 0); - Require(transfer.call(fd, reinterpret_cast(memory + page - sizeof(GuestIovec)), 1) == 1); + Require(transfer.call(fd, reinterpret_cast(memory + page - sizeof(KernelIovec)), 1) == 1); Require(sceKernelLseek(fd, 0, SEEK_CUR) == (transfer.positioned ? 0 : 1)); Require(sceKernelLseek(fd, 0, SEEK_SET) == 0); - std::array maximum{}; + std::array maximum{}; maximum.back() = {bytes.data(), 1}; Require(transfer.call(fd, maximum.data(), static_cast(maximum.size())) == 1); Require(sceKernelLseek(fd, 0, SEEK_CUR) == (transfer.positioned ? 0 : 1)); diff --git a/core/libs/tests/GuestFilesystem.cpp b/core/libs/tests/GuestFilesystem.cpp index 720a8e8188..b2bf77d497 100644 --- a/core/libs/tests/GuestFilesystem.cpp +++ b/core/libs/tests/GuestFilesystem.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "SceTypes.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libc/include/General.hpp" @@ -30,89 +32,7 @@ #ifdef __linux__ #include #endif -extern "C" { -int APS5_VABI remove_nid_postfix(const char*); -int APS5_VABI rename_nid_postfix(const char*, const char*); -int APS5_VABI sceKernelChmod_nid_postfix(const char*, unsigned short); -int APS5_VABI sceKernelFchmod(int, unsigned short); -int APS5_VABI fchmod_nid_postfix(int, int); -int APS5_VABI chmod_nid_postfix(const char*, int); -int APS5_VABI chflags_nid_postfix(const char*, std::uint64_t); -int APS5_VABI fchflags_nid_postfix(int, std::uint64_t); -int APS5_VABI kqueue_nid_postfix(); -int APS5_VABI futimes_nid_postfix(int, const KernelTimeval*); -int APS5_VABI sceKernelFutimes(int, const KernelTimeval*); -int APS5_VABI socket_nid_postfix(int, int, int); -int APS5_VABI sceKernelFsync(int); -int APS5_VABI fdatasync_nid_postfix(int); -int APS5_VABI fsync_nid_postfix(int); -int APS5_VABI sceKernelFdatasync(int); -int APS5_VABI sceKernelWriteThrottlingStatus(std::uint64_t*); -int APS5_VABI sceKernelFtruncate(int, long long); -int APS5_VABI sceKernelTruncate_nid_postfix(const char*, long long); -int APS5_VABI truncate_nid_postfix(const char*, long long); -int APS5_VABI sceKernelUtimes_nid_postfix(const char*, const void*); -int APS5_VABI open_nid_postfix(const char*, int, int); -int APS5_VABI creat_nid_postfix(const char*, int); -int APS5_VABI _open_nid_postfix(const char*, int, ...); -int APS5_VABI close_nid_postfix(int); -int APS5_VABI flock_nid_postfix(int, int); -int APS5_VABI stat_nid_postfix(const char*, FileStat*); -int APS5_VABI lstat_nid_postfix(const char*, FileStat*); -int APS5_VABI unlink_nid_postfix(const char*); -int APS5_VABI rmdir_nid_postfix(const char*); -int APS5_VABI mkdir_nid_postfix(const char*, unsigned short); -int APS5_VABI sceKernelOpen(const char*, int, unsigned short); -int APS5_VABI sceKernelClose(int); -int APS5_VABI sceKernelGetdents(int, char*, int); -int APS5_VABI getdents_nid_postfix(int, char*, int); -int APS5_VABI getdirentries_nid_postfix(int, char*, int, int64_t*); -std::int64_t APS5_VABI sceKernelRead(int, void*, std::size_t); -std::int64_t APS5_VABI sceKernelReadv(int, const void*, int); -std::int64_t APS5_VABI sceKernelPread(int, void*, std::size_t, std::int64_t); -std::int64_t APS5_VABI sceKernelPreadv(int, const void*, int, std::int64_t); -std::int64_t APS5_VABI sceKernelPwrite(int, const void*, std::size_t, std::int64_t); -int APS5_VABI sceKernelStat(const char*, FileStat*); -int APS5_VABI sceKernelCheckReachability(const char*); -int APS5_VABI sceKernelFstat(int, FileStat*); -int APS5_VABI sceKernelUnlink(const char*); -int APS5_VABI sceKernelRename(const char*, const char*); -int APS5_VABI sceKernelRmdir(const char*); -int APS5_VABI sceKernelMkdir(const char*, unsigned short); -int APS5_VABI sceKernelRename(const char*, const char*); -int APS5_VABI sceKernelCheckReachability(const char*); -int APS5_VABI access_nid_postfix(const char*, int); -int APS5_VABI chdir_nid_postfix(const char*); -void* APS5_VABI opendir_nid_postfix(const char*); -FileStream* APS5_VABI fopen_nid_postfix(const char*, const char*); -FileStream* APS5_VABI freopen_nid_postfix(const char*, const char*, FileStream*); -std::size_t APS5_VABI fread_nid_postfix(void*, std::size_t, std::size_t, FileStream*); -int APS5_VABI fclose_nid_postfix(FileStream*); -int APS5_VABI fgetc_nid_postfix(FileStream*); -int APS5_VABI fileno_nid_postfix(FileStream*); -char* APS5_VABI fgets_nid_postfix(char*, int, FileStream*); -int APS5_VABI fscanf_nid_postfix(FileStream*, const char*, ...); -int APS5_VABI fputc_nid_postfix(int, FileStream*); -int APS5_VABI fseek_nid_postfix(FileStream*, std::int64_t, int); -std::int64_t APS5_VABI ftell_nid_postfix(FileStream*); -void APS5_VABI clearerr_nid_postfix(FileStream*); -int APS5_VABI feof_nid_postfix(FileStream*); -int APS5_VABI ferror_nid_postfix(FileStream*); -int APS5_VABI setvbuf_nid_postfix(FileStream*, char*, int, std::size_t); -int APS5_VABI fflush_nid_postfix(FileStream*); -void APS5_VABI flockfile_nid_postfix(FileStream*); -void APS5_VABI funlockfile_nid_postfix(FileStream*); -int APS5_VABI ftrylockfile_nid_postfix(FileStream*); -int* APS5_VABI __error_nid_postfix(); -int APS5_VABI pipe_nid_postfix(int*); -int APS5_VABI dup2_nid_postfix(int, int); -std::int64_t APS5_VABI lseek_nid_postfix(int, std::int64_t, int); -std::int64_t APS5_VABI read_nid_postfix(int, void*, std::size_t); -std::int64_t APS5_VABI write_nid_postfix(int, const void*, std::size_t); -std::int64_t APS5_VABI pread_nid_postfix(int, void*, std::size_t, std::int64_t); -std::int64_t APS5_VABI sceKernelWrite(int, const void*, std::size_t); -int APS5_VABI sceKernelDebugOutText(int, const char*); -} + #ifdef _WIN32 static bool g_invalidParameter = false; static void RecordInvalidParameter(const wchar_t*, const wchar_t*, const wchar_t*, unsigned, std::uintptr_t) { g_invalidParameter = true; } @@ -140,6 +60,7 @@ static void Check(bool value, int line) { static bool ChflagsThrows(const std::filesystem::path& path, std::uint64_t flags, const char* names) { try { chflags_nid_postfix(path.string().c_str(), flags); + } catch (const std::runtime_error& error) { return std::strstr(error.what(), names) != nullptr; } @@ -149,6 +70,7 @@ static bool ChflagsThrows(const std::filesystem::path& path, std::uint64_t flags static bool FchflagsThrows(int descriptor, std::uint64_t flags, const char* names) { try { fchflags_nid_postfix(descriptor, flags); + } catch (const std::runtime_error& error) { return std::strstr(error.what(), names) != nullptr; } @@ -489,6 +411,7 @@ static void TestMissingPathListsDirectoryOnce() { bool ambiguous = false; try { sceKernelStat((root / "PLUGIN.prx").generic_string().c_str(), &status); + } catch (const std::runtime_error&) { ambiguous = true; } @@ -664,16 +587,20 @@ int main() { Require(fread_nid_postfix(unread, 1, sizeof(unread), directoryStream) == 0 && *__error_nid_postfix() == 21); Require(ferror_nid_postfix(directoryStream) != 0 && feof_nid_postfix(directoryStream) == 0); clearerr_nid_postfix(directoryStream); + Require(ferror_nid_postfix(directoryStream) == 0); *__error_nid_postfix() = 0; Require(fgetc_nid_postfix(directoryStream) == -1 && *__error_nid_postfix() == 21 && ferror_nid_postfix(directoryStream) != 0); clearerr_nid_postfix(directoryStream); + *__error_nid_postfix() = 0; Require(fgets_nid_postfix(unread, sizeof(unread), directoryStream) == nullptr && *__error_nid_postfix() == 21 && ferror_nid_postfix(directoryStream) != 0); clearerr_nid_postfix(directoryStream); + *__error_nid_postfix() = 0; Require(fscanf_nid_postfix(directoryStream, "%d", &scanned) == -1 && *__error_nid_postfix() == 21 && ferror_nid_postfix(directoryStream) != 0); clearerr_nid_postfix(directoryStream); + Require(fseek_nid_postfix(directoryStream, 0, 0) == 0 && ftell_nid_postfix(directoryStream) == 0); *__error_nid_postfix() = 0; Require(fputc_nid_postfix('x', directoryStream) == -1 && *__error_nid_postfix() == 9 && ferror_nid_postfix(directoryStream) != 0); @@ -849,6 +776,7 @@ int main() { Require(held != INVALID_HANDLE_VALUE); const int result = kernel ? sceKernelRename(name(lockedSource).c_str(), name(preservedTarget).c_str()) : rename_nid_postfix(name(lockedSource).c_str(), name(preservedTarget).c_str()); + Require(CloseHandle(held) != 0); Require(result != 0 && std::filesystem::is_regular_file(marker)); if (!std::filesystem::is_directory(preservedTarget)) @@ -1303,7 +1231,7 @@ int main() { const int directoryDescriptor = open_nid_postfix(rootName.c_str(), 0, 0); Require(directoryDescriptor >= 0); char directoryBytes[8]{}; - struct { void* base; std::size_t length; } directoryVector[2] = {{directoryBytes, 3}, {directoryBytes + 3, 5}}; + KernelIovec directoryVector[2] = {{directoryBytes, 3}, {directoryBytes + 3, 5}}; Require(read_nid_postfix(directoryDescriptor, directoryBytes, sizeof(directoryBytes)) == -1 && *__error_nid_postfix() == 21); Require(sceKernelRead(directoryDescriptor, directoryBytes, sizeof(directoryBytes)) == static_cast(0x80020015u)); Require(sceKernelReadv(directoryDescriptor, directoryVector, 2) == static_cast(0x80020015u)); @@ -1529,14 +1457,18 @@ int main() { Require(std::memcmp(first, second, sizeof(first)) != 0); Require(feof_nid_postfix(stream) == 0 && ferror_nid_postfix(stream) == 0); flockfile_nid_postfix(stream); + Require(fread_nid_postfix(first, 1, 4, stream) == 4); funlockfile_nid_postfix(stream); + Require(ftrylockfile_nid_postfix(stream) == 0); funlockfile_nid_postfix(stream); + Require(fflush_nid_postfix(stream) == 0); bool unsupported = false; try { fgetc_nid_postfix(stream); + } catch (const std::runtime_error&) { unsupported = true; } @@ -1546,6 +1478,7 @@ int main() { bool rejected = false; try { fopen_nid_postfix(device, mode); + } catch (const std::runtime_error&) { rejected = true; } diff --git a/core/libs/tests/GuestFiopen.cpp b/core/libs/tests/GuestFiopen.cpp index 044265f11c..b5d8e930bd 100644 --- a/core/libs/tests/GuestFiopen.cpp +++ b/core/libs/tests/GuestFiopen.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/FileStream.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -7,14 +8,6 @@ #include #include -extern "C" { -FileStream* APS5_VABI _ZSt7_FiopenPKcNSt5_IosbIiE9_OpenmodeEi_nid_postfix(const char*, int, int); -FileStream* APS5_VABI fopen_nid_postfix(const char*, const char*); -int APS5_VABI fopen_s_nid_postfix(FileStream**, const char*, const char*); -int APS5_VABI fclose_nid_postfix(FileStream*); -std::int64_t APS5_VABI ftello_nid_postfix(FileStream*); -} - static void Check(bool value, int line) { if (!value) { std::fprintf(stderr, "Fiopen check failed at line %d\n", line); @@ -38,6 +31,7 @@ static std::string Contents(const char* name) { std::string text; for (int c; (c = std::fgetc(stream->GetHandle())) != EOF;) text += static_cast(c); fclose_nid_postfix(stream); + return text; } @@ -45,6 +39,7 @@ static void Write(FileStream* stream, const char* text) { Require(stream != nullptr); Require(std::fputs(text, stream->GetHandle()) >= 0); fclose_nid_postfix(stream); + } static bool Exists(const char* name) { @@ -87,10 +82,12 @@ int main() { auto* stream = Open(file, In); Require(stream != nullptr && std::fgetc(stream->GetHandle()) == 'a'); fclose_nid_postfix(stream); + stream = Open(file, In); Require(stream != nullptr); std::fputc('x', stream->GetHandle()); fclose_nid_postfix(stream); + Require(Contents(file) == "abc"); Write(Open(file, App), "d"); @@ -101,6 +98,7 @@ int main() { stream = Open(file, In | Ate); Require(stream != nullptr && ftello_nid_postfix(stream) == 5); fclose_nid_postfix(stream); + stream = Open(file, In | Binary); Require(stream != nullptr && ftello_nid_postfix(stream) == 0); fclose_nid_postfix(stream); @@ -112,6 +110,7 @@ int main() { stream = Open(file, In | Noreplace); Require(stream != nullptr); fclose_nid_postfix(stream); + stream = Open(file, In | Binary | Noreplace); Require(stream != nullptr); fclose_nid_postfix(stream); @@ -128,6 +127,7 @@ int main() { stream = Open(file, In | Out); Require(stream != nullptr && std::fgetc(stream->GetHandle()) == 'X'); fclose_nid_postfix(stream); + Require(Contents(file) == "Xbcdef"); Write(Open(file, In | Out | App), "g"); diff --git a/core/libs/tests/GuestFlexibleMemoryBudget.cpp b/core/libs/tests/GuestFlexibleMemoryBudget.cpp index cba381e734..2b3b74f051 100644 --- a/core/libs/tests/GuestFlexibleMemoryBudget.cpp +++ b/core/libs/tests/GuestFlexibleMemoryBudget.cpp @@ -1,3 +1,4 @@ +#include "prx/libkernel/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libc/include/General.hpp" #include "prx/libkernel/DirectMemory/DirectMemory.hpp" @@ -12,24 +13,9 @@ #include extern "C" { -int APS5_VABI sceKernelConfiguredFlexibleMemorySize(std::size_t*); -int APS5_VABI sceKernelAvailableFlexibleMemorySize(std::size_t*); -int APS5_VABI sceKernelMapFlexibleMemory(void**, std::size_t, int, int); -int APS5_VABI sceKernelReleaseFlexibleMemory(void*, std::size_t); -int APS5_VABI munmap_nid_postfix(void*, std::size_t) noexcept; -int APS5_VABI sceKernelVirtualQuery(const void*, int, VirtualQueryInfo*, std::uint64_t); + std::uint64_t GuestImageSegmentBytes_nid_no_patch(); -void* APS5_VABI dlopen_nid_postfix(const char*, int); -char* APS5_VABI dlerror_nid_postfix(); -int APS5_VABI dlclose_nid_postfix(void*); -std::size_t APS5_VABI sceKernelGetDirectMemorySize(); -int APS5_VABI sceKernelAllocateDirectMemory(std::int64_t, std::int64_t, std::size_t, std::size_t, int, std::int64_t*); -int APS5_VABI sceKernelMapDirectMemory(void**, std::size_t, int, int, std::int64_t, std::size_t); -int APS5_VABI sceKernelMapDirectMemory2(void**, std::size_t, int, int, int, std::int64_t, std::size_t); -int APS5_VABI sceKernelMapNamedDirectMemory(void**, std::size_t, int, int, std::int64_t, std::size_t, const char*); -int APS5_VABI sceKernelBatchMap2(KernelBatchMapEntry*, int, int*, int); -int APS5_VABI sceKernelReleaseDirectMemory(std::int64_t, std::size_t); -int APS5_VABI sceKernelVirtualQuery(const void*, int, VirtualQueryInfo*, std::uint64_t); + } static void Require(bool condition, std::source_location location = std::source_location::current()) { diff --git a/core/libs/tests/GuestFloatBuiltins.cpp b/core/libs/tests/GuestFloatBuiltins.cpp index a64f17eb85..e8051b96c0 100644 --- a/core/libs/tests/GuestFloatBuiltins.cpp +++ b/core/libs/tests/GuestFloatBuiltins.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -6,75 +7,6 @@ #include #include -using Int128 = __int128; -using Uint128 = unsigned __int128; - -extern "C" { -double APS5_VABI __adddf3_nid_postfix(double, double); -float APS5_VABI __addsf3_nid_postfix(float, float); -double APS5_VABI __subdf3_nid_postfix(double, double); -float APS5_VABI __subsf3_nid_postfix(float, float); -double APS5_VABI __muldf3_nid_postfix(double, double); -float APS5_VABI __mulsf3_nid_postfix(float, float); -double APS5_VABI __divdf3_nid_postfix(double, double); -float APS5_VABI __divsf3_nid_postfix(float, float); -double APS5_VABI __negdf2_nid_postfix(double); -float APS5_VABI __negsf2_nid_postfix(float); -int APS5_VABI __eqdf2_nid_postfix(double, double); -int APS5_VABI __nedf2_nid_postfix(double, double); -int APS5_VABI __ltdf2_nid_postfix(double, double); -int APS5_VABI __ledf2_nid_postfix(double, double); -int APS5_VABI __gtdf2_nid_postfix(double, double); -int APS5_VABI __gedf2_nid_postfix(double, double); -int APS5_VABI __unorddf2_nid_postfix(double, double); -int APS5_VABI __eqsf2_nid_postfix(float, float); -int APS5_VABI __ltsf2_nid_postfix(float, float); -int APS5_VABI __gesf2_nid_postfix(float, float); -int APS5_VABI __unordsf2_nid_postfix(float, float); -double APS5_VABI __extendsfdf2_nid_postfix(float); -float APS5_VABI __truncdfsf2_nid_postfix(double); -std::int32_t APS5_VABI __fixsfsi_nid_postfix(float); -std::int64_t APS5_VABI __fixsfdi_nid_postfix(float); -Int128 APS5_VABI __fixsfti_nid_postfix(float); -std::int32_t APS5_VABI __fixdfsi_nid_postfix(double); -std::int64_t APS5_VABI __fixdfdi_nid_postfix(double); -Int128 APS5_VABI __fixdfti_nid_postfix(double); -std::uint32_t APS5_VABI __fixunssfsi_nid_postfix(float); -std::uint64_t APS5_VABI __fixunssfdi_nid_postfix(float); -Uint128 APS5_VABI __fixunssfti_nid_postfix(float); -std::uint32_t APS5_VABI __fixunsdfsi_nid_postfix(double); -std::uint64_t APS5_VABI __fixunsdfdi_nid_postfix(double); -Uint128 APS5_VABI __fixunsdfti_nid_postfix(double); -std::int64_t APS5_VABI __fixxfdi_nid_postfix(long double); -Int128 APS5_VABI __fixxfti_nid_postfix(long double); -std::uint32_t APS5_VABI __fixunsxfsi_nid_postfix(long double); -std::uint64_t APS5_VABI __fixunsxfdi_nid_postfix(long double); -Uint128 APS5_VABI __fixunsxfti_nid_postfix(long double); -double APS5_VABI __floatsidf_nid_postfix(std::int32_t); -double APS5_VABI __floatunsidf_nid_postfix(std::uint32_t); -float APS5_VABI __floatsisf_nid_postfix(std::int32_t); -float APS5_VABI __floatunsisf_nid_postfix(std::uint32_t); -double APS5_VABI __floatdidf_nid_postfix(std::int64_t); -float APS5_VABI __floatdisf_nid_postfix(std::int64_t); -long double APS5_VABI __floatdixf_nid_postfix(std::int64_t); -double APS5_VABI __floatundidf_nid_postfix(std::uint64_t); -float APS5_VABI __floatundisf_nid_postfix(std::uint64_t); -long double APS5_VABI __floatundixf_nid_postfix(std::uint64_t); -double APS5_VABI __floattidf_nid_postfix(Int128); -float APS5_VABI __floattisf_nid_postfix(Int128); -long double APS5_VABI __floattixf_nid_postfix(Int128); -double APS5_VABI __floatuntidf_nid_postfix(Uint128); -float APS5_VABI __floatuntisf_nid_postfix(Uint128); -long double APS5_VABI __floatuntixf_nid_postfix(Uint128); -__complex__ float APS5_VABI __mulsc3_nid_postfix(float, float, float, float); -__complex__ double APS5_VABI __muldc3_nid_postfix(double, double, double, double); -__complex__ long double APS5_VABI __mulxc3_nid_postfix(long double, long double, long double, long double); -__complex__ float APS5_VABI __divsc3_nid_postfix(float, float, float, float); -__complex__ double APS5_VABI __divdc3_nid_postfix(double, double, double, double); -__complex__ long double APS5_VABI __divxc3_nid_postfix(long double, long double, long double, long double); -long double APS5_VABI __powixf2_nid_postfix(long double, int); -} - static void Require(bool value) { if (!value) std::abort(); } static std::uint64_t Bits(double value) { return std::bit_cast(value); } diff --git a/core/libs/tests/GuestFloatingPoint.cpp b/core/libs/tests/GuestFloatingPoint.cpp index 9d0de18775..eb01ae2bc7 100644 --- a/core/libs/tests/GuestFloatingPoint.cpp +++ b/core/libs/tests/GuestFloatingPoint.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -17,24 +18,6 @@ #include #endif -extern "C" { -int* APS5_VABI __error_nid_postfix(); -void APS5_VABI _Feraise_nid_postfix(int); -int APS5_VABI fegetround_nid_postfix(); -int APS5_VABI fesetround_nid_postfix(int); -int APS5_VABI fetestexcept_nid_postfix(int); -int APS5_VABI feclearexcept_nid_postfix(int); -int APS5_VABI fegetexceptflag_nid_postfix(std::uint16_t*, int); -int APS5_VABI fesetexceptflag_nid_postfix(const std::uint16_t*, int); -int APS5_VABI feenableexcept_nid_postfix(int); -int APS5_VABI fedisableexcept_nid_postfix(int); -int APS5_VABI __feenableexcept_nid_postfix(int); -int APS5_VABI __fedisableexcept_nid_postfix(int); -int APS5_VABI fegettrapenable_nid_postfix(); -int APS5_VABI fegetexcept_nid_postfix(); -int APS5_VABI fesettrapenable_nid_postfix(int); -} - namespace { struct Environment { @@ -135,6 +118,7 @@ void CheckFeraise() { const auto seeded = SeedFlags(0, 0); *__error_nid_postfix() = 0; _Feraise_nid_postfix(static_cast(requested)); + const unsigned raised = (requested & 0x18) != 0 ? requested | 0x20 : requested; const auto state = ReadEnvironment(); Require((state.x87[1] & 0x3f) == raised && (state.sse & 0x3f) == raised, "_Feraise raises the flags on both units"); diff --git a/core/libs/tests/GuestFminf.cpp b/core/libs/tests/GuestFminf.cpp index fcf48171a6..a414e26444 100644 --- a/core/libs/tests/GuestFminf.cpp +++ b/core/libs/tests/GuestFminf.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -5,15 +6,6 @@ #include #include -extern "C" { -double APS5_VABI fmin_nid_postfix(double, double); -float APS5_VABI fminf_nid_postfix(float, float); -long double APS5_VABI fminl_nid_postfix(long double, long double); -double APS5_VABI fmax_nid_postfix(double, double); -float APS5_VABI fmaxf_nid_postfix(float, float); -long double APS5_VABI fmaxl_nid_postfix(long double, long double); -} - static void Check(bool condition, const char* name, int line) { if (!condition) { std::fprintf(stderr, "%s check failed at line %d\n", name, line); diff --git a/core/libs/tests/GuestFnmatch.cpp b/core/libs/tests/GuestFnmatch.cpp index e32ada6dfd..8ed07dc566 100644 --- a/core/libs/tests/GuestFnmatch.cpp +++ b/core/libs/tests/GuestFnmatch.cpp @@ -1,3 +1,5 @@ +#include "prx/libc/include/Api.hpp" +#include "prx/libScePosixForWebKit/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -5,10 +7,7 @@ #include #include #include -extern "C" int APS5_VABI fnmatch_nid_postfix(const char*, const char*, int); -extern "C" int APS5_VABI strcasecmp_nid_postfix(const char*, const char*); -extern "C" int APS5_VABI strncasecmp_nid_postfix(const char*, const char*, std::size_t); -extern "C" char* APS5_VABI strcasestr_nid_postfix(const char*, const char*); + struct Case { const char* pattern; const char* string; @@ -143,6 +142,7 @@ int main() { bool threw = false; try { fnmatch_nid_postfix(nullptr, "x", 0); + } catch (const std::invalid_argument&) { threw = true; } diff --git a/core/libs/tests/GuestFont.cpp b/core/libs/tests/GuestFont.cpp index e7c65bc726..ef5ea31984 100644 --- a/core/libs/tests/GuestFont.cpp +++ b/core/libs/tests/GuestFont.cpp @@ -1,3 +1,5 @@ +#include "prx/libSceFontFt/include/Api.hpp" +#include "prx/libSceFont/include/Api.hpp" #include "prx/libSceFont/include/FontDriver.hpp" #include "prx/libc/include/General.hpp" #include "tests/FontFixture.hpp" @@ -17,76 +19,6 @@ #include #include -extern "C" { -int APS5_VABI sceFontMemoryInit(FontMemory*, void*, std::uint32_t, const FontMemoryInterface*, void*, FontMemoryDestroyFunction, void*); -int APS5_VABI sceFontMemoryTerm(FontMemory*); -int APS5_VABI sceFontCreateLibrary(const FontMemory*, const void*, FontLibrary*); -int APS5_VABI sceFontDestroyLibrary(FontLibrary*); -int APS5_VABI sceFontCreateRenderer(const FontMemory*, const void*, FontRenderer*); -int APS5_VABI sceFontDestroyRenderer(FontRenderer*); -int APS5_VABI sceFontGetPixelResolution(FontLibrary, std::uint32_t*); -int APS5_VABI sceFontAttachDeviceCacheBuffer(FontLibrary, void*, std::uint32_t); -int APS5_VABI sceFontClearDeviceCache(FontLibrary); -int APS5_VABI sceFontDettachDeviceCacheBuffer(FontLibrary, void**, std::uint32_t*); -int APS5_VABI sceFontSupportSystemFonts(FontLibrary); -int APS5_VABI sceFontSupportExternalFonts(FontLibrary, std::uint32_t, std::uint32_t); -int APS5_VABI sceFontOpenFontSet(FontLibrary, std::uint32_t, std::uint32_t, const FontOpenDetail*, FontHandle*); -int APS5_VABI sceFontOpenFontMemory(FontLibrary, const void*, std::uint32_t, const FontOpenDetail*, FontHandle*); -int APS5_VABI sceFontOpenFontFile(FontLibrary, const char*, std::uint32_t, const FontOpenDetail*, FontHandle*); -int APS5_VABI sceFontCloseFont(FontHandle); -int APS5_VABI sceFontOpenFontInstance(FontHandle, FontHandle, FontHandle*); -int APS5_VABI sceFontSetScriptLanguage(FontHandle, int, int); -int APS5_VABI sceFontGetScriptLanguage(FontHandle, int, int*); -int APS5_VABI sceFontSetTypographicDesign(FontHandle, int, int); -int APS5_VABI sceFontGetTypographicDesign(FontHandle, int, int*); -int APS5_VABI sceFontDefineAttribute(FontHandle, int, int*); -int APS5_VABI sceFontGetAttribute(FontHandle, int, int*); -int APS5_VABI sceFontSetResolutionDpi(FontHandle, std::uint32_t, std::uint32_t); -int APS5_VABI sceFontGetResolutionDpi(FontHandle, std::uint32_t*, std::uint32_t*); -int APS5_VABI sceFontSetScalePixel(FontHandle, float, float); -int APS5_VABI sceFontSetScalePoint(FontHandle, float, float); -int APS5_VABI sceFontGetScalePixel(FontHandle, float*, float*); -int APS5_VABI sceFontGlyphGetScalePixel(FontGlyph, float*, float*); -int APS5_VABI sceFontBindRenderer(FontHandle, FontRenderer); -int APS5_VABI sceFontUnbindRenderer(FontHandle); -int APS5_VABI sceFontSetupRenderScalePixel(FontHandle, float, float); -int APS5_VABI sceFontSetupRenderScalePoint(FontHandle, float, float); -int APS5_VABI sceFontGetKerning(FontHandle, std::uint32_t, std::uint32_t, FontKerning*); -int APS5_VABI sceFontGetFontGlyphsCount(FontHandle, std::uint32_t*); -int APS5_VABI sceFontGetCharGlyphCode(FontHandle, std::uint32_t, std::uint32_t*); -int APS5_VABI sceFontGetFontResolution(FontHandle, std::uint32_t*, float*); -int APS5_VABI sceFontGetRenderScaledKerning(FontHandle, std::uint32_t, std::uint32_t, FontKerning*); -int APS5_VABI sceFontGenerateCharGlyph(FontHandle, std::uint32_t, const FontGenerateGlyphDetail*, FontGlyph*); -int APS5_VABI sceFontGlyphDefineAttribute(FontGlyph, std::int32_t, std::int32_t*); -int APS5_VABI sceFontGlyphGetAttribute(FontGlyph, int, int*); -int APS5_VABI sceFontDeleteGlyph(const FontMemory*, FontGlyph*); -int APS5_VABI sceFontTextSourceInit(FontTextSource*, const void*, std::uint32_t, FontTextParseFunction, void*); -int APS5_VABI sceFontCreateString(const FontMemory*, FontTextSource*, const FontCreateStringDetail*, FontString*); -int APS5_VABI sceFontDestroyString(FontString*); -FontTextCharacter* APS5_VABI sceFontStringRefersTextCharacters(FontString, std::uint32_t*); -int APS5_VABI sceFontWritingInit(FontWriting*, FontString, const FontTextCharacter*); -const FontWritingStep* APS5_VABI sceFontWritingRefersRenderStep(FontWriting*); -FontTextCharacter* APS5_VABI sceFontWritingRefersRenderStepCharacter(FontWriting*, const FontWritingLetterStep**); -const void* APS5_VABI sceFontSelectLibraryFt(int); -const void* APS5_VABI sceFontSelectRendererFt(int); -int APS5_VABI sceFontFtSupportBdf(FontLibrary library); -int APS5_VABI sceFontFtSupportCid(FontLibrary library); -int APS5_VABI sceFontFtSupportOpenType(FontLibrary library); -int APS5_VABI sceFontFtSupportOpenTypeOtf(FontLibrary library); -int APS5_VABI sceFontFtSupportOpenTypeTtf(FontLibrary library); -int APS5_VABI sceFontFtSupportPcf(FontLibrary library); -int APS5_VABI sceFontFtSupportPfr(FontLibrary library); -int APS5_VABI sceFontFtSupportTrueType(FontLibrary library); -int APS5_VABI sceFontFtSupportTrueTypeGx(FontLibrary library); -int APS5_VABI sceFontFtSupportType1(FontLibrary library); -int APS5_VABI sceFontFtSupportType42(FontLibrary library); -int APS5_VABI sceFontFtSupportWinFonts(FontLibrary library); -int APS5_VABI sceFontCharacterGetSyllableStringState(const FontTextCharacter*, int*); -FontTextCodes* APS5_VABI sceFontCharactersRefersTextCodes(const FontTextCharacter*, const FontTextCharacter*, FontTextCodes*); -FontTextCodes* APS5_VABI sceFontTextCodesStepNext(FontTextCodes*); -FontTextCodes* APS5_VABI sceFontTextCodesStepBack(FontTextCodes*); -} - static void Check(bool value, int line) { if (!value) { std::fprintf(stderr, "Font check failed at line %d\n", line); @@ -155,6 +87,25 @@ static std::int32_t APS5_VABI ParseText(FontTextSource* source, void** order, Fo return 1; } +struct ParsedCodes { + const std::uint32_t* codes; + std::size_t count; + std::size_t at; + FontHandle font; +}; + +static std::int32_t APS5_VABI ParseCodes(FontTextSource* source, void** order, FontTextParseResult* result) { + auto* parsed = static_cast(source->textObject); + *order = const_cast(parsed->codes + parsed->at); + if (parsed->at == parsed->count) { + result->Terminate.terminateCode = 0; + return 0; + } + result->FontCode.font = parsed->font; + result->FontCode.code = parsed->codes[parsed->at++]; + return 1; +} + static void CheckTextCodes(const FontMemory* memory, FontHandle font) { ParsedText parsed{"AVA", 0, font}; FontTextSource source{}; @@ -164,6 +115,73 @@ static void CheckTextCodes(const FontMemory* memory, FontHandle font) { std::uint32_t count = 0; FontTextCharacter* characters = sceFontStringRefersTextCharacters(string, &count); Require(characters != nullptr && count == 3); + Require(sceFontStringGetWritingForm(string) == 0x12); + FontString rtlString = nullptr; + Require(sceFontTextSourceSetWritingForm(&source, 0x11) == SCE_FONT_OK && sceFontCreateString(memory, &source, nullptr, &rtlString) == SCE_FONT_OK); + Require(sceFontStringGetWritingForm(rtlString) == 0x11); + Require(sceFontDestroyString(&rtlString) == SCE_FONT_OK); + Require(sceFontTextSourceSetWritingForm(&source, 0x12) == SCE_FONT_OK && sceFontCreateString(memory, &source, nullptr, &rtlString) == SCE_FONT_OK); + Require(sceFontStringGetWritingForm(rtlString) == 0x12); + Require(sceFontDestroyString(&rtlString) == SCE_FONT_OK); + Require(sceFontTextSourceSetWritingForm(&source, 0x10) == SCE_FONT_OK); + + const std::uint32_t latinCodes[]{'A', 0x00E9, 0x4E2D}; + const std::uint32_t greekCodes[]{0x03B1}; + const std::uint32_t digitsCodes[]{'1', '2', ' '}; + const std::uint32_t hebrewCodes[]{0x05E9, 0x05DC}; + const std::uint32_t arabicCodes[]{0x0627, 0x0644}; + const std::uint32_t syriacCodes[]{0x0710}; + const std::uint32_t thaanaCodes[]{0x0780}; + const std::uint32_t nkoCodes[]{0x07CA}; + const std::uint32_t hebrewLetterCodes[]{0xFB1D}; + const std::uint32_t arabicFormCodes[]{0xFE70}; + const std::uint32_t digitHebrewCodes[]{'1', ' ', 0x05D0}; + const std::uint32_t hebrewLatinCodes[]{0x05D0, 'A'}; + const std::uint32_t latinHebrewCodes[]{'A', 0x05D0}; + const std::uint32_t rlmLatinCodes[]{0x200F, 'A'}; + const std::uint32_t lrmHebrewCodes[]{0x200E, 0x05D0}; + const std::uint32_t embeddingCodes[]{0x202B, 'A'}; + const std::uint32_t overrideCodes[]{0x202E, 'A'}; + const std::uint32_t isolatedHebrewCodes[]{0x2067, 0x05D0, 0x2069, 'A'}; + const std::uint32_t isolatedLatinCodes[]{0x2066, 'A', 0x2069, 0x05D0}; + const std::uint32_t openIsolateCodes[]{0x2067, 0x05D0}; + const struct { const std::uint32_t* codes; std::size_t count; std::int32_t sourceForm; int expected; } forms[]{ + {latinCodes, 3, 0x10, 0x12}, + {greekCodes, 1, 0x10, 0x12}, + {digitsCodes, 3, 0x10, 0x12}, + {nullptr, 0, 0x10, 0x12}, + {hebrewCodes, 2, 0x10, 0x11}, + {arabicCodes, 2, 0x10, 0x11}, + {syriacCodes, 1, 0x10, 0x11}, + {thaanaCodes, 1, 0x10, 0x11}, + {nkoCodes, 1, 0x10, 0x11}, + {hebrewLetterCodes, 1, 0x10, 0x11}, + {arabicFormCodes, 1, 0x10, 0x11}, + {digitHebrewCodes, 3, 0x10, 0x11}, + {hebrewLatinCodes, 2, 0x10, 0x11}, + {latinHebrewCodes, 2, 0x10, 0x12}, + {rlmLatinCodes, 2, 0x10, 0x11}, + {lrmHebrewCodes, 2, 0x10, 0x12}, + {embeddingCodes, 2, 0x10, 0x12}, + {overrideCodes, 2, 0x10, 0x12}, + {isolatedHebrewCodes, 4, 0x10, 0x12}, + {isolatedLatinCodes, 4, 0x10, 0x11}, + {openIsolateCodes, 2, 0x10, 0x12}, + {hebrewCodes, 2, 0x11, 0x11}, + {hebrewCodes, 2, 0x12, 0x12}, + {latinCodes, 3, 0x11, 0x11}, + {latinCodes, 3, 0x12, 0x12}, + }; + for (const auto& form : forms) { + ParsedCodes parsedCodes{form.codes, form.count, 0, font}; + FontTextSource codeSource{}; + FontString codeString = nullptr; + Require(sceFontTextSourceInit(&codeSource, parsed.text, 3, ParseCodes, &parsedCodes) == SCE_FONT_OK); + Require(sceFontTextSourceSetWritingForm(&codeSource, form.sourceForm) == SCE_FONT_OK); + Require(sceFontCreateString(memory, &codeSource, nullptr, &codeString) == SCE_FONT_OK && codeString != nullptr); + Require(sceFontStringGetWritingForm(codeString) == form.expected); + Require(sceFontDestroyString(&codeString) == SCE_FONT_OK); + } FontTextCodes codes; std::memset(&codes, 0xa5, sizeof(codes)); @@ -202,6 +220,7 @@ static void CheckTextCodes(const FontMemory* memory, FontHandle font) { bool threw = false; try { sceFontCharactersRefersTextCodes(nullptr, nullptr, &codes); + } catch (const std::runtime_error&) { threw = true; } @@ -410,11 +429,13 @@ int main() { bool getThrew = false; try { sceFontSetScriptLanguage(font, script, script); + } catch (const std::logic_error&) { setThrew = true; } try { sceFontGetScriptLanguage(font, script, &setting); + } catch (const std::logic_error&) { getThrew = true; } @@ -436,6 +457,7 @@ int main() { bool getThrew = false; try { sceFontGetTypographicDesign(font, selector, &setting); + } catch (const std::logic_error&) { getThrew = true; } @@ -445,6 +467,7 @@ int main() { bool setThrew = false; try { sceFontSetTypographicDesign(font, selector, feature); + } catch (const std::logic_error&) { setThrew = true; } @@ -469,6 +492,7 @@ int main() { bool typographyQueryThrew = false; try { sceFontGetTypographicDesign(font, 65537, &setting); + } catch (const std::logic_error&) { typographyQueryThrew = true; } diff --git a/core/libs/tests/GuestFontMetrics.cpp b/core/libs/tests/GuestFontMetrics.cpp new file mode 100644 index 0000000000..24d5f2b1ca --- /dev/null +++ b/core/libs/tests/GuestFontMetrics.cpp @@ -0,0 +1,137 @@ +#include "prx/libSceFont/include/FontDriver.hpp" +#include "prx/libSceFont/libSceFont.hpp" +#include "prx/libSceFontFt/libSceFontFt.hpp" +#include "tests/FontFixture.hpp" +#include +#include +#include +#include +#include +#include +#include + +static void Check(bool value, int line) { + if (!value) { + std::fprintf(stderr, "Font metrics check failed at line %d\n", line); + std::abort(); + } +} +#define Require(value) Check((value), __LINE__) + +struct Expected { + std::uint32_t form; + float ascender; + float descender; + float lineGap; + float maxAdvance; + float verticalDescender; + float verticalAscender; +}; + +static FontMetrics Metrics(FontHandle font, std::uint32_t form) { + FontMetrics metrics{}; + std::memset(&metrics, 0x7F, sizeof(metrics)); + Require(sceFontGetFontMetrics(font, form, &metrics) == SCE_FONT_OK); + return metrics; +} + +static void RequireMetrics(FontHandle font, std::uint32_t form, const Expected& expected) { + const FontMetrics metrics = Metrics(font, form); + Require(metrics.form == expected.form); + Require(metrics.ascender == expected.ascender && metrics.descender == expected.descender && metrics.lineGap == expected.lineGap); + Require(metrics.maxAdvance == expected.maxAdvance); + Require(metrics.verticalDescender == expected.verticalDescender && metrics.verticalAscender == expected.verticalAscender); + Require(metrics.xMin == 0.0f && metrics.yMin == 0.0f && metrics.xMax == 0.0f && metrics.yMax == 0.0f); + Require(metrics.emWidth == 99.984375f && metrics.emHeight == 99.984375f); +} + +static void* APS5_VABI Allocate(void*, std::uint32_t size) { + return std::malloc(size); +} + +static void APS5_VABI Release(void*, void* pointer) { + std::free(pointer); +} + +using FontFixture::BuildFont; +using FontFixture::Words; + +static std::vector Os2Table() { + return Words({0, 500, 400, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0x20, 0x7E, 700, -300, 100, 900, 250}); +} + +static FontHandle Open(FontLibrary library, const std::vector& data) { + FontHandle font = nullptr; + Require(sceFontOpenFontMemory(library, data.data(), static_cast(data.size()), nullptr, &font) == SCE_FONT_OK && font != nullptr); + Require(sceFontSetScalePixel(font, 100.0f, 100.0f) == SCE_FONT_OK); + return font; +} + +static std::vector VerticalHeader(int major) { + return Words({major, 0, 880, -120, 60, 1000, 40, 0, 950, 0, 0, 0, 0, 0, 0, 0, 0, 1}); +} + +int main() { + const FontMemoryInterface iface{Allocate, Release, nullptr, nullptr, nullptr, nullptr}; + FontMemory memory{}; + Require(sceFontMemoryInit(&memory, nullptr, 0, &iface, nullptr, nullptr, nullptr) == SCE_FONT_OK); + FontLibrary library = nullptr; + Require(sceFontCreateLibrary(&memory, sceFontSelectLibraryFt(0), &library) == SCE_FONT_OK); + Require(sceFontSupportExternalFonts(library, 4, 0x52) == SCE_FONT_OK); + + const auto plainData = BuildFont(1, {}); + FontHandle plain = Open(library, plainData); + RequireMetrics(plain, 1, {1, 80.0f, -20.0f, 0.0f, 50.0f, 0.0f, 0.0f}); + RequireMetrics(plain, 2, {1, 80.0f, -20.0f, 0.0f, 50.0f, 0.0f, 0.0f}); + RequireMetrics(plain, 3, {1, 80.0f, -20.0f, 0.0f, 50.0f, 0.0f, 0.0f}); + RequireMetrics(plain, 4, {4, 0.0f, 100.0f, 0.0f, 100.0f, -50.0f, 80.0f}); + FontMetrics untouched{}; + untouched.ascender = 5.0f; + untouched.descender = 6.0f; + untouched.lineGap = 7.0f; + Require(sceFontGetFontMetrics(plain, 7, &untouched) == SCE_FONT_OK); + Require(untouched.form == 7 && untouched.ascender == 5.0f && untouched.descender == 6.0f && untouched.lineGap == 7.0f); + Require(untouched.maxAdvance == 50.0f && untouched.verticalDescender == 0.0f && untouched.verticalAscender == 0.0f); + + const auto typoData = BuildFont(1, {{"OS/2", Os2Table()}, {"vhea", VerticalHeader(0x11)}, {"vmtx", Words({1000, 40})}}); + FontHandle typo = Open(library, typoData); + RequireMetrics(typo, 1, {1, 80.0f, -20.0f, 0.0f, 50.0f, 0.0f, 0.0f}); + RequireMetrics(typo, 2, {2, 70.0f, -30.0f, 10.0f, 50.0f, 0.0f, 0.0f}); + RequireMetrics(typo, 3, {3, 90.0f, -25.0f, 0.0f, 50.0f, 0.0f, 0.0f}); + RequireMetrics(typo, 4, {4, 4.0f, 95.0f, -93.984375f, 100.0f, -12.0f, 70.0f}); + Require(sceFontSetEffectWeight(typo, 1.03125f, 0.984375f, 0) == SCE_FONT_OK); + Require(sceFontSetEffectSlant(typo, 0.25f) == SCE_FONT_OK); + const FontMetrics styled = Metrics(typo, 2); + Require(styled.effectWeightX == 0.03125f && styled.effectWeightY == -0.015625f && styled.slantRatio == 0.25f); + Require(sceFontSetEffectWeight(typo, 1.5f, 0.5f, 0) == SCE_FONT_OK); + const FontMetrics clamped = Metrics(typo, 2); + Require(clamped.effectWeightX == 0.04f && clamped.effectWeightY == -0.04f); + + const auto versionOneData = BuildFont(1, {{"vhea", VerticalHeader(1)}, {"vmtx", Words({1000, 40})}}); + FontHandle versionOne = Open(library, versionOneData); + RequireMetrics(versionOne, 4, {4, 4.0f, 95.0f, 0.0f, 100.0f, -12.0f, 4.0f}); + + const auto os2OnlyData = BuildFont(1, {{"OS/2", Os2Table()}}); + FontHandle os2Only = Open(library, os2OnlyData); + RequireMetrics(os2Only, 4, {4, 70.0f, 70.0f, 0.0f, 100.0f, -50.0f, 70.0f}); + + FontMetrics cleared{}; + std::memset(&cleared, 0x7F, sizeof(cleared)); + Require(sceFontGetFontMetrics(nullptr, 1, &cleared) == SCE_FONT_ERROR_INVALID_FONT_HANDLE); + Require(cleared.form == 0 && cleared.ascender == 0.0f && cleared.maxAdvance == 0.0f && cleared.emHeight == 0.0f); + Require(cleared.effectWeightX == 1.0f && cleared.effectWeightY == 1.0f && cleared.slantRatio == 0.0f); + std::uint64_t notAFont[32]{}; + std::memset(&cleared, 0x7F, sizeof(cleared)); + Require(sceFontGetFontMetrics(reinterpret_cast(notAFont), 1, &cleared) == SCE_FONT_ERROR_INVALID_FONT_HANDLE); + Require(cleared.form == 0 && cleared.effectWeightX == 1.0f); + Require(sceFontGetFontMetrics(plain, 1, nullptr) == SCE_FONT_ERROR_INVALID_FONT_HANDLE); + Require(sceFontGetFontMetrics(nullptr, 1, nullptr) == SCE_FONT_ERROR_INVALID_FONT_HANDLE); + + for (FontHandle font : {plain, typo, versionOne, os2Only}) Require(sceFontCloseFont(font) == SCE_FONT_OK); + Require(sceFontDestroyLibrary(&library) == SCE_FONT_OK); + Require(sceFontMemoryTerm(&memory) == SCE_FONT_OK); + std::puts("Font metrics tests passed"); + return 0; +} diff --git a/core/libs/tests/GuestFontOutlineProfile.cpp b/core/libs/tests/GuestFontOutlineProfile.cpp new file mode 100644 index 0000000000..1c57782d45 --- /dev/null +++ b/core/libs/tests/GuestFontOutlineProfile.cpp @@ -0,0 +1,121 @@ +#include "prx/libSceFont/include/FontDriver.hpp" +#include "prx/libSceFont/libSceFont.hpp" +#include "prx/libSceFontFt/libSceFontFt.hpp" +#include "tests/FontFixture.hpp" +#include +#include +#include +#include +#include +#include +#include +#include + +static void Check(bool value, int line) { + if (!value) { + std::fprintf(stderr, "Font outline profile check failed at line %d\n", line); + std::abort(); + } +} +#define Require(value) Check((value), __LINE__) + +static void* APS5_VABI Allocate(void*, std::uint32_t size) { + return std::malloc(size); +} + +static void APS5_VABI Release(void*, void* pointer) { + std::free(pointer); +} + +static void PatchMaxp(std::vector& font, std::initializer_list words) { + const int tableCount = (font[4] << 8) | font[5]; + for (int i = 0; i < tableCount; ++i) { + const std::size_t entry = 12 + 16 * static_cast(i); + if (std::memcmp(font.data() + entry, "maxp", 4) != 0) continue; + std::size_t offset = (static_cast(font[entry + 8]) << 24) | (static_cast(font[entry + 9]) << 16) | + (static_cast(font[entry + 10]) << 8) | font[entry + 11]; + for (const int word : words) { + if (word >= 0) { + font[offset] = static_cast((word >> 8) & 0xFF); + font[offset + 1] = static_cast(word & 0xFF); + } + offset += 2; + } + return; + } + Require(false); +} + +static FontHandle Open(FontLibrary library, const std::vector& data) { + FontHandle font = nullptr; + Require(sceFontOpenFontMemory(library, data.data(), static_cast(data.size()), nullptr, &font) == SCE_FONT_OK && font != nullptr); + return font; +} + +static void Fill(FontOutlineProfile& profile) { + std::memset(&profile, 0x7F, sizeof(profile)); +} + +static bool Zero(const FontOutlineProfile& profile) { + return profile.maxContours == 0 && profile.maxPoints == 0 && profile.maxCompositeContours == 0 && profile.maxCompositePoints == 0; +} + +int main() { + const FontMemoryInterface iface{Allocate, Release, nullptr, nullptr, nullptr, nullptr}; + FontMemory memory{}; + Require(sceFontMemoryInit(&memory, nullptr, 0, &iface, nullptr, nullptr, nullptr) == SCE_FONT_OK); + FontLibrary library = nullptr; + Require(sceFontCreateLibrary(&memory, sceFontSelectLibraryFt(0), &library) == SCE_FONT_OK); + Require(sceFontSupportExternalFonts(library, 4, 0x52) == SCE_FONT_OK); + + auto profiledData = FontFixture::BuildFont(1, {}); + PatchMaxp(profiledData, {-1, -1, -1, 120, 7, 300, 11}); + FontHandle profiled = Open(library, profiledData); + FontOutlineProfile profile{}; + Fill(profile); + Require(sceFontGetFontGlyphsOutlineProfile(profiled, &profile) == SCE_FONT_OK); + Require(profile.maxContours == 7 && profile.maxPoints == 120 && profile.maxCompositeContours == 11 && profile.maxCompositePoints == 300); + + const auto plainData = FontFixture::BuildFont(1, {}); + FontHandle plain = Open(library, plainData); + Fill(profile); + Require(sceFontGetFontGlyphsOutlineProfile(plain, &profile) == SCE_FONT_OK && Zero(profile)); + + auto shortData = FontFixture::BuildFont(1, {}); + PatchMaxp(shortData, {0, 0x5000}); + FontHandle shortMaxp = Open(library, shortData); + Fill(profile); + Require(sceFontGetFontGlyphsOutlineProfile(shortMaxp, &profile) == SCE_FONT_ERROR_NO_SUPPORT_FUNCTION && Zero(profile)); + + std::array record{}; + auto* nativeFont = reinterpret_cast(profiled); + nativeFont->open_info.fontset_record = record.data(); + Require(sceFontGetFontGlyphsOutlineProfile(profiled, nullptr) == SCE_FONT_ERROR_INVALID_PARAMETER); + nativeFont->open_info.fontset_record = nullptr; + Fill(profile); + Require(sceFontGetFontGlyphsOutlineProfile(profiled, &profile) == SCE_FONT_OK && profile.maxPoints == 120); + + Fill(profile); + Require(sceFontGetFontGlyphsOutlineProfile(nullptr, &profile) == SCE_FONT_ERROR_INVALID_FONT_HANDLE && Zero(profile)); + std::uint64_t notAFont[32]{}; + Fill(profile); + Require(sceFontGetFontGlyphsOutlineProfile(reinterpret_cast(notAFont), &profile) == SCE_FONT_ERROR_INVALID_FONT_HANDLE && Zero(profile)); + Require(sceFontGetFontGlyphsOutlineProfile(plain, nullptr) == SCE_FONT_ERROR_INVALID_PARAMETER); + Require(sceFontGetFontGlyphsOutlineProfile(nullptr, nullptr) == SCE_FONT_ERROR_INVALID_FONT_HANDLE); + Require(sceFontGetFontGlyphsOutlineProfile(reinterpret_cast(notAFont), nullptr) == SCE_FONT_ERROR_INVALID_FONT_HANDLE); + auto* plainFont = reinterpret_cast(plain); + const FontLibrary owner = plainFont->library; + plainFont->library = nullptr; + Fill(profile); + Require(sceFontGetFontGlyphsOutlineProfile(plain, &profile) == SCE_FONT_ERROR_INVALID_FONT_HANDLE && Zero(profile)); + Require(sceFontGetFontGlyphsOutlineProfile(plain, nullptr) == SCE_FONT_ERROR_INVALID_PARAMETER); + plainFont->library = owner; + Fill(profile); + Require(sceFontGetFontGlyphsOutlineProfile(plain, &profile) == SCE_FONT_OK && Zero(profile)); + + for (FontHandle font : {profiled, plain, shortMaxp}) Require(sceFontCloseFont(font) == SCE_FONT_OK); + Require(sceFontDestroyLibrary(&library) == SCE_FONT_OK); + Require(sceFontMemoryTerm(&memory) == SCE_FONT_OK); + std::puts("Font outline profile tests passed"); + return 0; +} diff --git a/core/libs/tests/GuestFontStyleInformation.cpp b/core/libs/tests/GuestFontStyleInformation.cpp new file mode 100644 index 0000000000..21443be90b --- /dev/null +++ b/core/libs/tests/GuestFontStyleInformation.cpp @@ -0,0 +1,158 @@ +#include "prx/libSceFont/include/FontDriver.hpp" +#include "prx/libSceFont/libSceFont.hpp" +#include "prx/libSceFontFt/libSceFontFt.hpp" +#include "tests/FontFixture.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void Check(bool value, int line) { + if (!value) { + std::fprintf(stderr, "Font style information check failed at line %d\n", line); + std::abort(); + } +} +#define Require(value) Check((value), __LINE__) + +using FontFixture::BuildFont; +using FontFixture::Words; + +static void* APS5_VABI Allocate(void*, std::uint32_t size) { + return std::malloc(size); +} + +static void APS5_VABI Release(void*, void* pointer) { + std::free(pointer); +} + +static std::vector NameTable(std::string_view family, std::string_view style) { + const int familyBytes = static_cast(family.size() * 2); + const int styleBytes = static_cast(style.size() * 2); + std::vector table = Words({0, 2, 30, 3, 1, 0x409, 1, familyBytes, 0, 3, 1, 0x409, 2, styleBytes, familyBytes}); + for (const char c : family) FontFixture::Put16(table, c); + for (const char c : style) FontFixture::Put16(table, c); + return table; +} + +static std::vector Os2Table(int weight, int width) { + return Words({0, 500, weight, width, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0x20, 0x7E, 700, -300, 100, 900, 250}); +} + +static void PatchHead(std::vector& font, int macStyle, int direction) { + const int tableCount = (font[4] << 8) | font[5]; + for (int i = 0; i < tableCount; ++i) { + const std::size_t entry = 12 + 16 * static_cast(i); + if (std::memcmp(font.data() + entry, "head", 4) != 0) continue; + const std::size_t offset = (static_cast(font[entry + 8]) << 24) | (static_cast(font[entry + 9]) << 16) | + (static_cast(font[entry + 10]) << 8) | font[entry + 11]; + font[offset + 44] = static_cast((macStyle >> 8) & 0xFF); + font[offset + 45] = static_cast(macStyle & 0xFF); + font[offset + 48] = static_cast((direction >> 8) & 0xFF); + font[offset + 49] = static_cast(direction & 0xFF); + return; + } + Require(false); +} + +static FontHandle Open(FontLibrary library, const std::vector& data) { + FontHandle font = nullptr; + Require(sceFontOpenFontMemory(library, data.data(), static_cast(data.size()), nullptr, &font) == SCE_FONT_OK && font != nullptr); + return font; +} + +static FontStyleInformation Information(FontHandle font) { + FontStyleInformation information{}; + std::memset(&information, 0x7F, sizeof(information)); + Require(sceFontGetFontStyleInformation(font, &information) == SCE_FONT_OK); + return information; +} + +static bool Cleared(const FontStyleInformation& information) { + return information.familyName && information.familyName[0] == '\0' && information.styleName && information.styleName[0] == '\0' && + information.styleFlags == 0 && information.weight == 0 && information.width == 0 && information.layoutFlags == 0; +} + +int main() { + const FontMemoryInterface iface{Allocate, Release, nullptr, nullptr, nullptr, nullptr}; + FontMemory memory{}; + Require(sceFontMemoryInit(&memory, nullptr, 0, &iface, nullptr, nullptr, nullptr) == SCE_FONT_OK); + FontLibrary library = nullptr; + Require(sceFontCreateLibrary(&memory, sceFontSelectLibraryFt(0), &library) == SCE_FONT_OK); + Require(sceFontSupportExternalFonts(library, 4, 0x52) == SCE_FONT_OK); + + auto namedData = BuildFont(1, {{"name", NameTable("Tst", "Bd")}}); + PatchHead(namedData, 3, -2); + FontHandle named = Open(library, namedData); + const FontStyleInformation namedInfo = Information(named); + Require(namedInfo.familyName && std::string(namedInfo.familyName) == "Tst"); + Require(namedInfo.styleName && std::string(namedInfo.styleName) == "Bd"); + Require(namedInfo.styleFlags == 3 && namedInfo.weight == 0 && namedInfo.width == 0 && namedInfo.layoutFlags == 2); + + const auto os2Data = BuildFont(1, {{"name", NameTable("Tst", "Rg")}, {"OS/2", Os2Table(400, 5)}, + {"vhea", Words({0x11, 0, 880, -120, 60, 1000, 40, 0, 950, 0, 0, 0, 0, 0, 0, 0, 0, 1})}, {"vmtx", Words({1000, 40})}}); + FontHandle os2 = Open(library, os2Data); + const FontStyleInformation os2Info = Information(os2); + Require(os2Info.styleFlags == 0 && os2Info.weight == 400 && os2Info.width == 5 && os2Info.layoutFlags == 0x81); + + const auto oddData = BuildFont(1, {{"name", NameTable("Tst", "Rg")}, {"OS/2", Os2Table(450, 12)}}); + FontHandle odd = Open(library, oddData); + const FontStyleInformation oddInfo = Information(odd); + Require(oddInfo.weight == 0 && oddInfo.width == 0 && oddInfo.layoutFlags == 1); + + for (const int weight : {100, 900}) { + const auto data = BuildFont(1, {{"name", NameTable("Tst", "Rg")}, {"OS/2", Os2Table(weight, 9)}}); + FontHandle font = Open(library, data); + const FontStyleInformation info = Information(font); + Require(info.weight == weight && info.width == 9); + Require(sceFontCloseFont(font) == SCE_FONT_OK); + } + for (const int weight : {0, 1000}) { + const auto data = BuildFont(1, {{"name", NameTable("Tst", "Rg")}, {"OS/2", Os2Table(weight, 10)}}); + FontHandle font = Open(library, data); + const FontStyleInformation info = Information(font); + Require(info.weight == 0 && info.width == 0); + Require(sceFontCloseFont(font) == SCE_FONT_OK); + } + + static const char recordFamily[] = "Rf"; + static const char recordStyle[] = "Rs"; + std::array record{}; + record[4] = std::byte{1}; + record[5] = std::byte{7}; + record[6] = std::byte{3}; + record[7] = std::byte{0x81}; + const char* familyPointer = recordFamily; + const char* stylePointer = recordStyle; + std::memcpy(record.data() + 8, &familyPointer, sizeof(familyPointer)); + std::memcpy(record.data() + 16, &stylePointer, sizeof(stylePointer)); + auto* nativeFont = reinterpret_cast(os2); + nativeFont->open_info.fontset_record = record.data(); + const FontStyleInformation recordInfo = Information(os2); + nativeFont->open_info.fontset_record = nullptr; + Require(recordInfo.familyName == recordFamily && recordInfo.styleName == recordStyle); + Require(recordInfo.styleFlags == 1 && recordInfo.weight == 700 && recordInfo.width == 3 && recordInfo.layoutFlags == 0x81); + + FontStyleInformation cleared{}; + std::memset(&cleared, 0x7F, sizeof(cleared)); + Require(sceFontGetFontStyleInformation(nullptr, &cleared) == SCE_FONT_ERROR_INVALID_FONT_HANDLE && Cleared(cleared)); + std::uint64_t notAFont[32]{}; + std::memset(&cleared, 0x7F, sizeof(cleared)); + Require(sceFontGetFontStyleInformation(reinterpret_cast(notAFont), &cleared) == SCE_FONT_ERROR_INVALID_FONT_HANDLE && Cleared(cleared)); + Require(sceFontGetFontStyleInformation(named, nullptr) == SCE_FONT_ERROR_INVALID_PARAMETER); + Require(sceFontGetFontStyleInformation(nullptr, nullptr) == SCE_FONT_ERROR_INVALID_FONT_HANDLE); + + for (FontHandle font : {named, os2, odd}) Require(sceFontCloseFont(font) == SCE_FONT_OK); + Require(sceFontDestroyLibrary(&library) == SCE_FONT_OK); + Require(sceFontMemoryTerm(&memory) == SCE_FONT_OK); + std::puts("Font style information tests passed"); + return 0; +} diff --git a/core/libs/tests/GuestFontWritingLine.cpp b/core/libs/tests/GuestFontWritingLine.cpp index 5c311aede3..0f41bb2066 100644 --- a/core/libs/tests/GuestFontWritingLine.cpp +++ b/core/libs/tests/GuestFontWritingLine.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceFont/include/Api.hpp" #include "prx/libSceFont/include/FontTypes.hpp" #include #include @@ -5,16 +6,6 @@ #include #include -extern "C" { -int APS5_VABI sceFontCreateWritingLine(const FontMemory*, std::int32_t, const void*, void**); -int APS5_VABI sceFontDestroyWritingLine(void**); -int APS5_VABI sceFontWritingLineClear(void*); -int APS5_VABI sceFontWritingLineWritesOrder(void*, std::uint64_t, const FontWritingMetrics*, void*); -const FontWritingLineStep* APS5_VABI sceFontWritingLineRefersRenderStep(void*); -int APS5_VABI sceFontWritingLineGetRenderMetrics(void*, FontWritingMetrics*); -int APS5_VABI sceFontWritingLineGetOrderingSpace(void*, float*, float*, float*, float*); -} - static void Check(bool value, int line) { if (!value) { std::fprintf(stderr, "Font writing line check failed at line %d\n", line); diff --git a/core/libs/tests/GuestFopenErrors.cpp b/core/libs/tests/GuestFopenErrors.cpp index 5c72df7df0..7cfd9c96b6 100644 --- a/core/libs/tests/GuestFopenErrors.cpp +++ b/core/libs/tests/GuestFopenErrors.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -8,14 +9,6 @@ #include #include -extern "C" { -void* APS5_VABI fopen_nid_postfix(const char* filename, const char* mode); -int APS5_VABI fclose_nid_postfix(void* stream); -void* APS5_VABI freopen_nid_postfix(const char* filename, const char* mode, void* stream); -int APS5_VABI fopen_s_nid_postfix(void** result, const char* filename, const char* mode); -int* APS5_VABI __error_nid_postfix(); -} - namespace { void Require(bool value, int line) { @@ -60,12 +53,12 @@ void Open() { Check(OpenFails((LongName + "/inside").c_str(), "a", GuestEnametoolong)); Check(OpenFails("missing.txt", "r", GuestEnoent)); Check(OpenFails("folder", "w", GuestEisdir)); - void* plain = fopen_nid_postfix("plain.txt", "r"); + FileStream* plain = fopen_nid_postfix("plain.txt", "r"); Check(plain != nullptr && fclose_nid_postfix(plain) == 0); } bool ReopenFails(const char* name, const char* mode, int error) { - void* stream = fopen_nid_postfix("plain.txt", "r"); + FileStream* stream = fopen_nid_postfix("plain.txt", "r"); Check(stream != nullptr); *__error_nid_postfix() = 0; const bool failed = freopen_nid_postfix(name, mode, stream) == nullptr && *__error_nid_postfix() == error; @@ -79,14 +72,14 @@ void Reopen() { Check(ReopenFails(LongName.c_str(), "r", GuestEnametoolong)); Check(ReopenFails(LongName.c_str(), "w", GuestEnametoolong)); Check(ReopenFails("missing.txt", "r", GuestEnoent)); - void* stream = fopen_nid_postfix("plain.txt", "r"); + FileStream* stream = fopen_nid_postfix("plain.txt", "r"); Check(stream != nullptr); - void* reopened = freopen_nid_postfix("plain.txt", "r", stream); + FileStream* reopened = freopen_nid_postfix("plain.txt", "r", stream); Check(reopened != nullptr && fclose_nid_postfix(reopened) == 0); } void CheckedOpen() { - void* stream = reinterpret_cast(1); + FileStream* stream = reinterpret_cast(1); Check(fopen_s_nid_postfix(&stream, "loop", "r") == GuestEloop && stream == nullptr); Check(fopen_s_nid_postfix(&stream, LongName.c_str(), "w") == GuestEnametoolong && stream == nullptr); Check(fopen_s_nid_postfix(&stream, "folder", "w") == GuestEisdir && stream == nullptr); diff --git a/core/libs/tests/GuestFopenLongHostPath.cpp b/core/libs/tests/GuestFopenLongHostPath.cpp index 9ebe1738ce..9a15819f63 100644 --- a/core/libs/tests/GuestFopenLongHostPath.cpp +++ b/core/libs/tests/GuestFopenLongHostPath.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/General.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -10,14 +11,6 @@ #define NOMINMAX #include -extern "C" { -void* APS5_VABI fopen_nid_postfix(const char*, const char*); -int APS5_VABI fclose_nid_postfix(void*); -std::size_t APS5_VABI fread_nid_postfix(void*, std::size_t, std::size_t, void*); -std::size_t APS5_VABI fwrite_nid_postfix(const void*, std::size_t, std::size_t, void*); -int* APS5_VABI __error_nid_postfix(); -} - namespace { void Require(bool value, const char* message) { @@ -29,7 +22,7 @@ std::filesystem::path Extended(const std::filesystem::path& path) { return native.starts_with(L"\\\\") ? L"\\\\?\\UNC\\" + native.substr(2) : L"\\\\?\\" + native; } -using Stream = std::unique_ptr; +using Stream = std::unique_ptr; Stream Open(const char* path, const char* mode) { Stream stream(fopen_nid_postfix(path, mode), fclose_nid_postfix); diff --git a/core/libs/tests/GuestForceTlsDestructor.cpp b/core/libs/tests/GuestForceTlsDestructor.cpp index 2bf6d13807..aba2bcafaa 100644 --- a/core/libs/tests/GuestForceTlsDestructor.cpp +++ b/core/libs/tests/GuestForceTlsDestructor.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libSceLibcInternal/include/Api.hpp" #include "SceTypes.hpp" #include #include @@ -10,15 +12,6 @@ #include #endif -extern "C" { -int APS5_VABI scePthreadCreate(Pthread* thread, const PthreadAttr* attr, PthreadEntry entry, void* arg, const char* name); -int APS5_VABI scePthreadJoin(Pthread thread, void** retval); -int APS5_VABI sceKernelGetModuleInfoFromAddr(std::uint64_t address, int flags, ModuleInfoEx* info); -int APS5_VABI _sceLibcInternalThreadAtexit_nid_postfix(void (APS5_VABI* destructor)(void*), void* object, void* dsoSymbol); -void APS5_VABI _sceLibcInternalThreadDtors_nid_postfix(); -int APS5_VABI _sceLibcInternalForceTlsDestructor_nid_postfix(KernelModule handle); -} - namespace { using Destructor = void (APS5_VABI*)(void*); @@ -64,6 +57,7 @@ KernelModule ModuleOf(const void* address) { bool ForceThrows(KernelModule handle) { try { _sceLibcInternalForceTlsDestructor_nid_postfix(handle); + } catch (const std::runtime_error&) { return true; } @@ -101,6 +95,7 @@ int main() { Require(_sceLibcInternalForceTlsDestructor_nid_postfix(0) == 0); Require(calls.size() == 2); _sceLibcInternalThreadDtors_nid_postfix(); + Require(calls == std::vector{3, 1, 2}); calls.clear(); @@ -108,6 +103,7 @@ int main() { Require(_sceLibcInternalForceTlsDestructor_nid_postfix(other) == 0); Require(calls.empty()); _sceLibcInternalThreadDtors_nid_postfix(); + Require(calls.empty()); Require(Register(RecordAndRegister, 10) == 0); diff --git a/core/libs/tests/GuestFreeType.cpp b/core/libs/tests/GuestFreeType.cpp index 422ebe3faf..453f2bfeb3 100644 --- a/core/libs/tests/GuestFreeType.cpp +++ b/core/libs/tests/GuestFreeType.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceFreeType/include/Api.hpp" #include "FreeTypeFontFixture.hpp" #include "prx/libSceFreeType/include/GuestFreeType.hpp" #include "prx/libc/include/General.hpp" @@ -27,27 +28,6 @@ using namespace FreeType; -extern "C" { -void APS5_VABI FT_Set_Transform_nid_postfix(GuestFaceRec*, const GuestMatrix*, const GuestVector*); -std::int64_t APS5_VABI FT_Cos_nid_postfix(std::int64_t); -std::int64_t APS5_VABI FT_Sin_nid_postfix(std::int64_t); -std::int64_t APS5_VABI FT_Tan_nid_postfix(std::int64_t); -std::int64_t APS5_VABI FT_Angle_Diff_nid_postfix(std::int64_t, std::int64_t); -void APS5_VABI FT_Vector_Unit_nid_postfix(GuestVector*, std::int64_t); -int APS5_VABI FT_Init_FreeType_nid_postfix(void**); -int APS5_VABI FT_Done_FreeType_nid_postfix(void*); -int APS5_VABI FT_New_Face_nid_postfix(void*, const char*, std::int64_t, GuestFaceRec**); -int APS5_VABI FT_New_Memory_Face_nid_postfix(void*, const unsigned char*, std::int64_t, std::int64_t, GuestFaceRec**); -int APS5_VABI FT_Done_Face_nid_postfix(GuestFaceRec*); -int APS5_VABI FT_Set_Pixel_Sizes_nid_postfix(GuestFaceRec*, std::uint32_t, std::uint32_t); -int APS5_VABI FT_Get_Kerning_nid_postfix(GuestFaceRec*, std::uint32_t, std::uint32_t, std::uint32_t, GuestVector*); -std::uint32_t APS5_VABI FT_Get_Char_Index_nid_postfix(GuestFaceRec*, std::uint64_t); -int APS5_VABI FT_Load_Glyph_nid_postfix(GuestFaceRec*, std::uint32_t, std::int32_t); -int APS5_VABI FT_Load_Char_nid_postfix(GuestFaceRec*, std::uint64_t, std::int32_t); -int APS5_VABI FT_Render_Glyph_nid_postfix(GuestGlyphSlotRec*, std::int32_t); -int APS5_VABI FT_Set_Char_Size_nid_postfix(GuestFaceRec*, std::int64_t, std::int64_t, std::uint32_t, std::uint32_t); -} - static void Check(bool value, int line) { if (!value) { std::fprintf(stderr, "FreeType check failed at line %d\n", line); @@ -56,12 +36,10 @@ static void Check(bool value, int line) { } #define Require(value) Check((value), __LINE__) -extern "C" int APS5_VABI FT_Get_Gasp_nid_postfix(GuestFaceRec*, std::uint32_t); - static void CheckGaspTable(const std::vector* table, const std::vector>& ranges, bool versionZero, bool render) { const auto font = SquareGlyphFont('A', 700, false, table); - void* library = nullptr; + FreeType::GuestLibrary* library = nullptr; GuestFaceRec* face = nullptr; FT_Library nativeLibrary = nullptr; FT_Face native = nullptr; @@ -138,7 +116,7 @@ template static bool ThrowsWith(TCall call, const std::string& return false; } -static void FaceMatches(const GuestFaceRec* face, FT_Face host, const void* library) { +static void FaceMatches(const GuestFaceRec* face, FT_Face host, const FreeType::GuestLibrary* library) { Require(face->num_faces == host->num_faces && face->face_index == host->face_index && face->face_flags == host->face_flags); Require(face->style_flags == host->style_flags && face->num_glyphs == host->num_glyphs && face->num_glyphs == 2); Require((face->family_name == nullptr) == (host->family_name == nullptr) && (face->style_name == nullptr) == (host->style_name == nullptr)); @@ -153,8 +131,6 @@ static void FaceMatches(const GuestFaceRec* face, FT_Face host, const void* libr Require(face->glyph != nullptr && face->glyph->face == face && face->glyph->library == library && face->size != nullptr && face->size->face == face); } -extern "C" int APS5_VABI FT_Outline_Get_Orientation_nid_postfix(GuestOutline*); - static unsigned orientationCases = 0; static void CheckOrientationCase(std::vector points, std::vector contours, @@ -239,7 +215,7 @@ static void CheckOutlineOrientation() { CheckOrientationCase(points, contours, twiceArea == 0 ? FT_ORIENTATION_NONE : expected == FT_ORIENTATION_POSTSCRIPT ? FT_ORIENTATION_TRUETYPE : FT_ORIENTATION_POSTSCRIPT); } const auto font = SquareGlyphFont('A', 700); - void* library = nullptr; + FreeType::GuestLibrary* library = nullptr; GuestFaceRec* face = nullptr; FT_Library nativeLibrary = nullptr; FT_Face native = nullptr; @@ -457,7 +433,7 @@ static void Trigonometry() { } } const auto font = SquareGlyphFont('A', 700); - void* library = nullptr; + GuestLibrary* library = nullptr; FT_Library oracle = nullptr; GuestFaceRec* face = nullptr; FT_Face native = nullptr; @@ -490,16 +466,247 @@ static void Trigonometry() { scalarCases, vectorCases, differenceCases, rendered); } +struct DecomposeEvents { + std::vector> calls; + std::size_t stopAt = static_cast(-1); + int result = 0; + + int Add(int kind, GuestVector first, GuestVector second = {}, GuestVector third = {}) { + calls.push_back({kind, first.x, first.y, second.x, second.y, third.x, third.y}); + return calls.size() - 1 == stopAt ? result : 0; + } +}; + +static GuestVector GuestPoint(const FT_Vector& point) { return {point.x, point.y}; } + +static int NativeMove(const FT_Vector* to, void* user) { return static_cast(user)->Add(1, GuestPoint(*to)); } +static int NativeLine(const FT_Vector* to, void* user) { return static_cast(user)->Add(2, GuestPoint(*to)); } +static int NativeConic(const FT_Vector* control, const FT_Vector* to, void* user) { + return static_cast(user)->Add(3, GuestPoint(*control), GuestPoint(*to)); +} +static int NativeCubic(const FT_Vector* first, const FT_Vector* second, const FT_Vector* to, void* user) { + return static_cast(user)->Add(4, GuestPoint(*first), GuestPoint(*second), GuestPoint(*to)); +} + +static int APS5_VABI GuestMove(const GuestVector* to, void* user) { return static_cast(user)->Add(1, *to); } +static int APS5_VABI GuestLine(const GuestVector* to, void* user) { return static_cast(user)->Add(2, *to); } +static int APS5_VABI GuestConic(const GuestVector* control, const GuestVector* to, void* user) { + return static_cast(user)->Add(3, *control, *to); +} +static int APS5_VABI GuestCubic(const GuestVector* first, const GuestVector* second, const GuestVector* to, void* user) { + return static_cast(user)->Add(4, *first, *second, *to); +} + +static int APS5_VABI NullUserMove(const GuestVector*, void* user) { + Require(user == nullptr); + return -17; +} + +static std::size_t CompareDecomposition(std::vector points, std::vector tags, + std::vector contours, int shift, std::int64_t delta, + std::size_t stopAt = static_cast(-1), int stopResult = 0) { + std::vector nativePoints; + for (const auto point : points) nativePoints.push_back({static_cast(point.x), static_cast(point.y)}); + GuestOutline outline{static_cast(contours.size()), static_cast(points.size()), points.data(), tags.data(), contours.data(), 0}; + FT_Outline native{outline.n_contours, outline.n_points, nativePoints.data(), tags.data(), contours.data(), 0}; + DecomposeEvents actual; + DecomposeEvents expected; + actual.stopAt = expected.stopAt = stopAt; + actual.result = expected.result = stopResult; + const GuestOutlineFuncs functions{GuestMove, GuestLine, GuestConic, GuestCubic, shift, delta}; + const FT_Outline_Funcs nativeFunctions{NativeMove, NativeLine, NativeConic, NativeCubic, shift, static_cast(delta)}; + const int result = FT_Outline_Decompose_nid_postfix(&outline, &functions, &actual); + Require(result == FT_Outline_Decompose(&native, &nativeFunctions, &expected)); + Require(actual.calls == expected.calls); + for (std::size_t index = 0; index < points.size(); ++index) { + Require(points[index].x == nativePoints[index].x && points[index].y == nativePoints[index].y); + } + if (stopAt < expected.calls.size()) Require(result == stopResult && actual.calls.size() == stopAt + 1); + return actual.calls.size(); +} + +struct ChangingDecomposition { + DecomposeEvents events; + GuestOutlineFuncs guest{}; + FT_Outline_Funcs native{}; + GuestOutline* outline = nullptr; + FT_Outline* nativeOutline = nullptr; + GuestVector* replacement = nullptr; + FT_Vector* nativeReplacement = nullptr; +}; + +static int NativeChangedLine(const FT_Vector* to, void* user) { + return static_cast(user)->events.Add(5, GuestPoint(*to)); +} +static int APS5_VABI GuestChangedLine(const GuestVector* to, void* user) { + return static_cast(user)->events.Add(5, *to); +} +static int NativeChangingMove(const FT_Vector* to, void* user) { + auto& state = *static_cast(user); + state.native.line_to = NativeChangedLine; + state.native.shift = 4; + state.native.delta = 999; + state.nativeOutline->points = state.nativeReplacement; + return state.events.Add(1, GuestPoint(*to)); +} +static int APS5_VABI GuestChangingMove(const GuestVector* to, void* user) { + auto& state = *static_cast(user); + state.guest.line_to = GuestChangedLine; + state.guest.shift = 4; + state.guest.delta = 999; + state.outline->points = state.replacement; + GuestOutline empty{}; + const GuestOutlineFuncs noCallbacks{}; + Require(FT_Outline_Decompose_nid_postfix(&empty, &noCallbacks, nullptr) == 0); + return state.events.Add(1, *to); +} + +static void OutlineDecomposition() { + GuestOutline empty{}; + const GuestOutlineFuncs callbacks{GuestMove, GuestLine, GuestConic, GuestCubic, 0, 0}; + const FT_Outline_Funcs nativeCallbacks{NativeMove, NativeLine, NativeConic, NativeCubic, 0, 0}; + Require(FT_Outline_Decompose_nid_postfix(nullptr, nullptr, nullptr) == FT_Outline_Decompose(nullptr, nullptr, nullptr)); + Require(FT_Outline_Decompose_nid_postfix(nullptr, &callbacks, nullptr) == FT_Outline_Decompose(nullptr, &nativeCallbacks, nullptr)); + Require(FT_Outline_Decompose_nid_postfix(&empty, nullptr, nullptr) == FT_Err_Invalid_Argument); + const GuestOutlineFuncs unused{nullptr, nullptr, nullptr, nullptr, -1, INT64_MIN}; + Require(FT_Outline_Decompose_nid_postfix(&empty, &unused, nullptr) == 0); + int scenarios = 0; + std::size_t calls = 0; + for (unsigned count = 1; count <= 6; ++count) { + std::vector points; + for (unsigned point = 0; point < count; ++point) points.push_back({static_cast(point) * 13 - 37, static_cast(point) * -17 + 23}); + const unsigned patterns = 1u << (2 * count); + for (unsigned pattern = 0; pattern < patterns; ++pattern) { + std::vector tags; + for (unsigned point = 0; point < count; ++point) tags.push_back(static_cast(((pattern >> (point * 2)) & 3) | 0xA4)); + for (const int shift : {0, 1, 4}) { + for (const int delta : {-17, 0, 19}) { + calls += CompareDecomposition(points, tags, {static_cast(count - 1)}, shift, delta); + ++scenarios; + } + } + } + } + const std::vector curve{{-17, 3}, {7, -5}, {29, 31}, {43, -11}, {59, 37}, {73, -13}, {89, 41}, {101, -17}}; + for (const auto& tags : std::vector>{{1, 0, 0, 1, 2, 2, 1, 0}, {1, 2, 2, 1, 0, 1, 2, 2}, {0, 0, 0, 0, 0, 0, 0, 0}}) { + for (const auto& contours : std::vector>{{7}, {2, 7}, {0, 3, 7}, {2, 1}}) { + const std::size_t events = CompareDecomposition(curve, tags, contours, 2, -3); + ++scenarios; + for (std::size_t stop = 0; stop < events; ++stop) { + for (const int error : {1, -17, 0x12345678, INT32_MIN}) { + calls += CompareDecomposition(curve, tags, contours, 2, -3, stop, error); + ++scenarios; + } + } + } + } + { + GuestVector points[]{{7, -5}, {11, 13}, {17, -19}, {23, 29}}; + FT_Vector nativePoints[]{{7, -5}, {11, 13}, {17, -19}, {23, 29}}; + GuestVector replacement[]{{107, 95}, {111, 113}, {117, 81}, {123, 129}}; + FT_Vector nativeReplacement[]{{107, 95}, {111, 113}, {117, 81}, {123, 129}}; + unsigned char tags[]{1, 1, 1, 1}; + unsigned short contours[]{1, 3}; + GuestOutline outline{2, 4, points, tags, contours, 0}; + FT_Outline native{2, 4, nativePoints, tags, contours, 0}; + ChangingDecomposition actual; + ChangingDecomposition expected; + actual.guest = {GuestChangingMove, nullptr, nullptr, nullptr, 1, -3}; + expected.native = {NativeChangingMove, nullptr, nullptr, nullptr, 1, -3}; + actual.outline = &outline; + actual.replacement = replacement; + expected.nativeOutline = &native; + expected.nativeReplacement = nativeReplacement; + Require(FT_Outline_Decompose_nid_postfix(&outline, &actual.guest, &actual) == FT_Outline_Decompose(&native, &expected.native, &expected)); + Require(actual.events.calls == expected.events.calls && actual.events.calls.size() == 6); + } + { + GuestVector point{7, -5}; + unsigned char tag = 1; + unsigned short contour = 0; + GuestOutline outline{1, 1, &point, &tag, &contour, 0}; + const GuestOutlineFuncs nullUser{NullUserMove, nullptr, nullptr, nullptr, 0, 0}; + Require(FT_Outline_Decompose_nid_postfix(&outline, &nullUser, nullptr) == -17); + } + { + GuestVector points[]{{0x10000000001ll, -0x10000000003ll}, {0x10000000005ll, -0x10000000007ll}, {0x10000000009ll, -0x1000000000Bll}}; + unsigned char tags[]{1, 1, 1}; + unsigned short contours[]{1}; + GuestOutline outline{1, 2, points, tags, contours, 0}; + auto functions = callbacks; + functions.shift = 2; + functions.delta = 0x100000000ll; + DecomposeEvents events; + Require(FT_Outline_Decompose_nid_postfix(&outline, &functions, &events) == 0); + const std::vector> expected{{1, 0x3FF00000004ll, -0x4010000000Cll, 0, 0, 0, 0}, + {2, 0x3FF00000014ll, -0x4010000001Cll, 0, 0, 0, 0}, + {2, 0x3FF00000004ll, -0x4010000000Cll, 0, 0, 0, 0}}; + Require(events.calls == expected); + tags[0] = tags[1] = 0; + events.calls.clear(); + Require(FT_Outline_Decompose_nid_postfix(&outline, &functions, &events) == 0); + const std::vector> conic{{1, 0x3FF0000000Cll, -0x40100000014ll, 0, 0, 0, 0}, + {3, 0x3FF00000004ll, -0x4010000000Cll, 0x3FF0000000Cll, -0x40100000014ll, 0, 0}, + {3, 0x3FF00000014ll, -0x4010000001Cll, 0x3FF0000000Cll, -0x40100000014ll, 0, 0}}; + Require(events.calls == conic); + tags[0] = 1; + tags[1] = tags[2] = 2; + contours[0] = 2; + outline.n_points = 3; + events.calls.clear(); + Require(FT_Outline_Decompose_nid_postfix(&outline, &functions, &events) == 0); + const std::vector> cubic{{1, 0x3FF00000004ll, -0x4010000000Cll, 0, 0, 0, 0}, + {4, 0x3FF00000014ll, -0x4010000001Cll, 0x3FF00000024ll, -0x4010000002Cll, 0x3FF00000004ll, -0x4010000000Cll}}; + Require(events.calls == cubic); + contours[0] = 1; + outline.n_points = 2; + for (const int shift : {-1, 63, INT32_MAX}) { + functions.shift = shift; + Require(ThrowsWith([&] { FT_Outline_Decompose_nid_postfix(&outline, &functions, &events); }, "FT_Outline_Decompose: a shift")); + } + functions.shift = 62; + functions.delta = 0; + Require(ThrowsWith([&] { FT_Outline_Decompose_nid_postfix(&outline, &functions, &events); }, "FT_Outline_Decompose: overflowing coordinate scaling")); + functions.shift = 0; + functions.delta = INT64_MIN; + Require(ThrowsWith([&] { FT_Outline_Decompose_nid_postfix(&outline, &functions, &events); }, "FT_Outline_Decompose: overflowing coordinate translation")); + functions.delta = 0; + points[0] = {INT64_MAX, 0}; + points[1] = {INT64_MAX, 0}; + tags[0] = tags[1] = 0; + Require(ThrowsWith([&] { FT_Outline_Decompose_nid_postfix(&outline, &functions, &events); }, "FT_Outline_Decompose: overflowing midpoint")); + } + const auto font = SquareGlyphFont('A', 700); + GuestLibrary* library = nullptr; + FT_Library oracle = nullptr; + GuestFaceRec* face = nullptr; + FT_Face native = nullptr; + Require(FT_Init_FreeType_nid_postfix(&library) == 0 && FT_Init_FreeType(&oracle) == 0); + Require(FT_New_Memory_Face_nid_postfix(library, font.data(), font.size(), 0, &face) == 0); + Require(FT_New_Memory_Face(oracle, font.data(), static_cast(font.size()), 0, &native) == 0); + int rendered = 0; + for (const unsigned pixels : {8u, 16u, 31u, 100u}) { + Require(FT_Set_Pixel_Sizes_nid_postfix(face, 0, pixels) == FT_Set_Pixel_Sizes(native, 0, pixels)); + for (const unsigned glyph : {0u, 1u}) { + Require(FT_Load_Glyph_nid_postfix(face, glyph, FT_LOAD_DEFAULT) == FT_Load_Glyph(native, glyph, FT_LOAD_DEFAULT)); + DecomposeEvents actual; + DecomposeEvents expected; + Require(FT_Outline_Decompose_nid_postfix(&face->glyph->outline, &callbacks, &actual) == FT_Outline_Decompose(&native->glyph->outline, &nativeCallbacks, &expected)); + Require(actual.calls == expected.calls); + SlotMatches(face->glyph, native->glyph); + Require(FT_Render_Glyph_nid_postfix(face->glyph, FT_RENDER_MODE_NORMAL) == FT_Render_Glyph(native->glyph, FT_RENDER_MODE_NORMAL)); + SlotMatches(face->glyph, native->glyph); + ++rendered; + } + } + Require(FT_Done_FreeType_nid_postfix(library) == 0 && FT_Done_FreeType(oracle) == 0); + std::printf("FreeType outline decomposition: %d native comparisons, %zu callbacks, %d rendered glyphs, wide coordinates and callback mutation\n", scenarios, calls, rendered); +} + struct Finalizers { std::vector calls; }; -extern "C" { -int APS5_VABI FT_Get_CID_Registry_Ordering_Supplement_nid_postfix(GuestFaceRec*, const char**, const char**, std::int32_t*); -int APS5_VABI FT_Get_CID_Is_Internally_CID_Keyed_nid_postfix(GuestFaceRec*, std::uint8_t*); -int APS5_VABI FT_Get_CID_From_Glyph_Index_nid_postfix(GuestFaceRec*, std::uint32_t, std::uint32_t*); -} - static std::vector CidMetadataFont(bool keyed, const std::string& registry, const std::string& ordering, int supplement, unsigned cid) { const auto index = [](const std::vector>& objects) { @@ -624,7 +831,7 @@ static void CheckCidMetadata() { {CidMetadataFont(false, "Adobe", "Identity", 0, 41), 0, 0, 0, nullptr, nullptr, 1}, {SquareGlyphFont('A', 700), -1, 0, 0, nullptr, nullptr, 1}}}; for (const auto& fixture : fixtures) { - void* library = nullptr; + FreeType::GuestLibrary* library = nullptr; GuestFaceRec* face = nullptr; FT_Library nativeLibrary = nullptr; FT_Face native = nullptr; @@ -690,12 +897,257 @@ static void APS5_VABI GuestFaceFinalizer(void* object) { static_cast(face->generic.data)->calls.push_back(3); } +static std::string BitmapStrikeFont(int width, int height, int descent) { + std::string font = "STARTFONT 2.1\nFONT -anyps5-strike-medium-r-normal--" + std::to_string(height) + "-0-72-72-c-0-iso10646-1\n"; + font += "SIZE " + std::to_string(height) + " 72 72\nFONTBOUNDINGBOX " + std::to_string(width) + " " + std::to_string(height) + " 0 -" + std::to_string(descent); + font += "\nSTARTPROPERTIES 4\nFONT_ASCENT " + std::to_string(height - descent) + "\nFONT_DESCENT " + std::to_string(descent); + font += "\nCHARSET_REGISTRY \"ISO10646\"\nCHARSET_ENCODING \"1\"\nENDPROPERTIES\nCHARS 1\nSTARTCHAR A\nENCODING 65\nSWIDTH 1000 0\nDWIDTH "; + font += std::to_string(width) + " 0\nBBX " + std::to_string(width) + " " + std::to_string(height) + " 0 -" + std::to_string(descent) + "\nBITMAP\n"; + for (int y = 0; y < height; ++y) { + for (int byte = 0; byte < (width + 7) / 8; ++byte) { + unsigned value = 0; + for (int bit = 0; bit < 8; ++bit) { + const int x = byte * 8 + bit; + if (x < width && (x == 0 || y == height - 1 || (x + y) % 3 == 0)) value |= 0x80u >> bit; + } + font += "0123456789ABCDEF"[value >> 4]; + font += "0123456789ABCDEF"[value & 15]; + } + font += '\n'; + } + return font + "ENDCHAR\nENDFONT\n"; +} + +static void CheckStrikeSelection(GuestLibrary* library, FT_Library nativeLibrary, GuestFaceRec* scalable, FT_Face nativeScalable) { + const auto sizeMatches = [](const GuestSizeRec* size, FT_Size host) { + const auto& actual = size->metrics; + const auto& expected = host->metrics; + Require(actual.x_ppem == expected.x_ppem && actual.y_ppem == expected.y_ppem); + Require(actual.x_scale == expected.x_scale && actual.y_scale == expected.y_scale); + Require(actual.ascender == expected.ascender && actual.descender == expected.descender); + Require(actual.height == expected.height && actual.max_advance == expected.max_advance); + }; + constexpr std::array invalidIndices{-1, 1, 2, std::numeric_limits::min(), std::numeric_limits::max()}; + int requests = 0; + int rendered = 0; + for (const auto index : invalidIndices) { + const auto nullError = FT_Select_Size(nullptr, index); + Require(nullError != 0 && FT_Select_Size_nid_postfix(nullptr, index) == nullError); + ++requests; + } + for (const auto index : {0, -1, std::numeric_limits::max()}) { + const auto error = FT_Select_Size(nativeScalable, index); + Require(error == FT_Err_Invalid_Face_Handle && FT_Select_Size_nid_postfix(scalable, index) == error); + sizeMatches(scalable->size, nativeScalable->size); + ++requests; + } + for (const auto& dimensions : {std::array{5, 7, 2}, std::array{11, 13, 3}}) { + const auto [width, height, descent] = dimensions; + const std::string font = BitmapStrikeFont(width, height, descent); + const auto* bytes = reinterpret_cast(font.data()); + GuestFaceRec* face = nullptr; + FT_Face native = nullptr; + Require(FT_New_Memory_Face_nid_postfix(library, bytes, static_cast(font.size()), 0, &face) == 0); + Require(FT_New_Memory_Face(nativeLibrary, bytes, static_cast(font.size()), 0, &native) == 0); + Require(FT_HAS_FIXED_SIZES(native) && !FT_IS_SCALABLE(native) && face->num_fixed_sizes == 1); + const GuestBitmapSize* strikes = face->available_sizes; + const auto& expectedStrike = native->available_sizes[0]; + Require(strikes[0].width == expectedStrike.width && strikes[0].height == expectedStrike.height && strikes[0].size == expectedStrike.size); + Require(strikes[0].x_ppem == expectedStrike.x_ppem && strikes[0].y_ppem == expectedStrike.y_ppem); + GuestSizeRec* size = face->size; + int marker = 0; + size->generic.data = ▮ + sizeMatches(size, native->size); + Require(size->metrics.y_ppem == 0); + const std::array indices{-1, 1, invalidIndices[3], invalidIndices[4], 0, 2, 0, -1, 0}; + for (const auto index : indices) { + face->glyph->advance.x = 0x123456789ABCll; + face->bbox.xMin = -0x123456789ABCll; + const auto error = FT_Select_Size(native, index); + Require((index == 0) == (error == 0)); + Require(FT_Select_Size_nid_postfix(face, index) == error); + ++requests; + sizeMatches(size, native->size); + Require(face->size == size && size->face == face && size->generic.data == &marker && face->available_sizes == strikes); + Require(face->glyph->advance.x == 0x123456789ABCll && face->bbox.xMin == -0x123456789ABCll); + if (error != 0) continue; + Require(size->metrics.y_ppem == height && size->metrics.ascender == (height - descent) * 64 && size->metrics.descender == -descent * 64); + for (const auto flags : std::array{FT_LOAD_DEFAULT, FT_LOAD_RENDER, FT_LOAD_RENDER | FT_LOAD_MONOCHROME}) { + Require(FT_Load_Char_nid_postfix(face, 'A', flags) == 0 && FT_Load_Char(native, 'A', flags) == 0); + SlotMatches(face->glyph, native->glyph); + const auto& bitmap = face->glyph->bitmap; + Require(face->glyph->format == FT_GLYPH_FORMAT_BITMAP && bitmap.pixel_mode == FT_PIXEL_MODE_MONO); + Require(bitmap.width == width && bitmap.rows == height && bitmap.pitch > 0 && face->glyph->bitmap_top == height - descent); + for (int y = 0; y < height; ++y) { + for (int x = 0; x < width; ++x) { + const bool pixel = (bitmap.buffer[y * bitmap.pitch + x / 8] & (0x80u >> (x % 8))) != 0; + Require(pixel == (x == 0 || y == height - 1 || (x + y) % 3 == 0)); + } + } + ++rendered; + } + } + Require(FT_Done_Face_nid_postfix(face) == 0 && FT_Done_Face(native) == 0); + } + std::printf("FT_Select_Size: %d native request comparisons, %d bitmap glyph comparisons\n", requests, rendered); +} + static void SetFinalizers(FT_Face face, Finalizers& events) { face->generic = {&events, NativeFaceFinalizer}; face->glyph->generic = {&events, NativeSlotFinalizer}; face->size->generic = {&events, NativeSizeFinalizer}; } +static bool Equal(GuestVector a, GuestVector b) { + return a.x == b.x && a.y == b.y; +} + +static bool Equal(const GuestOutline& a, const GuestOutline& b) { + return a.n_points == b.n_points && a.n_contours == b.n_contours && a.points == b.points && + a.tags == b.tags && a.contours == b.contours && a.flags == b.flags; +} + +static void CopyCase(std::uint16_t pointCount, std::uint16_t contourCount, int sourceFlags, int targetFlags, bool wide) { + const GuestVector guard{0x123456789ABCDEF, -0x123456789ABCDEF}; + std::vector points(pointCount + 2, guard), copied(pointCount + 2, guard); + std::vector tags(pointCount + 2, 0xA5), copiedTags(pointCount + 2, 0x5A); + std::vector contours(contourCount + 2, 0xABCD), copiedContours(contourCount + 2, 0xDCBA); + std::vector hostPoints(pointCount), hostCopied(pointCount); + std::vector hostTags(pointCount), hostCopiedTags(pointCount); + std::vector hostContours(contourCount), hostCopiedContours(contourCount); + for (unsigned index = 0; index < pointCount; ++index) { + const auto value = static_cast(index) * 65537 - 100000; + points[index + 1] = wide ? GuestVector{INT64_MIN + index, + INT64_MAX - index} + : GuestVector{value / 4, -value / 4}; + tags[index + 1] = static_cast(index); + hostPoints[index] = {static_cast(points[index + 1].x), static_cast(points[index + 1].y)}; + hostTags[index] = tags[index + 1]; + } + for (unsigned index = 0; index < contourCount; ++index) { + contours[index + 1] = static_cast(index); + hostContours[index] = contours[index + 1]; + } + GuestOutline source{contourCount, pointCount, pointCount ? points.data() + 1 : nullptr, + pointCount ? tags.data() + 1 : nullptr, contourCount ? contours.data() + 1 : nullptr, sourceFlags}; + GuestOutline target{contourCount, pointCount, pointCount ? copied.data() + 1 : nullptr, + pointCount ? copiedTags.data() + 1 : nullptr, contourCount ? copiedContours.data() + 1 : nullptr, targetFlags}; + const auto originalSource = source; + auto expectedTarget = target; + const auto originalPoints = points; + const auto originalTags = tags; + const auto originalContours = contours; + FT_Outline hostSource{contourCount, pointCount, hostPoints.data(), hostTags.data(), hostContours.data(), sourceFlags}; + FT_Outline hostTarget{contourCount, pointCount, hostCopied.data(), hostCopiedTags.data(), hostCopiedContours.data(), targetFlags}; + Require(FT_Outline_Copy_nid_postfix(&source, &target) == FT_Outline_Copy(&hostSource, &hostTarget)); + expectedTarget.flags = hostTarget.flags; + Require(Equal(source, originalSource) && Equal(target, expectedTarget)); + Require(Equal(copied.front(), guard) && Equal(copied.back(), guard)); + Require(copiedTags.front() == 0x5A && copiedTags.back() == 0x5A); + Require(copiedContours.front() == 0xDCBA && copiedContours.back() == 0xDCBA); + for (unsigned index = 0; index < pointCount; ++index) { + Require(Equal(copied[index + 1], originalPoints[index + 1])); + if (!wide) Require(copied[index + 1].x == hostCopied[index].x && copied[index + 1].y == hostCopied[index].y); + Require(copiedTags[index + 1] == hostCopiedTags[index]); + } + for (unsigned index = 0; index < contourCount; ++index) Require(copiedContours[index + 1] == hostCopiedContours[index]); + if (pointCount) { + target.points[0] = {321, -654}; + target.tags[0] ^= 0xFF; + } + if (contourCount) target.contours[0] ^= 0xFFFF; + for (std::size_t index = 0; index < points.size(); ++index) Require(Equal(points[index], originalPoints[index])); + Require(tags == originalTags && contours == originalContours); +} + +static void InvalidAndSelfCopies() { + GuestOutline source{1, 4, nullptr, nullptr, nullptr, 0x1234}; + auto target = source; + Require(FT_Outline_Copy_nid_postfix(nullptr, nullptr) == FT_Outline_Copy(nullptr, nullptr)); + Require(FT_Outline_Copy_nid_postfix(nullptr, &target) == FT_Err_Invalid_Outline); + Require(Equal(target, source)); + Require(FT_Outline_Copy_nid_postfix(&source, nullptr) == FT_Err_Invalid_Outline); + Require(FT_Outline_Copy_nid_postfix(&source, &source) == 0); + for (const auto counts : std::array, 3>{{{1, 3}, {0, 4}, {0, 0}}}) { + target.n_contours = counts[0]; + target.n_points = counts[1]; + const auto before = target; + FT_Outline nativeSource{1, 4, nullptr, nullptr, nullptr, source.flags}; + FT_Outline nativeTarget{target.n_contours, target.n_points, nullptr, nullptr, nullptr, target.flags}; + Require(FT_Outline_Copy_nid_postfix(&source, &target) == FT_Outline_Copy(&nativeSource, &nativeTarget)); + Require(Equal(target, before)); + } +} + +static void RenderCopy() { + const auto font = SquareGlyphFont('A', 700); + GuestLibrary* library = nullptr; + GuestFaceRec* face = nullptr; + FT_Library nativeLibrary = nullptr; + FT_Face nativeFace = nullptr; + Require(FT_Init_FreeType_nid_postfix(&library) == 0 && FT_Init_FreeType(&nativeLibrary) == 0); + Require(FT_New_Memory_Face_nid_postfix(library, font.data(), font.size(), 0, &face) == 0); + Require(FT_New_Memory_Face(nativeLibrary, font.data(), static_cast(font.size()), 0, &nativeFace) == 0); + Require(FT_Set_Pixel_Sizes_nid_postfix(face, 0, 32) == 0 && FT_Set_Pixel_Sizes(nativeFace, 0, 32) == 0); + for (const int offset : {0, 37, -129}) { + Require(FT_Load_Char_nid_postfix(face, 'A', FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP) == 0); + Require(FT_Load_Char(nativeFace, 'A', FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP) == 0); + auto& target = face->glyph->outline; + std::vector points(target.points, target.points + target.n_points); + std::vector nativePoints(nativeFace->glyph->outline.points, + nativeFace->glyph->outline.points + nativeFace->glyph->outline.n_points); + for (std::size_t index = 0; index < points.size(); ++index) { + points[index].x += offset + points[index].y / 4; + nativePoints[index].x += offset + nativePoints[index].y / 4; + } + auto source = target; + source.points = points.data(); + source.flags ^= FT_OUTLINE_OWNER; + auto nativeSource = nativeFace->glyph->outline; + nativeSource.points = nativePoints.data(); + nativeSource.flags ^= FT_OUTLINE_OWNER; + Require(FT_Outline_Copy_nid_postfix(&source, &target) == 0); + Require(FT_Outline_Copy(&nativeSource, &nativeFace->glyph->outline) == 0); + points[0] = {}; + nativePoints[0] = {}; + Require(FT_Render_Glyph_nid_postfix(face->glyph, FT_RENDER_MODE_NORMAL) == 0); + Require(FT_Render_Glyph(nativeFace->glyph, FT_RENDER_MODE_NORMAL) == 0); + const auto& actual = face->glyph->bitmap; + const auto& expected = nativeFace->glyph->bitmap; + Require(actual.rows > 0 && actual.width > 0); + Require(actual.rows == expected.rows && actual.width == expected.width && actual.pitch == expected.pitch); + Require(actual.pixel_mode == expected.pixel_mode && actual.num_grays == expected.num_grays); + Require(face->glyph->bitmap_left == nativeFace->glyph->bitmap_left && face->glyph->bitmap_top == nativeFace->glyph->bitmap_top); + const auto size = static_cast(actual.rows) * std::abs(actual.pitch); + Require(std::memcmp(actual.buffer, expected.buffer, size) == 0); + } + Require(FT_Done_Face_nid_postfix(face) == 0 && FT_Done_Face(nativeFace) == 0); + Require(FT_Done_FreeType_nid_postfix(library) == 0 && FT_Done_FreeType(nativeLibrary) == 0); +} + +static void CheckOutlineCopies() { + InvalidAndSelfCopies(); + for (const int sourceFlags : {0, FT_OUTLINE_OWNER, FT_OUTLINE_REVERSE_FILL, -1}) { + for (const int targetFlags : {0, FT_OUTLINE_OWNER, FT_OUTLINE_EVEN_ODD_FILL, -1}) { + CopyCase(0, 0, sourceFlags, targetFlags, false); + CopyCase(4, 2, sourceFlags, targetFlags, false); + CopyCase(4, 2, sourceFlags, targetFlags, true); + } + } + CopyCase(65535, 65535, FT_OUTLINE_REVERSE_FILL, FT_OUTLINE_OWNER, false); + CopyCase(65535, 65535, FT_OUTLINE_OWNER, 0, true); + std::mt19937 random(0xF7C0); + for (unsigned index = 0; index < 128; ++index) { + const auto count = static_cast(random() % 256 + 1); + const auto contours = static_cast(random() % (count + 1)); + const auto sourceFlags = static_cast(random() & 0x7FFFFFFFu); + const auto targetFlags = static_cast(random() & 0x7FFFFFFFu); + CopyCase(count, contours, sourceFlags, targetFlags, false); + } + RenderCopy(); + std::puts("FreeType outline copy: 178 copy cases, validation, self-copy and 3 rendered copies passed"); +} + static void SetFinalizers(GuestFaceRec* face, Finalizers& events) { face->generic = {&events, GuestFaceFinalizer}; face->glyph->generic = {&events, GuestSlotFinalizer}; @@ -706,7 +1158,7 @@ static void CheckTransforms(const std::vector& font) { FT_Library native = nullptr; FT_Face host = nullptr; FT_Face nativeOther = nullptr; - void* library = nullptr; + FreeType::GuestLibrary* library = nullptr; GuestFaceRec* face = nullptr; GuestFaceRec* other = nullptr; Require(FT_Init_FreeType(&native) == 0 && FT_Init_FreeType_nid_postfix(&library) == 0); @@ -734,6 +1186,7 @@ static void CheckTransforms(const std::vector& font) { std::memcpy(savedSlot.data(), face->glyph, savedSlot.size()); std::memcpy(savedSize.data(), face->size, savedSize.size()); FT_Set_Transform_nid_postfix(face, m < matrices.size() ? &input : nullptr, d < deltas.size() ? &delta : nullptr); + FT_Set_Transform(host, m < matrices.size() ? &matrix : nullptr, d < deltas.size() ? &translation : nullptr); Require(std::memcmp(savedSlot.data(), face->glyph, savedSlot.size()) == 0); Require(std::memcmp(savedSize.data(), face->size, savedSize.size()) == 0); @@ -785,6 +1238,7 @@ static void CheckTransforms(const std::vector& font) { rejectedDelta.x = std::numeric_limits::min(); FT_Set_Transform_nid_postfix(nullptr, &rejected, &rejectedDelta); FT_Set_Transform_nid_postfix(nullptr, nullptr, nullptr); + Require(FT_Done_FreeType_nid_postfix(library) == 0 && FT_Done_FreeType(native) == 0); std::printf("FT_Set_Transform: %zu native glyph and bitmap comparisons\n", comparisons); } @@ -794,7 +1248,9 @@ int main() { std::filesystem::create_directories(root / "app0"); CheckGasp(); Trigonometry(); + OutlineDecomposition(); const std::vector font = SquareGlyphFont('A', 700); + CheckOutlineCopies(); { std::ofstream file(root / "app0" / "font.ttf", std::ios::binary); file.write(reinterpret_cast(font.data()), static_cast(font.size())); @@ -813,7 +1269,7 @@ int main() { Require(secondFace != 0); Require(FT_Init_FreeType_nid_postfix(nullptr) == FT_Err_Invalid_Argument); - void* library = nullptr; + FreeType::GuestLibrary* library = nullptr; Require(FT_Init_FreeType_nid_postfix(&library) == 0 && library != nullptr); Require(FT_Done_FreeType_nid_postfix(nullptr) == FT_Err_Invalid_Library_Handle); Require(FT_Done_Face_nid_postfix(nullptr) == FT_Err_Invalid_Face_Handle); @@ -831,6 +1287,8 @@ int main() { Require(FT_New_Face_nid_postfix(library, "/app0/font.ttf", 0, &face) == 0 && face != nullptr && face != masked); FaceMatches(face, host, library); + CheckStrikeSelection(library, hostLibrary, face, host); + const auto fontSize = static_cast(font.size()); GuestFaceRec* memoryFace = nullptr; Require(FT_New_Memory_Face_nid_postfix(library, nullptr, fontSize, 0, &memoryFace) == FT_Err_Invalid_Argument); @@ -1106,7 +1564,7 @@ int main() { SetFinalizers(memoryFace, guestSecondEvents); Require(FT_Done_FreeType(hostLibrary) == 0); - void* independent = nullptr; + FreeType::GuestLibrary* independent = nullptr; GuestFaceRec* independentFace = nullptr; Require(FT_Init_FreeType_nid_postfix(&independent) == 0); Require(FT_New_Memory_Face_nid_postfix(independent, font.data(), fontSize, 0, &independentFace) == 0); @@ -1118,7 +1576,7 @@ int main() { Require(FT_Get_Char_Index_nid_postfix(independentFace, 'A') == 1); Require(FT_Done_FreeType_nid_postfix(independent) == 0 && independentEvents.calls == nativeDone.calls); - void* empty = nullptr; + FreeType::GuestLibrary* empty = nullptr; Require(FT_Init_FreeType_nid_postfix(&empty) == 0 && FT_Done_FreeType_nid_postfix(empty) == 0); CheckTransforms(font); std::filesystem::current_path(previous); diff --git a/core/libs/tests/GuestFreeTypeBitmap.cpp b/core/libs/tests/GuestFreeTypeBitmap.cpp index a0d5ddb9bc..6a05b55c58 100644 --- a/core/libs/tests/GuestFreeTypeBitmap.cpp +++ b/core/libs/tests/GuestFreeTypeBitmap.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceFreeType/include/Api.hpp" #include "FontFixture.hpp" #include "prx/libSceFreeType/include/GuestObjects.hpp" #include "prx/libc/include/general/VabiMacros.hpp" @@ -18,15 +19,6 @@ using namespace FreeType; -extern "C" { -int APS5_VABI FT_Init_FreeType_nid_postfix(GuestLibrary**); -int APS5_VABI FT_Load_Glyph_nid_postfix(GuestFaceRec*, std::uint32_t, std::int32_t); -void APS5_VABI FT_Bitmap_New_nid_postfix(GuestBitmap*); -int APS5_VABI FT_Bitmap_Copy_nid_postfix(GuestLibrary*, const GuestBitmap*, GuestBitmap*); -int APS5_VABI FT_Bitmap_Convert_nid_postfix(GuestLibrary*, const GuestBitmap*, GuestBitmap*, std::int32_t); -int APS5_VABI FT_Bitmap_Done_nid_postfix(GuestLibrary*, GuestBitmap*); -} - static void Check(bool value, int line) { if (!value) { std::fprintf(stderr, "FreeType bitmap check failed at line %d\n", line); diff --git a/core/libs/tests/GuestFreeTypeCharmap.cpp b/core/libs/tests/GuestFreeTypeCharmap.cpp index 27372b1526..cfa8f479b9 100644 --- a/core/libs/tests/GuestFreeTypeCharmap.cpp +++ b/core/libs/tests/GuestFreeTypeCharmap.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceFreeType/include/Api.hpp" #include "FreeTypeFontFixture.hpp" #include "prx/libSceFreeType/include/GuestFreeType.hpp" #include "prx/libc/include/general/VabiMacros.hpp" @@ -19,17 +20,6 @@ using namespace FreeType; -extern "C" { -int APS5_VABI FT_Init_FreeType_nid_postfix(void**); -int APS5_VABI FT_New_Face_nid_postfix(void*, const char*, std::int64_t, GuestFaceRec**); -std::uint32_t APS5_VABI FT_Get_Char_Index_nid_postfix(GuestFaceRec*, std::uint64_t); -int APS5_VABI FT_Load_Glyph_nid_postfix(GuestFaceRec*, std::uint32_t, std::int32_t); -int APS5_VABI FT_Select_Charmap_nid_postfix(GuestFaceRec*, std::int32_t); -int APS5_VABI FT_Set_Charmap_nid_postfix(GuestFaceRec*, GuestCharMapRec*); -std::uint64_t APS5_VABI FT_Get_First_Char_nid_postfix(GuestFaceRec*, std::uint32_t*); -std::uint64_t APS5_VABI FT_Get_Next_Char_nid_postfix(GuestFaceRec*, std::uint64_t, std::uint32_t*); -} - static void Check(bool value, int line) { if (!value) { std::fprintf(stderr, "FreeType charmap check failed at line %d\n", line); @@ -76,7 +66,7 @@ int main() { Require(FT_New_Memory_Face(native, font.data(), static_cast(font.size()), 0, &host) == 0); Require(FT_New_Memory_Face(native, font.data(), static_cast(font.size()), 0, &foreignHost) == 0); Require(FT_New_Memory_Face(native, zeroFont.data(), static_cast(zeroFont.size()), 0, &zeroHost) == 0); - void* library = nullptr; + FreeType::GuestLibrary* library = nullptr; GuestFaceRec* face = nullptr; GuestFaceRec* foreign = nullptr; GuestFaceRec* zero = nullptr; diff --git a/core/libs/tests/GuestFreeTypeCharmapInfo.cpp b/core/libs/tests/GuestFreeTypeCharmapInfo.cpp index 1c8ec9dd5a..33c47e7d1c 100644 --- a/core/libs/tests/GuestFreeTypeCharmapInfo.cpp +++ b/core/libs/tests/GuestFreeTypeCharmapInfo.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceFreeType/include/Api.hpp" #include "FontFixture.hpp" #include "prx/libSceFreeType/include/GuestObjects.hpp" #include "prx/libc/include/general/VabiMacros.hpp" @@ -14,13 +15,6 @@ using namespace FreeType; -extern "C" { -int APS5_VABI FT_Get_Charmap_Index_nid_postfix(GuestCharMapRec*); -std::uint64_t APS5_VABI FT_Get_CMap_Language_ID_nid_postfix(GuestCharMapRec*); -std::int64_t APS5_VABI FT_Get_CMap_Format_nid_postfix(GuestCharMapRec*); -int APS5_VABI FT_Set_Charmap_nid_postfix(GuestFaceRec*, GuestCharMapRec*); -} - static void Check(bool value, int line) { if (!value) { std::fprintf(stderr, "FreeType charmap info check failed at line %d\n", line); diff --git a/core/libs/tests/GuestFreeTypeFaceInfo.cpp b/core/libs/tests/GuestFreeTypeFaceInfo.cpp index f30e8e8a78..65ca766d9b 100644 --- a/core/libs/tests/GuestFreeTypeFaceInfo.cpp +++ b/core/libs/tests/GuestFreeTypeFaceInfo.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceFreeType/include/Api.hpp" #include "FontFixture.hpp" #include "prx/libSceFreeType/include/GuestObjects.hpp" #include "prx/libc/include/general/VabiMacros.hpp" @@ -13,11 +14,6 @@ using namespace FreeType; -extern "C" { -const char* APS5_VABI FT_Get_X11_Font_Format_nid_postfix(GuestFaceRec*); -std::uint16_t APS5_VABI FT_Get_FSType_Flags_nid_postfix(GuestFaceRec*); -} - static void Check(bool value, int line) { if (!value) { std::fprintf(stderr, "FreeType face info check failed at line %d\n", line); diff --git a/core/libs/tests/GuestFreeTypeList.cpp b/core/libs/tests/GuestFreeTypeList.cpp index ba2a805e48..0e93a0d850 100644 --- a/core/libs/tests/GuestFreeTypeList.cpp +++ b/core/libs/tests/GuestFreeTypeList.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceFreeType/include/Api.hpp" #include "prx/libSceFreeType/include/GuestList.hpp" #include @@ -9,16 +10,6 @@ using namespace FreeType; -extern "C" { -GuestListNodeRec* APS5_VABI FT_List_Find_nid_postfix(GuestListRec*, void*); -void APS5_VABI FT_List_Add_nid_postfix(GuestListRec*, GuestListNodeRec*); -void APS5_VABI FT_List_Insert_nid_postfix(GuestListRec*, GuestListNodeRec*); -void APS5_VABI FT_List_Remove_nid_postfix(GuestListRec*, GuestListNodeRec*); -void APS5_VABI FT_List_Up_nid_postfix(GuestListRec*, GuestListNodeRec*); -int APS5_VABI FT_List_Iterate_nid_postfix(GuestListRec*, GuestListIterator, void*); -void APS5_VABI FT_List_Finalize_nid_postfix(GuestListRec*, GuestListDestructor, GuestMemoryRec*, void*); -} - static void Check(bool value, int line) { if (!value) { std::fprintf(stderr, "FreeType list check failed at line %d\n", line); @@ -62,6 +53,7 @@ struct Lists { void Fill() { for (std::size_t i = 0; i < Count; ++i) { FT_List_Add_nid_postfix(&guest, &actual[i]); + FT_List_Add(&native, &expected[i]); } Match(); @@ -79,10 +71,12 @@ static void Mutations() { if (active[i]) { if (choice) { FT_List_Up_nid_postfix(&lists.guest, &lists.actual[i]); + FT_List_Up(&lists.native, &lists.expected[i]); ++operations[3]; } else { FT_List_Remove_nid_postfix(&lists.guest, &lists.actual[i]); + FT_List_Remove(&lists.native, &lists.expected[i]); active[i] = false; ++operations[2]; @@ -90,10 +84,12 @@ static void Mutations() { } else { if (choice) { FT_List_Insert_nid_postfix(&lists.guest, &lists.actual[i]); + FT_List_Insert(&lists.native, &lists.expected[i]); ++operations[1]; } else { FT_List_Add_nid_postfix(&lists.guest, &lists.actual[i]); + FT_List_Add(&lists.native, &lists.expected[i]); ++operations[0]; } @@ -236,14 +232,18 @@ static void FinalizationCases() { guest.live.emplace(a, i); native.live.emplace(b, i); FT_List_Add_nid_postfix(&guestList, a); + FT_List_Add(&nativeList, b); } const auto savedHead = guestList.head; FT_List_Finalize_nid_postfix(&guestList, GuestDestroy, nullptr, &token); + Require(guestList.head == savedHead && guest.events.empty()); FT_List_Finalize_nid_postfix(nullptr, GuestDestroy, &guestMemory, &token); + Require(guest.events.empty()); FT_List_Finalize_nid_postfix(&guestList, destroy ? GuestDestroy : nullptr, &guestMemory, &token); + FT_List_Finalize(&nativeList, destroy ? NativeDestroy : nullptr, &nativeMemory, &token); Require(guestList.head == nullptr && guestList.tail == nullptr && nativeList.head == nullptr && nativeList.tail == nullptr); Require(guest.live.empty() && native.live.empty()); diff --git a/core/libs/tests/GuestFreeTypeNames.cpp b/core/libs/tests/GuestFreeTypeNames.cpp index a6aa3b7673..7ae21fde1a 100644 --- a/core/libs/tests/GuestFreeTypeNames.cpp +++ b/core/libs/tests/GuestFreeTypeNames.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceFreeType/include/Api.hpp" #include "FontFixture.hpp" #include "prx/libSceFreeType/include/GuestObjects.hpp" #include "prx/libc/include/general/VabiMacros.hpp" @@ -13,12 +14,6 @@ using namespace FreeType; -extern "C" { -int APS5_VABI FT_Get_Glyph_Name_nid_postfix(GuestFaceRec*, std::uint32_t, void*, std::uint32_t); -std::uint32_t APS5_VABI FT_Get_Name_Index_nid_postfix(GuestFaceRec*, const char*); -const char* APS5_VABI FT_Get_Postscript_Name_nid_postfix(GuestFaceRec*); -} - static void Check(bool value, int line) { if (!value) { std::fprintf(stderr, "FreeType names check failed at line %d\n", line); diff --git a/core/libs/tests/GuestFreeTypeOutline.cpp b/core/libs/tests/GuestFreeTypeOutline.cpp index 234090218f..39013980a0 100644 --- a/core/libs/tests/GuestFreeTypeOutline.cpp +++ b/core/libs/tests/GuestFreeTypeOutline.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceFreeType/include/Api.hpp" #include "prx/libSceFreeType/include/GuestFreeType.hpp" #include "prx/libc/include/general/VabiMacros.hpp" @@ -13,11 +14,6 @@ using namespace FreeType; -extern "C" { -int APS5_VABI FT_Outline_Check_nid_postfix(GuestOutline*); -void APS5_VABI FT_Outline_Get_CBox_nid_postfix(const GuestOutline*, GuestBBox*); -} - static void Check(bool value, int line) { if (!value) { std::fprintf(stderr, "FreeType outline check failed at line %d\n", line); @@ -62,9 +58,11 @@ static void CompareBounds(std::vector points) { FT_BBox expected{91, 92, 93, 94}; FT_Outline_Get_CBox(&native, &expected); FT_Outline_Get_CBox_nid_postfix(&guest, &actual.value); + Require(Equal(actual.value, {expected.xMin, expected.yMin, expected.xMax, expected.yMax})); Require(actual.before == 0x1122334455667788 && actual.after == 0x8877665544332211); FT_Outline_Get_CBox_nid_postfix(&guest, nullptr); + Require(guest.n_contours == 65535 && guest.flags == 0x71 && guest.tags == nullptr && guest.contours == nullptr); } @@ -96,10 +94,13 @@ int main() { GuestOutline outline{0, static_cast(wide.size()), wide.data(), nullptr, nullptr, 0}; GuestBBox box{1, 2, 3, 4}; FT_Outline_Get_CBox_nid_postfix(&outline, &box); + Require(Equal(box, {std::numeric_limits::min(), std::numeric_limits::min(), std::numeric_limits::max(), std::numeric_limits::max()})); const GuestBBox retained = box; FT_Outline_Get_CBox_nid_postfix(nullptr, &box); + Require(Equal(box, retained)); FT_Outline_Get_CBox_nid_postfix(nullptr, nullptr); + } diff --git a/core/libs/tests/GuestFreeTypeOutlineMutations.cpp b/core/libs/tests/GuestFreeTypeOutlineMutations.cpp index 67144147f3..b7e437d03e 100644 --- a/core/libs/tests/GuestFreeTypeOutlineMutations.cpp +++ b/core/libs/tests/GuestFreeTypeOutlineMutations.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceFreeType/include/Api.hpp" #include "FreeTypeFontFixture.hpp" #include "prx/libSceFreeType/include/GuestObjects.hpp" #include "prx/libc/include/general/VabiMacros.hpp" @@ -14,12 +15,6 @@ using namespace FreeType; -extern "C" { -void APS5_VABI FT_Outline_Translate_nid_postfix(const GuestOutline*, std::int64_t, std::int64_t); -void APS5_VABI FT_Outline_Reverse_nid_postfix(GuestOutline*); -int APS5_VABI FT_Render_Glyph_nid_postfix(GuestGlyphSlotRec*, std::int32_t); -} - static void Check(bool value, int line) { if (!value) { std::fprintf(stderr, "FreeType outline mutation check failed at line %d\n", line); @@ -54,6 +49,7 @@ static void ReverseOracle(std::size_t count, std::vector contours FT_Outline native{guest.n_contours, guest.n_points, nativePoints.data(), nativeTags.data(), contours.data(), flags}; FT_Outline_Reverse(&native); FT_Outline_Reverse_nid_postfix(&guest); + Require(guest.flags == native.flags && guest.flags == (flags ^ FT_OUTLINE_REVERSE_FILL)); Require(guest.n_points == count && guest.n_contours == contours.size() && contours == originalContours); for (std::size_t index = 0; index < count; ++index) { @@ -64,6 +60,7 @@ static void ReverseOracle(std::size_t count, std::vector contours Require(Equal(storage.front(), original.front()) && Equal(storage.back(), original.back())); Require(tags.front() == 0xA5 && tags.back() == 0xA5); FT_Outline_Reverse_nid_postfix(&guest); + Require(guest.flags == flags && tags == originalTags); for (std::size_t index = 0; index < storage.size(); ++index) Require(Equal(storage[index], original[index])); } @@ -80,6 +77,7 @@ static void TranslateOracle(std::size_t count, FT_Pos xOffset, FT_Pos yOffset) { FT_Outline native{guest.n_contours, guest.n_points, nativePoints.data(), nullptr, nullptr, guest.flags}; FT_Outline_Translate(&native, xOffset, yOffset); FT_Outline_Translate_nid_postfix(&guest, xOffset, yOffset); + for (std::size_t index = 0; index < count; ++index) { Require(storage[index + 1].x == nativePoints[index].x && storage[index + 1].y == nativePoints[index].y); } @@ -97,16 +95,20 @@ static void WideTranslation() { const std::array expected = {{{low, high}, {low + 1, high - 1}, {0, -1}, {2, -2}, {wide + 1, -wide - 1}, {high - 4, low + 4}}}; GuestOutline guest{0, static_cast(points.size()), points.data(), nullptr, nullptr, 0}; FT_Outline_Translate_nid_postfix(&guest, 1, -1); + for (std::size_t index = 0; index < points.size(); ++index) Require(Equal(points[index], expected[index])); FT_Outline_Translate_nid_postfix(&guest, -1, 1); + for (std::size_t index = 0; index < points.size(); ++index) Require(Equal(points[index], original[index])); GuestVector point{7, -9}; guest.n_points = 1; guest.points = &point; FT_Outline_Translate_nid_postfix(&guest, wide, -wide); + Require(Equal(point, {wide + 7, -wide - 9})); point = {low, 1}; FT_Outline_Translate_nid_postfix(&guest, low, high); + Require(Equal(point, {0, low})); } @@ -126,6 +128,7 @@ static void RenderModifiedOutline() { SyncFace(guest); FT_Outline_Reverse_nid_postfix(&guest.slot.outline); FT_Outline_Translate_nid_postfix(&guest.slot.outline, 77, -129); + FT_Outline_Reverse(&native->glyph->outline); FT_Outline_Translate(&native->glyph->outline, 77, -129); Require(FT_Render_Glyph_nid_postfix(&guest.slot, FT_RENDER_MODE_NORMAL) == FT_Render_Glyph(native->glyph, FT_RENDER_MODE_NORMAL)); @@ -144,6 +147,7 @@ static void RenderModifiedOutline() { int main() { FT_Outline_Reverse_nid_postfix(nullptr); FT_Outline_Translate_nid_postfix(nullptr, std::numeric_limits::min(), std::numeric_limits::max()); + ReverseOracle(0, {}, FT_OUTLINE_REVERSE_FILL); for (std::size_t count = 1; count <= 8; ++count) { for (unsigned mask = 0; mask < (1u << (count - 1)); ++mask) { diff --git a/core/libs/tests/GuestFreeTypeRequestSize.cpp b/core/libs/tests/GuestFreeTypeRequestSize.cpp index 536d8493b1..a1e8356b3d 100644 --- a/core/libs/tests/GuestFreeTypeRequestSize.cpp +++ b/core/libs/tests/GuestFreeTypeRequestSize.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceFreeType/include/Api.hpp" #include "FreeTypeFontFixture.hpp" #include "prx/libSceFreeType/include/GuestFreeType.hpp" @@ -17,14 +18,6 @@ using namespace FreeType; -extern "C" { -int APS5_VABI FT_Init_FreeType_nid_postfix(void**); -int APS5_VABI FT_Done_FreeType_nid_postfix(void*); -int APS5_VABI FT_New_Memory_Face_nid_postfix(void*, const unsigned char*, std::int64_t, std::int64_t, GuestFaceRec**); -int APS5_VABI FT_Request_Size_nid_postfix(GuestFaceRec*, const GuestSizeRequestRec*); -int APS5_VABI FT_Load_Glyph_nid_postfix(GuestFaceRec*, std::uint32_t, std::int32_t); -} - static void Check(bool value, int line) { if (!value) { std::fprintf(stderr, "FreeType size request check failed at line %d\n", line); @@ -37,7 +30,7 @@ struct Fixture { std::vector bytes; FT_Library library = nullptr; FT_Face native = nullptr; - void* guestLibrary = nullptr; + FreeType::GuestLibrary* guestLibrary = nullptr; GuestFaceRec* guest = nullptr; explicit Fixture(std::vector font, int faceIndex = 0) : bytes(std::move(font)) { @@ -155,6 +148,7 @@ static void CheckInvalid() { bool threw = false; try { FT_Request_Size_nid_postfix(fixture.guest, &request); + } catch (const std::runtime_error&) { threw = true; } diff --git a/core/libs/tests/GuestFreeTypeSfntNames.cpp b/core/libs/tests/GuestFreeTypeSfntNames.cpp index 12affd6cbd..4cd1e8f14c 100644 --- a/core/libs/tests/GuestFreeTypeSfntNames.cpp +++ b/core/libs/tests/GuestFreeTypeSfntNames.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceFreeType/include/Api.hpp" #include "FontFixture.hpp" #include "prx/libSceFreeType/include/GuestObjects.hpp" #include "prx/libc/include/general/VabiMacros.hpp" @@ -14,11 +15,6 @@ using namespace FreeType; -extern "C" { -std::uint32_t APS5_VABI FT_Get_Sfnt_Name_Count_nid_postfix(GuestFaceRec*); -int APS5_VABI FT_Get_Sfnt_Name_nid_postfix(GuestFaceRec*, std::uint32_t, GuestSfntName*); -} - static void Check(bool value, int line) { if (!value) { std::fprintf(stderr, "FreeType SFNT names check failed at line %d\n", line); diff --git a/core/libs/tests/GuestFreebsdClocks.cpp b/core/libs/tests/GuestFreebsdClocks.cpp index 40972ab464..1ae0f71258 100644 --- a/core/libs/tests/GuestFreebsdClocks.cpp +++ b/core/libs/tests/GuestFreebsdClocks.cpp @@ -1,3 +1,6 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libkernel/Time/include/Time.hpp" +#include "prx/libc/include/Api.hpp" #include "SceTypes.hpp" #include #include @@ -8,20 +11,6 @@ #include #include -extern "C" { -int APS5_VABI clock_gettime_nid_postfix(int clockId, KernelTimespec* tp); -int APS5_VABI clock_getres_nid_postfix(int clockId, KernelTimespec* res); -int APS5_VABI clock_settime_nid_postfix(int clockId, const KernelTimespec* tp); -int APS5_VABI sceKernelClockGettime(KernelClockid clockId, KernelTimespec* tp); -int APS5_VABI sceKernelClockGetres(KernelClockid clockId, KernelTimespec* tp); -int* APS5_VABI __error_nid_postfix(); -int APS5_VABI sceKernelUsleep_nid_postfix(KernelUseconds microseconds); -int APS5_VABI gettimeofday_nid_postfix(KernelTimeval* tv, KernelTimezone* tz); -std::int64_t APS5_VABI _Xtime_get_ticks_nid_postfix(); -int APS5_VABI sceKernelConvertLocaltimeToUtc(std::int64_t, std::int64_t, std::int64_t*, KernelTimesec*, std::int32_t*); -int APS5_VABI sceKernelConvertUtcToLocaltime(std::int64_t, std::int64_t*, KernelTimesec*, std::int32_t*); -} - static constexpr int SCE_OK = 0; static constexpr int GUEST_CLOCK_REALTIME = 0; @@ -70,6 +59,7 @@ static void UnsupportedResolutionStillThrows() { bool rejected = false; try { clock_getres_nid_postfix(3, &resolution); + } catch (const std::runtime_error&) { rejected = true; } @@ -88,6 +78,7 @@ static void OmittedTimeIsFaultAfterClockValidation() { bool rejected = false; try { clock_gettime_nid_postfix(3, nullptr); + } catch (const std::runtime_error&) { rejected = true; } @@ -244,6 +235,7 @@ static void RequireSettimeError(int clockId, const KernelTimespec* time, int err static bool SettimeThrows(const KernelTimespec& time, const char* requested) { try { clock_settime_nid_postfix(GUEST_CLOCK_REALTIME, &time); + } catch (const std::runtime_error& error) { return std::strstr(error.what(), requested) != nullptr; } diff --git a/core/libs/tests/GuestFreopenHostStandard.cpp b/core/libs/tests/GuestFreopenHostStandard.cpp index 24669afdc8..cf8e85e536 100644 --- a/core/libs/tests/GuestFreopenHostStandard.cpp +++ b/core/libs/tests/GuestFreopenHostStandard.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/FileStream.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -18,8 +19,7 @@ #endif extern "C" { -FileStream* APS5_VABI freopen_nid_postfix(const char* filename, const char* mode, FileStream* stream); -int APS5_VABI fputs_nid_postfix(const char* str, FileStream* stream); + extern FileStream* __stdoutp_nid_postfix; } diff --git a/core/libs/tests/GuestFstatFault.cpp b/core/libs/tests/GuestFstatFault.cpp index 06524f7df8..669cb3c903 100644 --- a/core/libs/tests/GuestFstatFault.cpp +++ b/core/libs/tests/GuestFstatFault.cpp @@ -1,23 +1,34 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libkernel/File/include/File.hpp" +#include "prx/libc/include/Api.hpp" #include "SceTypes.hpp" #include "prx/libc/include/General.hpp" #include "prx/libkernel/File/include/FileFlags.hpp" #include +#include #include #include #include #include #include +#include #include -extern "C" { -std::int64_t APS5_VABI fstat_nid_disambig1_nid_postfix(int, FileStat*); -int APS5_VABI sceKernelFstat(int, FileStat*); -int APS5_VABI sceKernelOpen(const char*, int, std::uint16_t); -int APS5_VABI close_nid_postfix(int); -int APS5_VABI socketpair_nid_postfix(int, int, int, int*); -int* APS5_VABI __error_nid_postfix(); -} +#ifdef _WIN32 +#include +#else +#include +#include +#include +#endif +#ifdef __linux__ +#include +#include +#include +#include +#include +#endif static void Check(bool value, int line) { if (!value) { @@ -37,6 +48,72 @@ static void RequireFailure(int descriptor, int error) { Require(sceKernelFstat(descriptor, nullptr) == static_cast(0x80020000u | static_cast(error))); } +static void RequireBadPointerAt(int descriptor, const char* path, void* address) { + { + auto* bad = static_cast(address); + *__error_nid_postfix() = 0; + Require(fstat_nid_disambig1_nid_postfix(descriptor, bad) == -1 && *__error_nid_postfix() == GuestEfault); + Require(sceKernelFstat(descriptor, bad) == static_cast(0x80020000u | GuestEfault)); + *__error_nid_postfix() = 0; + Require(stat_nid_postfix(path, bad) == -1 && *__error_nid_postfix() == GuestEfault); + *__error_nid_postfix() = 0; + Require(lstat_nid_postfix(path, bad) == -1 && *__error_nid_postfix() == GuestEfault); + Require(sceKernelStat(path, bad) == static_cast(0x80020000u | GuestEfault)); + *__error_nid_postfix() = 0; + Require(_fstatfs_nid_postfix(descriptor, reinterpret_cast(bad)) == -1 && *__error_nid_postfix() == GuestEfault); + } +} + +static void RequireUnwritablePage(int descriptor, const char* path) { +#ifdef _WIN32 + void* page = VirtualAlloc(nullptr, 4096, MEM_COMMIT | MEM_RESERVE, PAGE_READONLY); + Require(page != nullptr); + void* none = VirtualAlloc(nullptr, 4096, MEM_COMMIT | MEM_RESERVE, PAGE_NOACCESS); + Require(none != nullptr); + RequireBadPointerAt(descriptor, path, page); + RequireBadPointerAt(descriptor, path, none); + VirtualFree(page, 0, MEM_RELEASE); + VirtualFree(none, 0, MEM_RELEASE); +#else + void* page = mmap(nullptr, 4096, PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + Require(page != MAP_FAILED); + void* none = mmap(nullptr, 4096, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + Require(none != MAP_FAILED); + RequireBadPointerAt(descriptor, path, page); + RequireBadPointerAt(descriptor, path, none); + munmap(page, 4096); + munmap(none, 4096); +#endif +} + +#ifdef __linux__ +static void RequireNonEfaultFailureThrows() { + const pid_t child = fork(); + Require(child >= 0); + if (child == 0) { + sock_filter filter[] = { + BPF_STMT(BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, nr)), + BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, SYS_process_vm_writev, 0, 1), + BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ERRNO | EPERM), + BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW), + }; + sock_fprog program{static_cast(sizeof(filter) / sizeof(filter[0])), filter}; + if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) != 0 || prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &program) != 0) _exit(2); + char source[8] = {1, 2, 3, 4, 5, 6, 7, 8}; + char destination[8] = {}; + try { + GuestCopyOut_nid_no_patch(destination, source, sizeof(source)); + } catch (const std::runtime_error&) { + _exit(destination[0] == 0 ? 0 : 3); + } + _exit(1); + } + int status = 0; + Require(waitpid(child, &status, 0) == child); + Require(WIFEXITED(status) && WEXITSTATUS(status) == 0); +} +#endif + int main() { const auto root = std::filesystem::temp_directory_path() / ("anyps5-fstat-fault-" + std::to_string(std::chrono::steady_clock::now().time_since_epoch().count())); @@ -53,6 +130,12 @@ int main() { FileStat status{}; Require(fstat_nid_disambig1_nid_postfix(file, &status) == 0 && status.st_size == 5); RequireFailure(file, GuestEfault); + for (const std::uintptr_t address : {std::uintptr_t{1}, ~std::uintptr_t{0xfff}}) + RequireBadPointerAt(file, "/anyps5-fstat-fault-test/file.txt", reinterpret_cast(address)); + RequireUnwritablePage(file, "/anyps5-fstat-fault-test/file.txt"); +#ifdef __linux__ + RequireNonEfaultFailureThrows(); +#endif int sockets[2]; Require(socketpair_nid_postfix(1, 1, 0, sockets) == 0); diff --git a/core/libs/tests/GuestFstatfs.cpp b/core/libs/tests/GuestFstatfs.cpp index 1a647f6094..9950e6b9dc 100644 --- a/core/libs/tests/GuestFstatfs.cpp +++ b/core/libs/tests/GuestFstatfs.cpp @@ -1,3 +1,6 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libkernel/File/include/File.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/General.hpp" #include "prx/libkernel/File/include/FileFlags.hpp" @@ -36,16 +39,6 @@ struct GuestStatfs { }; static_assert(sizeof(GuestStatfs) == 472); -extern "C" { -int APS5_VABI _fstatfs_nid_postfix(int, GuestStatfs*); -int APS5_VABI sceKernelOpen(const char*, int, std::uint16_t); -int APS5_VABI close_nid_postfix(int); -int APS5_VABI pipe_nid_postfix(int*); -int APS5_VABI socketpair_nid_postfix(int, int, int, int*); -int APS5_VABI kqueue_nid_postfix(); -int* APS5_VABI __error_nid_postfix(); -} - static void Check(bool value, int line) { if (!value) { std::fprintf(stderr, "fstatfs check failed at line %d\n", line); @@ -64,7 +57,7 @@ static void RequireFailure(int descriptor, int error) { GuestStatfs fs; std::memset(&fs, 0x5a, sizeof(fs)); *__error_nid_postfix() = 0; - Require(_fstatfs_nid_postfix(descriptor, &fs) == -1); + Require(_fstatfs_nid_postfix(descriptor, reinterpret_cast(&fs)) == -1); Require(*__error_nid_postfix() == error); for (std::size_t i = 0; i < sizeof(fs); ++i) Require(reinterpret_cast(&fs)[i] == 0x5a); } @@ -72,7 +65,7 @@ static void RequireFailure(int descriptor, int error) { static void RequireVolume(int descriptor, const std::filesystem::path& path) { GuestStatfs fs; std::memset(&fs, 0x5a, sizeof(fs)); - Require(_fstatfs_nid_postfix(descriptor, &fs) == 0); + Require(_fstatfs_nid_postfix(descriptor, reinterpret_cast(&fs)) == 0); const auto space = std::filesystem::space(path); Require(fs.f_version == StatfsVersion); Require(fs.f_bsize > 0 && fs.f_iosize > 0); @@ -87,7 +80,7 @@ static void RequireVolume(int descriptor, const std::filesystem::path& path) { static void RequireDeviceFilesystem(int descriptor) { GuestStatfs fs; std::memset(&fs, 0x5a, sizeof(fs)); - Require(_fstatfs_nid_postfix(descriptor, &fs) == 0); + Require(_fstatfs_nid_postfix(descriptor, reinterpret_cast(&fs)) == 0); GuestStatfs expected{}; expected.f_version = StatfsVersion; expected.f_bsize = 512; diff --git a/core/libs/tests/GuestFstatvfs.cpp b/core/libs/tests/GuestFstatvfs.cpp index 487e8bacc7..9137793fbb 100644 --- a/core/libs/tests/GuestFstatvfs.cpp +++ b/core/libs/tests/GuestFstatvfs.cpp @@ -1,3 +1,7 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libkernel/File/include/File.hpp" +#include "prx/libc/include/Api.hpp" +#include "prx/libSceLibcInternal/include/Api.hpp" #include "prx/libc/include/General.hpp" #include "prx/libkernel/File/include/FileFlags.hpp" #include @@ -11,16 +15,6 @@ #include #include -extern "C" { -int APS5_VABI fstatvfs_nid_postfix(int, void*); -int APS5_VABI sceKernelOpen(const char*, int, std::uint16_t); -std::int64_t APS5_VABI sceKernelLseek(int, std::int64_t, int); -int APS5_VABI close_nid_postfix(int); -int APS5_VABI pipe_nid_postfix(int*); -int APS5_VABI socketpair_nid_postfix(int, int, int, int*); -int* APS5_VABI __error_nid_postfix(); -} - static void Check(bool value, int line) { if (!value) { std::fprintf(stderr, "fstatvfs check failed at line %d\n", line); @@ -34,7 +28,7 @@ static void RequireFailure(int descriptor, int error) { output.fill(0x5A5A5A5A5A5A5A5Aull); const auto saved = output; *__error_nid_postfix() = 0; - Require(fstatvfs_nid_postfix(descriptor, output.data()) == -1); + Require(fstatvfs_nid_postfix(descriptor, reinterpret_cast(output.data())) == -1); Require(*__error_nid_postfix() == error); Require(output == saved); } @@ -43,7 +37,7 @@ static void RequireVolume(int descriptor, const std::filesystem::path& path) { std::array guarded; guarded.fill(0xA5A5A5A5A5A5A5A5ull); *__error_nid_postfix() = 12345; - Require(fstatvfs_nid_postfix(descriptor, guarded.data() + 1) == 0); + Require(fstatvfs_nid_postfix(descriptor, reinterpret_cast(guarded.data() + 1)) == 0); Require(*__error_nid_postfix() == 12345); Require(guarded.front() == 0xA5A5A5A5A5A5A5A5ull && guarded.back() == guarded.front()); const auto* fields = guarded.data() + 1; diff --git a/core/libs/tests/GuestFstatvfsConversion.cpp b/core/libs/tests/GuestFstatvfsConversion.cpp index f93e221e6b..d8533937ad 100644 --- a/core/libs/tests/GuestFstatvfsConversion.cpp +++ b/core/libs/tests/GuestFstatvfsConversion.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceLibcInternal/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libkernel/File/include/KernelStatfs.hpp" #include @@ -7,8 +8,6 @@ #include #include -extern "C" int APS5_VABI fstatvfs_nid_postfix(int, void*); - namespace { KernelStatfs backend; int backendError; @@ -55,7 +54,7 @@ int main() { }; const int before = calls; guestError = 12345; - Require(fstatvfs_nid_postfix(42, output.data() + 1) == 0); + Require(fstatvfs_nid_postfix(42, reinterpret_cast(output.data() + 1)) == 0); Require(calls == before + 1 && guestError == 12345); Require(output.front() == 0xA5A5A5A5A5A5A5A5ull && output.back() == output.front()); Require(std::memcmp(output.data() + 1, expected.data(), sizeof(expected)) == 0); @@ -63,7 +62,7 @@ int main() { backend.f_bavail = -1; backend.f_ffree = -2; std::array output{}; - Require(fstatvfs_nid_postfix(42, output.data()) == 0); + Require(fstatvfs_nid_postfix(42, reinterpret_cast(output.data())) == 0); Require(output[0] == std::numeric_limits::max()); Require(output[3] == std::numeric_limits::max() - 1 && output[4] == output[3]); Require(fstatvfs_nid_postfix(42, nullptr) == -1 && guestError == 14); @@ -71,7 +70,7 @@ int main() { backendError = failure; output.fill(0x5A5A5A5A5A5A5A5Aull); const auto saved = output; - Require(fstatvfs_nid_postfix(42, output.data()) == -1 && guestError == failure); + Require(fstatvfs_nid_postfix(42, reinterpret_cast(output.data())) == -1 && guestError == failure); Require(output == saved); Require(fstatvfs_nid_postfix(42, nullptr) == -1 && guestError == failure); } diff --git a/core/libs/tests/GuestG2PDialog.cpp b/core/libs/tests/GuestG2PDialog.cpp index a318e77f68..afb2800b64 100644 --- a/core/libs/tests/GuestG2PDialog.cpp +++ b/core/libs/tests/GuestG2PDialog.cpp @@ -1,21 +1,10 @@ +#include "prx/libSceCdlgG2P/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include "prx/libSceUserService/UserService.hpp" #include "prx/libSceCommonDialog/CommonDialog.hpp" #include -extern "C" { -int APS5_VABI sceUserServiceInitialize(const UserServiceInitParam* param); -int APS5_VABI sceUserServiceTerminate(); -int APS5_VABI sceG2PDialogInitialize(void); -int APS5_VABI sceG2PDialogOpen(const void* param); -int APS5_VABI sceG2PDialogUpdateStatus(void); -int APS5_VABI sceG2PDialogGetStatus(void); -int APS5_VABI sceG2PDialogGetResult(void* result); -int APS5_VABI sceG2PDialogClose(void); -int APS5_VABI sceG2PDialogTerminate(void); -} - namespace { void Require(bool value) { if (!value) std::abort(); } @@ -43,7 +32,7 @@ int main() { Require(sceG2PDialogTerminate() == kErrNotInitialized); Require(sceG2PDialogOpen(¶m) == kErrNotInitialized); Require(sceG2PDialogClose() == kErrNotInitialized); - Require(sceG2PDialogGetResult(result) == kErrNotInitialized); + Require(sceG2PDialogGetResult(reinterpret_cast(result)) == kErrNotInitialized); Require(sceG2PDialogOpen(nullptr) == static_cast(0x80B8000Du)); Require(sceG2PDialogGetResult(nullptr) == static_cast(0x80B8000Du)); Require(sceG2PDialogGetStatus() == kStatusNone); @@ -55,7 +44,7 @@ int main() { Require(sceG2PDialogUpdateStatus() == kStatusInitialized); Require(sceG2PDialogOpen(nullptr) == kErrArgNull); - Require(sceG2PDialogGetResult(result) == kErrNotFinished); + Require(sceG2PDialogGetResult(reinterpret_cast(result)) == kErrNotFinished); param.base.size = 0; Require(sceG2PDialogOpen(¶m) == static_cast(0x80B8000Au)); @@ -82,7 +71,7 @@ int main() { Require(sceG2PDialogUpdateStatus() == kStatusFinished); Require(sceG2PDialogGetResult(nullptr) == kErrArgNull); - Require(sceG2PDialogGetResult(result) == 0); + Require(sceG2PDialogGetResult(reinterpret_cast(result)) == 0); Require(result[0] == -1 && result[1] == -1 && result[3] == -1); Require(result[2] == kResultUserCanceled); Require(result[1] == -1); @@ -97,7 +86,7 @@ int main() { Require(sceG2PDialogClose() == static_cast(0x80B8000Bu)); Require(sceG2PDialogGetStatus() == kStatusInitialized); result[2] = -1; - Require(sceG2PDialogGetResult(result) == kErrNotFinished); + Require(sceG2PDialogGetResult(reinterpret_cast(result)) == kErrNotFinished); Require(result[0] == -1 && result[1] == -1 && result[3] == -1); Require(result[2] == -1); Require(sceG2PDialogTerminate() == 0); diff --git a/core/libs/tests/GuestGameCustomDataDialog.cpp b/core/libs/tests/GuestGameCustomDataDialog.cpp index f410bc031b..5d5d686a9b 100644 --- a/core/libs/tests/GuestGameCustomDataDialog.cpp +++ b/core/libs/tests/GuestGameCustomDataDialog.cpp @@ -1,17 +1,8 @@ +#include "prx/libSceGameCustomDataDialog/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include -extern "C" { -int APS5_VABI sceGameCustomDataDialogInitialize(void); -int APS5_VABI sceGameCustomDataDialogOpenA(const void* param); -int APS5_VABI sceGameCustomDataDialogUpdateStatus(void); -int APS5_VABI sceGameCustomDataDialogGetStatus(void); -int APS5_VABI sceGameCustomDataDialogGetResultA(void* result); -int APS5_VABI sceGameCustomDataDialogClose(void); -int APS5_VABI sceGameCustomDataDialogTerminate(void); -} - namespace { void Require(bool value) { if (!value) std::abort(); } diff --git a/core/libs/tests/GuestGameLiveStreaming.cpp b/core/libs/tests/GuestGameLiveStreaming.cpp index 22950d430e..7d641c4e23 100644 --- a/core/libs/tests/GuestGameLiveStreaming.cpp +++ b/core/libs/tests/GuestGameLiveStreaming.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceGameLiveStreaming/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -7,27 +8,8 @@ #include #include -struct GameLiveStreamingStatus2 { - std::int32_t userId; - bool isOnAir; - std::uint8_t align[3]; - std::uint32_t spectatorCounts; - std::uint32_t textMessageCounts; - std::uint32_t commandMessageCounts; - std::uint32_t broadcastVideoResolution; - std::uint8_t reserved[48]; -}; static_assert(sizeof(GameLiveStreamingStatus2) == 72); -extern "C" { -int APS5_VABI sceGameLiveStreamingInitialize(std::size_t heap_size); -int APS5_VABI sceGameLiveStreamingTerminate(void); -int APS5_VABI sceGameLiveStreamingGetCurrentStatus2(GameLiveStreamingStatus2* status); -struct GameLiveStreamingProgramInfo; -int APS5_VABI sceGameLiveStreamingGetProgramInfo(GameLiveStreamingProgramInfo*); -int APS5_VABI sceGameLiveStreamingEnableLiveStreaming(bool isEnableLiveStreaming); -} - namespace { void Require(bool value) { if (!value) std::abort(); } @@ -37,6 +19,7 @@ constexpr std::int32_t kInvalidUserId = -1; bool EnableThrowsNotInitialized(bool isEnableLiveStreaming) { try { sceGameLiveStreamingEnableLiveStreaming(isEnableLiveStreaming); + } catch (const std::logic_error&) { return true; } diff --git a/core/libs/tests/GuestGameUpdate.cpp b/core/libs/tests/GuestGameUpdate.cpp index c46d451c83..b3df072055 100644 --- a/core/libs/tests/GuestGameUpdate.cpp +++ b/core/libs/tests/GuestGameUpdate.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceGameUpdate/include/Api.hpp" #include "SceTypes.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -6,16 +7,6 @@ #include #include -extern "C" { -int APS5_VABI sceGameUpdateInitialize(void); -int APS5_VABI sceGameUpdateTerminate(void); -int APS5_VABI sceGameUpdateGetAddcontLatestVersion(std::uint32_t, const NpUnifiedEntitlementLabel*, GameUpdateAddcontVersionInfo*); -int APS5_VABI sceGameUpdateCreateRequest(void); -int APS5_VABI sceGameUpdateCheck(int, const GameUpdateCheckParam*, GameUpdateCheckResult*); -int APS5_VABI sceGameUpdateAbortRequest(int); -int APS5_VABI sceGameUpdateDeleteRequest(int); -} - static void Require(bool value) { if (!value) std::abort(); } template diff --git a/core/libs/tests/GuestGenericCategory.cpp b/core/libs/tests/GuestGenericCategory.cpp index bc279a1a56..36026d3f0b 100644 --- a/core/libs/tests/GuestGenericCategory.cpp +++ b/core/libs/tests/GuestGenericCategory.cpp @@ -1,6 +1,8 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/GuestLocale.hpp" #include "prx/libc/include/ApplicationHeap.hpp" #include +#include #include #include #include @@ -8,26 +10,14 @@ #include #include -struct Category { void* const* vtable; }; -struct ErrorCode { int reserved; int value; const Category* category; }; -using Message = GuestLocale::String* (APS5_VABI *)(GuestLocale::String*, const Category*, int); -using Name = const char* (APS5_VABI *)(const Category*); -using Condition = ErrorCode (APS5_VABI *)(const Category*, int); -using EquivalentCondition = bool (APS5_VABI *)(const Category*, int, const ErrorCode*); -using EquivalentCode = bool (APS5_VABI *)(const Category*, const ErrorCode*, int); -using Delete = void (APS5_VABI *)(const Category*); +using Message = GuestLocale::String* (APS5_VABI *)(GuestLocale::String*, const LibcException::CategoryObject*, int); +using Name = const char* (APS5_VABI *)(const LibcException::CategoryObject*); +using Condition = LibcException::ErrorCode (APS5_VABI *)(const LibcException::CategoryObject*, int); +using EquivalentCondition = bool (APS5_VABI *)(const LibcException::CategoryObject*, int, const LibcException::ErrorCode*); +using EquivalentCode = bool (APS5_VABI *)(const LibcException::CategoryObject*, const LibcException::ErrorCode*, int); +using Delete = void (APS5_VABI *)(const LibcException::CategoryObject*); struct TypeRecord { const void* vtable; const char* name; const TypeRecord* base; }; -extern "C" { -const char* APS5_VABI _ZSt13_Syserror_mapi_nid_postfix(int value); -const Category* APS5_VABI _ZSt16generic_categoryv_nid_postfix(); -const Category* APS5_VABI _ZSt15system_categoryv_nid_postfix(); -GuestLocale::String* APS5_VABI _ZNKSt23_Generic_error_category7messageEi_nid_postfix( - GuestLocale::String* result, const Category* self, int value); -int* APS5_VABI __error_nid_postfix(); -void APS5_VABI _ZdlPv_nid_postfix(void* pointer); -} - static void Require(bool value, int line) { if (value) return; std::fprintf(stderr, "generic category check failed at line %d\n", line); @@ -35,7 +25,7 @@ static void Require(bool value, int line) { } #define REQUIRE(value) Require((value), __LINE__) -static void CheckMessage(Message message, const Category* category, int value, const char* expected) { +static void CheckMessage(Message message, const LibcException::CategoryObject* category, int value, const char* expected) { constexpr std::uint64_t marker = 0xA55AA55AA55AA55Aull; struct Guarded { std::uint64_t before; GuestLocale::String result; std::uint64_t after; }; Guarded guarded {marker, {}, marker}; @@ -53,32 +43,32 @@ static void CheckMessage(Message message, const Category* category, int value, c if (length > 15) _ZdlPv_nid_postfix(guarded.result.pointer); } -static void CheckSystemCategory(const Category* generic) { - const Category* system = _ZSt15system_categoryv_nid_postfix(); +static void CheckSystemCategory(const LibcException::CategoryObject* generic) { + const LibcException::CategoryObject* system = _ZSt15system_categoryv_nid_postfix(); REQUIRE(system && system != generic && system == _ZSt15system_categoryv_nid_postfix()); - const auto* type = static_cast(system->vtable[-1]); + const auto* type = static_cast(static_cast(system->vtable)[-1]); REQUIRE(std::strcmp(type->name, "St22_System_error_category") == 0); REQUIRE(type->base && std::strcmp(type->base->name, "St14error_category") == 0); - REQUIRE(std::strcmp(reinterpret_cast(system->vtable[2])(system), "system") == 0); - const auto condition = reinterpret_cast(system->vtable[4]); - const ErrorCode known = condition(system, 2); + REQUIRE(std::strcmp(std::bit_cast(static_cast(system->vtable)[2])(system), "system") == 0); + const auto condition = std::bit_cast(static_cast(system->vtable)[4]); + const LibcException::ErrorCode known = condition(system, 2); std::uint64_t head = 0; std::memcpy(&head, &known, sizeof(head)); REQUIRE(head == std::uint64_t{2} << 32 && known.value == 2 && known.category == generic); - const ErrorCode unknown = condition(system, 44); + const LibcException::ErrorCode unknown = condition(system, 44); REQUIRE(unknown.reserved == 0 && unknown.value == 44 && unknown.category == system); - const auto equivalentCondition = reinterpret_cast(system->vtable[5]); + const auto equivalentCondition = std::bit_cast(static_cast(system->vtable)[5]); REQUIRE(equivalentCondition(system, 2, &known)); - const ErrorCode sameCategory {0, 2, system}; + const LibcException::ErrorCode sameCategory {0, 2, system}; REQUIRE(!equivalentCondition(system, 2, &sameCategory)); REQUIRE(equivalentCondition(system, 44, &unknown)); - const auto equivalentCode = reinterpret_cast(system->vtable[6]); + const auto equivalentCode = std::bit_cast(static_cast(system->vtable)[6]); REQUIRE(equivalentCode(system, &sameCategory, 2) && !equivalentCode(system, &known, 2)); - const auto message = reinterpret_cast(system->vtable[3]); + const auto message = std::bit_cast(static_cast(system->vtable)[3]); CheckMessage(message, system, 2, "no such file or directory"); CheckMessage(message, system, 44, "unknown error"); bool rejected = false; - try { reinterpret_cast(system->vtable[1])(system); } + try { std::bit_cast(static_cast(system->vtable)[1])(system); } catch (const std::invalid_argument&) { rejected = true; } REQUIRE(rejected); } @@ -86,13 +76,13 @@ static void CheckSystemCategory(const Category* generic) { int main() { const std::array api {}; ApplicationHeapRegister_nid_no_patch(api.data()); - const Category* category = _ZSt16generic_categoryv_nid_postfix(); + const LibcException::CategoryObject* category = _ZSt16generic_categoryv_nid_postfix(); REQUIRE(category && category == _ZSt16generic_categoryv_nid_postfix()); - REQUIRE(std::strcmp(reinterpret_cast(category->vtable[2])(category), "generic") == 0); - const auto message = reinterpret_cast(category->vtable[3]); - const auto condition = reinterpret_cast(category->vtable[4])(category, 35); + REQUIRE(std::strcmp(std::bit_cast(static_cast(category->vtable)[2])(category), "generic") == 0); + const auto message = std::bit_cast(static_cast(category->vtable)[3]); + const auto condition = std::bit_cast(static_cast(category->vtable)[4])(category, 35); REQUIRE(condition.reserved == 0 && condition.value == 35 && condition.category == category); - const auto equivalent = reinterpret_cast(category->vtable[5]); + const auto equivalent = std::bit_cast(static_cast(category->vtable)[5]); REQUIRE(equivalent(category, 35, &condition)); CheckSystemCategory(category); @@ -127,8 +117,10 @@ int main() { REQUIRE(message(&first, category, 25) == &first && message(&second, category, 11) == &second); REQUIRE(first.pointer != second.pointer); _ZdlPv_nid_postfix(second.pointer); + REQUIRE(std::strcmp(first.pointer, "inappropriate io control operation") == 0); _ZdlPv_nid_postfix(first.pointer); + bool rejected = false; try { message(nullptr, category, 22); } catch (const std::invalid_argument&) { rejected = true; } diff --git a/core/libs/tests/GuestGetitimer.cpp b/core/libs/tests/GuestGetitimer.cpp index 1fa5f82516..ae97af4f05 100644 --- a/core/libs/tests/GuestGetitimer.cpp +++ b/core/libs/tests/GuestGetitimer.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "SceTypes.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -10,19 +12,14 @@ #include #include -struct GuestItimerval { - KernelTimeval interval; - KernelTimeval value; -}; - static_assert(sizeof(GuestItimerval) == 32 && offsetof(GuestItimerval, value) == 16); extern "C" { -int APS5_VABI getitimer_nid_postfix(int, GuestItimerval*); + unsigned int APS5_VABI GuestAlarm_nid_no_patch(unsigned int); -int* APS5_VABI __error_nid_postfix(); + using Handler = void (APS5_VABI *)(int); -Handler APS5_VABI signal_nid_postfix(int, Handler); + } static void Require(bool value, const char* message) { diff --git a/core/libs/tests/GuestGetlogin.cpp b/core/libs/tests/GuestGetlogin.cpp index b006a283fc..385c37ce1a 100644 --- a/core/libs/tests/GuestGetlogin.cpp +++ b/core/libs/tests/GuestGetlogin.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -16,9 +18,6 @@ #include #endif -extern "C" int APS5_VABI getlogin_r_nid_postfix(char*, int); -extern "C" int* APS5_VABI __error_nid_postfix(); - static void Check(bool condition, int line) { if (!condition) { std::fprintf(stderr, "getlogin_r check failed at line %d\n", line); diff --git a/core/libs/tests/GuestGetloginNoSession.cpp b/core/libs/tests/GuestGetloginNoSession.cpp index c9f29f5513..fc31313d74 100644 --- a/core/libs/tests/GuestGetloginNoSession.cpp +++ b/core/libs/tests/GuestGetloginNoSession.cpp @@ -1,3 +1,4 @@ +#include "prx/libkernel/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -8,8 +9,6 @@ #include #include -extern "C" int APS5_VABI getlogin_r_nid_postfix(char*, int); - static int loginError = ENXIO; extern "C" int getlogin_r(char* output, std::size_t size) { diff --git a/core/libs/tests/GuestGetopt.cpp b/core/libs/tests/GuestGetopt.cpp index 26e0ca0803..13db14bc90 100644 --- a/core/libs/tests/GuestGetopt.cpp +++ b/core/libs/tests/GuestGetopt.cpp @@ -1,3 +1,5 @@ +#include "prx/libc/include/Api.hpp" +#include "prx/libSceLibcInternal/include/Api.hpp" #include "prx/libc/include/FileStream.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -7,19 +9,8 @@ #include #include -struct GuestOption { - const char* name; - int hasArgument; - int* flag; - int value; -}; - extern "C" { -int APS5_VABI getopt_nid_postfix(int, char* const*, const char*); -int APS5_VABI getopt_long_nid_postfix(int, char* const*, const char*, const GuestOption*, int*); -int APS5_VABI getopt_long_only_nid_postfix(int, char* const*, const char*, const GuestOption*, int*); -int APS5_VABI setenv_nid_postfix(const char*, const char*, int); -int APS5_VABI unsetenv_nid_postfix(const char*); + extern int opterr_nid_postfix; extern int optind_nid_postfix; extern int optopt_nid_postfix; diff --git a/core/libs/tests/GuestGetrlimit.cpp b/core/libs/tests/GuestGetrlimit.cpp index 14b00ab71a..9f2a39f589 100644 --- a/core/libs/tests/GuestGetrlimit.cpp +++ b/core/libs/tests/GuestGetrlimit.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -18,20 +20,6 @@ #include #endif -struct ResourceLimit { - std::int64_t rlim_cur; - std::int64_t rlim_max; -}; - -extern "C" int APS5_VABI getrlimit_nid_postfix(int resource, ResourceLimit* limit); -extern "C" int* APS5_VABI __error_nid_postfix(); -extern "C" int APS5_VABI getdtablesize_nid_postfix(void); -extern "C" int APS5_VABI setrlimit_nid_postfix(int resource, const ResourceLimit* limit); -extern "C" int APS5_VABI pipe_nid_postfix(int* descriptors); -extern "C" int APS5_VABI close_nid_postfix(int descriptor); -extern "C" void* APS5_VABI fopen_nid_postfix(const char* filename, const char* mode); -extern "C" int APS5_VABI fclose_nid_postfix(void* stream); - static constexpr int GUEST_EFAULT = 14; static constexpr int GUEST_EINVAL = 22; static constexpr int GUEST_RLIMIT_CPU = 0; @@ -54,15 +42,15 @@ static constexpr std::int64_t GUEST_RLIM_INFINITY = std::numeric_limits= 0 && limit.rlim_cur <= limit.rlim_max); return limit; } #if defined(_WIN32) || defined(__APPLE__) -static void RequireDescriptorsEndAt(const ResourceLimit& limit) { +static void RequireDescriptorsEndAt(const GuestResourceLimit& limit) { constexpr int GUEST_EMFILE = 24; std::vector descriptors; int pair[2]{-1, -1}; @@ -82,19 +70,19 @@ static void RequireDescriptorsEndAt(const ResourceLimit& limit) { #ifdef _WIN32 static void RequireStreamsOpen() { const auto path = (std::filesystem::temp_directory_path() / ("aps5-open-streams-" + std::to_string(GetCurrentProcessId()))).string(); - std::vector streams; + std::vector streams; for (int index = 0; index < 1024; ++index) { - void* stream = fopen_nid_postfix(path.c_str(), "ab"); + FileStream* stream = fopen_nid_postfix(path.c_str(), "ab"); Require(stream != nullptr); streams.push_back(stream); } - for (void* stream : streams) Require(fclose_nid_postfix(stream) == 0); + for (FileStream* stream : streams) Require(fclose_nid_postfix(stream) == 0); std::filesystem::remove(path); } #endif static void CheckOpenFileLimit() { - const ResourceLimit limit = GuestLimit(GUEST_RLIMIT_NOFILE); + const GuestResourceLimit limit = GuestLimit(GUEST_RLIMIT_NOFILE); Require(limit.rlim_cur == limit.rlim_max); #ifdef _WIN32 Require(limit.rlim_cur == 8192); @@ -114,20 +102,21 @@ static void CheckOpenFileLimit() { RequireDescriptorsEndAt(limit); #endif Require(setrlimit_nid_postfix(GUEST_RLIMIT_NOFILE, &limit) == 0); - const ResourceLimit lowered{limit.rlim_max > 1 ? limit.rlim_max - 1 : 1, limit.rlim_max}; + const GuestResourceLimit lowered{limit.rlim_max > 1 ? limit.rlim_max - 1 : 1, limit.rlim_max}; Require(setrlimit_nid_postfix(GUEST_RLIMIT_NOFILE, &lowered) == 0); - const ResourceLimit updated = GuestLimit(GUEST_RLIMIT_NOFILE); + const GuestResourceLimit updated = GuestLimit(GUEST_RLIMIT_NOFILE); Require(updated.rlim_cur == lowered.rlim_cur); Require(updated.rlim_max == lowered.rlim_max); Require(setrlimit_nid_postfix(GUEST_RLIMIT_NOFILE, &limit) == 0); - const ResourceLimit restored = GuestLimit(GUEST_RLIMIT_NOFILE); + const GuestResourceLimit restored = GuestLimit(GUEST_RLIMIT_NOFILE); Require(restored.rlim_cur == limit.rlim_cur); Require(restored.rlim_max == limit.rlim_max); if (limit.rlim_max != GUEST_RLIM_INFINITY) { - const ResourceLimit raised{limit.rlim_cur, limit.rlim_max + 1}; + const GuestResourceLimit raised{limit.rlim_cur, limit.rlim_max + 1}; bool raisedRejected = false; try { setrlimit_nid_postfix(GUEST_RLIMIT_NOFILE, &raised); + } catch (const std::runtime_error&) { raisedRejected = true; } @@ -135,14 +124,14 @@ static void CheckOpenFileLimit() { } } -static void RequireError(int resource, ResourceLimit* limit, int error) { +static void RequireError(int resource, GuestResourceLimit* limit, int error) { *__error_nid_postfix() = 0; Require(getrlimit_nid_postfix(resource, limit) == -1); Require(*__error_nid_postfix() == error); } static void RequireInvalidOutputPointer(int resource) { - auto* const invalid = reinterpret_cast(static_cast(1)); + auto* const invalid = reinterpret_cast(static_cast(1)); RequireError(resource, invalid, GUEST_EFAULT); } @@ -154,7 +143,7 @@ static std::int64_t Guest(rlim_t value) { static void RequireHostLimit(int resource, int hostResource) { rlimit host{}; Require(getrlimit(hostResource, &host) == 0); - const ResourceLimit guest = GuestLimit(resource); + const GuestResourceLimit guest = GuestLimit(resource); Require(guest.rlim_cur == Guest(host.rlim_cur)); Require(guest.rlim_max == Guest(host.rlim_max)); } @@ -190,12 +179,12 @@ int main() { GUEST_RLIMIT_KQUEUES, GUEST_RLIMIT_UMTXP, }) { - const ResourceLimit guest = GuestLimit(resource); + const GuestResourceLimit guest = GuestLimit(resource); Require(guest.rlim_cur == GUEST_RLIM_INFINITY); Require(guest.rlim_max == GUEST_RLIM_INFINITY); RequireError(resource, nullptr, GUEST_EFAULT); } - ResourceLimit limit{}; + GuestResourceLimit limit{}; RequireError(GUEST_RLIM_NLIMITS, &limit, GUEST_EINVAL); RequireError(-1, &limit, GUEST_EINVAL); RequireError(GUEST_RLIM_NLIMITS, nullptr, GUEST_EINVAL); @@ -203,13 +192,13 @@ int main() { RequireError(GUEST_RLIMIT_DATA, nullptr, GUEST_EFAULT); RequireInvalidOutputPointer(GUEST_RLIMIT_DATA); RequireInvalidOutputPointer(GUEST_RLIMIT_NOFILE); - const ResourceLimit stack = GuestLimit(GUEST_RLIMIT_STACK); + const GuestResourceLimit stack = GuestLimit(GUEST_RLIMIT_STACK); Require(stack.rlim_cur == 0x200000 && stack.rlim_max == 0x200000); RequireError(GUEST_RLIMIT_STACK, nullptr, GUEST_EFAULT); - const ResourceLimit processes = GuestLimit(GUEST_RLIMIT_NPROC); + const GuestResourceLimit processes = GuestLimit(GUEST_RLIMIT_NPROC); Require(processes.rlim_cur == 1604 && processes.rlim_max == 1604); RequireError(GUEST_RLIMIT_NPROC, nullptr, GUEST_EFAULT); - const ResourceLimit nofile = GuestLimit(GUEST_RLIMIT_NOFILE); + const GuestResourceLimit nofile = GuestLimit(GUEST_RLIMIT_NOFILE); const int tableSize = getdtablesize_nid_postfix(); std::int64_t expectedTableSize = nofile.rlim_cur; #ifndef _WIN32 diff --git a/core/libs/tests/GuestGetrusage.cpp b/core/libs/tests/GuestGetrusage.cpp index 7fefbdca94..5c37bcc0b6 100644 --- a/core/libs/tests/GuestGetrusage.cpp +++ b/core/libs/tests/GuestGetrusage.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -8,16 +10,10 @@ struct Timeval { std::int64_t tv_sec; std::int64_t tv_usec; }; -struct ResourceUsage { - Timeval ru_utime; - Timeval ru_stime; - std::int64_t rest[14]; -}; -extern "C" int APS5_VABI getrusage_nid_postfix(int who, ResourceUsage* usage); -extern "C" int* APS5_VABI __error_nid_postfix(); + static void Require(bool value) { if (!value) std::abort(); } static std::int64_t CpuMicros(int who) { - ResourceUsage usage{}; + GuestResourceUsage usage{}; Require(getrusage_nid_postfix(who, &usage) == 0); return (usage.ru_utime.tv_sec + usage.ru_stime.tv_sec) * 1000000 + usage.ru_utime.tv_usec + usage.ru_stime.tv_usec; } @@ -29,15 +25,15 @@ static void SpinUntil(int who, std::int64_t micros) { Require(std::chrono::steady_clock::now() < deadline); } } -static void RequireFailure(int who, ResourceUsage* usage, int error) { +static void RequireFailure(int who, GuestResourceUsage* usage, int error) { *__error_nid_postfix() = 0; Require(getrusage_nid_postfix(who, usage) == -1); Require(*__error_nid_postfix() == error); } int main() { - ResourceUsage untouched; + GuestResourceUsage untouched; std::memset(&untouched, 0x5a, sizeof(untouched)); - const ResourceUsage pattern = untouched; + const GuestResourceUsage pattern = untouched; RequireFailure(2, &untouched, 22); RequireFailure(-2, &untouched, 22); Require(std::memcmp(&untouched, &pattern, sizeof(untouched)) == 0); @@ -45,10 +41,15 @@ int main() { RequireFailure(0, nullptr, 14); RequireFailure(1, nullptr, 14); RequireFailure(-1, nullptr, 14); - ResourceUsage children; + auto* const invalid = reinterpret_cast(static_cast(1)); + RequireFailure(2, invalid, 22); + RequireFailure(0, invalid, 14); + RequireFailure(1, invalid, 14); + RequireFailure(-1, invalid, 14); + GuestResourceUsage children; std::memset(&children, 0xff, sizeof(children)); Require(getrusage_nid_postfix(-1, &children) == 0); - const ResourceUsage empty{}; + const GuestResourceUsage empty{}; Require(std::memcmp(&children, &empty, sizeof(children)) == 0); SpinUntil(0, 400000); const std::int64_t mainThread = CpuMicros(1); diff --git a/core/libs/tests/GuestGets.cpp b/core/libs/tests/GuestGets.cpp index 7b986b9381..4862729c19 100644 --- a/core/libs/tests/GuestGets.cpp +++ b/core/libs/tests/GuestGets.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/FileStream.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -17,7 +18,7 @@ extern "C" { extern FileStream* __stdinp_nid_postfix; -int* APS5_VABI __error_nid_postfix(); + } namespace { diff --git a/core/libs/tests/GuestGnmNeoDefaultState.cpp b/core/libs/tests/GuestGnmNeoDefaultState.cpp index 7288e795c4..c4731f75ea 100644 --- a/core/libs/tests/GuestGnmNeoDefaultState.cpp +++ b/core/libs/tests/GuestGnmNeoDefaultState.cpp @@ -1,16 +1,9 @@ +#include "prx/libSceGnmDriverForNeoMode/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include #include -extern "C" { -int APS5_VABI sceGnmDrawInitDefaultHardwareState(std::uint32_t*, std::uint32_t); -int APS5_VABI sceGnmDrawInitDefaultHardwareState200(std::uint32_t*, std::uint32_t); -int APS5_VABI sceGnmDrawInitDefaultHardwareState350(std::uint32_t*, std::uint32_t); -int APS5_VABI sceGnmDrawInitToDefaultContextState(std::uint32_t*, std::uint32_t); -int APS5_VABI sceGnmDrawInitToDefaultContextState400(std::uint32_t*, std::uint32_t); -} - namespace { using StateWriter = int (APS5_VABI *)(std::uint32_t*, std::uint32_t); diff --git a/core/libs/tests/GuestGnmNeoEmbedded.cpp b/core/libs/tests/GuestGnmNeoEmbedded.cpp index e802446b9f..fb8f7caa80 100644 --- a/core/libs/tests/GuestGnmNeoEmbedded.cpp +++ b/core/libs/tests/GuestGnmNeoEmbedded.cpp @@ -1,13 +1,9 @@ +#include "prx/libSceGnmDriverForNeoMode/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include #include -extern "C" { -int APS5_VABI sceGnmSetEmbeddedVsShader(std::uint32_t*, std::uint32_t, std::uint32_t, std::uint32_t); -int APS5_VABI sceGnmSetEmbeddedPsShader(std::uint32_t*, std::uint32_t, std::uint32_t, std::uint32_t); -} - namespace { constexpr int Failure = static_cast(0x8EEE00FFu); diff --git a/core/libs/tests/GuestGnmNeoPackets.cpp b/core/libs/tests/GuestGnmNeoPackets.cpp index 984bc33dad..b31a5d0897 100644 --- a/core/libs/tests/GuestGnmNeoPackets.cpp +++ b/core/libs/tests/GuestGnmNeoPackets.cpp @@ -1,28 +1,9 @@ +#include "prx/libSceGnmDriverForNeoMode/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include #include -extern "C" { -int APS5_VABI sceGnmInsertDingDongMarker(std::uint32_t*, std::uint32_t); -int APS5_VABI sceGnmDrawIndexAuto(std::uint32_t*, std::uint32_t, std::uint32_t, std::uint32_t); -int APS5_VABI sceGnmDrawIndex(std::uint32_t*, std::uint32_t, std::uint32_t, std::uint64_t, std::uint32_t, std::uint32_t); -int APS5_VABI sceGnmDrawIndexOffset(std::uint32_t*, std::uint32_t, std::uint32_t, std::uint32_t, std::uint32_t); -int APS5_VABI sceGnmDispatchDirect(std::uint32_t*, std::uint32_t, std::uint32_t, std::uint32_t, std::uint32_t, std::uint32_t); -int APS5_VABI sceGnmDispatchIndirect(std::uint32_t*, std::uint32_t, std::uint32_t, std::uint32_t); -int APS5_VABI sceGnmDispatchIndirectOnMec(std::uint32_t*, std::uint32_t, std::uint64_t, std::uint32_t); -int APS5_VABI sceGnmDrawIndirect(std::uint32_t*, std::uint32_t, std::uint32_t, std::uint32_t, std::uint32_t, std::uint32_t, std::uint32_t); -int APS5_VABI sceGnmDrawIndexIndirect(std::uint32_t*, std::uint32_t, std::uint32_t, std::uint32_t, std::uint32_t, std::uint32_t, std::uint32_t); -int APS5_VABI sceGnmDrawIndirectMulti(std::uint32_t*, std::uint32_t, std::uint32_t, std::uint32_t, std::uint32_t, std::uint32_t, std::uint32_t, std::uint32_t); -int APS5_VABI sceGnmDrawIndexIndirectMulti(std::uint32_t*, std::uint32_t, std::uint32_t, std::uint32_t, std::uint32_t, std::uint32_t, std::uint32_t, std::uint32_t); -int APS5_VABI sceGnmDrawIndirectCountMulti(std::uint32_t*, std::uint32_t, std::uint32_t, std::uint32_t, std::uint64_t, std::uint32_t, std::uint32_t, std::uint32_t, std::uint32_t); -int APS5_VABI sceGnmDrawIndexIndirectCountMulti(std::uint32_t*, std::uint32_t, std::uint32_t, std::uint32_t, std::uint64_t, std::uint32_t, std::uint32_t, std::uint32_t, std::uint32_t); -int APS5_VABI sceGnmComputeWaitSemaphore(std::uint32_t*, std::uint32_t, std::uint64_t, std::uint32_t); -int APS5_VABI sceGnmComputeWaitOnAddress(std::uint32_t*, std::uint32_t, std::uint64_t, std::uint32_t, std::uint32_t, std::uint32_t); -int APS5_VABI sceGnmSetVgtControl(std::uint32_t*, std::uint32_t, std::uint32_t, std::uint32_t, std::uint32_t); -int APS5_VABI sceGnmResetVgtControl(std::uint32_t*, std::uint32_t); -} - namespace { constexpr std::uint32_t Untouched = 0xa5a5a5a5u; diff --git a/core/libs/tests/GuestGnmNeoRetail.cpp b/core/libs/tests/GuestGnmNeoRetail.cpp index 29148976fa..3101ebb9b0 100644 --- a/core/libs/tests/GuestGnmNeoRetail.cpp +++ b/core/libs/tests/GuestGnmNeoRetail.cpp @@ -1,58 +1,8 @@ +#include "prx/libSceGnmDriverForNeoMode/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include -extern "C" { -int APS5_VABI sceGnmDebugModuleReset(void); -int APS5_VABI sceGnmDebugReset(void); -int APS5_VABI sceGnmDriverInternalRetrieveGnmInterface(void); -int APS5_VABI sceGnmDriverInternalRetrieveGnmInterfaceForGpuDebugger(void); -int APS5_VABI sceGnmDriverInternalRetrieveGnmInterfaceForReplay(void); -int APS5_VABI sceGnmDriverInternalRetrieveGnmInterfaceForResourceRegistration(void); -int APS5_VABI sceGnmDriverInternalRetrieveGnmInterfaceForValidation(void); -int APS5_VABI sceGnmDriverTraceInProgress(void); -int APS5_VABI sceGnmFindResources(void); -int APS5_VABI sceGnmFindResourcesPublic(void); -int APS5_VABI sceGnmGetDbgGcHandle(void); -int APS5_VABI sceGnmGetOwnerName(void); -int APS5_VABI sceGnmGetPhysicalCounterFromVirtualized(void); -int APS5_VABI sceGnmGetResourceBaseAddressAndSizeInBytes(void); -int APS5_VABI sceGnmGetResourceName(void); -int APS5_VABI sceGnmGetResourceRegistrationBuffers(void); -int APS5_VABI sceGnmGetResourceShaderGuid(void); -int APS5_VABI sceGnmGetResourceType(void); -int APS5_VABI sceGnmGetResourceUserData(void); -int APS5_VABI sceGnmQueryResourceRegistrationUserMemoryRequirements(void); -int APS5_VABI sceGnmRegisterGdsResource(void); -int APS5_VABI sceGnmRegisterOwner(void); -int APS5_VABI sceGnmRegisterOwnerForSystem(void); -int APS5_VABI sceGnmRegisterResource(void); -int APS5_VABI sceGnmSdmaClose(void); -int APS5_VABI sceGnmSdmaConstFill(void); -int APS5_VABI sceGnmSdmaCopyLinear(void); -int APS5_VABI sceGnmSdmaCopyTiled(void); -int APS5_VABI sceGnmSdmaCopyWindow(void); -int APS5_VABI sceGnmSdmaFlush(void); -int APS5_VABI sceGnmSdmaGetMinCmdSize(void); -int APS5_VABI sceGnmSdmaOpen(void); -int APS5_VABI sceGnmSetResourceRegistrationUserMemory(void); -int APS5_VABI sceGnmSetResourceUserData(void); -int APS5_VABI sceGnmSetSpiEnableSqCounters(void); -int APS5_VABI sceGnmSetSpiEnableSqCountersForUnitInstance(void); -int APS5_VABI sceGnmUnregisterAllResourcesForOwner(void); -int APS5_VABI sceGnmUnregisterOwnerAndResources(void); -int APS5_VABI sceGnmUnregisterResource(void); -int APS5_VABI sceGnmValidateDisableDiagnostics(void); -int APS5_VABI sceGnmValidateDisableDiagnostics2(void); -int APS5_VABI sceGnmValidateDispatchCommandBuffers(void); -int APS5_VABI sceGnmValidateDrawCommandBuffers(void); -int APS5_VABI sceGnmValidateGetDiagnosticInfo(void); -int APS5_VABI sceGnmValidateGetDiagnostics(void); -int APS5_VABI sceGnmValidateOnSubmitEnabled(void); -int APS5_VABI sceGnmValidateResetState(void); -int APS5_VABI sceGnmValidationRegisterMemoryCheckCallback(void); -} - namespace { constexpr int Failure = static_cast(0x8EEE00FFu); diff --git a/core/libs/tests/GuestGnmNeoShaders.cpp b/core/libs/tests/GuestGnmNeoShaders.cpp index 14f1f17264..75760c5b1e 100644 --- a/core/libs/tests/GuestGnmNeoShaders.cpp +++ b/core/libs/tests/GuestGnmNeoShaders.cpp @@ -1,23 +1,9 @@ +#include "prx/libSceGnmDriverForNeoMode/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include #include -extern "C" { -int APS5_VABI sceGnmUpdateVsShader(std::uint32_t*, std::uint32_t, const std::uint32_t*, std::uint32_t); -int APS5_VABI sceGnmUpdatePsShader(std::uint32_t*, std::uint32_t, const std::uint32_t*); -int APS5_VABI sceGnmUpdatePsShader350(std::uint32_t*, std::uint32_t, const std::uint32_t*); -int APS5_VABI sceGnmSetPsShader350(std::uint32_t*, std::uint32_t, const std::uint32_t*); -int APS5_VABI sceGnmUpdateGsShader(std::uint32_t*, std::uint32_t, const std::uint32_t*); -int APS5_VABI sceGnmUpdateHsShader(std::uint32_t*, std::uint32_t, const std::uint32_t*, std::uint32_t); -int APS5_VABI sceGnmSetCsShaderWithModifier(std::uint32_t*, std::uint32_t, const std::uint32_t*, std::uint32_t); -int APS5_VABI sceGnmCreateWorkloadStream(std::uint64_t, std::uint32_t*); -int APS5_VABI sceGnmBeginWorkload(std::uint32_t, std::uint64_t*); -int APS5_VABI sceGnmEndWorkload(std::uint64_t); -int APS5_VABI sceGnmGetGpuCoreClockFrequency(void); -int APS5_VABI sceGnmGetOffChipTessellationBufferSize(void); -} - namespace { constexpr std::uint32_t Untouched = 0xa5a5a5a5u; diff --git a/core/libs/tests/GuestHeapReportForGame.cpp b/core/libs/tests/GuestHeapReportForGame.cpp index 6986740948..ccc355a05d 100644 --- a/core/libs/tests/GuestHeapReportForGame.cpp +++ b/core/libs/tests/GuestHeapReportForGame.cpp @@ -1,3 +1,5 @@ +#include "prx/libc/include/Api.hpp" +#include "prx/libc/include/FileStream.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -14,10 +16,6 @@ #include #include -extern "C" { -void APS5_VABI sceLibcInternalBacktraceForGame_nid_postfix(const char* heapName); -void APS5_VABI sceLibcInternalHeapErrorReportForGame_nid_postfix(void* heap, void* block, std::uint32_t error); -} static std::string ReadAll(const std::filesystem::path& path) { std::ifstream file(path); @@ -61,10 +59,20 @@ int main() { threw = true; } Require(threw, "null heap accepted"); + std::fflush(stdout); + const bool closed = _Stdout_nid_postfix.Close() == 0; + bool closedThrew = false; + try { + sceLibcInternalHeapErrorReportForGame_nid_postfix(heap, &block, 1); + } catch (const std::exception&) { + closedThrew = true; + } + if (!closed || closedThrew) { + std::fputs("heap error report on a closed standard output\n", stderr); + std::abort(); + } std::fflush(stderr); std::fclose(stderr); - std::fflush(stdout); - std::fclose(stdout); const std::string report = ReadAll(path); const std::string output = ReadAll(outputPath); diff --git a/core/libs/tests/GuestHeapRounding.cpp b/core/libs/tests/GuestHeapRounding.cpp index f27c870d0d..e71d91abab 100644 --- a/core/libs/tests/GuestHeapRounding.cpp +++ b/core/libs/tests/GuestHeapRounding.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #ifndef NOMINMAX #define NOMINMAX #endif @@ -16,13 +17,6 @@ #include #include -extern "C" { -void* APS5_VABI malloc_nid_postfix(std::size_t); -void APS5_VABI free_nid_postfix(void*); -void* APS5_VABI realloc_nid_postfix(void*, std::size_t); -int* APS5_VABI __error_nid_postfix(); -} - namespace { constexpr std::size_t HeaderBytes = 2 * sizeof(void*); @@ -40,6 +34,7 @@ bool checkThreshold(std::size_t bytes, unsigned char value) { pointer[bytes - 1] = static_cast(value + 1); const bool preserved = pointer[0] == value && pointer[bytes - 1] == static_cast(value + 1); free_nid_postfix(pointer); + return preserved; } @@ -82,6 +77,7 @@ int runMallocOverflow() { auto* pointer = malloc_nid_postfix(std::numeric_limits::max() - HeaderBytes); if (pointer != nullptr) { free_nid_postfix(pointer); + return 1; } return *__error_nid_postfix() == 77 ? 0 : 4; @@ -105,6 +101,7 @@ int runReallocOverflow() { auto* result = realloc_nid_postfix(original, std::numeric_limits::max() - HeaderBytes); if (result != nullptr) { free_nid_postfix(result); + return 4; } rejectedWithExpectedError = *__error_nid_postfix() == 77; @@ -141,6 +138,7 @@ int runReallocOverflow() { if (result == 0) { free_nid_postfix(replacement); free_nid_postfix(original); + } return static_cast(result); } diff --git a/core/libs/tests/GuestHmd2.cpp b/core/libs/tests/GuestHmd2.cpp index e1bd7b8c52..6303182c1e 100644 --- a/core/libs/tests/GuestHmd2.cpp +++ b/core/libs/tests/GuestHmd2.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceHmd2/include/Api.hpp" #include "ProcessParametersFixture.hpp" #include "prx/libSceHmd/Hmd.hpp" #include "prx/libSceHmd2/Hmd2.hpp" @@ -11,57 +12,7 @@ #include namespace Hmd2 { -struct ReprojectionOutput; -} -extern "C" { -std::int32_t APS5_VABI Hmd2WriteStateTwo(void* a0); -std::int32_t APS5_VABI Hmd2WriteSize0x2000Align0x100(std::uint64_t* a0, std::uint64_t* a1); -std::int32_t APS5_VABI Hmd2WriteFourConstants(void* a0); -std::int32_t APS5_VABI Hmd2WriteSixHalvesThenInvalidHandle(std::uint64_t a0, void* a1); -std::int32_t APS5_VABI Hmd2WriteTwelveHalvesThenInvalidHandle(std::uint64_t a0, void* a1); -std::int32_t APS5_VABI Hmd2SlotUpTo3CheckSecondThirdThenZero(std::uint64_t a0, const void* a1, const void* a2); -std::int32_t APS5_VABI Hmd2SlotUpTo1ThenError1002(std::uint64_t a0); -std::int32_t APS5_VABI Hmd2SlotUpTo1CheckSecondThenError1002(std::uint64_t a0, const void* a1); -std::int32_t APS5_VABI Hmd2SlotUpTo1ThenMinusOne(std::uint64_t a0); -std::int32_t APS5_VABI Hmd2SlotUpTo2ThenMinusOne(std::uint64_t a0); -std::int32_t APS5_VABI Hmd2SlotUpTo2ThenError1002(std::uint64_t a0); -std::int32_t APS5_VABI Hmd2SlotUpTo2ThenError1003(std::uint64_t a0); -std::int32_t APS5_VABI Hmd2SlotUpTo2CheckSecondThenError002C(std::uint64_t a0, const void* a1); -std::int32_t APS5_VABI Hmd2IndexZeroCheckSecondThenZero(std::uint64_t a0, const void* a1); -std::int32_t APS5_VABI Hmd2CheckFirstThenError0004(const void*); -std::int32_t APS5_VABI Hmd2CheckFirstThenZero(const void*); -std::int32_t APS5_VABI Hmd2CheckFirstThenError1002(const void*); -std::int32_t APS5_VABI Hmd2CheckFirstThenMinusOne(const void*); -std::int32_t APS5_VABI Hmd2CheckFirstTwoThenParameterInvalid(const void*, const void*); -std::int32_t APS5_VABI Hmd2CheckSecondThenError002C(const void*, const void*); -std::int32_t APS5_VABI Hmd2CheckFirstThenParameterInvalid(const void*); -std::int32_t APS5_VABI Hmd2CheckAllSixThenZero(const void*, const void*, const void*, const void*, const void*, const void*); -std::int32_t APS5_VABI Hmd2CheckSecondThenParameterInvalid(const void*, const void*); -std::int32_t APS5_VABI Hmd2CheckFirstThenError800d0203(const void*); -std::int32_t APS5_VABI Hmd2CheckFirstThenError1003(const void*); -std::int32_t APS5_VABI Hmd2CheckFirstThenError1010(const void*); -std::int32_t APS5_VABI Hmd2CheckFirstTwoThenError1002(const void*, const void*); -std::int32_t APS5_VABI Hmd2CheckFirstTwoThenError1003(const void*, const void*); -std::int32_t APS5_VABI Hmd2CheckFirstAndThirdThenZero(const void*, const void*, const void*); -std::int32_t APS5_VABI Hmd2CheckFirstAndThirdThenError1003(const void*, const void*, const void*); -std::int32_t APS5_VABI Hmd2CheckSecondThenInvalidHandle(const void*, const void*); -std::int32_t APS5_VABI Hmd2CheckSecondThenError1002(const void*, const void*); -std::int32_t APS5_VABI Hmd2BeforeInitializeZero(); -std::int32_t APS5_VABI Hmd2BeforeInitializeNotInitialized(); -std::int32_t APS5_VABI Hmd2BeforeInitializeError0004(); -std::int32_t APS5_VABI Hmd2BeforeInitializeParameterNull(); -std::int32_t APS5_VABI Hmd2BeforeInitializeParameterInvalid(); -std::int32_t APS5_VABI Hmd2BeforeInitializeReprojectionNotInitialized(); -std::int32_t APS5_VABI Hmd2BeforeInitializeError002C(); -std::int32_t APS5_VABI Hmd2BeforeInitializeError1002(); -std::int32_t APS5_VABI Hmd2BeforeInitializeError1003(); -std::int32_t APS5_VABI Hmd2BeforeInitializeMinusOne(); -std::int32_t APS5_VABI Hmd2BeforeInitializeValue0400(); -std::int32_t APS5_VABI Hmd2BeforeInitializeValue20000(); -int APS5_VABI sceHmd2GazeActivateGazeTracking(std::int32_t mode); -int APS5_VABI sceHmd2ReprojectionGetCurrentOutput(Hmd2::ReprojectionOutput* output); -int APS5_VABI sceHmd2SetFieldOfView(const Hmd2::FieldOfView* fieldOfView); } namespace { diff --git a/core/libs/tests/GuestHmd2Gaze.cpp b/core/libs/tests/GuestHmd2Gaze.cpp index e3cce92206..7a9a674c36 100644 --- a/core/libs/tests/GuestHmd2Gaze.cpp +++ b/core/libs/tests/GuestHmd2Gaze.cpp @@ -1,3 +1,5 @@ +#include "prx/libSceHmd2/include/Api.hpp" +#include "prx/libSceHmd2/Hmd2.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -6,18 +8,6 @@ #include #include -struct GazeParam { - std::uint32_t size; - std::int32_t handle; - std::uint64_t reserved; -}; - -extern "C" { -std::int32_t APS5_VABI sceHmd2Initialize(const void* param); -std::int32_t APS5_VABI sceHmd2GazeGetResult(const GazeParam* param, void* result); -std::int32_t APS5_VABI sceHmd2GazeGetResultForFoveatedRendering(const GazeParam* param, void* result); -} - namespace { constexpr std::int32_t InvalidHandle = static_cast(0x8a720003); @@ -42,24 +32,24 @@ bool NegativeZero(float value) { } void CheckGazeResult() { - GazeParam param {sizeof(GazeParam), 0x0e010000, 0}; + Hmd2::GazeResultParameter param {sizeof(Hmd2::GazeResultParameter), 0x0e010000, 0}; unsigned char result[0x38]; std::memset(result, 0x5a, sizeof(result)); const std::uint32_t size = 0x38; std::memcpy(result, &size, sizeof(size)); - Require(sceHmd2GazeGetResult(nullptr, result) == ParameterNull, "null param"); + Require(sceHmd2GazeGetResult(nullptr, reinterpret_cast(result)) == ParameterNull, "null param"); Require(sceHmd2GazeGetResult(¶m, nullptr) == ParameterNull, "null result"); - GazeParam wrongParam = param; + Hmd2::GazeResultParameter wrongParam = param; wrongParam.size = 0x18; - Require(sceHmd2GazeGetResult(&wrongParam, result) == ParameterInvalid, "param size"); + Require(sceHmd2GazeGetResult(&wrongParam, reinterpret_cast(result)) == ParameterInvalid, "param size"); const std::uint32_t wrongSize = 0x18; std::memcpy(result, &wrongSize, sizeof(wrongSize)); - Require(sceHmd2GazeGetResult(¶m, result) == ParameterInvalid, "result size"); + Require(sceHmd2GazeGetResult(¶m, reinterpret_cast(result)) == ParameterInvalid, "result size"); Require(Read(result, 4) == 0x5a5a5a5a, "result untouched after a size error"); std::memcpy(result, &size, sizeof(size)); - Require(sceHmd2GazeGetResult(¶m, result) == InvalidHandle, "unopened handle"); + Require(sceHmd2GazeGetResult(¶m, reinterpret_cast(result)) == InvalidHandle, "unopened handle"); Require(Read(result, 0) == 0x38, "size kept"); Require(Read(result, 4) == -1, "+4 is -1"); for (const std::size_t offset : {0x8u, 0xcu, 0x10u, 0x20u, 0x24u, 0x28u, 0x2cu, 0x30u, 0x34u}) @@ -68,25 +58,25 @@ void CheckGazeResult() { Require(Read(result, 0x18) == 0, "+0x18 is 0.0"); Require(Read(result, 0x1c) == -1.0f, "+0x1c is -1.0"); - GazeParam zero {sizeof(GazeParam), 0, 0}; - Require(sceHmd2GazeGetResult(&zero, result) == InvalidHandle, "handle 0"); + Hmd2::GazeResultParameter zero {sizeof(Hmd2::GazeResultParameter), 0, 0}; + Require(sceHmd2GazeGetResult(&zero, reinterpret_cast(result)) == InvalidHandle, "handle 0"); } void CheckFoveatedResult() { - GazeParam param {sizeof(GazeParam), 0x0e010000, 0}; + Hmd2::GazeResultParameter param {sizeof(Hmd2::GazeResultParameter), 0x0e010000, 0}; unsigned char result[0x18]; std::memset(result, 0x5a, sizeof(result)); const std::uint32_t size = 0x18; std::memcpy(result, &size, sizeof(size)); - Require(sceHmd2GazeGetResultForFoveatedRendering(nullptr, result) == ParameterNull, "foveated null param"); + Require(sceHmd2GazeGetResultForFoveatedRendering(nullptr, reinterpret_cast(result)) == ParameterNull, "foveated null param"); Require(sceHmd2GazeGetResultForFoveatedRendering(¶m, nullptr) == ParameterNull, "foveated null result"); unsigned char large[0x38] = {}; const std::uint32_t largeSize = 0x38; std::memcpy(large, &largeSize, sizeof(largeSize)); - Require(sceHmd2GazeGetResultForFoveatedRendering(¶m, large) == ParameterInvalid, "foveated result size"); + Require(sceHmd2GazeGetResultForFoveatedRendering(¶m, reinterpret_cast(large)) == ParameterInvalid, "foveated result size"); - Require(sceHmd2GazeGetResultForFoveatedRendering(¶m, result) == InvalidHandle, "foveated unopened handle"); + Require(sceHmd2GazeGetResultForFoveatedRendering(¶m, reinterpret_cast(result)) == InvalidHandle, "foveated unopened handle"); Require(Read(result, 0) == 0x18, "foveated size kept"); Require(Read(result, 4) == -1, "foveated +4 is -1"); Require(NegativeZero(Read(result, 8)), "foveated +8 is -0.0"); diff --git a/core/libs/tests/GuestHmdSetupDialog.cpp b/core/libs/tests/GuestHmdSetupDialog.cpp index 7939b5eb8f..1b4f731d93 100644 --- a/core/libs/tests/GuestHmdSetupDialog.cpp +++ b/core/libs/tests/GuestHmdSetupDialog.cpp @@ -1,17 +1,8 @@ +#include "prx/libSceHmdSetupDialog/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include -extern "C" { -int APS5_VABI sceHmdSetupDialogInitialize(void); -int APS5_VABI sceHmdSetupDialogOpen(const void* param); -int APS5_VABI sceHmdSetupDialogUpdateStatus(void); -int APS5_VABI sceHmdSetupDialogGetStatus(void); -int APS5_VABI sceHmdSetupDialogGetResult(void* result); -int APS5_VABI sceHmdSetupDialogClose(void); -int APS5_VABI sceHmdSetupDialogTerminate(void); -} - namespace { void Require(bool value) { if (!value) std::abort(); } diff --git a/core/libs/tests/GuestHostStandardError.cpp b/core/libs/tests/GuestHostStandardError.cpp index 4c3fdc2309..131df792f6 100644 --- a/core/libs/tests/GuestHostStandardError.cpp +++ b/core/libs/tests/GuestHostStandardError.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/FileStream.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -16,18 +18,7 @@ #endif extern "C" { -FileStream* APS5_VABI freopen_nid_postfix(const char*, const char*, FileStream*); -int APS5_VABI setvbuf_nid_postfix(FileStream*, char*, int, std::size_t); -std::size_t APS5_VABI fwrite_nid_postfix(const void*, std::size_t, std::size_t, FileStream*); -int APS5_VABI fflush_nid_postfix(FileStream*); -int APS5_VABI pipe_nid_postfix(int*); -int APS5_VABI dup2_nid_postfix(int, int); -std::int64_t APS5_VABI write_nid_postfix(int, const void*, std::size_t); -int APS5_VABI printf_nid_postfix(const char*, ...); -int APS5_VABI puts_nid_postfix(const char*); -int APS5_VABI fprintf_nid_postfix(FileStream*, const char*, ...); -void APS5_VABI perror_nid_postfix(const char*); -int* APS5_VABI __error_nid_postfix(); + extern FileStream* __stderrp_nid_postfix; extern FileStream* __stdoutp_nid_postfix; } diff --git a/core/libs/tests/GuestHostStandardErrorWindows.cpp b/core/libs/tests/GuestHostStandardErrorWindows.cpp index 559b90d3f2..0248298110 100644 --- a/core/libs/tests/GuestHostStandardErrorWindows.cpp +++ b/core/libs/tests/GuestHostStandardErrorWindows.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/FileStream.hpp" #include "prx/libc/include/HostStandardStreams.hpp" #include "prx/libc/include/general/VabiMacros.hpp" @@ -13,19 +15,7 @@ #endif extern "C" { -int APS5_VABI pipe_nid_postfix(int*); -int APS5_VABI dup2_nid_postfix(int, int); -std::int64_t APS5_VABI write_nid_postfix(int, const void*, std::size_t); -int APS5_VABI printf_nid_postfix(const char*, ...); -int APS5_VABI puts_nid_postfix(const char*); -int APS5_VABI fprintf_nid_postfix(FileStream*, const char*, ...); -int APS5_VABI fflush_nid_postfix(FileStream*); -int APS5_VABI setvbuf_nid_postfix(FileStream*, char*, int, std::size_t); -void APS5_VABI setbuf_nid_postfix(FileStream*, char*); -void APS5_VABI flockfile_nid_postfix(FileStream*); -void APS5_VABI funlockfile_nid_postfix(FileStream*); -void APS5_VABI perror_nid_postfix(const char*); -int* APS5_VABI __error_nid_postfix(); + extern FileStream _Stdout_nid_postfix; extern FileStream _Stderr_nid_postfix; } @@ -89,6 +79,7 @@ static void GuestText(int standard, const std::string& text) { Require(fprintf_nid_postfix(&_Stderr_nid_postfix, "guest-fprintf\n") >= 0); *__error_nid_postfix() = 2; perror_nid_postfix("guest-perror"); + Require(fflush_nid_postfix(&_Stderr_nid_postfix) == 0); } std::string got(text.size(), '\0'); @@ -109,9 +100,11 @@ static void Buffering(int standard) { auto* guestStream = standard == 1 ? &_Stdout_nid_postfix : &_Stderr_nid_postfix; char buffer[4096]{}; flockfile_nid_postfix(guestStream); + if (standard == 1) setbuf_nid_postfix(guestStream, buffer); else Require(setvbuf_nid_postfix(guestStream, buffer, 0, sizeof(buffer)) == 0); funlockfile_nid_postfix(guestStream); + Require(fprintf_nid_postfix(guestStream, "guest-buffered") == 14); Require(std::fputs("host-immediate", standard == 1 ? stdout : stderr) >= 0); char bytes[64]{}; diff --git a/core/libs/tests/GuestHostStreams.cpp b/core/libs/tests/GuestHostStreams.cpp index 83a39b5768..f05f9f4b1b 100644 --- a/core/libs/tests/GuestHostStreams.cpp +++ b/core/libs/tests/GuestHostStreams.cpp @@ -1,14 +1,9 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libkernel/File/include/File.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include -extern "C" { -int APS5_VABI dup_nid_postfix(int); -int APS5_VABI pipe_nid_postfix(int*); -int APS5_VABI close_nid_postfix(int); -int APS5_VABI sceKernelClose(int); -int* APS5_VABI __error_nid_postfix(); -} - static void Require(bool value) { if (!value) std::abort(); } constexpr int GuestEperm = 1; diff --git a/core/libs/tests/GuestHostname.cpp b/core/libs/tests/GuestHostname.cpp index 36e18845dc..9b6e788e19 100644 --- a/core/libs/tests/GuestHostname.cpp +++ b/core/libs/tests/GuestHostname.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -8,11 +9,6 @@ #include #include -extern "C" { -int APS5_VABI gethostname_nid_postfix(char*, std::size_t); -int* APS5_VABI __error_nid_postfix(); -} - static void Require(bool condition, int line) { if (!condition) { std::fprintf(stderr, "Hostname check failed at line %d\n", line); diff --git a/core/libs/tests/GuestHttp.cpp b/core/libs/tests/GuestHttp.cpp index 49134461d3..fbbdd525bf 100644 --- a/core/libs/tests/GuestHttp.cpp +++ b/core/libs/tests/GuestHttp.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceHttp/include/Http.hpp" #include "SceTypes.hpp" #include "ProcessParametersFixture.hpp" #include @@ -13,55 +14,14 @@ #include #include -extern "C" { -int APS5_VABI sceHttpUriParse(SceHttpUriElement*, const char*, void*, std::size_t*, std::size_t); -int APS5_VABI sceHttpUriCopy(SceHttpUriElement*, const SceHttpUriElement*, void*, std::size_t, std::size_t*); -int APS5_VABI sceHttpUriMerge(char*, const char*, const char*, std::size_t*, std::size_t, std::uint32_t); -int APS5_VABI sceHttpSetInflateGZIPEnabled(int, int); -int APS5_VABI sceHttpSetRequestStatusCallback(int, void (APS5_VABI *)(int, int, void*), void*); -int APS5_VABI sceHttpSendRequest(int, const void*, std::size_t); -int APS5_VABI sceHttpUriBuild(char*, std::size_t*, std::size_t, const SceHttpUriElement*, std::uint32_t); -int APS5_VABI sceHttpUriEscape(char*, std::size_t*, std::size_t, const char*); -int APS5_VABI sceHttpUriUnescape(char*, std::size_t*, std::size_t, const char*); -int APS5_VABI sceHttpUriSweepPath(char*, const char*, std::size_t); -int APS5_VABI sceHttpCreateEpoll(int, HttpEpollHandle*); -int APS5_VABI sceHttpDestroyEpoll(int, HttpEpollHandle); -int APS5_VABI sceHttpWaitRequest(HttpEpollHandle, HttpNBEvent*, int, int); -int APS5_VABI sceHttpAbortWaitRequest(HttpEpollHandle); -int APS5_VABI sceHttpInit_nid_postfix(int, int, std::uint64_t); -int APS5_VABI sceHttpTerm_nid_postfix(int); -int APS5_VABI sceHttpAuthCacheFlush(int); -int APS5_VABI sceHttpCookieFlush(int); -int APS5_VABI sceHttpGetMemoryPoolStats(int, void*); -int APS5_VABI sceHttpReadData(int, void*, std::size_t); -int APS5_VABI sceHttpCreateRequest2(int, const char*, const char*, std::uint64_t); -int APS5_VABI sceHttpsEnableOption(int, std::uint32_t); -int APS5_VABI sceHttpsLoadCert(int, int, void*, void*, void*); -int APS5_VABI sceHttpGetLastErrno(int, int*); -int APS5_VABI sceHttpSetResponseHeaderMaxSize(int, std::uint64_t); -int APS5_VABI sceHttpSetRecvBlockSize(int, std::uint32_t); -int APS5_VABI sceHttpRedirectCacheFlush(int); -int APS5_VABI sceHttpsUnloadCert(int); -int APS5_VABI sceHttpsSetSslVersion(int, int); -int APS5_VABI sceHttpsGetSslError(int, int*, std::uint32_t*); -int APS5_VABI sceHttpSetRedirectCallback(int, HttpRedirectCallback, void*); -int APS5_VABI sceHttpSetCookieRecvCallback(int, HttpCookieRecvCallback, void*); -int APS5_VABI sceHttpSetAuthInfoCallback(int, HttpAuthInfoCallback, void*); -int APS5_VABI sceHttpParseStatusLine(const char*, std::size_t, std::int32_t*, std::int32_t*, std::int32_t*, const char**, std::size_t*); -} - alignas(16) static std::array processParameters{}; static void Require(bool value) { if (!value) std::abort(); } static bool Equal(const char* left, const char* right) { return std::strcmp(left, right) == 0; } -struct HttpPoolStats { - std::size_t poolSize; - std::size_t maxInuseSize; - std::size_t currentInuseSize; -}; -static_assert(sizeof(HttpPoolStats) == 24); + +static_assert(sizeof(HttpMemoryPoolStats) == 24); template static bool Throws(TCall call) { @@ -74,20 +34,20 @@ static bool Throws(TCall call) { } static void CheckPoolStatsRejected(int id, int expected) { - unsigned char buffer[sizeof(HttpPoolStats) + 16]; + alignas(HttpMemoryPoolStats) unsigned char buffer[sizeof(HttpMemoryPoolStats) + 16]; std::memset(buffer, 0x5a, sizeof(buffer)); - Require(sceHttpGetMemoryPoolStats(id, buffer) == expected); + Require(sceHttpGetMemoryPoolStats(id, reinterpret_cast(buffer)) == expected); for (unsigned char byte : buffer) Require(byte == 0x5a); } static void CheckPoolStats(int id, std::size_t poolSize) { - unsigned char buffer[sizeof(HttpPoolStats) + 16]; + alignas(HttpMemoryPoolStats) unsigned char buffer[sizeof(HttpMemoryPoolStats) + 16]; std::memset(buffer, 0x5a, sizeof(buffer)); - Require(sceHttpGetMemoryPoolStats(id, buffer) == 0); - HttpPoolStats stats; + Require(sceHttpGetMemoryPoolStats(id, reinterpret_cast(buffer)) == 0); + HttpMemoryPoolStats stats; std::memcpy(&stats, buffer, sizeof(stats)); Require(stats.poolSize == poolSize); - Require(stats.maxInuseSize == 0 && stats.currentInuseSize == 0); + Require(stats.peakUsedSize == 0 && stats.usedSize == 0); for (std::size_t i = sizeof(stats); i < sizeof(buffer); ++i) Require(buffer[i] == 0x5a); } diff --git a/core/libs/tests/GuestHttp2.cpp b/core/libs/tests/GuestHttp2.cpp index 102369b0c4..286b03b042 100644 --- a/core/libs/tests/GuestHttp2.cpp +++ b/core/libs/tests/GuestHttp2.cpp @@ -1,48 +1,10 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libSceHttp2/include/Http2.hpp" #include "SceTypes.hpp" #include #include #include -extern "C" { -int APS5_VABI sceHttp2Init(int, int, std::size_t, int); -int APS5_VABI sceHttp2CreateTemplate(int, const char*, int, int); -int APS5_VABI sceHttp2CreateRequestWithURL(int, const char*, const char*, std::uint64_t); -int APS5_VABI sceHttp2CreateCookieBox(std::size_t); -int APS5_VABI sceHttp2DeleteCookieBox(int); -int APS5_VABI sceHttp2SetCookieBox(int, int); -int APS5_VABI sceHttp2CookieFlush(int); -int APS5_VABI sceHttp2SetRequestNoContentLength(int); -int APS5_VABI sceHttp2SendRequest(int, const void*, std::size_t); -int APS5_VABI sceHttp2SendRequestAsync(int, const void*, std::size_t, Http2AsyncOption*, void*); -int APS5_VABI sceHttp2WaitAsync(int, Http2AsyncResult*, std::uint32_t*, void*); -int APS5_VABI sceHttp2DeleteRequest(int); -int APS5_VABI sceHttp2DeleteTemplate(int); -int APS5_VABI sceHttp2SetMinSslVersion(int, std::uint32_t); -int APS5_VABI sceHttp2SslEnableOption(int, std::uint32_t); -int APS5_VABI sceHttp2SslDisableOption(int, std::uint32_t); -int APS5_VABI sceHttp2Term(int); -int APS5_VABI sceKernelCreateEqueue(KernelEqueue* eq, const char* name); -int APS5_VABI sceKernelDeleteEqueue(KernelEqueue eq); -int APS5_VABI sceKernelWaitEqueue(KernelEqueue eq, KernelEvent* ev, int num, int* out, const KernelUseconds* timo); -int APS5_VABI sceKernelAddUserEventEdge(KernelEqueue eq, int id); -int APS5_VABI sceKernelDeleteUserEvent(KernelEqueue eq, int id); -uintptr_t APS5_VABI sceKernelGetEventId(const KernelEvent* ev); -void* APS5_VABI sceKernelGetEventUserData(const KernelEvent* ev); -} - -struct Http2MemoryPoolStats { - std::size_t pool_size; - std::size_t max_inuse_size; - std::size_t current_inuse_size; - std::int32_t reserved; -}; - -extern "C" { -int APS5_VABI sceHttp2GetMemoryPoolStats(int, Http2MemoryPoolStats*); -int APS5_VABI sceHttp2SetResolveRetry(int, std::int32_t); -int APS5_VABI sceHttp2WebSocketSetPingInterval(std::int32_t, std::uint32_t); -} - static void Require(bool value) { if (!value) std::abort(); } static constexpr int InvalidId = static_cast(0x817B1100); diff --git a/core/libs/tests/GuestHttpOptions.cpp b/core/libs/tests/GuestHttpOptions.cpp index a2f0f1ce7a..e396f51ccd 100644 --- a/core/libs/tests/GuestHttpOptions.cpp +++ b/core/libs/tests/GuestHttpOptions.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceHttp/include/Http.hpp" #include "SceTypes.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -5,42 +6,6 @@ #include #include -extern "C" { -int APS5_VABI sceHttpInit_nid_postfix(int, int, std::uint64_t); -int APS5_VABI sceHttpTerm_nid_postfix(int); -int APS5_VABI sceHttpCreateTemplate(int, const char*, int, int); -int APS5_VABI sceHttpDeleteTemplate(int); -int APS5_VABI sceHttpCreateConnectionWithURL(int, const char*, int); -int APS5_VABI sceHttpDeleteConnection(int); -int APS5_VABI sceHttpCreateRequestWithURL(int, int, const char*, std::uint64_t); -int APS5_VABI sceHttpDeleteRequest(int); -int APS5_VABI sceHttpSetAutoRedirect(int, int); -int APS5_VABI sceHttpGetAutoRedirect(int, int*); -int APS5_VABI sceHttpSetAuthEnabled(int, int); -int APS5_VABI sceHttpGetAuthEnabled(int, int*); -int APS5_VABI sceHttpSetCookieEnabled(int, int); -int APS5_VABI sceHttpGetCookieEnabled(int, int*); -int APS5_VABI sceHttpSetNonblock(int, int); -int APS5_VABI sceHttpGetNonblock(int, int*); -int APS5_VABI sceHttpTrySetNonblock(int, int); -int APS5_VABI sceHttpTryGetNonblock(int, int*); -int APS5_VABI sceHttpSetAcceptEncodingGZIPEnabled(int, int); -int APS5_VABI sceHttpGetAcceptEncodingGZIPEnabled(int, int*); -int APS5_VABI sceHttpSetDefaultAcceptEncodingGZIPEnabled(int, int); -int APS5_VABI sceHttpCreateEpoll(int, HttpEpollHandle*); -int APS5_VABI sceHttpDestroyEpoll(int, HttpEpollHandle); -int APS5_VABI sceHttpSetEpoll(int, HttpEpollHandle, void*); -int APS5_VABI sceHttpUnsetEpoll(int); -int APS5_VABI sceHttpGetEpoll(int, HttpEpollHandle*, void**); -int APS5_VABI sceHttpCacheRedirectedConnectionEnabled(int, int); -int APS5_VABI sceHttpsEnableOptionPrivate(int, std::uint32_t); -int APS5_VABI sceHttpsDisableOptionPrivate(int, std::uint32_t); -int APS5_VABI sceHttpAbortRequestForce(int); -int APS5_VABI sceHttpSetProxy(int, int, int, const char*, std::uint16_t); -int APS5_VABI sceHttpAddRequestHeader(int, const char*, const char*, std::uint32_t); -int APS5_VABI sceHttpRemoveRequestHeader(int, const char*); -} - namespace { constexpr int BeforeInit = static_cast(0x80431001u); diff --git a/core/libs/tests/GuestHttpResponseHeader.cpp b/core/libs/tests/GuestHttpResponseHeader.cpp index 76bbc60b5d..46244f8153 100644 --- a/core/libs/tests/GuestHttpResponseHeader.cpp +++ b/core/libs/tests/GuestHttpResponseHeader.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceHttp/include/Http.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -13,8 +14,6 @@ #include #endif -extern "C" int APS5_VABI sceHttpParseResponseHeader(const char*, std::size_t, const char*, const char**, std::size_t*); - static void Require(bool value) { if (!value) { std::fputs("HTTP response header check failed\n", stderr); diff --git a/core/libs/tests/GuestImeDialog.cpp b/core/libs/tests/GuestImeDialog.cpp index 3087ec13b5..cd5fce7fcb 100644 --- a/core/libs/tests/GuestImeDialog.cpp +++ b/core/libs/tests/GuestImeDialog.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceImeDialog/include/Api.hpp" #include "SceTypes.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libSceIme/include/ImeInput.hpp" @@ -7,21 +8,6 @@ #include #include -extern "C" { -int APS5_VABI sceImeDialogInit(const Param*, const ExtendedParam*); -int APS5_VABI sceImeDialogGetStatus(void); -int APS5_VABI sceImeDialogGetResult(Result*); -int APS5_VABI sceImeDialogAbort(void); -int APS5_VABI sceImeDialogTerm(void); -int APS5_VABI sceImeDialogGetPanelPositionAndForm(PositionAndForm*); -int APS5_VABI sceImeDialogGetPanelSize(const Param*, std::uint32_t*, std::uint32_t*); -int APS5_VABI sceImeDialogGetPanelSizeExtended(const Param*, const ExtendedParam*, std::uint32_t*, std::uint32_t*); -int APS5_VABI sceImeDialogForceClose(void); -int APS5_VABI sceImeDialogGetCurrentStarState(std::int64_t); -int APS5_VABI sceImeDialogInitInternal(const Param*, const ExtendedParam*); -int APS5_VABI sceImeDialogSetPanelPosition(std::int32_t, std::int32_t); -} - namespace { constexpr int StatusNone = 0; diff --git a/core/libs/tests/GuestImeFilterText.cpp b/core/libs/tests/GuestImeFilterText.cpp index bac9e2daa2..f2f6cf3e11 100644 --- a/core/libs/tests/GuestImeFilterText.cpp +++ b/core/libs/tests/GuestImeFilterText.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceIme/include/Api.hpp" #include "SceTypes.hpp" #include "prx/libSceIme/include/ImeFilterText.hpp" #include @@ -7,11 +8,6 @@ #include #include -extern "C" { -int APS5_VABI sceImeFilterText(char16_t* dst, int32_t* out_length, uint32_t capacity, - const ime_filter::FilterParam* param, const char16_t* src, uint32_t src_length); -} - namespace { constexpr int kInvalidParam = static_cast(0x80bc0030u); diff --git a/core/libs/tests/GuestImeKeyboard.cpp b/core/libs/tests/GuestImeKeyboard.cpp index 180a47106f..449089bc13 100644 --- a/core/libs/tests/GuestImeKeyboard.cpp +++ b/core/libs/tests/GuestImeKeyboard.cpp @@ -1,15 +1,9 @@ +#include "prx/libSceIme/include/Api.hpp" #include "SceTypes.hpp" #include #include #include -extern "C" { -int APS5_VABI sceImeKeyboardOpen(int32_t user_id, const KeyboardParam* param); -int APS5_VABI sceImeKeyboardClose(int32_t user_id); -int APS5_VABI sceImeKeyboardGetInfo(uint32_t resource_id, KeyboardInfo* info); -int APS5_VABI sceImeKeyboardSetMode(int32_t user_id, uint32_t mode); -} - static_assert(sizeof(KeyboardInfo) == 36); constexpr int AlreadyOpened = static_cast(0x80bc0001u); diff --git a/core/libs/tests/GuestImeOpen.cpp b/core/libs/tests/GuestImeOpen.cpp index 39c7278c1e..04cefbca47 100644 --- a/core/libs/tests/GuestImeOpen.cpp +++ b/core/libs/tests/GuestImeOpen.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceIme/include/Api.hpp" #include "SceTypes.hpp" #include "prx/libSceIme/include/ImeInput.hpp" #include "prx/libSceVideoOut/include/ImeTextInput.hpp" @@ -10,16 +11,6 @@ #include #include -extern "C" { -int APS5_VABI sceImeOpen_nid_postfix(const Param* param, const ExtendedParam* extended); -int APS5_VABI sceImeClose_nid_postfix(void); -int APS5_VABI sceImeUpdate(EventHandler handler); -int APS5_VABI sceImeSetText(const char16_t* text, uint32_t length); -int APS5_VABI sceImeSetCaret(const Caret* caret); -int APS5_VABI sceImeGetPanelPositionAndForm(PositionAndForm* form); -void APS5_VABI sceImeParamInit(Param* param); -} - namespace { constexpr int Busy = static_cast(0x80bc0001u); @@ -181,6 +172,7 @@ struct Buffers { Param MakeParam(Buffers& buffers, uint32_t maxLength) { Param param; sceImeParamInit(¶m); + param.user_id = 1; param.max_text_length = maxLength; param.input_text_buffer = buffers.text; diff --git a/core/libs/tests/GuestImeParameters.cpp b/core/libs/tests/GuestImeParameters.cpp index 23f590a389..82ec0959f8 100644 --- a/core/libs/tests/GuestImeParameters.cpp +++ b/core/libs/tests/GuestImeParameters.cpp @@ -1,22 +1,10 @@ +#include "prx/libSceIme/include/Api.hpp" #include "SceTypes.hpp" #include #include #include #include -extern "C" { -void APS5_VABI sceImeParamInit(Param* param); -int APS5_VABI sceImeGetPanelSize(const Param* param, uint32_t* width, uint32_t* height); -int APS5_VABI sceImeClose_nid_postfix(void); -int APS5_VABI sceImeGetPanelPositionAndForm(PositionAndForm* form); -int APS5_VABI sceImeSetCaret(const Caret* caret); -int APS5_VABI sceImeSetText(const char16_t* text, uint32_t length); -int APS5_VABI sceImeSetTextGeometry(TextAreaMode mode, const TextGeometry* geometry); -int APS5_VABI sceImeKeyboardOpen(int32_t user_id, const KeyboardParam* param); -int APS5_VABI sceImeKeyboardClose(int32_t user_id); -int APS5_VABI sceImeKeyboardGetResourceId(int32_t user_id, KeyboardResourceIdArray* resource_ids); -} - static_assert(sizeof(Param) == 96); static_assert(offsetof(Param, option) == 32); static_assert(offsetof(Param, reserved) == 88); @@ -36,6 +24,7 @@ static void CheckInitialization() { std::memset(&guarded, 0xa5, sizeof(guarded)); sceImeParamInit(nullptr); sceImeParamInit(&guarded.param); + Require(guarded.param.user_id == -1, "initial user must be invalid"); const auto* bytes = reinterpret_cast(&guarded.param); for (size_t i = sizeof(guarded.param.user_id); i < sizeof(Param); ++i) { @@ -47,6 +36,7 @@ static void CheckInitialization() { guarded.param.option = 0x4000; guarded.param.max_text_length = 32; sceImeParamInit(&guarded.param); + Require(guarded.param.user_id == -1 && guarded.param.type == 0 && guarded.param.option == 0 && guarded.param.max_text_length == 0, "reinitialization must reset previous values"); diff --git a/core/libs/tests/GuestIndexedDraw.cpp b/core/libs/tests/GuestIndexedDraw.cpp index 3c6ed23b0b..14333e04f6 100644 --- a/core/libs/tests/GuestIndexedDraw.cpp +++ b/core/libs/tests/GuestIndexedDraw.cpp @@ -1,15 +1,11 @@ +#include "prx/libSceAgc/DcbDraw/include/IndexBuffer.hpp" +#include "prx/libSceAgc/DcbDraw/include/DrawIndexed.hpp" #include "SceTypes.hpp" #include "prx/libSceAgcDriver/Execution/include/Pm4.hpp" #include #include #include -extern "C" { -std::uint32_t* APS5_VABI sceAgcDcbSetIndexCount(CommandBuffer*, std::uint32_t); -std::uint32_t APS5_VABI sceAgcDcbSetIndexCountGetSize(); -std::uint32_t* APS5_VABI sceAgcDcbDrawIndex(CommandBuffer*, std::uint32_t, const volatile void*, std::uint64_t); -std::uint32_t APS5_VABI sceAgcDcbDrawIndexGetSize(); -} static void Require(bool condition) { if (!condition) std::abort(); } template static void Reject(TAction action) { bool rejected = false; diff --git a/core/libs/tests/GuestInetAddress.cpp b/core/libs/tests/GuestInetAddress.cpp index ad2275caee..444bfb5b21 100644 --- a/core/libs/tests/GuestInetAddress.cpp +++ b/core/libs/tests/GuestInetAddress.cpp @@ -1,3 +1,5 @@ +#include "prx/libc/include/Api.hpp" +#include "prx/libSceLibcInternal/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -5,15 +7,6 @@ #include #include -extern "C" { -int APS5_VABI inet_aton_nid_postfix(const char* text, std::uint32_t* address); -std::uint32_t APS5_VABI inet_addr_nid_postfix(const char* text); -char* APS5_VABI inet_ntoa_nid_postfix(std::uint32_t address); -char* APS5_VABI inet_ntoa_r_nid_postfix(std::uint32_t address, char* buffer, std::uint32_t size); -char* APS5_VABI __inet_ntoa_r_nid_postfix(std::uint32_t address, char* buffer, std::uint32_t size); -int* APS5_VABI __error_nid_postfix(); -} - namespace { void Require(bool value, const char* what) { diff --git a/core/libs/tests/GuestInitOnce.cpp b/core/libs/tests/GuestInitOnce.cpp index 0a33705835..c7140ac745 100644 --- a/core/libs/tests/GuestInitOnce.cpp +++ b/core/libs/tests/GuestInitOnce.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceLibcInternal/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -5,11 +6,6 @@ #include #include -extern "C" { -int APS5_VABI __std_init_once_begin_initialize_clr_nid_postfix(void** once, unsigned long flags, int* pending, void** context); -int APS5_VABI __std_init_once_complete_clr_nid_postfix(void** once, unsigned long flags, void* context); -} - namespace { constexpr unsigned long InitFailed = 4; diff --git a/core/libs/tests/GuestIntegerBuiltins.cpp b/core/libs/tests/GuestIntegerBuiltins.cpp index 64f5cbb0e1..e0b4eaac19 100644 --- a/core/libs/tests/GuestIntegerBuiltins.cpp +++ b/core/libs/tests/GuestIntegerBuiltins.cpp @@ -1,73 +1,9 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include #include -using Int128 = __int128; -using Uint128 = unsigned __int128; - -extern "C" { -std::int64_t APS5_VABI __ashldi3_nid_postfix(std::int64_t, int); -std::int64_t APS5_VABI __ashrdi3_nid_postfix(std::int64_t, int); -std::int64_t APS5_VABI __lshrdi3_nid_postfix(std::int64_t, int); -Int128 APS5_VABI __ashlti3_nid_postfix(Int128, int); -Int128 APS5_VABI __ashrti3_nid_postfix(Int128, int); -Int128 APS5_VABI __lshrti3_nid_postfix(Int128, int); -int APS5_VABI __clzsi2_nid_postfix(std::uint32_t); -int APS5_VABI __clzdi2_nid_postfix(std::uint64_t); -int APS5_VABI __clzti2_nid_postfix(Uint128); -int APS5_VABI __ctzsi2_nid_postfix(std::uint32_t); -int APS5_VABI __ctzdi2_nid_postfix(std::uint64_t); -int APS5_VABI __ctzti2_nid_postfix(Uint128); -int APS5_VABI __ffsdi2_nid_postfix(std::uint64_t); -int APS5_VABI __ffsti2_nid_postfix(Uint128); -int APS5_VABI __paritysi2_nid_postfix(std::uint32_t); -int APS5_VABI __paritydi2_nid_postfix(std::uint64_t); -int APS5_VABI __parityti2_nid_postfix(Uint128); -int APS5_VABI __popcountsi2_nid_postfix(std::uint32_t); -int APS5_VABI __popcountdi2_nid_postfix(std::uint64_t); -int APS5_VABI __popcountti2_nid_postfix(Uint128); -int APS5_VABI __cmpdi2_nid_postfix(std::int64_t, std::int64_t); -int APS5_VABI __cmpti2_nid_postfix(Int128, Int128); -int APS5_VABI __ucmpdi2_nid_postfix(std::uint64_t, std::uint64_t); -int APS5_VABI __ucmpti2_nid_postfix(Uint128, Uint128); -std::int64_t APS5_VABI __negdi2_nid_postfix(std::int64_t); -Int128 APS5_VABI __negti2_nid_postfix(Int128); -std::int64_t APS5_VABI __muldi3_nid_postfix(std::int64_t, std::int64_t); -Int128 APS5_VABI __multi3_nid_postfix(Int128, Int128); -std::int32_t APS5_VABI __divsi3_nid_postfix(std::int32_t, std::int32_t); -std::int64_t APS5_VABI __divdi3_nid_postfix(std::int64_t, std::int64_t); -std::int32_t APS5_VABI __modsi3_nid_postfix(std::int32_t, std::int32_t); -std::int64_t APS5_VABI __moddi3_nid_postfix(std::int64_t, std::int64_t); -std::uint32_t APS5_VABI __udivsi3_nid_postfix(std::uint32_t, std::uint32_t); -std::uint64_t APS5_VABI __udivdi3_nid_postfix(std::uint64_t, std::uint64_t); -std::uint32_t APS5_VABI __umodsi3_nid_postfix(std::uint32_t, std::uint32_t); -std::uint64_t APS5_VABI __umoddi3_nid_postfix(std::uint64_t, std::uint64_t); -std::int32_t APS5_VABI __divmodsi4_nid_postfix(std::int32_t, std::int32_t, std::int32_t*); -std::int64_t APS5_VABI __divmoddi4_nid_postfix(std::int64_t, std::int64_t, std::int64_t*); -std::uint32_t APS5_VABI __udivmodsi4_nid_postfix(std::uint32_t, std::uint32_t, std::uint32_t*); -std::uint64_t APS5_VABI __udivmoddi4_nid_postfix(std::uint64_t, std::uint64_t, std::uint64_t*); -Uint128 APS5_VABI __udivmodti4_nid_postfix(Uint128, Uint128, Uint128*); -std::int32_t APS5_VABI __mulosi4_nid_postfix(std::int32_t, std::int32_t, int*); -std::int64_t APS5_VABI __mulodi4_nid_postfix(std::int64_t, std::int64_t, int*); -Int128 APS5_VABI __muloti4_nid_postfix(Int128, Int128, int*); -std::int32_t APS5_VABI __mulvsi3_nid_postfix(std::int32_t, std::int32_t); -std::int64_t APS5_VABI __mulvdi3_nid_postfix(std::int64_t, std::int64_t); -Int128 APS5_VABI __mulvti3_nid_postfix(Int128, Int128); -std::int32_t APS5_VABI __addvsi3_nid_postfix(std::int32_t, std::int32_t); -std::int64_t APS5_VABI __addvdi3_nid_postfix(std::int64_t, std::int64_t); -Int128 APS5_VABI __addvti3_nid_postfix(Int128, Int128); -std::int32_t APS5_VABI __subvsi3_nid_postfix(std::int32_t, std::int32_t); -std::int64_t APS5_VABI __subvdi3_nid_postfix(std::int64_t, std::int64_t); -Int128 APS5_VABI __subvti3_nid_postfix(Int128, Int128); -std::int32_t APS5_VABI __negvsi2_nid_postfix(std::int32_t); -std::int64_t APS5_VABI __negvdi2_nid_postfix(std::int64_t); -Int128 APS5_VABI __negvti2_nid_postfix(Int128); -std::int32_t APS5_VABI __absvsi2_nid_postfix(std::int32_t); -std::int64_t APS5_VABI __absvdi2_nid_postfix(std::int64_t); -Int128 APS5_VABI __absvti2_nid_postfix(Int128); -} - static void Require(bool value) { if (!value) std::abort(); } template diff --git a/core/libs/tests/GuestInterfaces.cpp b/core/libs/tests/GuestInterfaces.cpp index c737ea2e11..6306850521 100644 --- a/core/libs/tests/GuestInterfaces.cpp +++ b/core/libs/tests/GuestInterfaces.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN #include @@ -27,15 +28,6 @@ #include #include -struct GuestInterfaceAddress { - GuestInterfaceAddress* next; - char* name; - std::uint32_t flags; - void* address; - void* netmask; - void* destination; - void* data; -}; static_assert(sizeof(GuestInterfaceAddress) == 56); static_assert(offsetof(GuestInterfaceAddress, flags) == 16); static_assert(offsetof(GuestInterfaceAddress, address) == 24); @@ -43,13 +35,6 @@ static_assert(offsetof(GuestInterfaceAddress, netmask) == 32); static_assert(offsetof(GuestInterfaceAddress, destination) == 40); static_assert(offsetof(GuestInterfaceAddress, data) == 48); -extern "C" { -int APS5_VABI getifaddrs_nid_postfix(GuestInterfaceAddress** list); -void APS5_VABI freeifaddrs_nid_postfix(GuestInterfaceAddress* list); -void APS5_VABI free_nid_postfix(void* pointer); -int* APS5_VABI __error_nid_postfix(); -} - static void Require(bool value) { if (!value) std::abort(); } struct HostInterfaceAddress { @@ -297,6 +282,7 @@ int main() { } matched = equal && entries == host.size() && loopback; freeifaddrs_nid_postfix(list); + } Require(matched); #ifdef __linux__ @@ -306,6 +292,7 @@ int main() { Require(getifaddrs_nid_postfix(&released) == 0 && released != nullptr); free_nid_postfix(released); freeifaddrs_nid_postfix(nullptr); + *__error_nid_postfix() = 0; Require(getifaddrs_nid_postfix(nullptr) == -1); Require(*__error_nid_postfix() == 14); diff --git a/core/libs/tests/GuestItimer.cpp b/core/libs/tests/GuestItimer.cpp index 4e1e9d5845..7a688d67d0 100644 --- a/core/libs/tests/GuestItimer.cpp +++ b/core/libs/tests/GuestItimer.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "SceTypes.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -12,33 +14,14 @@ #include #include -struct GuestItimerval { - KernelTimeval interval; - KernelTimeval value; -}; static_assert(sizeof(GuestItimerval) == 32 && offsetof(GuestItimerval, value) == 16); -struct GuestSignalSet { - std::uint32_t bits[4]; -}; -struct GuestTimespec { - std::int64_t seconds; - std::int64_t nanoseconds; -}; using Handler = void (APS5_VABI *)(int); using TerminateHandler = void (*)(); extern "C" { -int APS5_VABI setitimer_nid_postfix(int, const GuestItimerval*, GuestItimerval*); -int APS5_VABI getitimer_nid_postfix(int, GuestItimerval*); + unsigned int APS5_VABI GuestAlarm_nid_no_patch(unsigned int); -Handler APS5_VABI signal_nid_postfix(int, Handler); -int APS5_VABI _sigprocmask_nid_postfix(int, const GuestSignalSet*, GuestSignalSet*); -int APS5_VABI sigtimedwait_nid_postfix(const GuestSignalSet*, void*, const GuestTimespec*); -int APS5_VABI sigpending_nid_postfix(GuestSignalSet*); -int* APS5_VABI __error_nid_postfix(); -void* APS5_VABI __cxa_current_primary_exception_nid_postfix(); -std::type_info* APS5_VABI __cxa_current_exception_type_nid_postfix(); -TerminateHandler APS5_VABI _ZSt13set_terminatePFvvE_nid_postfix(TerminateHandler); + } static void Require(bool value, const char* message) { @@ -140,6 +123,7 @@ int main(int argc, char** argv) { bool threw = false; try { setitimer_nid_postfix(cpu, &valid, &previous); + } catch (const std::runtime_error&) { threw = true; } @@ -150,6 +134,7 @@ int main(int argc, char** argv) { const GuestItimerval tiny{{0, 999}, {1, 0}}; try { setitimer_nid_postfix(0, &tiny, nullptr); + } catch (const std::runtime_error&) { threw = true; } @@ -189,8 +174,8 @@ int main(int argc, char** argv) { Require(GuestAlarm_nid_no_patch(0) == 0, "setitimer did not cancel the alarm"); const GuestSignalSet alarmSet{{1u << 13, 0, 0, 0}}; - const GuestTimespec poll{0, 0}; - const GuestTimespec patience{2, 0}; + const KernelTimespec poll{0, 0}; + const KernelTimespec patience{2, 0}; GuestSignalSet unblocked{}; Require(_sigprocmask_nid_postfix(1, &alarmSet, &unblocked) == 0, "blocking SIGALRM failed"); ExpireOnce(); @@ -220,6 +205,7 @@ int main(int argc, char** argv) { Require(signal_nid_postfix(14, OnAlarm) == ignore, "SIGALRM handler was not installed"); _ZSt13set_terminatePFvvE_nid_postfix(OnTerminate); + const GuestItimerval handled{{0, 250000}, {0, 50000}}; Require(setitimer_nid_postfix(0, &handled, nullptr) == 0, "arming the handled timer failed"); std::this_thread::sleep_for(std::chrono::seconds(2)); diff --git a/core/libs/tests/GuestJitSharedMemory.cpp b/core/libs/tests/GuestJitSharedMemory.cpp index ea38bffa71..02a9cf253f 100644 --- a/core/libs/tests/GuestJitSharedMemory.cpp +++ b/core/libs/tests/GuestJitSharedMemory.cpp @@ -1,3 +1,4 @@ +#include "prx/libkernel/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libkernel/KernelErrors.hpp" #include @@ -7,19 +8,6 @@ #include #include -extern "C" { -int APS5_VABI sceKernelJitCreateSharedMemory(const char*, std::size_t, int, int*); -int APS5_VABI sceKernelJitCreateAliasOfSharedMemory(int, int, int*); -int APS5_VABI sceKernelJitMapSharedMemory(int, int, void**); -int APS5_VABI sceKernelMunmap(void*, std::size_t); -int APS5_VABI close_nid_postfix(int); -int APS5_VABI dup_nid_postfix(int); -int APS5_VABI dup2_nid_postfix(int, int); -int APS5_VABI shm_open_nid_postfix(const char*, int, int); -void* APS5_VABI mmap_nid_postfix(void*, std::size_t, int, int, int, std::int64_t) noexcept; -int APS5_VABI munmap_nid_postfix(void*, std::size_t) noexcept; -} - namespace { constexpr std::size_t Size = 0x10000; @@ -79,10 +67,10 @@ void WriteThroughAliasRunsThroughExecutableView() { Require(close_nid_postfix(fd) == 0); auto* again = static_cast(Map(alias, Read)); Require(again[Size - 1] == 0x5a); - Require(sceKernelMunmap(again, Size) == 0); - Require(sceKernelMunmap(writable, Size) == 0); + Require(sceKernelMunmap(reinterpret_cast(again), Size) == 0); + Require(sceKernelMunmap(reinterpret_cast(writable), Size) == 0); Require(Call(executable) == 0x12345678); - Require(sceKernelMunmap(executable, Size) == 0); + Require(sceKernelMunmap(reinterpret_cast(executable), Size) == 0); Require(close_nid_postfix(alias) == 0); } @@ -98,8 +86,8 @@ void OneViewWritesAndRuns() { Require(close_nid_postfix(fd) == 0); auto* view = static_cast(Map(duplicate, Read | Execute)); Require(Call(view) == 42); - Require(sceKernelMunmap(view, Size) == 0); - Require(sceKernelMunmap(code, Size) == 0); + Require(sceKernelMunmap(reinterpret_cast(view), Size) == 0); + Require(sceKernelMunmap(reinterpret_cast(code), Size) == 0); Require(close_nid_postfix(duplicate) == 0); } @@ -114,7 +102,7 @@ void MmapOfTheDescriptorSharesTheObject() { view[0x300] = 0x6b; Require(jit[0x300] == 0x6b); Require(munmap_nid_postfix(mapped, Size) == 0); - Require(sceKernelMunmap(const_cast(jit), Size) == 0); + Require(sceKernelMunmap(reinterpret_cast(const_cast(jit)), Size) == 0); Require(close_nid_postfix(fd) == 0); } @@ -138,9 +126,9 @@ void Dup2KeepsTheDescriptorTableInStep() { address = nullptr; Require(sceKernelJitMapSharedMemory(target, Read, &address) == SCE_KERNEL_ERROR_EBADF); Require(address == nullptr); - Require(sceKernelMunmap(same, Size) == 0); - Require(sceKernelMunmap(readable, Size) == 0); - Require(sceKernelMunmap(writable, Size) == 0); + Require(sceKernelMunmap(reinterpret_cast(same), Size) == 0); + Require(sceKernelMunmap(reinterpret_cast(readable), Size) == 0); + Require(sceKernelMunmap(reinterpret_cast(writable), Size) == 0); Require(close_nid_postfix(plain) == 0); Require(close_nid_postfix(target) == 0); Require(close_nid_postfix(fd) == 0); diff --git a/core/libs/tests/GuestJobManager.cpp b/core/libs/tests/GuestJobManager.cpp index e8bfeb526f..af4995720a 100644 --- a/core/libs/tests/GuestJobManager.cpp +++ b/core/libs/tests/GuestJobManager.cpp @@ -1,3 +1,6 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libkernel/Time/include/Time.hpp" +#include "prx/libSceJobManager/libSceJobManager.hpp" #include "SceTypes.hpp" #include #include @@ -14,65 +17,6 @@ #include #endif -struct MemorySizeQueryParams { - std::uint32_t version; - std::uint32_t workers; - std::uint32_t sequences; - std::uint32_t invocations; - std::uint32_t dispatches; - std::uint32_t syncPoints; - std::uint32_t waits; - std::uint32_t computeSequences; - std::uint64_t computeQueueMask; -}; - -struct ConfigParams { - std::uint32_t version; - std::uint32_t threadFlags; - std::uint32_t stackSize; - std::uint32_t priority; - const char* threadName; - std::uint32_t spinMicroseconds; - std::uint32_t computeAffinity; - std::uint32_t computePriority; - std::uint32_t reserved; -}; - -using JobEntry = void (APS5_VABI*)(void*, std::uint32_t); - -struct Sequence { - APS5_VABI virtual int Dispatch(JobEntry, void*, std::uint32_t, const char*) = 0; - APS5_VABI virtual int SyncPoint() = 0; - APS5_VABI virtual int Wait() = 0; - APS5_VABI virtual void CompleteDestructor() = 0; - APS5_VABI virtual void DeletingDestructor() = 0; -}; - -struct SequenceFactory { - APS5_VABI virtual int Create(Sequence**, std::uint32_t, std::uint32_t, std::uint32_t, std::uint32_t, const char*) = 0; - APS5_VABI virtual int Destroy(Sequence*) = 0; - APS5_VABI virtual void CompleteDestructor() = 0; - APS5_VABI virtual void DeletingDestructor() = 0; - APS5_VABI virtual int CreateCompute(Sequence**, std::uint32_t, std::uint32_t, std::uint32_t, std::uint32_t, const char*) = 0; - APS5_VABI virtual int DestroyCompute(Sequence*) = 0; -}; - -extern "C" { -Pthread APS5_VABI scePthreadSelf(); -int APS5_VABI pthread_getcpuclockid_nid_postfix(Pthread thread, int* clockId); -int APS5_VABI sceKernelClockGettime(KernelClockid clockId, KernelTimespec* time); -int APS5_VABI sceKernelUsleep_nid_postfix(KernelUseconds microseconds); -void APS5_VABI _ZN3sce3Job10JobManagerC1Ev(void*); -void APS5_VABI _ZN3sce3Job10JobManagerD1Ev(void*); -std::uint64_t APS5_VABI _ZN3sce3Job10JobManager27calculateRequiredMemorySizeEPKNS1_21MemorySizeQueryParamsE(const MemorySizeQueryParams*); -int APS5_VABI _ZN3sce3Job10JobManager10initializeEPvmjjjmPKNS1_12ConfigParamsE(void*, void*, std::uint64_t, std::uint32_t, std::uint32_t, std::uint32_t, std::uint64_t, const ConfigParams*); -int APS5_VABI _ZN3sce3Job10JobManager10initializeEPvmjjPKNS1_12ConfigParamsE(void*, void*, std::uint64_t, std::uint32_t, std::uint32_t, const ConfigParams*); -int APS5_VABI _ZN3sce3Job10JobManager8shutdownEv(void*); -SequenceFactory* APS5_VABI _ZN3sce3Job10JobManager27getSequenceFactoryInterfaceENS1_8PriorityE(void*, std::uint32_t); -SequenceFactory* APS5_VABI _ZN3sce3Job10JobManager34getUnifiedSequenceFactoryInterfaceENS1_8PriorityE(void*, std::uint32_t); -int APS5_VABI _ZN3sce3Job10JobManager24setPersistentThreadCountEj(void*, std::uint32_t); -} - #define Construct _ZN3sce3Job10JobManagerC1Ev #define Destruct _ZN3sce3Job10JobManagerD1Ev #define RequiredSize _ZN3sce3Job10JobManager27calculateRequiredMemorySizeEPKNS1_21MemorySizeQueryParamsE @@ -145,6 +89,46 @@ static void MemoryCase() { static void APS5_VABI Nothing(void*, std::uint32_t) { } +static void OwnedStateCase() { + for (const auto [workers, count] : {std::pair{1u, 1u}, std::pair{3u, 32u}, std::pair{13u, 2u}}) { + const auto size = SizeFor(workers, count, count * 4, count * 2, count * 2); + Block block(size + 256); + std::memset(block.memory, 0xa5, block.bytes); + ManagerObject manager; + const auto begin = reinterpret_cast(block.memory); + const auto inside = [begin, size](const void* pointer) { + const auto address = reinterpret_cast(pointer); + return address >= begin && address < begin + size; + }; + for (int round = 0; round < 3; ++round) { + Require(Initialize(manager.storage, block.memory, size, workers, count, nullptr) == 0); + void* implementation = nullptr; + std::memcpy(&implementation, manager.storage, sizeof(implementation)); + Require(inside(implementation)); + for (std::uint32_t priority = 0; priority < 2; ++priority) { + Require(inside(Factories(manager.storage, priority))); + Require(inside(UnifiedFactories(manager.storage, priority))); + } + auto* factory = Factories(manager.storage, round % 2); + std::array sequences{}; + for (std::uint32_t index = 0; index < count; ++index) { + auto*& sequence = sequences[index]; + Require(factory->Create(&sequence, 4, 4, 2, 2, nullptr) == 0 && inside(sequence)); + Require(sequence->Dispatch(Nothing, nullptr, 1, nullptr) == 0); + Require(sequence->SyncPoint() == 0); + Require(sequence->Dispatch(Nothing, nullptr, 1, nullptr) == 0); + } + for (std::uint32_t index = count; index != 0; --index) { + Require(sequences[index - 1]->Wait() == 0); + Require(factory->Destroy(sequences[index - 1]) == 0); + } + Require(Shutdown(manager.storage) == 0); + const auto* bytes = static_cast(block.memory); + for (auto offset = size; offset < block.bytes; ++offset) Require(bytes[offset] == 0xa5); + } + } +} + static void ValidationCase() { Block block(SizeFor(2, 2, 16, 4, 4)); ManagerObject manager; @@ -184,10 +168,10 @@ static void ValidationCase() { Require(Initialize(manager.storage, block.memory, block.bytes, 2, 2, nullptr) == AlreadyInitialized); Require(SetPersistentThreadCount(manager.storage, 3) == InvalidArgument); Require(SetPersistentThreadCount(manager.storage, 2) == 0); - SequenceFactory* factory = Factories(manager.storage, 0); + ISequenceFactory* factory = Factories(manager.storage, 0); Require(factory != nullptr && Factories(manager.storage, 1) != nullptr && factory != Factories(manager.storage, 1)); Require(UnifiedFactories(manager.storage, 0) != nullptr); - Sequence* sequence = nullptr; + ISequence* sequence = nullptr; Require(factory->Create(nullptr, 1, 1, 1, 1, nullptr) == NullArgument); Require(factory->Create(&sequence, 0, 0, 0, 0, nullptr) == OutOfRange); Require(factory->Create(&sequence, 0x8000, 1, 1, 1, nullptr) == OutOfRange); @@ -195,13 +179,13 @@ static void ValidationCase() { Require(factory->Create(&sequence, 1, 1, 0x100, 1, nullptr) == OutOfRange); Require(factory->Create(&sequence, 1, 1, 1, 0x40, nullptr) == OutOfRange); Require(factory->CreateCompute(&sequence, 1, 1, 1, 1, nullptr) == NoneFree && sequence == nullptr); - Sequence* first = nullptr; - Sequence* second = nullptr; + ISequence* first = nullptr; + ISequence* second = nullptr; Require(factory->Create(&first, 8, 8, 2, 2, "first") == 0 && first != nullptr); Require(factory->Create(&second, 8, 8, 2, 2, "second") == 0 && second != nullptr && second != first); Require(factory->Create(&sequence, 8, 8, 2, 2, "third") == NoneFree); Require(factory->DestroyCompute(first) == Invalid); - Require(factory->Destroy(reinterpret_cast(block.memory)) == Invalid); + Require(factory->Destroy(reinterpret_cast(block.memory)) == Invalid); Require(factory->Destroy(first) == 0 && factory->Destroy(first) == Invalid); Require(factory->Create(&sequence, 8, 8, 2, 2, "again") == 0 && sequence == first); Require(sequence->Dispatch(nullptr, nullptr, 1, nullptr) == NullArgument); @@ -227,8 +211,8 @@ static void DispatchCase() { Block block(SizeFor(4, 1, 8, 2, 2)); ManagerObject manager; Require(Initialize(manager.storage, block.memory, block.bytes, 4, 1, nullptr) == 0); - SequenceFactory* factory = Factories(manager.storage, 0); - Sequence* sequence = nullptr; + ISequenceFactory* factory = Factories(manager.storage, 0); + ISequence* sequence = nullptr; Require(factory->Create(&sequence, 0x7fff, 8, 2, 2, "dispatch") == 0); Tally tally(1000); Tally single(1); @@ -259,8 +243,8 @@ static void OrderingCase() { Block block(SizeFor(4, 1, 8, 4, 2)); ManagerObject manager; Require(Initialize(manager.storage, block.memory, block.bytes, 4, 1, nullptr) == 0); - SequenceFactory* factory = Factories(manager.storage, 1); - Sequence* sequence = nullptr; + ISequenceFactory* factory = Factories(manager.storage, 1); + ISequence* sequence = nullptr; Require(factory->Create(&sequence, 256, 8, 4, 2, "ordering") == 0); std::atomic finished{0}; std::atomic early{0}; @@ -281,7 +265,7 @@ static void OrderingCase() { } struct Nested { - Sequence* sequence; + ISequence* sequence; std::atomic barrierAppended{false}; std::atomic followerAppended{false}; std::atomic leaderFinished{false}; @@ -307,7 +291,7 @@ static void RequireParked(int clock); struct WorkerWait { int spareClock = 0; - Sequence* child; + ISequence* child; std::atomic publisherEntered{false}; std::atomic spareEntered{false}; std::atomic publish{false}; @@ -339,8 +323,8 @@ static void WorkerWaitCase() { const ConfigParams config{0, 0x21fff, 0x10000, 0x2bc, "WorkerWait", 0, 0, 0, 0}; Require(Initialize(manager.storage, block.memory, block.bytes, 2, 2, &config) == 0); Require(SetPersistentThreadCount(manager.storage, 0) == 0); - SequenceFactory* factory = Factories(manager.storage, 0); - Sequence* publisher = nullptr; + ISequenceFactory* factory = Factories(manager.storage, 0); + ISequence* publisher = nullptr; WorkerWait state{}; Require(factory->Create(&publisher, 2, 1, 0, 1, "publisher") == 0); Require(factory->Create(&state.child, 1, 1, 0, 1, "child") == 0); @@ -362,7 +346,7 @@ static void NestedCase() { Block block(SizeFor(2, 1, 4, 2, 2)); ManagerObject manager; Require(Initialize(manager.storage, block.memory, block.bytes, 2, 1, nullptr) == 0); - SequenceFactory* factory = Factories(manager.storage, 0); + ISequenceFactory* factory = Factories(manager.storage, 0); Nested nested{}; Require(factory->Create(&nested.sequence, 16, 4, 2, 2, "nested") == 0); Require(nested.sequence->Dispatch(LeaderJob, &nested, 1, "leader") == 0); @@ -386,8 +370,8 @@ static void LimitsCase() { Block block(SizeFor(2, 2, 2, 1, 1)); ManagerObject manager; Require(Initialize(manager.storage, block.memory, block.bytes, 2, 2, nullptr) == 0); - SequenceFactory* factory = Factories(manager.storage, 0); - Sequence* sequence = nullptr; + ISequenceFactory* factory = Factories(manager.storage, 0); + ISequence* sequence = nullptr; Require(factory->Create(&sequence, 4, 2, 1, 1, "limits") == 0); for (int round = 0; round < 3; ++round) { Require(sequence->Dispatch(Nothing, nullptr, 2, nullptr) == 0); @@ -418,8 +402,8 @@ static void NodePoolCase() { Block block(SizeFor(2, 2, 2, 1, 1)); ManagerObject manager; Require(Initialize(manager.storage, block.memory, block.bytes, 2, 2, nullptr) == 0); - SequenceFactory* factory = Factories(manager.storage, 0); - Sequence* sequence = nullptr; + ISequenceFactory* factory = Factories(manager.storage, 0); + ISequence* sequence = nullptr; Require(factory->Create(&sequence, 0x7fff, 0x3ff, 0xff, 1, "nodes") == 0); int result = 0; int accepted = 0; @@ -485,9 +469,9 @@ static void PriorityCase() { Block block(SizeFor(1, 3, 8, 2, 4)); ManagerObject manager; Require(Initialize(manager.storage, block.memory, block.bytes, 1, 3, nullptr) == 0); - Sequence* gate = nullptr; - Sequence* low = nullptr; - Sequence* high = nullptr; + ISequence* gate = nullptr; + ISequence* low = nullptr; + ISequence* high = nullptr; Require(Factories(manager.storage, 0)->Create(&gate, 4, 4, 1, 1, "gate") == 0); Require(Factories(manager.storage, 0)->Create(&low, 4, 4, 1, 1, "low") == 0); Require(Factories(manager.storage, 1)->Create(&high, 4, 4, 1, 1, "high") == 0); @@ -509,8 +493,8 @@ static void ShutdownCase() { ManagerObject manager; for (int round = 0; round < 3; ++round) { Require(Initialize(manager.storage, block.memory, block.bytes, 3, 2, nullptr) == 0); - SequenceFactory* factory = UnifiedFactories(manager.storage, 0); - Sequence* sequence = nullptr; + ISequenceFactory* factory = UnifiedFactories(manager.storage, 0); + ISequence* sequence = nullptr; Tally tally(64); Require(factory->Create(&sequence, 64, 8, 2, 2, "shutdown") == 0); Require(sequence->Dispatch(CountJob, &tally, 64, nullptr) == 0 && sequence->Wait() == 0 && tally.calls == 64); @@ -550,7 +534,7 @@ static void WorkerPolicyCase() { const ConfigParams config{0, mode | 0x1fff, 0x10000, 0x2bc, "WorkerPolicy", spin, 0, 0, 0}; Require(Initialize(manager.storage, block.memory, block.bytes, 1, 1, &config) == 0); auto* factory = Factories(manager.storage, 0); - Sequence* sequence = nullptr; + ISequence* sequence = nullptr; Require(factory->Create(&sequence, 8, 8, 2, 2, "worker policy") == 0); int clock = 0; Require(sequence->Dispatch(CaptureWorkerClock, &clock, 1, nullptr) == 0 && sequence->Wait() == 0); @@ -581,7 +565,7 @@ static void WorkerWakeCase() { for (const std::uint32_t mode : {0x10000u, 0x20000u}) { const ConfigParams config{0, mode | 0x1fff, 0x10000, 0x2bc, "WorkerWake", 50, 0, 0, 0}; Require(Initialize(manager.storage, block.memory, block.bytes, 4, 1, &config) == 0); - Sequence* sequence = nullptr; + ISequence* sequence = nullptr; auto* factory = Factories(manager.storage, 0); Require(factory->Create(&sequence, 1024, 8, 2, 2, "worker wake") == 0); for (std::uint32_t round = 0; round < 60; ++round) { @@ -656,8 +640,8 @@ static SpinSample MeasureWorkerSpin(std::uint32_t spin, std::uint32_t rounds, bo const ConfigParams config{0, 0x10003, 0x10000, 0x2bc, "WorkerSpin", spin, 0, 0, 0}; Require(Initialize(manager.storage, block.memory, block.bytes, 2, 2, &config) == 0); auto* factory = Factories(manager.storage, 0); - Sequence* held = nullptr; - Sequence* pulse = nullptr; + ISequence* held = nullptr; + ISequence* pulse = nullptr; Require(factory->Create(&held, 4, 4, 2, 2, "held worker") == 0); Require(factory->Create(&pulse, 4, 4, 2, 2, "idle worker") == 0); HeldWorker worker; @@ -686,11 +670,22 @@ static SpinSample MeasureWorkerSpin(std::uint32_t spin, std::uint32_t rounds, bo return {consumed, clock.reference}; } +static SpinSample QuietestWorkerSpin(std::uint32_t spin, std::uint32_t rounds, bool pending) { + auto best = MeasureWorkerSpin(spin, rounds, pending); + for (int attempt = 1; attempt < 3; ++attempt) { + const auto sample = MeasureWorkerSpin(spin, rounds, pending); + if (sample.consumed < best.consumed) { + best = sample; + } + } + return best; +} + static void WorkerSpinCase() { constexpr std::uint32_t rounds = 512; const auto parked = MeasureWorkerSpin(0, rounds, true); const auto spinning = MeasureWorkerSpin(50, rounds, true); - const auto noPending = MeasureWorkerSpin(50, rounds, false); + const auto noPending = QuietestWorkerSpin(50, rounds, false); #ifdef _WIN32 constexpr const char* units = "cycles"; #else @@ -722,7 +717,7 @@ static void WorkerCountCase() { ManagerObject manager; const ConfigParams config{0, 0x1000f, 0x10000, 0x2bc, "WorkerCount", 0, 0, 0, 0}; Require(Initialize(manager.storage, block.memory, block.bytes, 4, 1, &config) == 0); - Sequence* sequence = nullptr; + ISequence* sequence = nullptr; Require(Factories(manager.storage, 0)->Create(&sequence, 8, 8, 2, 2, "worker count") == 0); WorkerClocks workers; Require(sequence->Dispatch(CaptureWorkerClocks, &workers, 4, nullptr) == 0); @@ -754,9 +749,150 @@ static void WorkerCountCase() { Require(Shutdown(manager.storage) == 0); } +static void APS5_VABI ShutdownGateJob(void* argument, std::uint32_t index) { + GateJob(argument, index); + ++static_cast(argument)->next; +} + +static void ShutdownActiveCase(bool wait, bool queue, bool destroy, std::uint32_t count = 1) { + for (int round = 0; round < 3; ++round) { + Block block(SizeFor(1, 1, 4, 2, 2)); + ManagerObject manager; + Require(Initialize(manager.storage, block.memory, block.bytes, 1, 1, nullptr) == 0); + ISequenceFactory* factory = Factories(manager.storage, 0); + ISequence* sequence = nullptr; + Require(factory->Create(&sequence, 4, 4, 2, 2, "shutdown active") == 0); + Order order; + Require(sequence->Dispatch(ShutdownGateJob, &order, count, nullptr) == 0); + while (!order.started) std::this_thread::yield(); + if (queue) { + Require(sequence->SyncPoint() == 0); + Require(sequence->Dispatch(LowJob, &order, 1, nullptr) == 0); + } + std::atomic entered{false}; + std::atomic returned{false}; + std::thread waiter; + if (wait) { + waiter = std::thread([&] { + entered = true; + Require(destroy ? factory->Destroy(sequence) == 0 : sequence->Wait() == 0); + returned = true; + }); + while (!entered) std::this_thread::yield(); + std::this_thread::sleep_for(std::chrono::milliseconds(30)); + Require(!returned); + } + std::atomic stopping{false}; + std::atomic stopped{false}; + std::thread shutdown([&] { + stopping = true; + Require(Shutdown(manager.storage) == 0); + stopped = true; + }); + while (!stopping) std::this_thread::yield(); + std::this_thread::sleep_for(std::chrono::milliseconds(30)); + Require(!stopped); + order.release = true; + shutdown.join(); + if (waiter.joinable()) waiter.join(); + Require(stopped && (!wait || returned)); + Require(order.next == 1); + Require(Factories(manager.storage, 0) == nullptr); + Require(Initialize(manager.storage, block.memory, block.bytes, 1, 1, nullptr) == 0); + Require(Shutdown(manager.storage) == 0); + } +} + +struct ShutdownCrossWait { + ISequence* sequence; + std::atomic entered{false}; + std::atomic returned{false}; +}; + +static void APS5_VABI ShutdownWaitOther(void* argument, std::uint32_t) { + auto& state = *static_cast(argument); + state.entered = true; + Require(state.sequence->Wait() == 0); + state.returned = true; +} + +static void ConcurrentWaitCase() { + for (const bool stop : {false, true}) { + for (int round = 0; round < 3; ++round) { + Block block(SizeFor(2, 1, 4, 2, 8)); + ManagerObject manager; + Require(Initialize(manager.storage, block.memory, block.bytes, 2, 1, nullptr) == 0); + auto* factory = Factories(manager.storage, 0); + ISequence* sequence = nullptr; + Require(factory->Create(&sequence, 2, 2, 1, 8, nullptr) == 0); + Order order; + Require(sequence->Dispatch(ShutdownGateJob, &order, 1, nullptr) == 0); + while (!order.started) std::this_thread::yield(); + std::atomic entered{0}; + std::atomic returned{0}; + std::array waiters; + for (auto& waiter : waiters) waiter = std::thread([&] { + ++entered; + Require(sequence->Wait() == 0); + ++returned; + }); + while (entered != waiters.size()) std::this_thread::yield(); + std::this_thread::sleep_for(std::chrono::milliseconds(50)); + Require(returned == 0); + std::thread shutdown; + if (stop) { + shutdown = std::thread([&] { Require(Shutdown(manager.storage) == 0); }); + std::this_thread::sleep_for(std::chrono::milliseconds(50)); + } + order.release = true; + for (auto& waiter : waiters) waiter.join(); + Require(returned == waiters.size() && order.next == 1); + if (stop) shutdown.join(); + else { + Require(sequence->Dispatch(Nothing, nullptr, 1, nullptr) == 0); + Require(factory->Destroy(sequence) == 0); + Require(Shutdown(manager.storage) == 0); + } + } + } +} + +static void ShutdownCrossWaitCase() { + Block block(SizeFor(2, 2, 4, 2, 2)); + ManagerObject manager; + Require(Initialize(manager.storage, block.memory, block.bytes, 2, 2, nullptr) == 0); + auto* factory = Factories(manager.storage, 0); + ISequence* producer = nullptr; + ISequence* consumer = nullptr; + Require(factory->Create(&producer, 1, 1, 1, 1, nullptr) == 0); + Require(factory->Create(&consumer, 1, 1, 1, 1, nullptr) == 0); + Order order; + Require(producer->Dispatch(ShutdownGateJob, &order, 1, nullptr) == 0); + while (!order.started) std::this_thread::yield(); + ShutdownCrossWait state{producer}; + Require(consumer->Dispatch(ShutdownWaitOther, &state, 1, nullptr) == 0); + while (!state.entered) std::this_thread::yield(); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + Require(!state.returned); + std::atomic stopping{false}; + std::atomic stopped{false}; + std::thread shutdown([&] { + stopping = true; + Require(Shutdown(manager.storage) == 0); + stopped = true; + }); + while (!stopping) std::this_thread::yield(); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + Require(!stopped); + order.release = true; + shutdown.join(); + Require(state.returned && stopped && order.next == 1); +} + int RunJobManagerCase(const char* caseName) { const std::string name = caseName; if (name == "memory") MemoryCase(); + else if (name == "owned_state") OwnedStateCase(); else if (name == "validation") ValidationCase(); else if (name == "dispatch") DispatchCase(); else if (name == "ordering") OrderingCase(); @@ -770,6 +906,13 @@ int RunJobManagerCase(const char* caseName) { else if (name == "worker_wake") WorkerWakeCase(); else if (name == "worker_spin") WorkerSpinCase(); else if (name == "worker_count") WorkerCountCase(); + else if (name == "shutdown_running") ShutdownActiveCase(false, false, false); + else if (name == "shutdown_waiter") ShutdownActiveCase(true, false, false); + else if (name == "shutdown_queued") ShutdownActiveCase(true, true, false); + else if (name == "shutdown_destroy") ShutdownActiveCase(true, true, true); + else if (name == "shutdown_partial") ShutdownActiveCase(true, false, false, 4); + else if (name == "shutdown_cross_wait") ShutdownCrossWaitCase(); + else if (name == "concurrent_wait") ConcurrentWaitCase(); else return 2; return 0; } diff --git a/core/libs/tests/GuestJpegDec.cpp b/core/libs/tests/GuestJpegDec.cpp index 6a8273a54e..6c6183b175 100644 --- a/core/libs/tests/GuestJpegDec.cpp +++ b/core/libs/tests/GuestJpegDec.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceJpegDec/include/Api.hpp" #include "SceTypes.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "Decoder/Jpeg.hpp" @@ -25,14 +26,6 @@ static_assert(offsetof(JpegDecImageInfo, component_id) == 0xC && offsetof(JpegDe static_assert(offsetof(JpegDecImageInfo, coefficient_mem_size) == 0x14 && offsetof(JpegDecImageInfo, suitable_csc_attribute) == 0x18); static_assert(offsetof(JpegDecImageInfo, output_image_width) == 0x1C && offsetof(JpegDecImageInfo, output_image_height) == 0x20); -extern "C" { -std::int32_t APS5_VABI sceJpegDecQueryMemorySize(const JpegDecCreateParam*); -std::int32_t APS5_VABI sceJpegDecCreate(const JpegDecCreateParam*, void*, std::uint32_t, void**); -std::int32_t APS5_VABI sceJpegDecDelete(void*); -std::int32_t APS5_VABI sceJpegDecParseHeader(const JpegDecParseParam*, JpegDecImageInfo*); -std::int32_t APS5_VABI sceJpegDecDecode(void*, const JpegDecDecodeParam*, JpegDecImageInfo*); -} - static void Require(bool value) { if (!value) std::abort(); } template diff --git a/core/libs/tests/GuestJpegEnc.cpp b/core/libs/tests/GuestJpegEnc.cpp index 5475dde235..c97ce0d6a1 100644 --- a/core/libs/tests/GuestJpegEnc.cpp +++ b/core/libs/tests/GuestJpegEnc.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceJpegEnc/include/Api.hpp" #include "SceTypes.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "Decoder/Jpeg.hpp" @@ -8,13 +9,6 @@ #include #include -extern "C" { -std::int32_t APS5_VABI sceJpegEncQueryMemorySize(const JpegEncCreateParam*); -std::int32_t APS5_VABI sceJpegEncCreate(const JpegEncCreateParam*, void*, std::uint32_t, void**); -std::int32_t APS5_VABI sceJpegEncDelete(void*); -std::int32_t APS5_VABI sceJpegEncEncode(void*, const JpegEncEncodeParam*, JpegEncOutputInfo*); -} - static void Require(bool value) { if (!value) std::abort(); } alignas(4) static unsigned char image[16 * 16 * 4]; diff --git a/core/libs/tests/GuestJson.cpp b/core/libs/tests/GuestJson.cpp index 89f76dbf29..1cc2993f93 100644 --- a/core/libs/tests/GuestJson.cpp +++ b/core/libs/tests/GuestJson.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceJson2/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -12,154 +13,14 @@ #include #include -struct Value { void* node; }; -struct String { void* text; }; -struct Array { void* items; }; -struct Object { void* items; }; -struct Iterator { void* position; }; -struct Pair { - String key; - std::uint64_t reserved; - Value value; -}; -using NullAccessCallback = const Value& (APS5_VABI*)(std::int32_t, const Value*, void*); +using namespace SceJson2; + using SetNullAccessCallback = int (APS5_VABI*)(void*, NullAccessCallback, void*); -using TypeMismatchHandler = const Value& (APS5_VABI*)(std::int32_t, const Value*, const Value*, void*); -using SpecialFloatHandler = Value* (APS5_VABI*)(Value*, std::int32_t, double, const Value*, void*, bool*); -using ElementAccessFailureHandler = void (APS5_VABI*)(std::int32_t, const String*, const std::size_t*, const Value*, const Value*, void*); extern "C" { -int APS5_VABI _ZN3sce4Json11InitializerC1Ev(void*); -int APS5_VABI _ZN3sce4Json11InitializerD1Ev(void*); -int APS5_VABI _ZN3sce4Json11Initializer10initializeEPKNS0_13InitParameterE(void*, const void*); -int APS5_VABI _ZN3sce4Json11Initializer9terminateEv(void*); -int APS5_VABI _ZN3sce4Json11Initializer27setGlobalNullAccessCallBackEPFRKNS0_5ValueENS0_9ValueTypeEPS3_PvES7_(void*, NullAccessCallback, void*); -int APS5_VABI _ZN3sce4Json11Initializer27setGlobalNullAccessCallbackEPFRKNS0_5ValueENS0_9ValueTypeEPS3_PvES7_(void*, NullAccessCallback, void*); -void APS5_VABI _ZN3sce4Json5Value21setNullAccessCallBackEPFRKS1_NS0_9ValueTypeEPS2_PvES6_(NullAccessCallback, void*); -int APS5_VABI _ZN3sce4Json5Value22setTypeMismatchHandlerEPFRKS1_NS0_9ValueTypeEPS2_S5_PvES6_(Value*, TypeMismatchHandler, void*); -int APS5_VABI _ZN3sce4Json5Value22setSpecialFloatHandlerEPFKS1_NS0_12FunctionTypeEdPS2_PvPbES5_(Value*, SpecialFloatHandler, void*); -int APS5_VABI _ZN3sce4Json5Value30setElementAccessFailureHandlerEPFviPKNS0_6StringEPKmPKS1_S8_PvES9_(Value*, ElementAccessFailureHandler, void*); -int APS5_VABI _ZN3sce4Json5Value3setEd(Value*, double); -int APS5_VABI _ZN3sce4Json5Value3setERKS1_(Value*, const Value*); -Value* APS5_VABI _ZN3sce4Json5ValueaSERKS1_(Value*, const Value*); -void APS5_VABI _ZN3sce4Json5ValueC1ERKS1_(Value*, const Value*); -void APS5_VABI _ZN3sce4Json6StringC1Ev(String*); -void APS5_VABI _ZN3sce4Json6StringC1EPKc(String*, const char*); -void APS5_VABI _ZN3sce4Json6StringD1Ev(String*); -const char* APS5_VABI _ZNK3sce4Json6String5c_strEv(const String*); -std::size_t APS5_VABI _ZNK3sce4Json6String6lengthEv(const String*); -bool APS5_VABI _ZNK3sce4Json6String5emptyEv(const String*); -void APS5_VABI _ZN3sce4Json5ArrayC1Ev(Array*); -void APS5_VABI _ZN3sce4Json5ArrayC1ERKS1_(Array*, const Array*); -void APS5_VABI _ZN3sce4Json5Array5clearEv(Array*); -const Value* APS5_VABI _ZNK3sce4Json5Array5frontEv(const Array*); -Value* APS5_VABI _ZNK3sce4Json5Array8iteratorptEv(const Iterator*); -void APS5_VABI _ZN3sce4Json5ArrayD1Ev(Array*); -Array* APS5_VABI _ZN3sce4Json5ArrayaSERKS1_(Array*, const Array*); -void APS5_VABI _ZN3sce4Json5Array9push_backERKNS0_5ValueE(Array*, const Value*); -Iterator* APS5_VABI _ZNK3sce4Json5Array5beginEv(Iterator*, const Array*); -Iterator* APS5_VABI _ZNK3sce4Json5Array3endEv(Iterator*, const Array*); -std::size_t APS5_VABI _ZNK3sce4Json5Array4sizeEv(const Array*); -const Value* APS5_VABI _ZNK3sce4Json5Array4backEv(const Array*); -void APS5_VABI _ZN3sce4Json5Array9pop_frontEv(Array*); -bool APS5_VABI _ZNK3sce4Json5Array5emptyEv(const Array*); -void APS5_VABI _ZN3sce4Json5Array8iteratorD1Ev(Iterator*); -Iterator* APS5_VABI _ZN3sce4Json5Array8iteratorppEv(Iterator*); -Value* APS5_VABI _ZNK3sce4Json5Array8iteratordeEv(const Iterator*); -bool APS5_VABI _ZNK3sce4Json5Array8iteratorneERKS2_(const Iterator*, const Iterator*); -void APS5_VABI _ZN3sce4Json6ObjectC1Ev(Object*); -void APS5_VABI _ZN3sce4Json6ObjectD1Ev(Object*); -Value* APS5_VABI _ZN3sce4Json6ObjectixERKNS0_6StringE(Object*, const String*); -Iterator* APS5_VABI _ZNK3sce4Json6Object5beginEv(Iterator*, const Object*); -Iterator* APS5_VABI _ZNK3sce4Json6Object3endEv(Iterator*, const Object*); -void APS5_VABI _ZN3sce4Json6Object8iteratorD1Ev(Iterator*); -Iterator* APS5_VABI _ZN3sce4Json6Object8iteratorppEv(Iterator*); -Pair* APS5_VABI _ZNK3sce4Json6Object8iteratordeEv(const Iterator*); -Pair* APS5_VABI _ZNK3sce4Json6Object8iteratorptEv(const Iterator*); -Iterator* APS5_VABI _ZNK3sce4Json6Object4findERKNS0_6StringE(Iterator*, const Object*, const String*); -int APS5_VABI _ZNK3sce4Json6String7compareEPKc(const String*, const char*); -int APS5_VABI _ZNK3sce4Json6String7compareERKS1_(const String*, const String*); -std::size_t APS5_VABI _ZNK3sce4Json6String4sizeEv(const String*); -std::size_t APS5_VABI _ZNK3sce4Json6String8capacityEv(const String*); -bool APS5_VABI _ZNK3sce4Json6StringeqEPKc(const String*, const char*); -bool APS5_VABI _ZNK3sce4Json6StringeqERKS1_(const String*, const String*); + extern std::size_t _ZN3sce4Json6String4nposE; -void APS5_VABI _ZN3sce4Json6String5clearEv(String*); -void APS5_VABI _ZN3sce4Json6String6resizeEm(String*, std::size_t); -void APS5_VABI _ZN3sce4Json6String7reserveEm(String*, std::size_t); -String* APS5_VABI _ZN3sce4Json6String6appendERKS1_(String*, const String*); -String* APS5_VABI _ZN3sce4Json6String6appendEPKc(String*, const char*); -String* APS5_VABI _ZN3sce4Json6String6appendEPKcm(String*, const char*, std::size_t); -String* APS5_VABI _ZN3sce4Json6StringpLEPKc(String*, const char*); -String* APS5_VABI _ZN3sce4Json6StringpLEh(String*, unsigned char); -String* APS5_VABI _ZNK3sce4Json6String6substrEmm(String*, const String*, std::size_t, std::size_t); -std::size_t APS5_VABI _ZNK3sce4Json6String4findEcm(const String*, char, std::size_t); -std::size_t APS5_VABI _ZNK3sce4Json6String5rfindEcm(const String*, char, std::size_t); -char APS5_VABI _ZNK3sce4Json6String2atEm(const String*, std::size_t); -std::size_t APS5_VABI _ZNK3sce4Json6String4findEPKcm(const String*, const char*, std::size_t); -std::size_t APS5_VABI _ZNK3sce4Json6String4findEPKcmm(const String*, const char*, std::size_t, std::size_t); -std::size_t APS5_VABI _ZNK3sce4Json6String4findERKS1_m(const String*, const String*, std::size_t); -std::size_t APS5_VABI _ZNK3sce4Json6String5rfindEPKcm(const String*, const char*, std::size_t); -std::size_t APS5_VABI _ZNK3sce4Json6String5rfindEPKcmm(const String*, const char*, std::size_t, std::size_t); -std::size_t APS5_VABI _ZNK3sce4Json6String5rfindERKS1_m(const String*, const String*, std::size_t); -bool APS5_VABI _ZNK3sce4Json6Object8iteratorneERKS2_(const Iterator*, const Iterator*); -bool APS5_VABI _ZNK3sce4Json6Object8iteratoreqERKS2_(const Iterator*, const Iterator*); -void APS5_VABI _ZN3sce4Json5ValueC1Ev(Value*); -void APS5_VABI _ZN3sce4Json5ValueC1Eb(Value*, bool); -void APS5_VABI _ZN3sce4Json5ValueC1Ed(Value*, double); -void APS5_VABI _ZN3sce4Json5ValueC1ERKNS0_6ObjectE(Value*, const Object*); -void APS5_VABI _ZN3sce4Json5ValueD1Ev(Value*); -void APS5_VABI _ZN3sce4Json5Value5clearEv(Value*); -int APS5_VABI _ZN3sce4Json5Value3setEl(Value*, std::int64_t); -int APS5_VABI _ZN3sce4Json5Value3setEm(Value*, std::uint64_t); -int APS5_VABI _ZN3sce4Json5Value3setEPKc(Value*, const char*); -std::int32_t APS5_VABI _ZNK3sce4Json5Value7getTypeEv(const Value*); -const bool* APS5_VABI _ZNK3sce4Json5Value10getBooleanEv(const Value*); -const std::int64_t* APS5_VABI _ZNK3sce4Json5Value10getIntegerEv(const Value*); -const std::uint64_t* APS5_VABI _ZNK3sce4Json5Value11getUIntegerEv(const Value*); -const double* APS5_VABI _ZNK3sce4Json5Value7getRealEv(const Value*); -const String* APS5_VABI _ZNK3sce4Json5Value9getStringEv(const Value*); -const Array* APS5_VABI _ZNK3sce4Json5Value8getArrayEv(const Value*); -std::size_t APS5_VABI _ZNK3sce4Json5Value5countEv(const Value*); -const Value* APS5_VABI _ZNK3sce4Json5ValueixEPKc(const Value*, const char*); -Value* APS5_VABI _ZN3sce4Json5Value10referValueERKNS0_6StringE(Value*, const String*); -const Value* APS5_VABI _ZNK3sce4Json5ValueixEm(const Value*, std::size_t); -int APS5_VABI _ZN3sce4Json5Value9serializeERNS0_6StringE(Value*, String*); -int APS5_VABI _ZN3sce4Json6Parser5parseERNS0_5ValueEPKcm(Value*, const char*, std::size_t); -int APS5_VABI _ZN3sce4Json6Parser5parseERNS0_5ValueEPFiRcPvES5_(Value*, int (APS5_VABI*)(char&, void*), void*); -bool APS5_VABI _ZNK3sce4Json6Object5emptyEv(const Object*); -std::size_t APS5_VABI _ZNK3sce4Json6Object4sizeEv(const Object*); -const Object* APS5_VABI _ZNK3sce4Json5Value9getObjectEv(const Value*); -void APS5_VABI _ZN3sce4Json5ValueC1ENS0_9ValueTypeE(Value*, std::int32_t); -const Value* APS5_VABI _ZNK3sce4Json5Value8getValueEm(const Value*, std::size_t); -const Value* APS5_VABI _ZNK3sce4Json5Value8getValueERKNS0_6StringE(const Value*, const String*); -Value* APS5_VABI _ZN3sce4Json5Value10referValueEm(Value*, std::size_t); -void APS5_VABI _ZN3sce4Json14InitParameter2C1Ev(void*); -void APS5_VABI _ZN3sce4Json14InitParameter2C2Ev(void*); -void APS5_VABI _ZN3sce4Json14InitParameter212setAllocatorEPNS0_12MemAllocatorEPv(void*, void*, void*); -void APS5_VABI _ZN3sce4Json14InitParameter217setFileBufferSizeEm(void*, std::size_t); -int APS5_VABI _ZN3sce4Json11Initializer10initializeEPKNS0_14InitParameter2E(void*, const void*); -void APS5_VABI _ZN3sce4Json18InitParameterRtti216setAllocatorRttiEPNS0_14AllocParamRttiEPv(void*, void*, void*); -void APS5_VABI _ZN3sce4Json14InitParameter225setSpecialFloatFormatTypeENS0_22SpecialFloatFormatTypeE(void*, std::int32_t); -void APS5_VABI _ZN3sce4Json17InitParameterRttiC1EPNS0_14AllocParamRttiEPvm(void*, void*, void*, std::size_t); -void APS5_VABI _ZN3sce4Json6Object4PairC1Ev(Pair*); -void APS5_VABI _ZN3sce4Json6Object4PairC1ERKNS0_6StringERKNS0_5ValueE(Pair*, const String*, const Value*); -void APS5_VABI _ZN3sce4Json6Object4PairD1Ev(Pair*); -Iterator* APS5_VABI _ZN3sce4Json6Object6insertERKNS1_4PairE(Iterator*, Object*, const Pair*); -void APS5_VABI _ZN3sce4Json6Object8iteratorC1Ev(Iterator*); -Iterator* APS5_VABI _ZN3sce4Json6Object8iteratoraSERKS2_(Iterator*, const Iterator*); -Iterator* APS5_VABI _ZN3sce4Json6Object8iteratorppEi(Iterator*, Iterator*, int); -void APS5_VABI _ZN3sce4Json5Array8iteratorC1Ev(Iterator*); -Iterator* APS5_VABI _ZN3sce4Json5Array8iteratoraSERKS2_(Iterator*, const Iterator*); -Iterator* APS5_VABI _ZN3sce4Json5Array8iteratorppEi(Iterator*, Iterator*, int); -void APS5_VABI _ZN3sce4Json12MemAllocator11notifyErrorEimPv(void*, int, std::size_t, void*); -bool APS5_VABI _ZNK3sce4Json5ValuecvbEv(const Value*); -void APS5_VABI _ZN3sce4Json5Value4swapERS1_(Value*, Value*); -void APS5_VABI _ZN3sce4Json5Array8iteratorC1ERKS2_(Iterator*, const Iterator*); -Iterator* APS5_VABI _ZN3sce4Json5Array8iterator7advanceEm(Iterator*, std::size_t); -void APS5_VABI _ZN3sce4Json6Object8iteratorC1ERKS2_(Iterator*, const Iterator*); -Iterator* APS5_VABI _ZN3sce4Json6Object8iterator7advanceEm(Iterator*, std::size_t); -void APS5_VABI _ZN3sce4Json6Object5eraseERKNS0_6StringE(Object*, const String*); + } static void Check(bool value, int line) { @@ -170,7 +31,6 @@ static void Check(bool value, int line) { } #define Require(value) Check((value), __LINE__) -enum : std::int32_t { TypeNull, TypeBoolean, TypeInteger, TypeUInteger, TypeReal, TypeString, TypeArray, TypeObject }; constexpr int JsonErrorParse = static_cast(0x80848101); static Value fallback{}; @@ -179,7 +39,7 @@ static std::int32_t lastRequested = -1; static const Value* lastParent = nullptr; static void* lastContext = nullptr; -static const Value& APS5_VABI OnNullAccess(std::int32_t requested, const Value* parent, void* context) { +static const Value& APS5_VABI OnNullAccess(ValueType requested, const Value* parent, void* context) { ++callbackCalls; lastRequested = requested; lastParent = parent; @@ -190,9 +50,11 @@ static const Value& APS5_VABI OnNullAccess(std::int32_t requested, const Value* static std::string Serialize(Value& value) { String out{}; _ZN3sce4Json6StringC1Ev(&out); + Require(_ZN3sce4Json5Value9serializeERNS0_6StringE(&value, &out) == 0); std::string text(_ZNK3sce4Json6String5c_strEv(&out), _ZNK3sce4Json6String6lengthEv(&out)); _ZN3sce4Json6StringD1Ev(&out); + return text; } @@ -206,6 +68,7 @@ static void ParseAndRoundTrip() { " \"pi\": 1.5, \"ok\": true, \"none\": null, \"list\": [1, \"two\", [3]] }"; Value root{}; _ZN3sce4Json5ValueC1Ev(&root); + Require(_ZN3sce4Json6Parser5parseERNS0_5ValueEPKcm(&root, text.c_str(), text.size()) == 0); Require(_ZNK3sce4Json5Value7getTypeEv(&root) == TypeObject); Require(_ZNK3sce4Json5Value5countEv(&root) == 8); @@ -224,6 +87,7 @@ static void ParseAndRoundTrip() { String absent{}; _ZN3sce4Json6StringC1EPKc(&present, "ok"); _ZN3sce4Json6StringC1EPKc(&absent, "applyToAll"); + Require(_ZN3sce4Json5Value10referValueERKNS0_6StringE(&root, &present) == &Member(root, "ok")); Require(_ZN3sce4Json5Value10referValueERKNS0_6StringE(&root, &absent) == nullptr); Require(_ZNK3sce4Json5Value5countEv(&root) == 8); @@ -234,13 +98,15 @@ static void ParseAndRoundTrip() { const Array* array = _ZNK3sce4Json5Value8getArrayEv(&list); Require(_ZNK3sce4Json5Array4sizeEv(array) == 3); std::vector types; - Iterator it{}, end{}; + ArrayIterator it{}, end{}; _ZNK3sce4Json5Array5beginEv(&it, array); _ZNK3sce4Json5Array3endEv(&end, array); + for (; _ZNK3sce4Json5Array8iteratorneERKS2_(&it, &end); _ZN3sce4Json5Array8iteratorppEv(&it)) types.push_back(_ZNK3sce4Json5Value7getTypeEv(_ZNK3sce4Json5Array8iteratordeEv(&it))); _ZN3sce4Json5Array8iteratorD1Ev(&it); _ZN3sce4Json5Array8iteratorD1Ev(&end); + Require((types == std::vector{TypeUInteger, TypeString, TypeArray})); Require(*_ZNK3sce4Json5Value10getIntegerEv(_ZNK3sce4Json5ValueixEm(_ZNK3sce4Json5ValueixEm(&list, 2), 0)) == 3); @@ -249,6 +115,7 @@ static void ParseAndRoundTrip() { "\"name\":\"x\xc3\xa9\\n\",\"neg\":-5,\"none\":null,\"ok\":true,\"pi\":1.5}"); Value reparsed{}; _ZN3sce4Json5ValueC1Ev(&reparsed); + Require(_ZN3sce4Json6Parser5parseERNS0_5ValueEPKcm(&reparsed, serialized.c_str(), serialized.size()) == 0); Require(Serialize(reparsed) == serialized); _ZN3sce4Json5ValueD1Ev(&reparsed); @@ -261,6 +128,7 @@ static void ParseAndRoundTrip() { bool nullTextRejected = false; try { _ZN3sce4Json6Parser5parseERNS0_5ValueEPKcm(&root, nullptr, 10); + } catch (const std::invalid_argument&) { nullTextRejected = true; } @@ -271,6 +139,7 @@ static void ParseAndRoundTrip() { bool unverified = false; try { _ZN3sce4Json6Parser5parseERNS0_5ValueEPKcm(&root, overflow, std::strlen(overflow)); + } catch (const std::runtime_error& error) { unverified = std::string(error.what()).find("unverified") != std::string::npos; } @@ -278,6 +147,7 @@ static void ParseAndRoundTrip() { Require(_ZNK3sce4Json5Value7getTypeEv(&root) == TypeObject && _ZNK3sce4Json5Value5countEv(&root) == 8); } _ZN3sce4Json5ValueD1Ev(&root); + } static std::string Nested(std::size_t depth, bool objects) { @@ -291,6 +161,7 @@ static std::string Nested(std::size_t depth, bool objects) { static void NestingDepth() { Value root{}; _ZN3sce4Json5ValueC1Ev(&root); + for (const bool objects : {false, true}) { const std::string accepted = Nested(512, objects); Require(_ZN3sce4Json6Parser5parseERNS0_5ValueEPKcm(&root, accepted.c_str(), accepted.size()) == 0); @@ -300,12 +171,14 @@ static void NestingDepth() { } } _ZN3sce4Json5ValueD1Ev(&root); + } static void ArrayAssignment() { Array source{}, target{}; _ZN3sce4Json5ArrayC1Ev(&source); _ZN3sce4Json5ArrayC1Ev(&target); + Value flag{}, real{}; _ZN3sce4Json5ValueC1Eb(&flag, true); _ZN3sce4Json5ValueC1Ed(&real, 1.5); @@ -313,10 +186,12 @@ static void ArrayAssignment() { _ZN3sce4Json5Array9push_backERKNS0_5ValueE(&source, &real); _ZN3sce4Json5Array9push_backERKNS0_5ValueE(&source, &flag); _ZN3sce4Json5Array9push_backERKNS0_5ValueE(&target, &real); + Require(_ZN3sce4Json5ArrayaSERKS1_(&target, &source) == &target); Require(_ZNK3sce4Json5Array4sizeEv(&target) == 3); Require(_ZNK3sce4Json5Array4sizeEv(&source) == 3); _ZN3sce4Json5Array5clearEv(&source); + Require(_ZNK3sce4Json5Array4sizeEv(&target) == 3); Require(*_ZNK3sce4Json5Value10getBooleanEv(_ZNK3sce4Json5Array5frontEv(&target))); Require(*_ZNK3sce4Json5Value10getBooleanEv(_ZNK3sce4Json5Array4backEv(&target))); @@ -326,14 +201,17 @@ static void ArrayAssignment() { _ZN3sce4Json5ValueD1Ev(&real); _ZN3sce4Json5ArrayD1Ev(&source); _ZN3sce4Json5ArrayD1Ev(&target); + } static void ObjectsAndArrays() { Object object{}; _ZN3sce4Json6ObjectC1Ev(&object); + String alpha{}, beta{}; _ZN3sce4Json6StringC1EPKc(&alpha, "alpha"); _ZN3sce4Json6StringC1EPKc(&beta, "beta"); + Require(_ZNK3sce4Json6Object5emptyEv(&object)); Value* first = _ZN3sce4Json6ObjectixERKNS0_6StringE(&object, &alpha); Require(!_ZNK3sce4Json6Object5emptyEv(&object)); @@ -343,9 +221,10 @@ static void ObjectsAndArrays() { Require(_ZN3sce4Json6ObjectixERKNS0_6StringE(&object, &alpha) == first); std::vector keys; - Iterator it{}, end{}; + ObjectIterator it{}, end{}; _ZNK3sce4Json6Object5beginEv(&it, &object); _ZNK3sce4Json6Object3endEv(&end, &object); + for (; _ZNK3sce4Json6Object8iteratorneERKS2_(&it, &end); _ZN3sce4Json6Object8iteratorppEv(&it)) { const Pair* pair = _ZNK3sce4Json6Object8iteratordeEv(&it); keys.emplace_back(_ZNK3sce4Json6String5c_strEv(&pair->key)); @@ -353,10 +232,12 @@ static void ObjectsAndArrays() { } _ZN3sce4Json6Object8iteratorD1Ev(&it); _ZN3sce4Json6Object8iteratorD1Ev(&end); + Require((keys == std::vector{"alpha", "beta"})); Value wrapped{}; _ZN3sce4Json5ValueC1ERKNS0_6ObjectE(&wrapped, &object); + Require(Serialize(wrapped) == "{\"alpha\":1,\"beta\":\"b\"}"); _ZN3sce4Json5ValueD1Ev(&wrapped); _ZN3sce4Json6StringD1Ev(&alpha); @@ -365,6 +246,7 @@ static void ObjectsAndArrays() { Array array{}; _ZN3sce4Json5ArrayC1Ev(&array); + Value flag{}, real{}; _ZN3sce4Json5ValueC1Eb(&flag, true); _ZN3sce4Json5ValueC1Ed(&real, 2.5); @@ -372,23 +254,29 @@ static void ObjectsAndArrays() { _ZN3sce4Json5Array9push_backERKNS0_5ValueE(&array, &real); _ZN3sce4Json5ValueD1Ev(&flag); _ZN3sce4Json5ValueD1Ev(&real); + Require(_ZNK3sce4Json5Array4sizeEv(&array) == 2); Require(*_ZNK3sce4Json5Value7getRealEv(_ZNK3sce4Json5Array4backEv(&array)) == 2.5); + ArrayIterator arrayIt{}, arrayEnd{}; int visited = 0; - _ZNK3sce4Json5Array5beginEv(&it, &array); - _ZNK3sce4Json5Array3endEv(&end, &array); - for (; _ZNK3sce4Json5Array8iteratorneERKS2_(&it, &end); _ZN3sce4Json5Array8iteratorppEv(&it)) ++visited; + _ZNK3sce4Json5Array5beginEv(&arrayIt, &array); + _ZNK3sce4Json5Array3endEv(&arrayEnd, &array); + + for (; _ZNK3sce4Json5Array8iteratorneERKS2_(&arrayIt, &arrayEnd); _ZN3sce4Json5Array8iteratorppEv(&arrayIt)) ++visited; Require(visited == 2); Require(*_ZNK3sce4Json5Value10getBooleanEv(_ZNK3sce4Json5Array5frontEv(&array))); - _ZNK3sce4Json5Array5beginEv(&it, &array); - Require(_ZNK3sce4Json5Array8iteratorptEv(&it) == _ZNK3sce4Json5Array8iteratordeEv(&it)); + _ZNK3sce4Json5Array5beginEv(&arrayIt, &array); + + Require(_ZNK3sce4Json5Array8iteratorptEv(&arrayIt) == _ZNK3sce4Json5Array8iteratordeEv(&arrayIt)); Array copy{}; _ZN3sce4Json5ArrayC1ERKS1_(©, &array); _ZN3sce4Json5Array5clearEv(&array); + Require(_ZNK3sce4Json5Array4sizeEv(&array) == 0); bool threw = false; try { _ZNK3sce4Json5Array5frontEv(&array); + } catch (const std::out_of_range&) { threw = true; } @@ -397,31 +285,38 @@ static void ObjectsAndArrays() { Require(*_ZNK3sce4Json5Value10getBooleanEv(_ZNK3sce4Json5Array5frontEv(©))); Require(*_ZNK3sce4Json5Value7getRealEv(_ZNK3sce4Json5Array4backEv(©)) == 2.5); _ZN3sce4Json5Array9pop_frontEv(©); + Require(_ZNK3sce4Json5Array4sizeEv(©) == 1); Require(*_ZNK3sce4Json5Value7getRealEv(_ZNK3sce4Json5Array5frontEv(©)) == 2.5); _ZN3sce4Json5Array9pop_frontEv(©); + Require(_ZNK3sce4Json5Array5emptyEv(©)); threw = false; try { _ZN3sce4Json5Array9pop_frontEv(©); + } catch (const std::out_of_range&) { threw = true; } Require(threw && _ZNK3sce4Json5Array5emptyEv(©)); _ZN3sce4Json5ArrayD1Ev(©); _ZN3sce4Json5ArrayD1Ev(&array); + } static void ObjectPair() { String key{}; _ZN3sce4Json6StringC1EPKc(&key, "answer"); + Value value{}; _ZN3sce4Json5ValueC1Ev(&value); + Require(_ZN3sce4Json5Value3setEPKc(&value, "forty-two") == 0); Pair pair{}; std::memset(&pair, 0x5a, sizeof(pair)); _ZN3sce4Json6Object4PairC1ERKNS0_6StringERKNS0_5ValueE(&pair, &key, &value); + Require(pair.reserved == 0); Require(pair.key.text != key.text && pair.value.node != value.node); Require(std::strcmp(_ZNK3sce4Json6String5c_strEv(&pair.key), "answer") == 0); @@ -431,38 +326,46 @@ static void ObjectPair() { Require(_ZN3sce4Json5Value3setEl(&value, 7) == 0); _ZN3sce4Json6StringD1Ev(&key); _ZN3sce4Json5ValueD1Ev(&value); + Require(std::strcmp(_ZNK3sce4Json6String5c_strEv(&pair.key), "answer") == 0); Require(_ZNK3sce4Json5Value7getTypeEv(&pair.value) == TypeString); _ZN3sce4Json6Object4PairD1Ev(&pair); + Require(pair.key.text == nullptr && pair.value.node == nullptr); } static void ArrayIteratorCopies() { Array array{}; _ZN3sce4Json5ArrayC1Ev(&array); + for (std::int64_t i = 1; i <= 3; ++i) { Value item{}; _ZN3sce4Json5ValueC1Ev(&item); + Require(_ZN3sce4Json5Value3setEl(&item, i) == 0); _ZN3sce4Json5Array9push_backERKNS0_5ValueE(&array, &item); _ZN3sce4Json5ValueD1Ev(&item); + } - Iterator it{}; + ArrayIterator it{}; std::memset(&it, 0x5a, sizeof(it)); _ZN3sce4Json5Array8iteratorC1Ev(&it); - Require(it.position != nullptr); - Iterator begin{}, end{}; + Require(it.state != nullptr); + + ArrayIterator begin{}, end{}; _ZNK3sce4Json5Array5beginEv(&begin, &array); _ZNK3sce4Json5Array3endEv(&end, &array); + Require(_ZN3sce4Json5Array8iteratoraSERKS2_(&it, &begin) == &it); Require(!_ZNK3sce4Json5Array8iteratorneERKS2_(&it, &begin)); std::vector seen; - Iterator previous{}; + ArrayIterator previous{}; while (_ZNK3sce4Json5Array8iteratorneERKS2_(&it, &end)) { _ZN3sce4Json5Array8iteratorD1Ev(&previous); + Require(_ZN3sce4Json5Array8iteratorppEi(&previous, &it, 0) == &previous); seen.push_back(*_ZNK3sce4Json5Value10getIntegerEv(_ZNK3sce4Json5Array8iteratordeEv(&previous))); Require(_ZNK3sce4Json5Array8iteratorneERKS2_(&previous, &it)); @@ -471,9 +374,9 @@ static void ArrayIteratorCopies() { Require(!_ZNK3sce4Json5Array8iteratorneERKS2_(&it, &end)); Require(*_ZNK3sce4Json5Value10getIntegerEv(_ZNK3sce4Json5Array8iteratordeEv(&previous)) == 3); Require(_ZN3sce4Json5Array8iteratoraSERKS2_(&it, &end) == &it); - Require(it.position == nullptr); + Require(it.state == nullptr); Require(_ZN3sce4Json5Array8iteratoraSERKS2_(&it, &begin) == &it); - Require(it.position == nullptr); + Require(it.state == nullptr); Require(!_ZNK3sce4Json5Array8iteratorneERKS2_(&it, &begin)); _ZN3sce4Json5Array8iteratorD1Ev(&previous); @@ -487,19 +390,23 @@ static void AllocatorNotifyError() { int allocator = 0x1234; int userData = 0x5678; _ZN3sce4Json12MemAllocator11notifyErrorEimPv(&allocator, -1, 64, &userData); + Require(allocator == 0x1234 && userData == 0x5678); } static void ObjectFind() { Object object{}; _ZN3sce4Json6ObjectC1Ev(&object); + String alpha{}, beta{}, gamma{}; _ZN3sce4Json6StringC1EPKc(&alpha, "alpha"); _ZN3sce4Json6StringC1EPKc(&beta, "beta"); _ZN3sce4Json6StringC1EPKc(&gamma, "gamma"); - Iterator found{}, end{}; + + ObjectIterator found{}, end{}; _ZNK3sce4Json6Object3endEv(&end, &object); _ZNK3sce4Json6Object4findERKNS0_6StringE(&found, &object, &alpha); + Require(!_ZNK3sce4Json6Object8iteratorneERKS2_(&found, &end)); _ZN3sce4Json6Object8iteratorD1Ev(&found); _ZN3sce4Json6Object8iteratorD1Ev(&end); @@ -509,7 +416,8 @@ static void ObjectFind() { Require(_ZN3sce4Json5Value3setEPKc(second, "b") == 0); _ZNK3sce4Json6Object3endEv(&end, &object); _ZN3sce4Json6Object8iteratorD1Ev(&found); - Iterator* returned = _ZNK3sce4Json6Object4findERKNS0_6StringE(&found, &object, &beta); + + ObjectIterator* returned = _ZNK3sce4Json6Object4findERKNS0_6StringE(&found, &object, &beta); Require(returned == &found); Require(_ZNK3sce4Json6Object8iteratorneERKS2_(&found, &end)); const Pair* pair = _ZNK3sce4Json6Object8iteratorptEv(&found); @@ -517,9 +425,11 @@ static void ObjectFind() { Require(&pair->value == second); Require(std::strcmp(_ZNK3sce4Json6String5c_strEv(&pair->key), "beta") == 0); _ZN3sce4Json6Object8iteratorppEv(&found); + Require(!_ZNK3sce4Json6Object8iteratorneERKS2_(&found, &end)); _ZN3sce4Json6Object8iteratorD1Ev(&found); _ZNK3sce4Json6Object4findERKNS0_6StringE(&found, &object, &gamma); + Require(!_ZNK3sce4Json6Object8iteratorneERKS2_(&found, &end)); Require(_ZNK3sce4Json6Object4sizeEv(&object) == 2); _ZN3sce4Json6Object8iteratorD1Ev(&found); @@ -540,49 +450,56 @@ static void ObjectFind() { _ZN3sce4Json6StringD1Ev(&beta); _ZN3sce4Json6StringD1Ev(&gamma); _ZN3sce4Json6ObjectD1Ev(&object); + } static void ObjectIteratorCopies() { Object object{}; _ZN3sce4Json6ObjectC1Ev(&object); + String key1{}, key2{}; _ZN3sce4Json6StringC1EPKc(&key1, "one"); _ZN3sce4Json6StringC1EPKc(&key2, "two"); + Value val1{}, val2{}; _ZN3sce4Json5ValueC1Ev(&val1); _ZN3sce4Json5ValueC1Ev(&val2); + Require(_ZN3sce4Json5Value3setEl(&val1, 10) == 0); Require(_ZN3sce4Json5Value3setEl(&val2, 20) == 0); Pair p1{}, p2{}; _ZN3sce4Json6Object4PairC1ERKNS0_6StringERKNS0_5ValueE(&p1, &key1, &val1); _ZN3sce4Json6Object4PairC1ERKNS0_6StringERKNS0_5ValueE(&p2, &key2, &val2); - Iterator ins1{}, ins2{}; + + ObjectIterator ins1{}, ins2{}; Require(_ZN3sce4Json6Object6insertERKNS1_4PairE(&ins1, &object, &p1) == &ins1); Require(_ZN3sce4Json6Object6insertERKNS1_4PairE(&ins2, &object, &p2) == &ins2); _ZN3sce4Json6Object8iteratorD1Ev(&ins1); _ZN3sce4Json6Object8iteratorD1Ev(&ins2); - Iterator it{}; + ObjectIterator it{}; std::memset(&it, 0x5a, sizeof(it)); _ZN3sce4Json6Object8iteratorC1Ev(&it); - Require(it.position != nullptr); + + Require(it.state != nullptr); _ZN3sce4Json6Object8iteratorD1Ev(&it); - Iterator begin{}, end{}; + ObjectIterator begin{}, end{}; _ZNK3sce4Json6Object5beginEv(&begin, &object); _ZNK3sce4Json6Object3endEv(&end, &object); Require(!_ZNK3sce4Json6Object8iteratoreqERKS2_(&begin, &end)); Require(_ZNK3sce4Json6Object8iteratorneERKS2_(&begin, &end)); - Iterator post{}; + ObjectIterator post{}; Require(_ZN3sce4Json6Object8iteratorppEi(&post, &begin, 0) == &post); Require(std::strcmp(_ZNK3sce4Json6String5c_strEv(&_ZNK3sce4Json6Object8iteratordeEv(&post)->key), "one") == 0); Require(std::strcmp(_ZNK3sce4Json6String5c_strEv(&_ZNK3sce4Json6Object8iteratordeEv(&begin)->key), "two") == 0); _ZN3sce4Json6Object8iteratorD1Ev(&post); - Iterator assigned{}; + ObjectIterator assigned{}; _ZN3sce4Json6Object8iteratorC1Ev(&assigned); + Require(_ZN3sce4Json6Object8iteratoraSERKS2_(&assigned, &begin) == &assigned); Require(_ZNK3sce4Json6Object8iteratoreqERKS2_(&assigned, &begin)); Require(!_ZNK3sce4Json6Object8iteratorneERKS2_(&assigned, &begin)); @@ -603,16 +520,20 @@ static void ObjectIteratorCopies() { static void ObjectInsert() { Object object{}; _ZN3sce4Json6ObjectC1Ev(&object); + String key{}; _ZN3sce4Json6StringC1EPKc(&key, "score"); + Value value{}; _ZN3sce4Json5ValueC1Ev(&value); + Require(_ZN3sce4Json5Value3setEl(&value, 100) == 0); Pair pair{}; _ZN3sce4Json6Object4PairC1ERKNS0_6StringERKNS0_5ValueE(&pair, &key, &value); - Iterator inserted{}, end{}; + ObjectIterator inserted{}, end{}; _ZNK3sce4Json6Object3endEv(&end, &object); + Require(_ZN3sce4Json6Object6insertERKNS1_4PairE(&inserted, &object, &pair) == &inserted); Require(_ZNK3sce4Json6Object8iteratorneERKS2_(&inserted, &end)); Require(_ZNK3sce4Json6Object4sizeEv(&object) == 1); @@ -621,7 +542,7 @@ static void ObjectInsert() { Require(*_ZNK3sce4Json5Value10getIntegerEv(&p->value) == 100); Require(_ZN3sce4Json5Value3setEl(&pair.value, 200) == 0); - Iterator duplicate{}; + ObjectIterator duplicate{}; Require(_ZN3sce4Json6Object6insertERKNS1_4PairE(&duplicate, &object, &pair) == &duplicate); Require(_ZNK3sce4Json6Object8iteratoreqERKS2_(&duplicate, &inserted)); Require(_ZNK3sce4Json6Object4sizeEv(&object) == 1); @@ -630,16 +551,20 @@ static void ObjectInsert() { String otherKey{}; _ZN3sce4Json6StringC1EPKc(&otherKey, "other"); + Value otherValue{}; _ZN3sce4Json5ValueC1Ev(&otherValue); + Require(_ZN3sce4Json5Value3setEPKc(&otherValue, "str") == 0); Pair otherPair{}; _ZN3sce4Json6Object4PairC1ERKNS0_6StringERKNS0_5ValueE(&otherPair, &otherKey, &otherValue); - Iterator otherInserted{}; + + ObjectIterator otherInserted{}; Require(_ZN3sce4Json6Object6insertERKNS1_4PairE(&otherInserted, &object, &otherPair) == &otherInserted); Require(_ZNK3sce4Json6Object4sizeEv(&object) == 2); - Iterator first{}; + ObjectIterator first{}; _ZNK3sce4Json6Object5beginEv(&first, &object); + Require(_ZNK3sce4Json6Object8iteratoreqERKS2_(&first, &otherInserted)); Require(*_ZNK3sce4Json5Value10getIntegerEv(&_ZNK3sce4Json6Object8iteratordeEv(&inserted)->value) == 100); _ZN3sce4Json6Object8iteratorD1Ev(&first); @@ -659,43 +584,56 @@ static void ObjectInsert() { static void ObjectKeyOrder() { Object object{}; _ZN3sce4Json6ObjectC1Ev(&object); + for (const char* name : {"z", "\xc3\xa9", "a", "A", ""}) { String key{}; _ZN3sce4Json6StringC1EPKc(&key, name); _ZN3sce4Json6ObjectixERKNS0_6StringE(&object, &key); _ZN3sce4Json6StringD1Ev(&key); + } - Iterator member{}; + ObjectIterator member{}; _ZNK3sce4Json6Object5beginEv(&member, &object); + for (const char* expected : {"", "A", "a", "z", "\xc3\xa9"}) { Require(std::strcmp(_ZNK3sce4Json6String5c_strEv(&_ZNK3sce4Json6Object8iteratordeEv(&member)->key), expected) == 0); _ZN3sce4Json6Object8iteratorppEv(&member); + } _ZN3sce4Json6Object8iteratorD1Ev(&member); + String key{}; _ZN3sce4Json6StringC1EPKc(&key, "a"); + Value* existing = _ZN3sce4Json6ObjectixERKNS0_6StringE(&object, &key); _ZN3sce4Json6String6appendEPKcm(&key, "\0suffix", 7); + Require(_ZN3sce4Json6ObjectixERKNS0_6StringE(&object, &key) == existing); _ZNK3sce4Json6Object4findERKNS0_6StringE(&member, &object, &key); + Require(&_ZNK3sce4Json6Object8iteratordeEv(&member)->value == existing); _ZN3sce4Json6Object8iteratorD1Ev(&member); + Require(_ZNK3sce4Json6Object4sizeEv(&object) == 5); _ZN3sce4Json6Object5eraseERKNS0_6StringE(&object, &key); + Require(_ZNK3sce4Json6Object4sizeEv(&object) == 4); _ZN3sce4Json6StringD1Ev(&key); _ZN3sce4Json6ObjectD1Ev(&object); + } static void ParseDuplicateKeys() { Value root{}; _ZN3sce4Json5ValueC1Ev(&root); + for (const char* text : {R"({"a":1,"a":2})", R"({"a":[1,2],"a":2})", R"({"a":{"old":true},"a":2})", R"({"a":1,"a\u0000suffix":2})"}) { Require(_ZN3sce4Json6Parser5parseERNS0_5ValueEPKcm(&root, text, std::strlen(text)) == 0); Require(_ZNK3sce4Json5Value5countEv(&root) == 1); Require(Serialize(root) == R"({"a":2})"); } _ZN3sce4Json5ValueD1Ev(&root); + } static void StringComparison() { @@ -703,6 +641,7 @@ static void StringComparison() { _ZN3sce4Json6StringC1EPKc(&left, "a"); _ZN3sce4Json6StringC1EPKc(&right, "a"); _ZN3sce4Json6String6appendEPKcm(&left, "\0suffix", 7); + Require(_ZNK3sce4Json6StringeqERKS1_(&left, &right)); Require(_ZNK3sce4Json6StringeqEPKc(&left, "a")); Require(_ZNK3sce4Json6String7compareERKS1_(&left, &right) == 0); @@ -712,6 +651,7 @@ static void StringComparison() { Require(_ZNK3sce4Json6String7compareEPKc(&left, "\xff") == -158); _ZN3sce4Json6StringD1Ev(&right); _ZN3sce4Json6StringD1Ev(&left); + } static void StringMethods() { @@ -721,6 +661,7 @@ static void StringMethods() { String suffix{}; _ZN3sce4Json6StringC1EPKc(&base, "a/b/c"); _ZN3sce4Json6StringC1EPKc(&suffix, "-tail"); + Require(_ZNK3sce4Json6String4findEcm(&base, '/', 0) == 1); Require(_ZNK3sce4Json6String4findEcm(&base, '/', 2) == 3); Require(_ZNK3sce4Json6String4findEcm(&base, 'z', 0) == _ZN3sce4Json6String4nposE); @@ -732,6 +673,7 @@ static void StringMethods() { bool atRefused = false; try { _ZNK3sce4Json6String2atEm(&base, 5); + } catch (const std::out_of_range&) { atRefused = true; } @@ -750,14 +692,17 @@ static void StringMethods() { Require(_ZNK3sce4Json6String5rfindEPKcmm(&base, "zz", npos, 2) == npos); String needle{}; _ZN3sce4Json6StringC1EPKc(&needle, "/c"); + Require(_ZNK3sce4Json6String4findERKS1_m(&base, &needle, 0) == 3); Require(_ZNK3sce4Json6String4findERKS1_m(&base, &needle, 4) == npos); Require(_ZNK3sce4Json6String5rfindERKS1_m(&base, &needle, npos) == 3); Require(_ZNK3sce4Json6String5rfindERKS1_m(&base, &needle, 2) == npos); _ZN3sce4Json6StringD1Ev(&needle); + bool findRefused = false; try { _ZNK3sce4Json6String4findEPKcm(&base, nullptr, 0); + } catch (const std::invalid_argument&) { findRefused = true; } @@ -766,12 +711,15 @@ static void StringMethods() { Require(_ZNK3sce4Json6String6substrEmm(&part, &base, 2, 3) == &part); Require(text(part) == "b/c"); _ZN3sce4Json6StringD1Ev(&part); + Require(_ZNK3sce4Json6String6substrEmm(&part, &base, 5, _ZN3sce4Json6String4nposE) == &part); Require(text(part).empty()); _ZN3sce4Json6StringD1Ev(&part); + bool refused = false; try { _ZNK3sce4Json6String6substrEmm(&part, &base, 6, 1); + } catch (const std::out_of_range&) { refused = true; } @@ -780,10 +728,12 @@ static void StringMethods() { Require(_ZNK3sce4Json6String6lengthEv(&base) == 5); String match{}; _ZN3sce4Json6StringC1EPKc(&match, "a/b/c"); + Require(_ZNK3sce4Json6StringeqERKS1_(&base, &match)); Require(_ZNK3sce4Json6String7compareERKS1_(&base, &match) == 0); _ZN3sce4Json6StringD1Ev(&match); _ZN3sce4Json6String7reserveEm(&base, 64); + Require(_ZNK3sce4Json6String8capacityEv(&base) >= 64); Require(_ZN3sce4Json6String6appendERKS1_(&base, &suffix) == &base); Require(_ZN3sce4Json6String6appendEPKc(&base, "!") == &base); @@ -792,73 +742,91 @@ static void StringMethods() { Require(_ZN3sce4Json6StringpLEh(&base, '?') == &base); Require(text(base) == "a/b/c-tail!12+?"); _ZN3sce4Json6String6resizeEm(&base, 5); + Require(_ZNK3sce4Json6String4sizeEv(&base) == 5); Require(text(base) == "a/b/c"); _ZN3sce4Json6String6appendERKS1_(&base, &base); + Require(text(base) == "a/b/ca/b/c"); _ZN3sce4Json6String5clearEv(&base); + Require(text(base).empty()); _ZN3sce4Json6StringD1Ev(&suffix); _ZN3sce4Json6StringD1Ev(&base); + } static void ValueSwap() { Value v1{}, v2{}; _ZN3sce4Json5ValueC1Ev(&v1); _ZN3sce4Json5ValueC1Ev(&v2); + Require(_ZN3sce4Json5Value3setEl(&v1, 123) == 0); Require(_ZN3sce4Json5Value3setEPKc(&v2, "hello") == 0); _ZN3sce4Json5Value4swapERS1_(&v1, &v2); + Require(*_ZNK3sce4Json5Value10getIntegerEv(&v2) == 123); Require(std::strcmp(_ZNK3sce4Json6String5c_strEv(_ZNK3sce4Json5Value9getStringEv(&v1)), "hello") == 0); Require(_ZN3sce4Json5Value3setEl(&v1, -456) == 0); const auto* firstStorage = _ZNK3sce4Json5Value10getIntegerEv(&v1); const auto* secondStorage = _ZNK3sce4Json5Value10getIntegerEv(&v2); _ZN3sce4Json5Value4swapERS1_(&v1, &v2); + Require(_ZNK3sce4Json5Value10getIntegerEv(&v1) == firstStorage && *firstStorage == 123); Require(_ZNK3sce4Json5Value10getIntegerEv(&v2) == secondStorage && *secondStorage == -456); _ZN3sce4Json5Value4swapERS1_(&v1, &v1); + Require(*_ZNK3sce4Json5Value10getIntegerEv(&v1) == 123); _ZN3sce4Json5ValueD1Ev(&v1); _ZN3sce4Json5ValueD1Ev(&v2); + } static void ArrayIteratorAdvance() { Array array{}; _ZN3sce4Json5ArrayC1Ev(&array); + for (int i = 0; i < 5; ++i) { Value val{}; _ZN3sce4Json5ValueC1Ev(&val); _ZN3sce4Json5Value3setEl(&val, i * 10); _ZN3sce4Json5Array9push_backERKNS0_5ValueE(&array, &val); _ZN3sce4Json5ValueD1Ev(&val); + } - Iterator begin{}; + ArrayIterator begin{}; _ZNK3sce4Json5Array5beginEv(&begin, &array); - Iterator copy{}; + + ArrayIterator copy{}; _ZN3sce4Json5Array8iteratorC1ERKS2_(©, &begin); + Require(_ZN3sce4Json5Array8iterator7advanceEm(©, 3) == ©); Require(*_ZNK3sce4Json5Value10getIntegerEv(_ZNK3sce4Json5Array8iteratordeEv(©)) == 30); - Iterator end{}; + ArrayIterator end{}; _ZNK3sce4Json5Array3endEv(&end, &array); _ZN3sce4Json5Array8iterator7advanceEm(©, std::numeric_limits::max()); + Require(!_ZNK3sce4Json5Array8iteratorneERKS2_(©, &end)); _ZN3sce4Json5Array8iteratorppEv(©); + Require(!_ZNK3sce4Json5Array8iteratorneERKS2_(©, &end)); Require(*_ZNK3sce4Json5Value10getIntegerEv(_ZNK3sce4Json5Array8iteratordeEv(&begin)) == 0); _ZN3sce4Json5Array8iteratorD1Ev(&end); _ZN3sce4Json5Array8iteratorD1Ev(&begin); _ZN3sce4Json5Array8iteratorD1Ev(©); _ZN3sce4Json5ArrayD1Ev(&array); + } static void ObjectOperations() { Object object{}; _ZN3sce4Json6ObjectC1Ev(&object); + String k1{}, k2{}, k3{}; _ZN3sce4Json6StringC1EPKc(&k1, "alpha"); _ZN3sce4Json6StringC1EPKc(&k2, "beta"); _ZN3sce4Json6StringC1EPKc(&k3, "gamma"); + Value v1{}, v2{}, v3{}; _ZN3sce4Json5ValueC1Ev(&v1); _ZN3sce4Json5ValueC1Ev(&v2); @@ -866,11 +834,13 @@ static void ObjectOperations() { _ZN3sce4Json5Value3setEl(&v1, 1); _ZN3sce4Json5Value3setEl(&v2, 2); _ZN3sce4Json5Value3setEl(&v3, 3); + Pair p1{}, p2{}, p3{}; _ZN3sce4Json6Object4PairC1ERKNS0_6StringERKNS0_5ValueE(&p1, &k1, &v1); _ZN3sce4Json6Object4PairC1ERKNS0_6StringERKNS0_5ValueE(&p2, &k2, &v2); _ZN3sce4Json6Object4PairC1ERKNS0_6StringERKNS0_5ValueE(&p3, &k3, &v3); - Iterator ins{}; + + ObjectIterator ins{}; _ZN3sce4Json6Object6insertERKNS1_4PairE(&ins, &object, &p3); _ZN3sce4Json6Object8iteratorD1Ev(&ins); _ZN3sce4Json6Object6insertERKNS1_4PairE(&ins, &object, &p2); @@ -878,16 +848,20 @@ static void ObjectOperations() { _ZN3sce4Json6Object6insertERKNS1_4PairE(&ins, &object, &p1); _ZN3sce4Json6Object8iteratorD1Ev(&ins); - Iterator begin{}; + ObjectIterator begin{}; _ZNK3sce4Json6Object5beginEv(&begin, &object); - Iterator copy{}; + + ObjectIterator copy{}; _ZN3sce4Json6Object8iteratorC1ERKS2_(©, &begin); + Require(_ZN3sce4Json6Object8iterator7advanceEm(©, 2) == ©); Require(std::strcmp(_ZNK3sce4Json6String5c_strEv(&_ZNK3sce4Json6Object8iteratordeEv(©)->key), "gamma") == 0); _ZN3sce4Json6Object8iterator7advanceEm(©, 1); + bool endRejected = false; try { _ZN3sce4Json6Object8iterator7advanceEm(©, 1); + } catch (const std::out_of_range&) { endRejected = true; } @@ -897,13 +871,16 @@ static void ObjectOperations() { Require(_ZNK3sce4Json6Object4sizeEv(&object) == 3); _ZN3sce4Json6Object5eraseERKNS0_6StringE(&object, &k2); + Require(_ZNK3sce4Json6Object4sizeEv(&object) == 2); _ZN3sce4Json6Object5eraseERKNS0_6StringE(&object, &k2); + Require(_ZNK3sce4Json6Object4sizeEv(&object) == 2); - Iterator findResult{}, end{}; + ObjectIterator findResult{}, end{}; _ZNK3sce4Json6Object4findERKNS0_6StringE(&findResult, &object, &k2); _ZNK3sce4Json6Object3endEv(&end, &object); + Require(_ZNK3sce4Json6Object8iteratoreqERKS2_(&findResult, &end)); _ZN3sce4Json6Object8iteratorD1Ev(&findResult); _ZN3sce4Json6Object8iteratorD1Ev(&end); @@ -932,10 +909,12 @@ static void NullAccess(SetNullAccessCallback setCallback) { int context = 0; Require(setCallback(initializer, OnNullAccess, &context) == 0); _ZN3sce4Json5ValueC1Ev(&fallback); + Require(_ZN3sce4Json5Value3setEl(&fallback, 99) == 0); Value root{}; _ZN3sce4Json5ValueC1Ev(&root); + const char text[] = "{\"present\":\"text\"}"; Require(_ZN3sce4Json6Parser5parseERNS0_5ValueEPKcm(&root, text, sizeof(text) - 1) == 0); Require(&Member(root, "missing") == &fallback); @@ -952,33 +931,40 @@ static void NullAccess(SetNullAccessCallback setCallback) { Require(callbackCalls == 4); _ZN3sce4Json5ValueD1Ev(&root); _ZN3sce4Json5ValueD1Ev(&fallback); + Require(_ZN3sce4Json11InitializerD1Ev(initializer) == 0); } static void ValueAccess() { for (std::int32_t type = TypeNull; type <= TypeObject; ++type) { Value typed{}; - _ZN3sce4Json5ValueC1ENS0_9ValueTypeE(&typed, type); + _ZN3sce4Json5ValueC1ENS0_9ValueTypeE(&typed, static_cast(type)); + Require(_ZNK3sce4Json5Value7getTypeEv(&typed) == type); Require(_ZNK3sce4Json5Value5countEv(&typed) == 0); _ZN3sce4Json5ValueD1Ev(&typed); + } Value root{}; _ZN3sce4Json5ValueC1Ev(&root); + const char text[] = "{\"list\":[10,20,30],\"name\":\"value\",\"flag\":true}"; Require(_ZN3sce4Json6Parser5parseERNS0_5ValueEPKcm(&root, text, sizeof(text) - 1) == 0); Require(_ZNK3sce4Json6Object4sizeEv(_ZNK3sce4Json5Value9getObjectEv(&root)) == 3); - Iterator member{}; + ObjectIterator member{}; _ZNK3sce4Json6Object5beginEv(&member, _ZNK3sce4Json5Value9getObjectEv(&root)); + for (const char* expected : {"flag", "list", "name"}) { Require(std::strcmp(_ZNK3sce4Json6String5c_strEv(&_ZNK3sce4Json6Object8iteratordeEv(&member)->key), expected) == 0); _ZN3sce4Json6Object8iteratorppEv(&member); + } _ZN3sce4Json6Object8iteratorD1Ev(&member); String key{}; _ZN3sce4Json6StringC1EPKc(&key, "list"); + const Value* list = _ZNK3sce4Json5Value8getValueERKNS0_6StringE(&root, &key); Require(_ZNK3sce4Json5Value7getTypeEv(list) == TypeArray); Require(*_ZNK3sce4Json5Value10getIntegerEv(_ZNK3sce4Json5Value8getValueEm(list, 1)) == 20); @@ -996,23 +982,26 @@ static void ValueAccess() { String missing{}; _ZN3sce4Json6StringC1EPKc(&missing, "missing"); + Require(_ZNK3sce4Json5Value7getTypeEv(_ZNK3sce4Json5Value8getValueERKNS0_6StringE(&root, &missing)) == TypeNull); _ZN3sce4Json6StringD1Ev(&missing); _ZN3sce4Json5ValueD1Ev(&root); alignas(16) std::uint8_t parameter[40]; std::memset(parameter, 0xff, sizeof(parameter)); - _ZN3sce4Json14InitParameter2C1Ev(parameter); + _ZN3sce4Json14InitParameter2C1Ev(reinterpret_cast(parameter)); + int allocator = 0; int userData = 0; - _ZN3sce4Json14InitParameter212setAllocatorEPNS0_12MemAllocatorEPv(parameter, &allocator, &userData); - _ZN3sce4Json14InitParameter217setFileBufferSizeEm(parameter, 4096); + _ZN3sce4Json14InitParameter212setAllocatorEPNS0_12MemAllocatorEPv(reinterpret_cast(parameter), &allocator, &userData); + _ZN3sce4Json14InitParameter217setFileBufferSizeEm(reinterpret_cast(parameter), 4096); + void* stored[3]{}; std::memcpy(stored, parameter, sizeof(stored)); Require(stored[0] == &allocator && stored[1] == &userData && reinterpret_cast(stored[2]) == 4096); alignas(16) std::uint8_t initializer[16]{}; Require(_ZN3sce4Json11InitializerC1Ev(initializer) == 0); - Require(_ZN3sce4Json11Initializer10initializeEPKNS0_14InitParameter2E(initializer, parameter) == 0); + Require(_ZN3sce4Json11Initializer10initializeEPKNS0_14InitParameter2E(initializer, reinterpret_cast(parameter)) == 0); Require(_ZN3sce4Json11Initializer9terminateEv(initializer) == 0); Require(_ZN3sce4Json11InitializerD1Ev(initializer) == 0); } @@ -1020,11 +1009,13 @@ static void ValueAccess() { static void InitParameter2BaseConstructor() { alignas(16) std::uint8_t parameter[40]; std::memset(parameter, 0xff, sizeof(parameter)); - _ZN3sce4Json14InitParameter2C1Ev(parameter); + _ZN3sce4Json14InitParameter2C1Ev(reinterpret_cast(parameter)); + alignas(16) std::uint8_t baseStorage[72]; std::memset(baseStorage, 0xff, sizeof(baseStorage)); auto* baseParameter = baseStorage + 16; - _ZN3sce4Json14InitParameter2C2Ev(baseParameter); + _ZN3sce4Json14InitParameter2C2Ev(reinterpret_cast(baseParameter)); + Require(std::memcmp(parameter, baseParameter, sizeof(parameter)) == 0); void* defaultAllocator; void* defaultUserData; @@ -1035,8 +1026,9 @@ static void InitParameter2BaseConstructor() { Require(defaultAllocator == nullptr && defaultUserData == nullptr && defaultFileBufferSize == 0); int allocator = 0; int userData = 0; - _ZN3sce4Json14InitParameter212setAllocatorEPNS0_12MemAllocatorEPv(baseParameter, &allocator, &userData); - _ZN3sce4Json14InitParameter217setFileBufferSizeEm(baseParameter, 4096); + _ZN3sce4Json14InitParameter212setAllocatorEPNS0_12MemAllocatorEPv(reinterpret_cast(baseParameter), &allocator, &userData); + _ZN3sce4Json14InitParameter217setFileBufferSizeEm(reinterpret_cast(baseParameter), 4096); + void* storedAllocator; void* storedUserData; std::size_t storedFileBufferSize; @@ -1049,22 +1041,15 @@ static void InitParameter2BaseConstructor() { Require(baseStorage[i] == 0xff); alignas(16) std::uint8_t initializer[16]{}; Require(_ZN3sce4Json11InitializerC1Ev(initializer) == 0); - Require(_ZN3sce4Json11Initializer10initializeEPKNS0_14InitParameter2E(initializer, baseParameter) == 0); + Require(_ZN3sce4Json11Initializer10initializeEPKNS0_14InitParameter2E(initializer, reinterpret_cast(baseParameter)) == 0); Require(_ZN3sce4Json11Initializer9terminateEv(initializer) == 0); Require(_ZN3sce4Json11InitializerD1Ev(initializer) == 0); } -struct StoredInitParameter2 { - void* allocator; - void* userData; - std::size_t fileBufferSize; - std::int32_t specialFloatFormatType; - std::uint32_t reserved[3]; -}; -static_assert(sizeof(StoredInitParameter2) == 40); +static_assert(sizeof(InitParameter2) == 40); -static StoredInitParameter2 Stored(const std::uint8_t* parameter) { - StoredInitParameter2 stored{}; +static InitParameter2 Stored(const std::uint8_t* parameter) { + InitParameter2 stored{}; std::memcpy(&stored, parameter, sizeof(stored)); return stored; } @@ -1076,32 +1061,33 @@ static bool Untouched(const std::uint8_t* parameter, std::size_t from) { } static void InitParameters() { - using Constructor = void (APS5_VABI*)(void*); + using Constructor = decltype(&_ZN3sce4Json14InitParameter2C1Ev); for (Constructor construct : {_ZN3sce4Json14InitParameter2C1Ev, _ZN3sce4Json14InitParameter2C2Ev}) { alignas(16) std::uint8_t parameter[40]; std::memset(parameter, 0xff, sizeof(parameter)); - construct(parameter); - StoredInitParameter2 stored = Stored(parameter); + construct(reinterpret_cast(parameter)); + InitParameter2 stored = Stored(parameter); Require(stored.allocator == nullptr && stored.userData == nullptr && stored.fileBufferSize == 0); Require(stored.specialFloatFormatType == 2); Require(stored.reserved[0] == 0 && stored.reserved[1] == 0 && stored.reserved[2] == 0); int allocParam = 0; int userData = 0; - _ZN3sce4Json14InitParameter217setFileBufferSizeEm(parameter, 8192); - _ZN3sce4Json14InitParameter225setSpecialFloatFormatTypeENS0_22SpecialFloatFormatTypeE(parameter, 2); - _ZN3sce4Json18InitParameterRtti216setAllocatorRttiEPNS0_14AllocParamRttiEPv(parameter, &allocParam, &userData); + _ZN3sce4Json14InitParameter217setFileBufferSizeEm(reinterpret_cast(parameter), 8192); + _ZN3sce4Json14InitParameter225setSpecialFloatFormatTypeENS0_22SpecialFloatFormatTypeE(reinterpret_cast(parameter), 2); + _ZN3sce4Json18InitParameterRtti216setAllocatorRttiEPNS0_14AllocParamRttiEPv(reinterpret_cast(parameter), &allocParam, &userData); + stored = Stored(parameter); Require(stored.allocator == &allocParam && stored.userData == &userData && stored.fileBufferSize == 8192); Require(stored.specialFloatFormatType == 2); Require(stored.reserved[0] == 0 && stored.reserved[1] == 0 && stored.reserved[2] == 0); - _ZN3sce4Json14InitParameter225setSpecialFloatFormatTypeENS0_22SpecialFloatFormatTypeE(parameter, 0); + _ZN3sce4Json14InitParameter225setSpecialFloatFormatTypeENS0_22SpecialFloatFormatTypeE(reinterpret_cast(parameter), 0); Require(Stored(parameter).specialFloatFormatType == 0 && Stored(parameter).fileBufferSize == 8192); alignas(16) std::uint8_t initializer[16]{}; Require(_ZN3sce4Json11InitializerC1Ev(initializer) == 0); - Require(_ZN3sce4Json11Initializer10initializeEPKNS0_14InitParameter2E(initializer, parameter) == 0); + Require(_ZN3sce4Json11Initializer10initializeEPKNS0_14InitParameter2E(initializer, reinterpret_cast(parameter)) == 0); Require(_ZN3sce4Json11Initializer9terminateEv(initializer) == 0); Require(_ZN3sce4Json11InitializerD1Ev(initializer) == 0); } @@ -1110,7 +1096,8 @@ static void InitParameters() { std::memset(rttiParameter, 0xff, sizeof(rttiParameter)); int allocParam = 0; int userData = 0; - _ZN3sce4Json17InitParameterRttiC1EPNS0_14AllocParamRttiEPvm(rttiParameter, &allocParam, &userData, 4096); + _ZN3sce4Json17InitParameterRttiC1EPNS0_14AllocParamRttiEPvm(reinterpret_cast(rttiParameter), &allocParam, &userData, 4096); + void* rttiStored[3]{}; std::memcpy(rttiStored, rttiParameter, sizeof(rttiStored)); Require(rttiStored[0] == &allocParam && rttiStored[1] == &userData && reinterpret_cast(rttiStored[2]) == 4096); @@ -1120,30 +1107,38 @@ static void InitParameters() { static void ValueClear() { Value value{}; _ZN3sce4Json5ValueC1Ev(&value); + Require(_ZNK3sce4Json5Value7getTypeEv(&value) == TypeNull); _ZN3sce4Json5Value5clearEv(&value); + Require(_ZNK3sce4Json5Value7getTypeEv(&value) == TypeNull); Require(_ZN3sce4Json5Value3setEl(&value, 12345) == 0); Require(_ZNK3sce4Json5Value7getTypeEv(&value) == TypeInteger); _ZN3sce4Json5Value5clearEv(&value); + Require(_ZNK3sce4Json5Value7getTypeEv(&value) == TypeNull); Require(_ZN3sce4Json5Value3setEPKc(&value, "test string") == 0); Require(_ZNK3sce4Json5Value7getTypeEv(&value) == TypeString); _ZN3sce4Json5Value5clearEv(&value); + Require(_ZNK3sce4Json5Value7getTypeEv(&value) == TypeNull); Object obj{}; _ZN3sce4Json6ObjectC1Ev(&obj); + String key{}; _ZN3sce4Json6StringC1EPKc(&key, "prop"); + Value* item = _ZN3sce4Json6ObjectixERKNS0_6StringE(&obj, &key); _ZN3sce4Json5Value3setEl(item, 999); _ZN3sce4Json5ValueD1Ev(&value); _ZN3sce4Json5ValueC1ERKNS0_6ObjectE(&value, &obj); + Require(_ZNK3sce4Json5Value7getTypeEv(&value) == TypeObject); _ZN3sce4Json5Value5clearEv(&value); + Require(_ZNK3sce4Json5Value7getTypeEv(&value) == TypeNull); _ZN3sce4Json6StringD1Ev(&key); _ZN3sce4Json6ObjectD1Ev(&obj); @@ -1177,6 +1172,7 @@ static int APS5_VABI ReadNext(char& ch, void* context) { static void IntegerRepresentation() { Value value{}; _ZN3sce4Json5ValueC1Ev(&value); + for (const char* text : {"0", "1", "9223372036854775807", "9223372036854775808", "18446744073709551615"}) { Require(_ZN3sce4Json6Parser5parseERNS0_5ValueEPKcm(&value, text, std::strlen(text)) == 0); Require(_ZNK3sce4Json5Value7getTypeEv(&value) == TypeUInteger); @@ -1194,11 +1190,13 @@ static void IntegerRepresentation() { Require(*_ZNK3sce4Json5Value11getUIntegerEv(&value) == (std::uint64_t{1} << 63)); Require(_ZNK3sce4Json5Value7getTypeEv(&value) == TypeInteger); _ZN3sce4Json5ValueD1Ev(&value); + } static void StreamParse() { Value root{}; _ZN3sce4Json5ValueC1Ev(&root); + ReadState valid{"{\"list\": [1, 2.5, true]}", 0, 0}; Require(_ZN3sce4Json6Parser5parseERNS0_5ValueEPFiRcPvES5_(&root, ReadNext, &valid) == 0); Require(valid.calls == static_cast(std::strlen(valid.text))); @@ -1223,6 +1221,7 @@ static void StreamParse() { Require(_ZN3sce4Json6Parser5parseERNS0_5ValueEPKcm(&root, "01", 2) == 0); Require(Serialize(root) == "1"); _ZN3sce4Json5ValueD1Ev(&root); + } static void StaticNullAccess() { @@ -1233,10 +1232,12 @@ static void StaticNullAccess() { int context = 0; _ZN3sce4Json5Value21setNullAccessCallBackEPFRKS1_NS0_9ValueTypeEPS2_PvES6_(OnNullAccess, &context); _ZN3sce4Json5ValueC1Ev(&fallback); + Require(_ZN3sce4Json5Value3setEl(&fallback, 99) == 0); Value root{}; _ZN3sce4Json5ValueC1Ev(&root); + const char text[] = "{\"present\":\"text\"}"; Require(_ZN3sce4Json6Parser5parseERNS0_5ValueEPKcm(&root, text, sizeof(text) - 1) == 0); Require(&Member(root, "missing") == &fallback); @@ -1250,6 +1251,7 @@ static void StaticNullAccess() { Require(callbackCalls == 2); _ZN3sce4Json5ValueD1Ev(&root); _ZN3sce4Json5ValueD1Ev(&fallback); + } static Value replacement{}; @@ -1259,7 +1261,7 @@ static const Value* mismatchValue = nullptr; static const Value* mismatchSecond = nullptr; static void* mismatchContext = nullptr; -static const Value& APS5_VABI OnTypeMismatch(std::int32_t requested, const Value* value, const Value* second, void* context) { +static const Value& APS5_VABI OnTypeMismatch(ValueType requested, const Value* value, const Value* second, void* context) { ++mismatchCalls; mismatchRequested = requested; mismatchValue = value; @@ -1268,17 +1270,19 @@ static const Value& APS5_VABI OnTypeMismatch(std::int32_t requested, const Value return replacement; } -static void RequireMismatch(int calls, std::int32_t requested, const Value* value, void* context) { +static void RequireMismatch(int calls, ValueType requested, const Value* value, void* context) { Require(mismatchCalls == calls && mismatchRequested == requested && mismatchValue == value); Require(mismatchSecond == nullptr && mismatchContext == context); } static void ValueTypeMismatchHandler() { _ZN3sce4Json5ValueC1Ev(&replacement); + Require(_ZN3sce4Json5Value3setEl(&replacement, 42) == 0); int context = 0; Value root{}; _ZN3sce4Json5ValueC1Ev(&root); + Require(_ZN3sce4Json5Value22setTypeMismatchHandlerEPFRKS1_NS0_9ValueTypeEPS2_S5_PvES6_(&root, OnTypeMismatch, &context) == 0); const char text[] = "{\"name\":\"text\",\"none\":null,\"list\":[true]}"; Require(_ZN3sce4Json6Parser5parseERNS0_5ValueEPKcm(&root, text, sizeof(text) - 1) == 0); @@ -1300,6 +1304,7 @@ static void ValueTypeMismatchHandler() { Value later{}; _ZN3sce4Json5ValueC1Ev(&later); + Require(_ZN3sce4Json6Parser5parseERNS0_5ValueEPKcm(&later, text, sizeof(text) - 1) == 0); Require(*_ZNK3sce4Json5Value10getIntegerEv(&Member(later, "name")) == 0); Require(mismatchCalls == 4); @@ -1310,6 +1315,7 @@ static void ValueTypeMismatchHandler() { Value other{}; _ZN3sce4Json5ValueC1Ev(&other); + Require(_ZN3sce4Json5Value3setEPKc(&other, "other") == 0); Require(_ZN3sce4Json5ValueaSERKS1_(&root, &other) == &root); Require(*_ZNK3sce4Json5Value10getIntegerEv(&root) == 42); @@ -1321,11 +1327,13 @@ static void ValueTypeMismatchHandler() { Require(*_ZNK3sce4Json5Value10getIntegerEv(&root) == 42); RequireMismatch(7, TypeInteger, &root, &context); _ZN3sce4Json5Value5clearEv(&root); + Require(_ZN3sce4Json5Value3setEPKc(&root, "cleared") == 0); Require(*_ZNK3sce4Json5Value10getIntegerEv(&root) == 42); RequireMismatch(8, TypeInteger, &root, &context); Value copy{}; _ZN3sce4Json5ValueC1ERKS1_(©, &root); + Require(*_ZNK3sce4Json5Value10getIntegerEv(©) == 0); Require(mismatchCalls == 8); @@ -1337,6 +1345,7 @@ static void ValueTypeMismatchHandler() { _ZN3sce4Json5ValueD1Ev(&later); _ZN3sce4Json5ValueD1Ev(&root); _ZN3sce4Json5ValueD1Ev(&replacement); + } static int failureCalls = 0; @@ -1358,6 +1367,7 @@ static bool ThrowsUnverified(const TAccess& access) { static void ValueElementAccessFailureHandler() { Value root{}; _ZN3sce4Json5ValueC1Ev(&root); + const char text[] = "{\"list\":[1],\"key\":2}"; Require(_ZN3sce4Json6Parser5parseERNS0_5ValueEPKcm(&root, text, sizeof(text) - 1) == 0); int context = 0; @@ -1368,6 +1378,7 @@ static void ValueElementAccessFailureHandler() { Require(*_ZNK3sce4Json5Value10getIntegerEv(_ZNK3sce4Json5Value8getValueEm(&list, 0)) == 1); String missing{}; _ZN3sce4Json6StringC1EPKc(&missing, "missing"); + Require(ThrowsUnverified([&] { _ZNK3sce4Json5ValueixEPKc(&root, "missing"); })); Require(ThrowsUnverified([&] { _ZNK3sce4Json5Value8getValueERKNS0_6StringE(&root, &missing); })); Require(ThrowsUnverified([&] { _ZNK3sce4Json5ValueixEm(&root, 0); })); @@ -1379,6 +1390,7 @@ static void ValueElementAccessFailureHandler() { Require(_ZNK3sce4Json5Value7getTypeEv(_ZNK3sce4Json5Value8getValueEm(&list, 1)) == TypeNull); _ZN3sce4Json6StringD1Ev(&missing); _ZN3sce4Json5ValueD1Ev(&root); + } static int specialFloatCalls = 0; @@ -1386,49 +1398,59 @@ static int specialFloatCalls = 0; static Value* APS5_VABI OnSpecialFloat(Value* result, std::int32_t, double, const Value*, void*, bool*) { ++specialFloatCalls; _ZN3sce4Json5ValueC1Ev(result); + return result; } static void ValueSpecialFloatHandler() { Value real{}; _ZN3sce4Json5ValueC1Ed(&real, std::numeric_limits::quiet_NaN()); + int context = 0; Require(_ZN3sce4Json5Value22setSpecialFloatHandlerEPFKS1_NS0_12FunctionTypeEdPS2_PvPbES5_(&real, OnSpecialFloat, &context) == 0); String out{}; _ZN3sce4Json6StringC1Ev(&out); + Require(ThrowsUnverified([&] { _ZN3sce4Json5Value9serializeERNS0_6StringE(&real, &out); })); Require(_ZN3sce4Json5Value3setEd(&real, std::numeric_limits::infinity()) == 0); Require(ThrowsUnverified([&] { _ZN3sce4Json5Value9serializeERNS0_6StringE(&real, &out); })); _ZN3sce4Json6StringD1Ev(&out); + Require(_ZN3sce4Json5Value3setEd(&real, 2.5) == 0); Require(Serialize(real) == "2.5"); Require(specialFloatCalls == 0); _ZN3sce4Json5ValueD1Ev(&real); + } static void ValueOperatorBool() { Value nullVal{}; _ZN3sce4Json5ValueC1Ev(&nullVal); + Require(!_ZNK3sce4Json5ValuecvbEv(&nullVal)); _ZN3sce4Json5ValueD1Ev(&nullVal); Value typedNull{}; _ZN3sce4Json5ValueC1ENS0_9ValueTypeE(&typedNull, TypeNull); + Require(!_ZNK3sce4Json5ValuecvbEv(&typedNull)); _ZN3sce4Json5ValueD1Ev(&typedNull); Value boolFalse{}; _ZN3sce4Json5ValueC1Eb(&boolFalse, false); + Require(!_ZNK3sce4Json5ValuecvbEv(&boolFalse)); _ZN3sce4Json5ValueD1Ev(&boolFalse); Value boolTrue{}; _ZN3sce4Json5ValueC1Eb(&boolTrue, true); + Require(_ZNK3sce4Json5ValuecvbEv(&boolTrue)); _ZN3sce4Json5ValueD1Ev(&boolTrue); Value scalar{}; _ZN3sce4Json5ValueC1Ev(&scalar); + for (std::int64_t value : {std::int64_t{0}, std::int64_t{1}, std::int64_t{-1}}) { Require(_ZN3sce4Json5Value3setEl(&scalar, value) == 0); Require(_ZNK3sce4Json5ValuecvbEv(&scalar) == (value != 0)); @@ -1446,19 +1468,25 @@ static void ValueOperatorBool() { Require(_ZNK3sce4Json5ValuecvbEv(&scalar) == (*text != 0)); } _ZN3sce4Json5ValueD1Ev(&scalar); + for (std::int32_t type : {TypeArray, TypeObject}) { Value container{}; - _ZN3sce4Json5ValueC1ENS0_9ValueTypeE(&container, type); + _ZN3sce4Json5ValueC1ENS0_9ValueTypeE(&container, static_cast(type)); + Require(_ZNK3sce4Json5ValuecvbEv(&container)); _ZN3sce4Json5ValueD1Ev(&container); + } Value cleared{}; _ZN3sce4Json5ValueC1Eb(&cleared, true); + Require(_ZNK3sce4Json5ValuecvbEv(&cleared)); _ZN3sce4Json5Value5clearEv(&cleared); + Require(!_ZNK3sce4Json5ValuecvbEv(&cleared)); _ZN3sce4Json5ValueD1Ev(&cleared); + } static int NumericLocale() { @@ -1487,14 +1515,17 @@ static int NumericLocale() { std::numeric_limits::min(), std::numeric_limits::denorm_min()}) { Value value{}; _ZN3sce4Json5ValueC1Ed(&value, number); + const auto text = Serialize(value); check(text.find(',') == std::string::npos, "Decimal-point serialization", text.c_str()); Value parsed{}; _ZN3sce4Json5ValueC1Ev(&parsed); + const int result = _ZN3sce4Json6Parser5parseERNS0_5ValueEPKcm(&parsed, text.c_str(), text.size()); check(result == 0 && *_ZNK3sce4Json5Value7getRealEv(&parsed) == number, "Numeric round trip", text.c_str()); _ZN3sce4Json5ValueD1Ev(&parsed); _ZN3sce4Json5ValueD1Ev(&value); + } for (const auto [text, number] : {std::pair{"1.5", 1.5}, {"-1.25e2", -125.0}, {"4.9406564584124654e-324", std::numeric_limits::denorm_min()}, @@ -1504,13 +1535,16 @@ static int NumericLocale() { {"1e-999", 0.0}, {"-1e-999", -0.0}}) { Value value{}; _ZN3sce4Json5ValueC1Ev(&value); + const int result = _ZN3sce4Json6Parser5parseERNS0_5ValueEPKcm(&value, text, std::strlen(text)); const auto parsed = *_ZNK3sce4Json5Value7getRealEv(&value); check(result == 0 && parsed == number && std::signbit(parsed) == std::signbit(number), "Decimal-point parsing", text); _ZN3sce4Json5ValueD1Ev(&value); + } Value root{}; _ZN3sce4Json5ValueC1Ev(&root); + constexpr char document[] = "{\"list\":[2.5,-0.125],\"value\":1.5}"; check(_ZN3sce4Json6Parser5parseERNS0_5ValueEPKcm(&root, document, sizeof(document) - 1) == 0, "Nested numeric parsing", document); @@ -1521,11 +1555,13 @@ static int NumericLocale() { bool overflow = false; try { _ZN3sce4Json6Parser5parseERNS0_5ValueEPKcm(&root, "1e309", 5); + } catch (const std::runtime_error&) { overflow = true; } check(overflow, "Retain overflow rejection", "1e309"); _ZN3sce4Json5ValueD1Ev(&root); + check(std::strcmp(std::localeconv()->decimal_point, ",") == 0, "Preserve host locale", selected); std::setlocale(LC_NUMERIC, previous.c_str()); return failures ? 1 : 0; diff --git a/core/libs/tests/GuestJxr.cpp b/core/libs/tests/GuestJxr.cpp index 1bcda397b1..6c295e4822 100644 --- a/core/libs/tests/GuestJxr.cpp +++ b/core/libs/tests/GuestJxr.cpp @@ -1,3 +1,5 @@ +#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 @@ -6,11 +8,6 @@ #include #include -extern "C" { -void* APS5_VABI malloc_nid_postfix(std::size_t size); -std::int64_t APS5_VABI PKFree_nid_postfix(void** memory); -} - namespace { void Require(bool value) { if (!value) std::abort(); } diff --git a/core/libs/tests/GuestKernelAppArchive.cpp b/core/libs/tests/GuestKernelAppArchive.cpp index 3fcb0f4094..f09c256ba8 100644 --- a/core/libs/tests/GuestKernelAppArchive.cpp +++ b/core/libs/tests/GuestKernelAppArchive.cpp @@ -1,3 +1,6 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libkernel/File/include/File.hpp" +#include "prx/libc/include/Api.hpp" #include "AppArchiveFixture.hpp" #include "SceTypes.hpp" #include "prx/libc/include/general/VabiMacros.hpp" @@ -16,48 +19,10 @@ #include #include -struct KernelIovec { - void* base; - std::size_t length; -}; - extern "C" { -int APS5_VABI sceKernelOpen(const char* path, int flags, std::uint16_t mode); -int APS5_VABI sceKernelClose(int d); -std::int64_t APS5_VABI sceKernelRead(int d, void* buf, std::size_t nbytes); -std::int64_t APS5_VABI sceKernelWrite(int d, const void* buf, std::size_t nbytes); -std::int64_t APS5_VABI sceKernelPread(int d, void* buf, std::size_t nbytes, std::int64_t offset); -std::int64_t APS5_VABI sceKernelReadv(int d, const KernelIovec* iov, int iovcnt); -std::int64_t APS5_VABI sceKernelPreadv(int d, const KernelIovec* iov, int iovcnt, std::int64_t offset); -std::int64_t APS5_VABI sceKernelLseek(int d, std::int64_t offset, int whence); -int APS5_VABI sceKernelStat(const char* path, FileStat* sb); -int APS5_VABI sceKernelFstat(int d, FileStat* sb); -int APS5_VABI sceKernelCheckReachability(const char* path); -int APS5_VABI dup_nid_postfix(int d); -int APS5_VABI dup2_nid_postfix(int from, int to); -int APS5_VABI close_nid_postfix(int d); -std::int64_t APS5_VABI pread_nid_postfix(int d, void* buf, std::size_t nbytes, std::int64_t offset); -std::int64_t APS5_VABI lseek_nid_postfix(int d, std::int64_t offset, int whence); -int APS5_VABI fcntl_nid_postfix(int d, int command, ...); -int APS5_VABI ioctl_nid_postfix(int d, std::uint64_t request, void* argument); -void* APS5_VABI opendir_nid_postfix(const char* path); -void* APS5_VABI fdopen_nid_postfix(int d, const char* mode); -int APS5_VABI sceKernelAioSubmitReadCommands(KernelAioRwRequest* req, std::int32_t size, std::int32_t prio, std::int32_t* id); -int APS5_VABI sceKernelAioWaitRequest(std::int32_t id, std::int32_t* state, std::uint32_t* usec); -int APS5_VABI sceKernelAioDeleteRequest(std::int32_t id, std::int32_t* ret); -int APS5_VABI flock_nid_postfix(int d, int operation); -int APS5_VABI _fstatfs_nid_postfix(int d, void* buf); -int APS5_VABI ftruncate_nid_postfix(int d, std::int64_t length); -int APS5_VABI sceKernelFsync(int d); -int APS5_VABI sceKernelFdatasync(int d); -int APS5_VABI sceKernelGetdents(int d, char* buf, int nbytes); -int APS5_VABI sceKernelFchmod(int d, std::uint16_t mode); -int APS5_VABI sceKernelFutimes(int d, const void* times); -void* APS5_VABI mmap_nid_postfix(void* address, std::size_t length, int protection, int flags, int descriptor, std::int64_t offset) noexcept; -void* APS5_VABI __cxa_current_primary_exception_nid_postfix(); -std::type_info* APS5_VABI __cxa_current_exception_type_nid_postfix(); + using TerminateHandler = void (*)(); -TerminateHandler APS5_VABI _ZSt13set_terminatePFvvE_nid_postfix(TerminateHandler); + } namespace { @@ -198,7 +163,7 @@ void Refusals() { Check(fd >= 0); Check(NotImplemented([fd] { (void)fdopen_nid_postfix(fd, "r"); })); Check(NotImplemented([fd] { (void)flock_nid_postfix(fd, 1); })); - Check(NotImplemented([fd] { alignas(8) char statfs[512]; (void)_fstatfs_nid_postfix(fd, statfs); })); + Check(NotImplemented([fd] { alignas(8) char statfs[512]; (void)_fstatfs_nid_postfix(fd, reinterpret_cast(statfs)); })); Check(NotImplemented([fd] { (void)ftruncate_nid_postfix(fd, 0); })); Check(NotImplemented([fd] { (void)sceKernelFsync(fd); })); Check(NotImplemented([fd] { (void)sceKernelFdatasync(fd); })); @@ -243,6 +208,7 @@ int main(int argc, char** argv) { const int fd = sceKernelOpen("/app0/Data/Small.txt", SCE_KERNEL_O_RDONLY, 0); Check(fd >= 0); _ZSt13set_terminatePFvvE_nid_postfix(OnMmapRefused); + (void)mmap_nid_postfix(nullptr, 16384, 1, 2, fd, 0); return 1; } else if (mode == "plain") { diff --git a/core/libs/tests/GuestKernelErrors.cpp b/core/libs/tests/GuestKernelErrors.cpp index 66b6210e17..0cc54fbfe9 100644 --- a/core/libs/tests/GuestKernelErrors.cpp +++ b/core/libs/tests/GuestKernelErrors.cpp @@ -1,3 +1,9 @@ +#include "prx/libkernel/KernelErrors.hpp" +#include "prx/libkernel/include/Api.hpp" +#include "prx/libkernel/Semaphore/include/Semaphore.hpp" +#include "prx/libkernel/Pthread/include/Mutex.hpp" +#include "prx/libkernel/Pthread/include/Rwlock.hpp" +#include "prx/libSceSaveData/SaveDataCore.hpp" #include "SceTypes.hpp" #include #include @@ -8,55 +14,11 @@ #include extern "C" { -int APS5_VABI sceKernelCreateSema(KernelSema*, const char*, std::uint32_t, int, int, void*); -int APS5_VABI sceKernelDeleteSema(KernelSema); -int APS5_VABI sceKernelSignalSema(KernelSema, int); -int APS5_VABI sceKernelPollSema(KernelSema, int); -int APS5_VABI sceKernelCreateEqueue(KernelEqueue* eq, const char* name); -int APS5_VABI sceKernelDeleteEqueue(KernelEqueue eq); -int APS5_VABI sceKernelWaitEqueue(KernelEqueue eq, KernelEvent* ev, int num, int* out, const KernelUseconds* timo); -int APS5_VABI sceKernelDeleteUserEvent(KernelEqueue eq, int id); -int APS5_VABI scePthreadMutexattrInit(PthreadMutexattr* attr); -int APS5_VABI pthread_mutexattr_init_nid_postfix(PthreadMutexattr* attr); -int APS5_VABI pthread_mutexattr_settype_nid_postfix(PthreadMutexattr* attr, int type); -int APS5_VABI pthread_mutexattr_destroy_nid_postfix(PthreadMutexattr* attr); -int APS5_VABI pthread_mutex_init_nid_postfix(PthreadMutex* mutex, const PthreadMutexattr* attr); -int APS5_VABI pthread_mutex_lock_nid_postfix(PthreadMutex* mutex); -int APS5_VABI pthread_mutex_unlock_nid_postfix(PthreadMutex* mutex); -int APS5_VABI pthread_mutex_destroy_nid_postfix(PthreadMutex* mutex); -int APS5_VABI scePthreadMutexattrDestroy(PthreadMutexattr* attr); -int APS5_VABI scePthreadMutexattrSettype(PthreadMutexattr* attr, int type); -int APS5_VABI scePthreadMutexattrSetprotocol(PthreadMutexattr* attr, int protocol); -int APS5_VABI scePthreadMutexInit(PthreadMutex* mutex, const PthreadMutexattr* attr, const char* name); -int APS5_VABI scePthreadMutexDestroy(PthreadMutex* mutex); -int APS5_VABI scePthreadMutexLock(PthreadMutex* mutex); -int APS5_VABI scePthreadMutexUnlock(PthreadMutex* mutex); -int APS5_VABI scePthreadMutexTrylock(PthreadMutex* mutex); -int APS5_VABI sceKernelCreateEventFlag(KernelEventFlag* ef, const char* name, std::uint32_t attr, std::uint64_t init_pattern, const void* param); -int APS5_VABI sceKernelDeleteEventFlag(KernelEventFlag ef); -int APS5_VABI sceKernelOpenEventFlag(KernelEventFlag* ef, const char* name); -int APS5_VABI sceKernelCloseEventFlag(KernelEventFlag ef); -int APS5_VABI sceKernelSetEventFlag(KernelEventFlag ef, std::uint64_t bit_pattern); -int APS5_VABI sceKernelClearEventFlag(KernelEventFlag ef, std::uint64_t bit_pattern); -int APS5_VABI sceKernelCancelEventFlag(KernelEventFlag ef, std::uint64_t set_pattern, int* num_wait_threads); -int APS5_VABI sceKernelPollEventFlag(KernelEventFlag ef, std::uint64_t bit_pattern, std::uint32_t wait_mode, std::uint64_t* result_pat); -int APS5_VABI sceKernelWaitEventFlag(KernelEventFlag ef, std::uint64_t bit_pattern, std::uint32_t wait_mode, std::uint64_t* result_pat, KernelUseconds* timeout); + int APS5_Test_GetEventFlagWaiterCount(KernelEventFlag handle); } static constexpr int SCE_OK = 0; -static constexpr int SCE_KERNEL_ERROR_EPERM = static_cast(0x80020001); -static constexpr int SCE_KERNEL_ERROR_ENOENT = static_cast(0x80020002); -static constexpr int SCE_KERNEL_ERROR_ESRCH = static_cast(0x80020003); -static constexpr int SCE_KERNEL_ERROR_EBADF = static_cast(0x80020009); -static constexpr int SCE_KERNEL_ERROR_EDEADLK = static_cast(0x8002000B); -static constexpr int SCE_KERNEL_ERROR_EFAULT = static_cast(0x8002000E); -static constexpr int SCE_KERNEL_ERROR_EACCES = static_cast(0x8002000D); -static constexpr int SCE_KERNEL_ERROR_EINVAL = static_cast(0x80020016); -static constexpr int SCE_KERNEL_ERROR_EBUSY = static_cast(0x80020010); -static constexpr int SCE_KERNEL_ERROR_ETIMEDOUT = static_cast(0x8002003C); -static constexpr int SCE_KERNEL_ERROR_ENAMETOOLONG = static_cast(0x8002003F); -static constexpr int SCE_KERNEL_ERROR_ECANCELED = static_cast(0x80020055); static constexpr std::uint32_t EVF_ATTR_SINGLE = 0x10; static constexpr std::uint32_t EVF_ATTR_MULTI = 0x20; static constexpr std::uint32_t EVF_ATTR_SHARED = 0x100; @@ -65,6 +27,7 @@ static constexpr std::uint32_t EVF_WAITMODE_OR = 0x02; static constexpr std::uint32_t EVF_WAITMODE_CLEAR_ALL = 0x10; static constexpr std::uint32_t EVF_WAITMODE_CLEAR_PAT = 0x20; static constexpr int MUTEX_TYPE_ERRORCHECK = 1; +static constexpr int MUTEX_TYPE_NORMAL = 3; static constexpr int PRIO_NONE = 0; static constexpr int PRIO_INHERIT = 1; static constexpr int PRIO_PROTECT = 2; @@ -81,6 +44,13 @@ static void WaitForEventFlagWaiters(KernelEventFlag handle, int expected) { } } +template +static void RequireTimesOut(TLock lock) { + const auto start = std::chrono::steady_clock::now(); + Require(lock(20000) == SCE_KERNEL_ERROR_ETIMEDOUT); + Require(std::chrono::steady_clock::now() - start >= std::chrono::milliseconds(15)); +} + int main() { constexpr int maximum = std::numeric_limits::max(); KernelSema semaphore = nullptr; @@ -129,6 +99,7 @@ int main() { Require(scePthreadMutexattrDestroy(&attr) == SCE_OK); Require(scePthreadMutexLock(&mutex) == SCE_OK); Require(scePthreadMutexLock(&mutex) == SCE_KERNEL_ERROR_EDEADLK); + RequireTimesOut([&](KernelUseconds usec) { return scePthreadMutexTimedlock(&mutex, usec); }); Require(scePthreadMutexDestroy(&mutex) == SCE_KERNEL_ERROR_EBUSY); Require(scePthreadMutexUnlock(&mutex) == SCE_OK); Require(scePthreadMutexDestroy(&mutex) == SCE_OK); @@ -140,9 +111,41 @@ int main() { Require(scePthreadMutexattrDestroy(&attr) == SCE_OK); Require(scePthreadMutexLock(&adaptive) == SCE_OK); Require(scePthreadMutexLock(&adaptive) == SCE_KERNEL_ERROR_EDEADLK); + RequireTimesOut([&](KernelUseconds usec) { return scePthreadMutexTimedlock(&adaptive, usec); }); Require(scePthreadMutexUnlock(&adaptive) == SCE_OK); Require(scePthreadMutexDestroy(&adaptive) == SCE_OK); + PthreadMutex timedDefault = nullptr; + Require(scePthreadMutexInit(&timedDefault, nullptr, nullptr) == SCE_OK); + Require(scePthreadMutexLock(&timedDefault) == SCE_OK); + RequireTimesOut([&](KernelUseconds usec) { return scePthreadMutexTimedlock(&timedDefault, usec); }); + Require(scePthreadMutexUnlock(&timedDefault) == SCE_OK); + Require(scePthreadMutexTimedlock(&timedDefault, 20000) == SCE_OK); + Require(scePthreadMutexUnlock(&timedDefault) == SCE_OK); + Require(scePthreadMutexDestroy(&timedDefault) == SCE_OK); + + Require(scePthreadMutexattrInit(&attr) == SCE_OK); + Require(scePthreadMutexattrSettype(&attr, MUTEX_TYPE_NORMAL) == SCE_OK); + PthreadMutex normal = nullptr; + Require(scePthreadMutexInit(&normal, &attr, nullptr) == SCE_OK); + Require(scePthreadMutexattrDestroy(&attr) == SCE_OK); + Require(scePthreadMutexLock(&normal) == SCE_OK); + RequireTimesOut([&](KernelUseconds usec) { return scePthreadMutexTimedlock(&normal, usec); }); + Require(scePthreadMutexUnlock(&normal) == SCE_OK); + Require(scePthreadMutexDestroy(&normal) == SCE_OK); + + PthreadRwlock rwlock = nullptr; + Require(scePthreadRwlockInit(&rwlock, nullptr, nullptr) == SCE_OK); + Require(scePthreadRwlockWrlock(&rwlock) == SCE_OK); + Require(scePthreadRwlockTrywrlock(&rwlock) == SCE_KERNEL_ERROR_EBUSY); + Require(scePthreadRwlockWrlock(&rwlock) == SCE_KERNEL_ERROR_EDEADLK); + RequireTimesOut([&](KernelUseconds usec) { return scePthreadRwlockTimedrdlock(&rwlock, usec); }); + RequireTimesOut([&](KernelUseconds usec) { return scePthreadRwlockTimedwrlock(&rwlock, usec); }); + Require(scePthreadRwlockUnlock(&rwlock) == SCE_OK); + Require(scePthreadRwlockTimedwrlock(&rwlock, 20000) == SCE_OK); + Require(scePthreadRwlockUnlock(&rwlock) == SCE_OK); + Require(scePthreadRwlockDestroy(&rwlock) == SCE_OK); + PthreadMutex adaptiveStatic = reinterpret_cast(std::uintptr_t{1}); Require(scePthreadMutexLock(&adaptiveStatic) == SCE_OK); Require(adaptiveStatic != reinterpret_cast(std::uintptr_t{1})); diff --git a/core/libs/tests/GuestKernelFcntl.cpp b/core/libs/tests/GuestKernelFcntl.cpp index 164a289714..1e57a5b542 100644 --- a/core/libs/tests/GuestKernelFcntl.cpp +++ b/core/libs/tests/GuestKernelFcntl.cpp @@ -1,3 +1,6 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libkernel/File/include/File.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/General.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -14,23 +17,7 @@ #include #include #endif -extern "C" { -int APS5_VABI socket_nid_postfix(int, int, int); -int APS5_VABI __sys_socketex_nid_postfix(const char*, int, int, int); -int APS5_VABI close_nid_postfix(int); -int APS5_VABI pipe_nid_postfix(int*); -int APS5_VABI fcntl_nid_postfix(int, int, ...); -int APS5_VABI _fcntl_nid_postfix(int, int, ...); -int APS5_VABI ioctl_nid_postfix(int, std::uint64_t, void*); -std::int64_t APS5_VABI read_nid_postfix(int, void*, std::uint64_t); -std::int64_t APS5_VABI write_nid_postfix(int, const char*, std::int64_t); -int* APS5_VABI __error_nid_postfix(); -int APS5_VABI sceKernelFcntl(int, int, ...); -int APS5_VABI sceKernelOpen(const char*, int, std::uint16_t); -int APS5_VABI sceKernelClose(int); -std::int64_t APS5_VABI sceKernelRead(int, void*, std::size_t); -std::int64_t APS5_VABI sceKernelLseek(int, std::int64_t, int); -} + static void Require(bool value) { if (!value) std::abort(); } static constexpr int DuplicateCommand = 0; static constexpr int GetDescriptorFlags = 1; diff --git a/core/libs/tests/GuestKernelIsStack.cpp b/core/libs/tests/GuestKernelIsStack.cpp index 968cdc981f..e9fdbae01d 100644 --- a/core/libs/tests/GuestKernelIsStack.cpp +++ b/core/libs/tests/GuestKernelIsStack.cpp @@ -1,24 +1,16 @@ +#include "prx/libkernel/KernelErrors.hpp" +#include "prx/libkernel/include/Api.hpp" #include "SceTypes.hpp" #include #include #include -extern "C" { -int APS5_VABI scePthreadCreate(Pthread* thread, const PthreadAttr* attr, PthreadEntry entry, void* arg, const char* name); -int APS5_VABI scePthreadJoin(Pthread thread, void** retval); -int APS5_VABI sceKernelIsStack(void* addr, void** start, void** end); -int APS5_VABI sceKernelMapFlexibleMemory(void** addr, std::size_t len, int prot, int flags); -int APS5_VABI sceKernelMunmap(std::uint64_t addr, std::size_t len); -int APS5_VABI sceKernelVirtualQuery(const void* addr, int flags, VirtualQueryInfo* info, std::uint64_t infoSize); -} - static constexpr int SCE_OK = 0; #ifdef ANYPS5_ENABLE_ASAN static constexpr std::uintptr_t APPLICATION_AREA_END = 0x000010FC00000000ull; #else static constexpr std::uintptr_t APPLICATION_AREA_END = 0x000000FC00000000ull; #endif -static constexpr int SCE_KERNEL_ERROR_EACCES = static_cast(0x8002000d); static int global = 0; static void Require(bool value) { if (!value) std::abort(); } diff --git a/core/libs/tests/GuestKernelRename.cpp b/core/libs/tests/GuestKernelRename.cpp index 6b74a12f95..22cbbdbf65 100644 --- a/core/libs/tests/GuestKernelRename.cpp +++ b/core/libs/tests/GuestKernelRename.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -11,9 +12,7 @@ #else #include #endif -extern "C" { -int* APS5_VABI __error_nid_postfix(); -} + using RenameFunction = int (APS5_VABI*)(const char*, const char*); static RenameFunction LoadKernelRename() { #ifdef _WIN32 diff --git a/core/libs/tests/GuestKernelStackProtect.cpp b/core/libs/tests/GuestKernelStackProtect.cpp index a980ea9d09..2574e5e198 100644 --- a/core/libs/tests/GuestKernelStackProtect.cpp +++ b/core/libs/tests/GuestKernelStackProtect.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "SceTypes.hpp" #include #include @@ -18,18 +20,6 @@ #include #endif -extern "C" { -int APS5_VABI scePthreadCreate(Pthread* thread, const PthreadAttr* attr, PthreadEntry entry, void* arg, const char* name); -int APS5_VABI scePthreadJoin(Pthread thread, void** retval); -int APS5_VABI scePthreadKeyCreate(PthreadKey* key, pthread_key_destructor_func_t destructor); -int APS5_VABI scePthreadKeyDelete(PthreadKey key); -int APS5_VABI scePthreadSetspecific(PthreadKey key, void* value); -int APS5_VABI sceKernelIsStack(void* addr, void** start, void** end); -void* APS5_VABI mmap_nid_postfix(void* address, std::size_t length, int protection, int flags, int descriptor, std::int64_t offset) noexcept; -int APS5_VABI mprotect_nid_postfix(void* address, std::size_t length, int protection) noexcept; -int* APS5_VABI __error_nid_postfix(); -} - static constexpr int SCE_OK = 0; static constexpr std::uintptr_t Page = 0x4000; static constexpr std::size_t GuardBytes = 0x10000; diff --git a/core/libs/tests/GuestKernelSync.cpp b/core/libs/tests/GuestKernelSync.cpp index fbe8391437..6386538124 100644 --- a/core/libs/tests/GuestKernelSync.cpp +++ b/core/libs/tests/GuestKernelSync.cpp @@ -1,3 +1,6 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libkernel/File/include/File.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/General.hpp" #include #include @@ -12,19 +15,7 @@ #define WIN32_LEAN_AND_MEAN #include #endif -extern "C" { -int APS5_VABI sceKernelOpen(const char*, int, unsigned short); -int APS5_VABI sceKernelClose(int); -std::int64_t APS5_VABI sceKernelWrite(int, const void*, std::size_t); -int APS5_VABI sceKernelMkdir(const char*, unsigned short); -int APS5_VABI sceKernelRename(const char*, const char*); -int APS5_VABI sceKernelUnlink(const char*); -int APS5_VABI sceKernelChmod_nid_postfix(const char*, std::uint16_t); -void APS5_VABI sceKernelSync(); -void APS5_VABI sync_nid_postfix(); -void* APS5_VABI fopen_nid_postfix(const char*, const char*); -int APS5_VABI fclose_nid_postfix(void*); -} + static void Check(bool value, int line) { if (!value) { std::fprintf(stderr, "Kernel sync check failed at line %d\n", line); @@ -50,7 +41,7 @@ int main() { Require(sceKernelMkdir("kernel_sync_probe/existing.bin/child", 0777) == static_cast(0x80020014u)); const int reader = sceKernelOpen("kernel_sync_probe/existing.bin", 0x0, 0); Require(reader >= 0 && sceKernelClose(reader) == 0); - void* stream = fopen_nid_postfix("kernel_sync_probe/existing.bin", "r"); + FileStream* stream = fopen_nid_postfix("kernel_sync_probe/existing.bin", "r"); Require(stream != nullptr && fclose_nid_postfix(stream) == 0); Require(!Recorded("kernel_sync_probe/existing.bin")); stream = fopen_nid_postfix("kernel_sync_probe/existing.bin", "a"); @@ -63,27 +54,33 @@ int main() { Require(Recorded("kernel_sync_probe/moved.bin")); Require(sceKernelUnlink("kernel_sync_probe/moved.bin") == 0); sceKernelSync(); + Require(!Recorded("kernel_sync_probe/data.bin") && !Recorded("kernel_sync_probe/moved.bin")); sceKernelSync(); + const int locked = sceKernelOpen("kernel_sync_probe/read_only.bin", 0x1 | 0x200, 0644); Require(locked >= 0 && sceKernelWrite(locked, "data", 4) == 4 && sceKernelClose(locked) == 0); Require(sceKernelChmod_nid_postfix("kernel_sync_probe/read_only.bin", 0444) == 0); Require(Recorded("kernel_sync_probe/read_only.bin")); sceKernelSync(); + Require(sceKernelChmod_nid_postfix("kernel_sync_probe/read_only.bin", 0644) == 0); #ifdef _WIN32 const auto exclusive = CreateFileW(ResolvePath_nid_no_patch("kernel_sync_probe/read_only.bin").c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); Require(exclusive != INVALID_HANDLE_VALUE); sceKernelSync(); + CloseHandle(exclusive); #endif sceKernelSync(); + const int synced = sceKernelOpen("kernel_sync_probe/synced.bin", 0x1 | 0x200 | 0x400, 0644); Require(synced >= 0 && sceKernelWrite(synced, "data", 4) == 4 && sceKernelClose(synced) == 0); Require(Recorded("kernel_sync_probe/synced.bin")); Require(sceKernelUnlink("kernel_sync_probe/synced.bin") == 0); sync_nid_postfix(); + Require(!Recorded("kernel_sync_probe/synced.bin")); std::filesystem::remove_all("kernel_sync_probe"); } diff --git a/core/libs/tests/GuestKernelSys.cpp b/core/libs/tests/GuestKernelSys.cpp index 1650d050d4..81997c91e1 100644 --- a/core/libs/tests/GuestKernelSys.cpp +++ b/core/libs/tests/GuestKernelSys.cpp @@ -1,5 +1,11 @@ +#include "prx/libkernel_sys/include/Api.hpp" +#include "prx/libkernel/include/Api.hpp" +#include "prx/libkernel/Pthread/include/Cond.hpp" +#include "prx/libkernel/File/include/File.hpp" +#include "prx/libc/include/Api.hpp" #include "SceTypes.hpp" #include "prx/libc/include/general/VabiMacros.hpp" +#include "prx/libc/include/General.hpp" #include "prx/libc/include/RemoveTree.hpp" #include "prx/libkernel/File/include/FileFlags.hpp" #include "prx/libkernel/KernelErrors.hpp" @@ -25,65 +31,10 @@ #endif #ifndef _WIN32 #include +#include #include #endif -extern "C" { -int APS5_VABI fstatfs_nid_postfix(int, void*); -int APS5_VABI _fstatfs_nid_postfix(int, void*); -int APS5_VABI fstat_nid_postfix(int, FileStat*); -std::int64_t APS5_VABI _fstat_nid_postfix(int, FileStat*); -int APS5_VABI open_nid_postfix(const char*, int, int); -int APS5_VABI close_nid_postfix(int); -int APS5_VABI pipe_nid_postfix(int*); -int APS5_VABI socket_nid_postfix(int, int, int); -std::int64_t APS5_VABI readlink_nid_postfix(const char*, char*, std::size_t); -int APS5_VABI lstat_nid_postfix(const char*, FileStat*); -std::int64_t APS5_VABI pathconf_nid_postfix(const char*, int); -std::int64_t APS5_VABI fpathconf_nid_postfix(int, int); -std::int64_t APS5_VABI _fpathconf_nid_postfix(int, int); -int APS5_VABI fchdir_nid_postfix(int); -int APS5_VABI chdir_nid_postfix(const char*); -int APS5_VABI chroot_nid_postfix(const char*); -char* APS5_VABI getcwd_nid_postfix(char*, std::size_t); -int APS5_VABI getpid_nid_postfix(); -int APS5_VABI sceKernelTitleWorkaroundIsEnabled(const void*, std::int32_t, std::int32_t*); -int APS5_VABI sceKernelGetProcessType(int); -int APS5_VABI sceKernelOpen(const char*, int, std::uint16_t); -int APS5_VABI sceKernelClose(int); -int APS5_VABI sceKernelRename(const char*, const char*); -int APS5_VABI sceKernelFstat(int, FileStat*); -int APS5_VABI sceKernelGetdents(int, char*, int); -std::int64_t APS5_VABI sceKernelLseek(int, std::int64_t, int); -std::int64_t APS5_VABI sceKernelPread(int, void*, std::size_t, std::int64_t); -int APS5_VABI dup_nid_postfix(int); -int APS5_VABI dup2_nid_postfix(int, int); -int APS5_VABI setsid_nid_postfix(void); -int APS5_VABI link_nid_postfix(const char*, const char*); -int APS5_VABI symlink_nid_postfix(const char*, const char*); -int APS5_VABI openat_nid_postfix(int, const char*, int, ...); -int APS5_VABI _openat_nid_postfix(int, const char*, int, ...); -int APS5_VABI unlinkat_nid_postfix(int, const char*, int); -std::int64_t APS5_VABI readlinkat_nid_postfix(int, const char*, char*, std::size_t); -int APS5_VABI mkdirat_nid_postfix(int, const char*, std::uint16_t); -int APS5_VABI renameat_nid_postfix(int, const char*, int, const char*); -int APS5_VABI fchmodat_nid_postfix(int, const char*, int, int); -int APS5_VABI lchmod_nid_postfix(const char*, std::uint16_t); -int APS5_VABI fchown_nid_postfix(int, std::uint32_t, std::uint32_t); -int APS5_VABI chown_nid_postfix(const char*, std::uint32_t, std::uint32_t); -int APS5_VABI lchown_nid_postfix(const char*, std::uint32_t, std::uint32_t); -int APS5_VABI fchownat_nid_postfix(int, const char*, std::uint32_t, std::uint32_t, int); -int APS5_VABI linkat_nid_postfix(int, const char*, int, const char*, int); -int APS5_VABI fstatat_nid_postfix(int, const char*, FileStat*, int); -std::int64_t APS5_VABI sceKernelRead(int, void*, std::size_t); -std::uint16_t APS5_VABI umask_nid_postfix(std::uint16_t); -int APS5_VABI scePthreadCondattrInit(PthreadCondattr*); -int APS5_VABI scePthreadCondattrDestroy(PthreadCondattr*); -int APS5_VABI scePthreadCondattrSetclock(PthreadCondattr*, KernelClockid); -int APS5_VABI scePthreadCondattrGetclock(const PthreadCondattr*, KernelClockid*); -int* APS5_VABI __error_nid_postfix(); -} - void Require(bool condition, std::source_location location = std::source_location::current()) { if (!condition) { std::fprintf(stderr, "Kernel sys check failed at line %u (guest errno %d)\n", location.line(), *__error_nid_postfix()); @@ -98,6 +49,7 @@ int Error() { bool PathconfThrows(const char* path, int name) { try { pathconf_nid_postfix(path, name); + } catch (const std::runtime_error&) { return true; } @@ -107,6 +59,7 @@ bool PathconfThrows(const char* path, int name) { bool ChrootThrows(const std::string& path) { try { chroot_nid_postfix(path.c_str()); + } catch (const std::runtime_error& error) { return std::strstr(error.what(), path.c_str()) != nullptr; } @@ -164,8 +117,26 @@ void OwnershipAndLinkTests(const std::filesystem::path& root) { Require(linkat_nid_postfix(-100, file.c_str(), -100, other.c_str(), 0x200) == -1 && Error() == 22); Require(linkat_nid_postfix(-100, nullptr, -100, other.c_str(), 0) == -1 && Error() == 14); Require(linkat_nid_postfix(-100, "", -100, other.c_str(), 0) == -1 && Error() == 2); - Require(ThrowsNaming([&] { linkat_nid_postfix(directory, "owned.txt", -100, other.c_str(), 0); }, "linkat: a relative path")); - Require(ThrowsNaming([&] { linkat_nid_postfix(-100, file.c_str(), directory, "other.txt", 0); }, "linkat: a relative path")); + Require(linkat_nid_postfix(directory, "owned.txt", -100, other.c_str(), 0) == 0); + Require(std::filesystem::hard_link_count(file) == 3 && std::filesystem::remove(other)); + Require(linkat_nid_postfix(-100, file.c_str(), directory, "other.txt", 0) == 0); + Require(std::filesystem::hard_link_count(file) == 3); + Require(linkat_nid_postfix(directory, "owned.txt", directory, "other.txt", 0) == -1 && Error() == 17); + Require(linkat_nid_postfix(directory, "missing.txt", directory, "absent.txt", 0) == -1 && Error() == 2); + Require(linkat_nid_postfix(4321, "owned.txt", directory, "absent.txt", 0) == -1 && Error() == 9); + Require(linkat_nid_postfix(directory, "owned.txt", 4321, "absent.txt", 0) == -1 && Error() == 9); + Require(linkat_nid_postfix(directory, "missing.txt", 4321, "absent.txt", 0) == -1 && Error() == 2); + Require(linkat_nid_postfix(directory, "missing.txt", -100, nullptr, 0) == -1 && Error() == 2); + Require(linkat_nid_postfix(-100, root.string().c_str(), 4321, "absent.txt", 0) == -1 && Error() == 1); + Require(linkat_nid_postfix(-100, root.string().c_str(), -100, "", 0) == -1 && Error() == 1); + Require(linkat_nid_postfix(directory, "owned.txt", -100, nullptr, 0) == -1 && Error() == 14); + Require(linkat_nid_postfix(directory, "owned.txt", -100, "", 0) == -1 && Error() == 2); + const int plain = sceKernelOpen(file.c_str(), SCE_KERNEL_O_RDONLY, 0); + Require(plain >= 0); + Require(linkat_nid_postfix(plain, "owned.txt", directory, "absent.txt", 0) == -1 && Error() == 20); + Require(linkat_nid_postfix(directory, "owned.txt", plain, "absent.txt", 0) == -1 && Error() == 20); + Require(sceKernelClose(plain) == 0 && std::filesystem::remove(other)); + Require(!std::filesystem::exists(root / "absent.txt")); const auto symbolic = (root / "owned.link").string(); const auto dangling = (root / "dangling.link").string(); if (symlink_nid_postfix("owned.txt", symbolic.c_str()) == 0) { @@ -192,6 +163,7 @@ void OwnershipAndLinkTests(const std::filesystem::path& root) { bool SymlinkTargetThrows(const char* target, const std::string& created) { try { symlink_nid_postfix(target, created.c_str()); + } catch (const std::runtime_error&) { return true; } @@ -211,6 +183,119 @@ bool RemoveSymlink(const std::string& link) { #endif } +class GuardedPaths { +public: + GuardedPaths() { +#ifdef _WIN32 + SYSTEM_INFO info{}; + GetSystemInfo(&info); + page = info.dwPageSize; + memory = static_cast(VirtualAlloc(nullptr, 2 * page, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE)); + Require(memory != nullptr); + DWORD previous = 0; + Require(VirtualProtect(memory + page, page, PAGE_NOACCESS, &previous) != 0); +#else + const long size = sysconf(_SC_PAGESIZE); + Require(size > 0); + page = static_cast(size); + memory = static_cast(mmap(nullptr, 2 * page, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)); + Require(memory != MAP_FAILED); + Require(mprotect(memory + page, page, PROT_NONE) == 0); +#endif + } + + ~GuardedPaths() { +#ifdef _WIN32 + Require(VirtualFree(memory, 0, MEM_RELEASE) != 0); +#else + Require(munmap(memory, 2 * page) == 0); +#endif + } + + char* Unreadable() const { return memory + page; } + char* Crossing() const { return memory + page - 3; } + char* Boundary() const { return memory + page - 2; } + +private: + char* memory = nullptr; + std::size_t page = 0; +}; + +void CheckUnreadablePaths(const std::string& renameSource, int directory) { + constexpr int Fault = 14; + constexpr int KernelFault = static_cast(0x8002000Eu); + GuardedPaths paths; + std::memcpy(paths.Crossing(), "abc", 3); + std::string copy; + Require(CopyGuestPath_nid_no_patch(paths.Unreadable(), copy) == Fault); + Require(CopyGuestPath_nid_no_patch(paths.Crossing(), copy) == Fault); + paths.Boundary()[0] = '.'; + paths.Boundary()[1] = '\0'; + Require(CopyGuestPath_nid_no_patch(paths.Boundary(), copy) == 0 && copy == "."); + const std::string maximum(1023, 'p'); + std::array unterminated{}; + unterminated.fill('p'); + Require(CopyGuestPath_nid_no_patch(maximum.c_str(), copy) == 0 && copy == maximum); + Require(CopyGuestPath_nid_no_patch(unterminated.data(), copy) == 63); + const auto posixFault = [&](auto call) { + *__error_nid_postfix() = 0; + Require(call() == -1 && Error() == Fault); + }; + FileStat status{}; + char linkBuffer[16]{}; + posixFault([&] { return open_nid_postfix(paths.Unreadable(), SCE_KERNEL_O_RDONLY, 0); }); + posixFault([&] { return chmod_nid_postfix(paths.Unreadable(), 0); }); + posixFault([&] { return mkdir_nid_postfix(paths.Unreadable(), 0755); }); + posixFault([&] { return rmdir_nid_postfix(paths.Unreadable()); }); + posixFault([&] { return unlink_nid_postfix(paths.Unreadable()); }); + posixFault([&] { return stat_nid_postfix(paths.Unreadable(), &status); }); + posixFault([&] { return lstat_nid_postfix(paths.Unreadable(), &status); }); + posixFault([&] { return truncate_nid_postfix(paths.Unreadable(), 0); }); + posixFault([&] { return utimes_nid_postfix(paths.Unreadable(), nullptr); }); + posixFault([&] { return lutimes_nid_postfix(paths.Unreadable(), nullptr); }); + posixFault([&] { return readlink_nid_postfix(paths.Unreadable(), linkBuffer, sizeof(linkBuffer)); }); + posixFault([&] { return pathconf_nid_postfix(paths.Unreadable(), 4); }); + posixFault([&] { return link_nid_postfix(paths.Unreadable(), "unused-link"); }); + posixFault([&] { return link_nid_postfix(renameSource.c_str(), paths.Unreadable()); }); + posixFault([&] { return symlink_nid_postfix(paths.Unreadable(), "unused-symlink"); }); + posixFault([&] { return symlink_nid_postfix("target", paths.Unreadable()); }); + posixFault([&] { return openat_nid_postfix(-100, paths.Unreadable(), SCE_KERNEL_O_RDONLY); }); + posixFault([&] { return mkdirat_nid_postfix(-100, paths.Unreadable(), 0755); }); + posixFault([&] { return fchmodat_nid_postfix(-100, paths.Unreadable(), 0, 0); }); + posixFault([&] { return lchmod_nid_postfix(paths.Unreadable(), 0); }); + posixFault([&] { return fstatat_nid_postfix(-100, paths.Unreadable(), &status, 0); }); + posixFault([&] { return unlinkat_nid_postfix(-100, paths.Unreadable(), 0); }); + posixFault([&] { return readlinkat_nid_postfix(-100, paths.Unreadable(), linkBuffer, sizeof(linkBuffer)); }); + posixFault([&] { return renameat_nid_postfix(-100, paths.Unreadable(), -100, "unused-rename"); }); + posixFault([&] { return renameat_nid_postfix(-100, renameSource.c_str(), -100, paths.Unreadable()); }); + posixFault([&] { return openat_nid_postfix(directory, paths.Unreadable(), SCE_KERNEL_O_RDONLY); }); + posixFault([&] { return mkdirat_nid_postfix(directory, paths.Unreadable(), 0755); }); + posixFault([&] { return fchmodat_nid_postfix(directory, paths.Unreadable(), 0, 0); }); + posixFault([&] { return fstatat_nid_postfix(directory, paths.Unreadable(), &status, 0); }); + posixFault([&] { return unlinkat_nid_postfix(directory, paths.Unreadable(), 0); }); + posixFault([&] { return readlinkat_nid_postfix(directory, paths.Unreadable(), linkBuffer, sizeof(linkBuffer)); }); + posixFault([&] { return renameat_nid_postfix(directory, paths.Unreadable(), directory, "unused-rename"); }); + posixFault([&] { return renameat_nid_postfix(directory, "file.txt", directory, paths.Unreadable()); }); + *__error_nid_postfix() = 0; + Require(renameat_nid_postfix(directory, "missing", directory, paths.Unreadable()) == -1 && Error() == 2); + *__error_nid_postfix() = 0; + Require(link_nid_postfix("missing", paths.Unreadable()) == -1 && Error() == 2); + posixFault([&] { return shm_open_nid_postfix(paths.Unreadable(), SCE_KERNEL_O_RDWR, 0600); }); + posixFault([&] { return shm_unlink_nid_postfix(paths.Unreadable()); }); + Require(sceKernelOpen(paths.Unreadable(), SCE_KERNEL_O_RDONLY, 0) == KernelFault); + Require(sceKernelStat(paths.Unreadable(), &status) == KernelFault); + Require(sceKernelMkdir(paths.Unreadable(), 0755) == KernelFault); + Require(sceKernelRmdir(paths.Unreadable()) == KernelFault); + Require(sceKernelUnlink(paths.Unreadable()) == KernelFault); + Require(sceKernelChmod_nid_postfix(paths.Unreadable(), 0) == KernelFault); + Require(sceKernelTruncate_nid_postfix(paths.Unreadable(), 0) == KernelFault); + Require(sceKernelUtimes_nid_postfix(paths.Unreadable(), nullptr) == KernelFault); + Require(sceKernelCheckReachability(paths.Unreadable()) == KernelFault); + Require(sceKernelRename(paths.Unreadable(), ".") == KernelFault); + Require(sceKernelRename(renameSource.c_str(), paths.Unreadable()) == KernelFault); + Require(!std::filesystem::exists("unused-link") && !std::filesystem::exists("unused-symlink") && !std::filesystem::exists("unused-rename")); +} + void CheckSymlinkTargetRestrictions(const std::filesystem::path& root) { const auto created = (root / "rejected").string(); for (const auto& target : {std::string(".."), std::string("../x"), std::string("a/../b"), std::string("a/../../x"), std::string("/abs")}) @@ -375,11 +460,7 @@ void DirectoryRenameTests(const std::filesystem::path& parent) { } static void CheckProcessQueries() { - struct { - std::int32_t version; - std::int32_t align; - std::uint64_t ids[2]; - } workaround{1, 0, {(1ull << 3) | (1ull << 0x39), ~0ull}}; + KernelTitleWorkaround workaround{1, 0, {(1ull << 3) | (1ull << 0x39), ~0ull}}; std::int32_t enabled = -1; Require(sceKernelTitleWorkaroundIsEnabled(nullptr, 3, &enabled) == static_cast(0x8002000E)); Require(sceKernelTitleWorkaroundIsEnabled(&workaround, 3, nullptr) == static_cast(0x8002000E)); @@ -463,9 +544,11 @@ int main() { CheckPathconf(root, file); const int descriptor = open_nid_postfix(file.c_str(), 0, 0); Require(descriptor >= 0); - unsigned char viaPublic[472] = {}; - unsigned char viaSyscall[472] = {}; - Require(fstatfs_nid_postfix(descriptor, viaPublic) == 0 && _fstatfs_nid_postfix(descriptor, viaSyscall) == 0); + KernelStatfs publicStats{}; + auto* viaPublic = reinterpret_cast(&publicStats); + KernelStatfs syscallStats{}; + auto* viaSyscall = reinterpret_cast(&syscallStats); + Require(fstatfs_nid_postfix(descriptor, reinterpret_cast(viaPublic)) == 0 && _fstatfs_nid_postfix(descriptor, reinterpret_cast(viaSyscall)) == 0); Require(std::memcmp(viaPublic, viaSyscall, 4) == 0 && std::memcmp(viaPublic + 16, viaSyscall + 16, 8) == 0); Require(std::memcmp(viaPublic + 280, viaSyscall + 280, 16) == 0); Require(fstatfs_nid_postfix(descriptor, nullptr) == -1 && Error() == 14); @@ -479,7 +562,7 @@ int main() { CheckPipePathconf(fpathconf_nid_postfix); CheckPipePathconf(_fpathconf_nid_postfix); Require(close_nid_postfix(descriptor) == 0); - Require(fstatfs_nid_postfix(-1, viaPublic) == -1 && Error() == 9); + Require(fstatfs_nid_postfix(-1, reinterpret_cast(viaPublic)) == -1 && Error() == 9); Require(fstat_nid_postfix(descriptor, &viaFstat) == -1 && Error() == 9); Require(fstat_nid_postfix(-1, &viaFstat) == -1 && Error() == 9); Require(fpathconf_nid_postfix(descriptor, 4) == -1 && Error() == 9); @@ -769,6 +852,7 @@ int main() { CheckSymlinkTargetRestrictions(root); const int base = sceKernelOpen(root.string().c_str(), SCE_KERNEL_O_RDONLY | SCE_KERNEL_O_DIRECTORY, 0); Require(base >= 0); + CheckUnreadablePaths(file, base); const int relative = openat_nid_postfix(base, "file.txt", SCE_KERNEL_O_RDONLY); char byte = 0; Require(relative >= 0 && sceKernelRead(relative, &byte, 1) == 1 && byte == 'x'); diff --git a/core/libs/tests/GuestKernelSysAio.cpp b/core/libs/tests/GuestKernelSysAio.cpp index 7eb23d13ad..200d3290b8 100644 --- a/core/libs/tests/GuestKernelSysAio.cpp +++ b/core/libs/tests/GuestKernelSysAio.cpp @@ -1,3 +1,6 @@ +#include "prx/libkernel_sys/include/Api.hpp" +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "SceTypes.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -12,48 +15,10 @@ namespace { -struct Sigevent { - int notify; - int signo; - std::int64_t value; - std::int64_t extra[8]; -}; - -struct Aiocb { - int fildes; - std::int64_t offset; - void* buf; - std::uint64_t nbytes; - int spare[2]; - void* spare2; - int lioOpcode; - int reqprio; - std::int64_t status; - std::int64_t error; - void* kernelinfo; - Sigevent sigevent; -}; - -struct Timespec { - std::int64_t seconds; - std::int64_t nanoseconds; -}; - } extern "C" { -int* APS5_VABI __error_nid_postfix(); -int APS5_VABI open_nid_postfix(const char* path, int flags, int mode); -int APS5_VABI close_nid_postfix(int descriptor); -int APS5_VABI pipe_nid_postfix(int* descriptors); -int APS5_VABI aio_read_nid_postfix(Aiocb* aiocb); -int APS5_VABI aio_write_nid_postfix(Aiocb* aiocb); -int APS5_VABI aio_fsync_nid_postfix(int operation, Aiocb* aiocb); -int APS5_VABI aio_error_nid_postfix(const Aiocb* aiocb); -std::int64_t APS5_VABI aio_return_nid_postfix(Aiocb* aiocb); -int APS5_VABI aio_suspend_nid_postfix(const Aiocb* const* list, int count, const Timespec* timeout); -std::int64_t APS5_VABI aio_waitcomplete_nid_postfix(Aiocb** result, const Timespec* timeout); -int APS5_VABI aio_cancel_nid_postfix(int descriptor, Aiocb* aiocb); + void AioHoldWorkerForTest_nid_no_patch(bool hold); } @@ -84,8 +49,8 @@ int Error() { return *__error_nid_postfix(); } -Aiocb Request(int descriptor, void* buffer, std::uint64_t bytes, std::int64_t offset = 0) { - Aiocb request{}; +GuestAiocb Request(int descriptor, void* buffer, std::uint64_t bytes, std::int64_t offset = 0) { + GuestAiocb request{}; request.fildes = descriptor; request.buf = buffer; request.nbytes = bytes; @@ -93,14 +58,14 @@ Aiocb Request(int descriptor, void* buffer, std::uint64_t bytes, std::int64_t of return request; } -void Wait(Aiocb& request) { - const Aiocb* list[] = {&request}; +void Wait(GuestAiocb& request) { + const GuestAiocb* list[] = {&request}; Require(aio_suspend_nid_postfix(list, 1, nullptr) == 0); } void BeforeUse() { - Aiocb request{}; - const Aiocb* list[] = {&request}; + GuestAiocb request{}; + const GuestAiocb* list[] = {&request}; Require(aio_error_nid_postfix(&request) == Einval); Require(aio_return_nid_postfix(&request) == -1 && Error() == Einval); Require(aio_suspend_nid_postfix(list, 1, nullptr) == -1 && Error() == Eagain); @@ -163,12 +128,12 @@ void ReadAndWrite(int file) { Wait(empty); Require(aio_return_nid_postfix(&empty) == 0); - const Aiocb* none[] = {&request}; + const GuestAiocb* none[] = {&request}; Require(aio_suspend_nid_postfix(none, 1, nullptr) == 0); Require(aio_suspend_nid_postfix(none, 0, nullptr) == 0); Require(aio_suspend_nid_postfix(none, -1, nullptr) == -1 && Error() == Einval); Require(aio_suspend_nid_postfix(none, 257, nullptr) == -1 && Error() == Einval); - const Timespec badTime{0, 1000000000}; + const KernelTimespec badTime{0, 1000000000}; Require(aio_suspend_nid_postfix(none, 1, &badTime) == -1 && Error() == Einval); } @@ -179,8 +144,8 @@ void Cancel(int file) { auto second = Request(file, buffer, sizeof(buffer)); Require(aio_read_nid_postfix(&first) == 0 && aio_read_nid_postfix(&second) == 0); Require(first.error == Einprogress && aio_error_nid_postfix(&first) == Einprogress); - const Aiocb* list[] = {&first}; - const Timespec brief{0, 5000000}; + const GuestAiocb* list[] = {&first}; + const KernelTimespec brief{0, 5000000}; Require(aio_suspend_nid_postfix(list, 1, &brief) == -1 && Error() == Eagain); Require(aio_cancel_nid_postfix(file, &first) == AioCanceled); @@ -207,14 +172,14 @@ void SyncOrder(int file) { Require(aio_error_nid_postfix(&sync) == Einprogress); AioHoldWorkerForTest_nid_no_patch(false); - Aiocb* done = nullptr; + GuestAiocb* done = nullptr; Require(aio_waitcomplete_nid_postfix(&done, nullptr) == 7 && done == &write); Require(aio_waitcomplete_nid_postfix(&done, nullptr) == 0 && done == &sync && sync.status == 0); - const Timespec zero{0, 0}; + const KernelTimespec zero{0, 0}; Require(aio_waitcomplete_nid_postfix(&done, &zero) == -1 && Error() == Eagain && done == nullptr); - const Timespec brief{0, 5000000}; + const KernelTimespec brief{0, 5000000}; Require(aio_waitcomplete_nid_postfix(&done, &brief) == -1 && Error() == Eagain); - const Timespec badTime{0, -1}; + const KernelTimespec badTime{0, -1}; Require(aio_waitcomplete_nid_postfix(&done, &badTime) == -1 && Error() == Einval); } diff --git a/core/libs/tests/GuestKernelSysBarrier.cpp b/core/libs/tests/GuestKernelSysBarrier.cpp index 6969511d3a..084228c772 100644 --- a/core/libs/tests/GuestKernelSysBarrier.cpp +++ b/core/libs/tests/GuestKernelSysBarrier.cpp @@ -1,3 +1,6 @@ +#include "prx/libkernel/KernelErrors.hpp" +#include "prx/libkernel_sys/include/Api.hpp" +#include "prx/libkernel/include/Api.hpp" #include "SceTypes.hpp" #include #include @@ -5,30 +8,6 @@ #include #include -struct GuestBarrier; -struct GuestBarrierattr; - -extern "C" { -int APS5_VABI scePthreadCreate(Pthread* thread, const PthreadAttr* attr, PthreadEntry entry, void* arg, const char* name); -int APS5_VABI scePthreadJoin(Pthread thread, void** retval); -Pthread APS5_VABI scePthreadSelf(); -int APS5_VABI scePthreadBarrierattrInit(GuestBarrierattr** attr); -int APS5_VABI scePthreadBarrierattrDestroy(GuestBarrierattr** attr); -int APS5_VABI scePthreadBarrierattrGetpshared(GuestBarrierattr* const* attr, int* pshared); -int APS5_VABI scePthreadBarrierattrSetpshared(GuestBarrierattr** attr, int pshared); -int APS5_VABI scePthreadBarrierInit(GuestBarrier** barrier, GuestBarrierattr* const* attr, unsigned count, const char* name); -int APS5_VABI scePthreadBarrierWait(GuestBarrier** barrier); -int APS5_VABI scePthreadBarrierDestroy(GuestBarrier** barrier); -int APS5_VABI scePthreadGetcpuclockid(Pthread thread, int* clockId); -int APS5_VABI pthread_getcpuclockid_nid_postfix(Pthread thread, int* clockId); -int APS5_VABI scePthreadGetconcurrency(); -int APS5_VABI pthread_setconcurrency_nid_postfix(int level); -int APS5_VABI sceKernelMsync(void* address, std::size_t length, int flags); -} - -static constexpr int SCE_KERNEL_ERROR_EINVAL = static_cast(0x80020016); -static constexpr int SCE_KERNEL_ERROR_EFAULT = static_cast(0x8002000E); -static constexpr int SCE_KERNEL_ERROR_ENOMEM = static_cast(0x8002000C); static constexpr int PROCESS_PRIVATE = 0; static constexpr int PROCESS_SHARED = 1; static constexpr int BARRIER_SERIAL_THREAD = -1; @@ -39,7 +18,7 @@ static constexpr unsigned WAITERS = 4; static void Require(bool value) { if (!value) std::abort(); } struct Context { - GuestBarrier* barrier = nullptr; + PthreadBarrierPrivate* barrier = nullptr; std::atomic serial{0}; std::atomic released{0}; }; @@ -54,7 +33,7 @@ static void* APS5_VABI Waiter(void* arg) { } int main() { - GuestBarrierattr* attr = nullptr; + PthreadBarrierattrPrivate* attr = nullptr; Require(scePthreadBarrierattrInit(nullptr) == SCE_KERNEL_ERROR_EINVAL); Require(scePthreadBarrierattrInit(&attr) == 0 && attr != nullptr); int pshared = -1; @@ -82,7 +61,7 @@ int main() { Require(scePthreadBarrierDestroy(&context.barrier) == SCE_KERNEL_ERROR_EINVAL); Require(scePthreadBarrierWait(nullptr) == SCE_KERNEL_ERROR_EINVAL); - GuestBarrier* single = nullptr; + PthreadBarrierPrivate* single = nullptr; Require(scePthreadBarrierInit(&single, nullptr, 1, nullptr) == 0); Require(scePthreadBarrierWait(&single) == BARRIER_SERIAL_THREAD); Require(scePthreadBarrierDestroy(&single) == 0); diff --git a/core/libs/tests/GuestKernelSysConstants.cpp b/core/libs/tests/GuestKernelSysConstants.cpp new file mode 100644 index 0000000000..8565415fc8 --- /dev/null +++ b/core/libs/tests/GuestKernelSysConstants.cpp @@ -0,0 +1,45 @@ +#include "SceTypes.hpp" +#include "prx/libkernel_sys/libkernel_sys.hpp" +#include + +namespace { + +constexpr int GUEST_ENOTSUP = 45; +constexpr int SCE_KERNEL_ERROR_EPERM = static_cast(0x80020001); +constexpr int SCE_KERNEL_ERROR_ENOENT = static_cast(0x80020002); +constexpr int SCE_KERNEL_ERROR_ENOTSUP = static_cast(0x8002002d); +constexpr int SCE_KERNEL_ERROR_ENOSYS = static_cast(0x8002004e); + +void Require(bool value) { if (!value) std::abort(); } + +} + +int main() { + Require(pthread_switch_add_np_nid_postfix() == GUEST_ENOTSUP); + Require(pthread_switch_delete_np_nid_postfix() == GUEST_ENOTSUP); + + Require(sceKernelAddResource() == 0); + Require(sceKernelEventLogInit() == 0); + Require(sceKernelIsGenuineKratosCex() == 0); + Require(sceKernelReleaseTraceDirectMemory() == 0); + + Require(sceKernelHasNeoMode() == 1); + Require(sceKernelIsAuthenticNeo() == 1); + Require(sceKernelIsGenuineN() == 1); + + Require(sceKernelCreateEport() == SCE_KERNEL_ERROR_EPERM); + Require(sceKernelDeleteEport() == SCE_KERNEL_ERROR_EPERM); + Require(sceKernelOpenEport() == SCE_KERNEL_ERROR_EPERM); + Require(sceKernelCloseEport() == SCE_KERNEL_ERROR_EPERM); + Require(sceKernelTriggerEport() == SCE_KERNEL_ERROR_EPERM); + + Require(sceKernelQueryTraceMemory() == SCE_KERNEL_ERROR_ENOENT); + + Require(sceKernelIccGetCPMode() == SCE_KERNEL_ERROR_ENOTSUP); + Require(sceKernelIccSetCPMode() == SCE_KERNEL_ERROR_ENOTSUP); + + Require(sceKernelClearGameDirectMemory() == SCE_KERNEL_ERROR_ENOSYS); + Require(sceKernelMapTraceMemory() == SCE_KERNEL_ERROR_ENOSYS); + Require(sceKernelTraceMemoryTypeProtect() == SCE_KERNEL_ERROR_ENOSYS); + return 0; +} diff --git a/core/libs/tests/GuestKernelSysKtimer.cpp b/core/libs/tests/GuestKernelSysKtimer.cpp index 2dc1cc763f..bb189576b4 100644 --- a/core/libs/tests/GuestKernelSysKtimer.cpp +++ b/core/libs/tests/GuestKernelSysKtimer.cpp @@ -1,3 +1,6 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libkernel/Time/include/Time.hpp" +#include "prx/libc/include/Api.hpp" #include "SceTypes.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -10,33 +13,6 @@ namespace { -struct Sigevent { - int notify; - int signo; - std::int64_t value; - std::int64_t extra[6]; -}; - -struct Timespec { - std::int64_t seconds; - std::int64_t nanoseconds; -}; - -struct Itimerspec { - Timespec interval; - Timespec value; -}; - -} - -extern "C" { -int* APS5_VABI __error_nid_postfix(); -int APS5_VABI clock_gettime_nid_postfix(int clock, Timespec* time); -int APS5_VABI ktimer_create_nid_postfix(int clock, const Sigevent* event, int* timerid); -int APS5_VABI ktimer_delete_nid_postfix(int timerid); -int APS5_VABI ktimer_settime_nid_postfix(int timerid, int flags, const Itimerspec* value, Itimerspec* oldValue); -int APS5_VABI ktimer_gettime_nid_postfix(int timerid, Itimerspec* value); -int APS5_VABI ktimer_getoverrun_nid_postfix(int timerid); } namespace { @@ -51,7 +27,7 @@ constexpr int TimerAbstime = 1; constexpr std::int64_t Millisecond = 1000000; constexpr std::int64_t Second = 1000000000; -const Sigevent None{0, 0, 0, {}}; +const GuestSigevent None{0, 0, 0, {}}; void Require(bool condition, std::source_location location = std::source_location::current()) { if (condition) return; @@ -63,8 +39,8 @@ int Error() { return *__error_nid_postfix(); } -std::int64_t Nanoseconds(const Timespec& time) { - return time.seconds * Second + time.nanoseconds; +std::int64_t Nanoseconds(const KernelTimespec& time) { + return time.tv_sec * Second + time.tv_nsec; } int Create(int clock = ClockMonotonic) { @@ -73,8 +49,8 @@ int Create(int clock = ClockMonotonic) { return id; } -Itimerspec Get(int id) { - Itimerspec value{{-1, -1}, {-1, -1}}; +GuestItimerspec Get(int id) { + GuestItimerspec value{{-1, -1}, {-1, -1}}; Require(ktimer_gettime_nid_postfix(id, &value) == 0); return value; } @@ -85,9 +61,9 @@ void Sleep(std::int64_t nanoseconds) { void Creation() { int id = -1; - const Sigevent badNotify{2, 0, 0, {}}; - const Sigevent noSignal{1, 0, 0, {}}; - const Sigevent badSignal{4, 129, 0, {}}; + const GuestSigevent badNotify{2, 0, 0, {}}; + const GuestSigevent noSignal{1, 0, 0, {}}; + const GuestSigevent badSignal{4, 129, 0, {}}; Require(ktimer_create_nid_postfix(ClockUptime, &None, &id) == -1 && Error() == Einval && id == -1); Require(ktimer_create_nid_postfix(-1, &None, &id) == -1 && Error() == Einval); Require(ktimer_create_nid_postfix(ClockMonotonic, &badNotify, &id) == -1 && Error() == Einval); @@ -107,7 +83,7 @@ void Creation() { } void InvalidIds() { - Itimerspec value{}; + GuestItimerspec value{}; const int id = Create(); Require(ktimer_delete_nid_postfix(id) == 0); for (const int bad : {-1, 0, 2, id, 32}) { @@ -121,50 +97,50 @@ void InvalidIds() { void Values() { const int id = Create(); - Itimerspec disarmed = Get(id); - Require(Nanoseconds(disarmed.value) == 0 && Nanoseconds(disarmed.interval) == 0); - for (const Itimerspec bad : {Itimerspec{{0, 0}, {-1, 0}}, Itimerspec{{0, 0}, {0, -1}}, Itimerspec{{0, 0}, {0, Second}}, - Itimerspec{{-1, 0}, {1, 0}}, Itimerspec{{0, Second}, {1, 0}}}) + GuestItimerspec disarmed = Get(id); + Require(Nanoseconds(disarmed.it_value) == 0 && Nanoseconds(disarmed.it_interval) == 0); + for (const GuestItimerspec bad : {GuestItimerspec{{0, 0}, {-1, 0}}, GuestItimerspec{{0, 0}, {0, -1}}, GuestItimerspec{{0, 0}, {0, Second}}, + GuestItimerspec{{-1, 0}, {1, 0}}, GuestItimerspec{{0, Second}, {1, 0}}}) Require(ktimer_settime_nid_postfix(id, 0, &bad, nullptr) == -1 && Error() == Einval); - const Itimerspec clear{{-1, 0}, {0, 0}}; + const GuestItimerspec clear{{-1, 0}, {0, 0}}; Require(ktimer_settime_nid_postfix(id, 0, &clear, nullptr) == 0); disarmed = Get(id); - Require(Nanoseconds(disarmed.value) == 0 && Nanoseconds(disarmed.interval) == 0); + Require(Nanoseconds(disarmed.it_value) == 0 && Nanoseconds(disarmed.it_interval) == 0); - const Itimerspec small{{0, 1}, {10, 0}}; + const GuestItimerspec small{{0, 1}, {10, 0}}; Require(ktimer_settime_nid_postfix(id, 0, &small, nullptr) == 0); - Itimerspec old{}; - const Itimerspec later{{0, 0}, {20, 0}}; + GuestItimerspec old{}; + const GuestItimerspec later{{0, 0}, {20, 0}}; Require(ktimer_settime_nid_postfix(id, 0, &later, &old) == 0); - Require(Nanoseconds(old.interval) == Millisecond); - Require(Nanoseconds(old.value) > 9 * Second && Nanoseconds(old.value) <= 10 * Second); - const Itimerspec tiny{{0, 0}, {0, 1}}; + Require(Nanoseconds(old.it_interval) == Millisecond); + Require(Nanoseconds(old.it_value) > 9 * Second && Nanoseconds(old.it_value) <= 10 * Second); + const GuestItimerspec tiny{{0, 0}, {0, 1}}; Require(ktimer_settime_nid_postfix(id, 0, &tiny, &old) == 0); - Require(Nanoseconds(old.value) > 19 * Second && Nanoseconds(old.value) <= 20 * Second); - const Itimerspec off{}; + Require(Nanoseconds(old.it_value) > 19 * Second && Nanoseconds(old.it_value) <= 20 * Second); + const GuestItimerspec off{}; Require(ktimer_settime_nid_postfix(id, 0, &off, &old) == 0); - Require(Nanoseconds(old.interval) == 0 && Nanoseconds(old.value) <= Millisecond); + Require(Nanoseconds(old.it_interval) == 0 && Nanoseconds(old.it_value) <= Millisecond); Require(ktimer_delete_nid_postfix(id) == 0); } void Expiry() { const int id = Create(); - const Itimerspec once{{0, 0}, {0, 30 * Millisecond}}; + const GuestItimerspec once{{0, 0}, {0, 30 * Millisecond}}; Require(ktimer_settime_nid_postfix(id, 0, &once, nullptr) == 0); const auto running = Get(id); - Require(Nanoseconds(running.value) > 0 && Nanoseconds(running.value) <= 30 * Millisecond); + Require(Nanoseconds(running.it_value) > 0 && Nanoseconds(running.it_value) <= 30 * Millisecond); Sleep(60 * Millisecond); const auto expired = Get(id); - Require(Nanoseconds(expired.value) == 0 && Nanoseconds(expired.interval) == 0); + Require(Nanoseconds(expired.it_value) == 0 && Nanoseconds(expired.it_interval) == 0); Require(ktimer_getoverrun_nid_postfix(id) == 0); - const Itimerspec periodic{{0, 10 * Millisecond}, {0, 10 * Millisecond}}; + const GuestItimerspec periodic{{0, 10 * Millisecond}, {0, 10 * Millisecond}}; Require(ktimer_settime_nid_postfix(id, 0, &periodic, nullptr) == 0); Sleep(55 * Millisecond); const auto period = Get(id); - Require(Nanoseconds(period.interval) == 10 * Millisecond); - Require(Nanoseconds(period.value) > 0 && Nanoseconds(period.value) <= 10 * Millisecond); + Require(Nanoseconds(period.it_interval) == 10 * Millisecond); + Require(Nanoseconds(period.it_value) > 0 && Nanoseconds(period.it_value) <= 10 * Millisecond); Require(ktimer_getoverrun_nid_postfix(id) == 0); Require(ktimer_delete_nid_postfix(id) == 0); } @@ -172,21 +148,21 @@ void Expiry() { void Absolute() { for (const int clock : {ClockRealtime, ClockMonotonic}) { const int id = Create(clock); - Timespec now{}; + KernelTimespec now{}; Require(clock_gettime_nid_postfix(clock, &now) == 0); - const Itimerspec future{{0, 0}, {now.seconds + 5, now.nanoseconds}}; + const GuestItimerspec future{{0, 0}, {now.tv_sec + 5, now.tv_nsec}}; Require(ktimer_settime_nid_postfix(id, TimerAbstime, &future, nullptr) == 0); const auto remaining = Get(id); - Require(Nanoseconds(remaining.value) > 4 * Second && Nanoseconds(remaining.value) <= 5 * Second); + Require(Nanoseconds(remaining.it_value) > 4 * Second && Nanoseconds(remaining.it_value) <= 5 * Second); - const Itimerspec past{{0, 0}, {now.seconds - 1, now.nanoseconds}}; + const GuestItimerspec past{{0, 0}, {now.tv_sec - 1, now.tv_nsec}}; Require(ktimer_settime_nid_postfix(id, TimerAbstime, &past, nullptr) == 0); - Require(Nanoseconds(Get(id).value) == 0); - const Itimerspec pastPeriodic{{1, 0}, {now.seconds - 10, now.nanoseconds}}; + Require(Nanoseconds(Get(id).it_value) == 0); + const GuestItimerspec pastPeriodic{{1, 0}, {now.tv_sec - 10, now.tv_nsec}}; Require(ktimer_settime_nid_postfix(id, TimerAbstime, &pastPeriodic, nullptr) == 0); const auto moved = Get(id); - Require(Nanoseconds(moved.value) > 0 && Nanoseconds(moved.value) <= Second); - Require(Nanoseconds(moved.interval) == Second); + Require(Nanoseconds(moved.it_value) > 0 && Nanoseconds(moved.it_value) <= Second); + Require(Nanoseconds(moved.it_interval) == Second); Require(ktimer_delete_nid_postfix(id) == 0); } } diff --git a/core/libs/tests/GuestKernelSysModuleInternal.cpp b/core/libs/tests/GuestKernelSysModuleInternal.cpp index 0785445b57..2674a6ab3d 100644 --- a/core/libs/tests/GuestKernelSysModuleInternal.cpp +++ b/core/libs/tests/GuestKernelSysModuleInternal.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel_sys/include/Api.hpp" +#include "prx/libkernel/include/Api.hpp" #include "SceTypes.hpp" #include "prx/libkernel/KernelErrors.hpp" #include @@ -8,14 +10,6 @@ #include #include -extern "C" { -int APS5_VABI sceKernelGetModuleInfoInternal(KernelModule, ModuleInfoEx*); -int APS5_VABI sceKernelGetModuleListInternal(KernelModule*, std::size_t, std::size_t*); -int APS5_VABI sceKernelGetModuleList(KernelModule*, std::size_t, std::size_t*); -int APS5_VABI sceKernelGetModuleInfo(KernelModule, ModuleInfo*); -int APS5_VABI sceKernelGetModuleInfoFromAddr(std::uint64_t, int, ModuleInfoEx*); -} - static void Require(bool value) { if (!value) std::abort(); } static std::vector List(int (APS5_VABI* list)(KernelModule*, std::size_t, std::size_t*)) { diff --git a/core/libs/tests/GuestKernelSysPselect.cpp b/core/libs/tests/GuestKernelSysPselect.cpp index e3924a7f43..773ab2b80a 100644 --- a/core/libs/tests/GuestKernelSysPselect.cpp +++ b/core/libs/tests/GuestKernelSysPselect.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "SceTypes.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -8,15 +10,6 @@ #include #include -extern "C" { -int* APS5_VABI __error_nid_postfix(); -int APS5_VABI pipe_nid_postfix(int* descriptors); -int APS5_VABI close_nid_postfix(int descriptor); -std::int64_t APS5_VABI write_nid_postfix(int descriptor, const char* buffer, std::int64_t size); -int APS5_VABI sigprocmask_nid_postfix(int how, const void* set, void* previousSet); -int APS5_VABI pselect_nid_postfix(int nfds, void* readfds, void* writefds, void* exceptfds, const void* timeout, const void* sigmask); -} - namespace { constexpr int Einval = 22; diff --git a/core/libs/tests/GuestKernelSysPthread.cpp b/core/libs/tests/GuestKernelSysPthread.cpp index 9d352aa66c..1fbcc5054b 100644 --- a/core/libs/tests/GuestKernelSysPthread.cpp +++ b/core/libs/tests/GuestKernelSysPthread.cpp @@ -1,18 +1,10 @@ +#include "prx/libkernel/KernelErrors.hpp" +#include "prx/libkernel_sys/include/Api.hpp" +#include "prx/libkernel/include/Api.hpp" #include "SceTypes.hpp" #include "prx/libkernel/Pthread/include/Atfork.hpp" #include -extern "C" { -int APS5_VABI scePthreadAttrInit(PthreadAttr* attr); -int APS5_VABI scePthreadAttrDestroy(PthreadAttr* attr); -int APS5_VABI scePthreadAttrGetscope(const PthreadAttr* attr, int* scope); -int APS5_VABI scePthreadAttrSetscope(PthreadAttr* attr, int scope); -int APS5_VABI scePthreadAtfork(PthreadAtforkHandler prepare, PthreadAtforkHandler parent, PthreadAtforkHandler child); -int APS5_VABI scePthreadSetconcurrency(int level); -int APS5_VABI scePthreadGetconcurrency(); -} - -static constexpr int SCE_KERNEL_ERROR_EINVAL = static_cast(0x80020016); static constexpr int SCOPE_PROCESS = 0; static constexpr int SCOPE_SYSTEM = 2; diff --git a/core/libs/tests/GuestKernelSysSdkVersion.cpp b/core/libs/tests/GuestKernelSysSdkVersion.cpp index 5579fe7e5e..dc20a51ac8 100644 --- a/core/libs/tests/GuestKernelSysSdkVersion.cpp +++ b/core/libs/tests/GuestKernelSysSdkVersion.cpp @@ -1,3 +1,4 @@ +#include "prx/libkernel_sys/include/Api.hpp" #include "ProcessParametersFixture.hpp" #include "prx/libc/include/general/VabiMacros.hpp" @@ -8,8 +9,6 @@ #include #include -extern "C" int APS5_VABI sceKernelGetCompiledSdkVersion(std::int32_t* version); - namespace { alignas(16) std::array process{}; diff --git a/core/libs/tests/GuestKernelSysSwapcontext.cpp b/core/libs/tests/GuestKernelSysSwapcontext.cpp new file mode 100644 index 0000000000..1aa364e87e --- /dev/null +++ b/core/libs/tests/GuestKernelSysSwapcontext.cpp @@ -0,0 +1,172 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" +#include "prx/libSceLibcInternal/include/Api.hpp" +#include "prx/libc/include/general/AsmMacros.hpp" +#include "prx/libc/include/general/VabiMacros.hpp" +#include "prx/libkernel/System/include/UserContext.hpp" +#include +#include +#include +#include +#include + +using ContextEntry = void (APS5_VABI*)(); + +extern "C" { +int APS5_VABI SwapKeepingRegisters(UserUcontext* saved, const UserUcontext* next); +int APS5_VABI SwapClobberingRegisters(UserUcontext* saved, const UserUcontext* next); +} + +asm(".text\n" + APS5_ASM_FUNCTION("SwapKeepingRegisters") + " push %rbx\n" + " push %rbp\n" + " push %r12\n" + " push %r13\n" + " push %r14\n" + " push %r15\n" + " sub $8, %rsp\n" + " movabsq $0x1111111111111111, %rbx\n" + " movabsq $0x2222222222222222, %rbp\n" + " movabsq $0x3333333333333333, %r12\n" + " movabsq $0x4444444444444444, %r13\n" + " movabsq $0x5555555555555555, %r14\n" + " movabsq $0x6666666666666666, %r15\n" + " call " APS5_ASM_SYMBOL("swapcontext_nid_postfix") "\n" + " movabsq $0x1111111111111111, %rcx\n" + " cmp %rcx, %rbx\n" + " jne 1f\n" + " movabsq $0x2222222222222222, %rcx\n" + " cmp %rcx, %rbp\n" + " jne 1f\n" + " movabsq $0x3333333333333333, %rcx\n" + " cmp %rcx, %r12\n" + " jne 1f\n" + " movabsq $0x4444444444444444, %rcx\n" + " cmp %rcx, %r13\n" + " jne 1f\n" + " movabsq $0x5555555555555555, %rcx\n" + " cmp %rcx, %r14\n" + " jne 1f\n" + " movabsq $0x6666666666666666, %rcx\n" + " cmp %rcx, %r15\n" + " je 2f\n" + "1:\n" + " mov $-100, %eax\n" + "2:\n" + " add $8, %rsp\n" + " pop %r15\n" + " pop %r14\n" + " pop %r13\n" + " pop %r12\n" + " pop %rbp\n" + " pop %rbx\n" + " ret\n" + APS5_ASM_FUNCTION("SwapClobberingRegisters") + " push %rbx\n" + " push %rbp\n" + " push %r12\n" + " push %r13\n" + " push %r14\n" + " push %r15\n" + " sub $8, %rsp\n" + " movabsq $0x0badc0de0badc0de, %rbx\n" + " mov %rbx, %rbp\n" + " mov %rbx, %r12\n" + " mov %rbx, %r13\n" + " mov %rbx, %r14\n" + " mov %rbx, %r15\n" + " call " APS5_ASM_SYMBOL("swapcontext_nid_postfix") "\n" + " add $8, %rsp\n" + " pop %r15\n" + " pop %r14\n" + " pop %r13\n" + " pop %r12\n" + " pop %rbp\n" + " pop %rbx\n" + " ret\n"); + +namespace { + +constexpr int Einval = 22; +constexpr int SigBlock = 1; +constexpr int SigSetmask = 3; +constexpr int SigUsr1 = 30; +constexpr std::size_t StackBytes = 256 * 1024; + +struct alignas(16) Stack { + unsigned char bytes[StackBytes]; +}; + +Stack g_stack; +UserUcontext g_main = {}; +UserUcontext g_coroutine = {}; +int g_steps = 0; +bool g_coroutineSawBlocked = true; + +void Require(bool condition, std::source_location location = std::source_location::current()) { + if (condition) return; + std::fprintf(stderr, "check failed at line %u\n", static_cast(location.line())); + std::exit(1); +} + +int Error() { + return *__error_nid_postfix(); +} + +bool Usr1Blocked() { + std::uint32_t mask[4] = {}; + Require(sigprocmask_nid_postfix(SigBlock, nullptr, mask) == 0); + return (mask[0] & (1u << (SigUsr1 - 1))) != 0; +} + +void APS5_VABI Coroutine() { + g_coroutineSawBlocked = Usr1Blocked(); + for (int step = 0; step < 3; ++step) { + ++g_steps; + Require(SwapClobberingRegisters(&g_coroutine, &g_main) == 0); + } +} + +void Arguments() { + UserUcontext context = {}; + Require(getcontext_nid_postfix(&context) == 0); + Require(swapcontext_nid_postfix(nullptr, &context) == -1 && Error() == Einval); + Require(swapcontext_nid_postfix(&context, nullptr) == -1 && Error() == Einval); + + UserUcontext saved = {}; + UserUcontext invalid = context; + invalid.mcontext.len = 0; + Require(swapcontext_nid_postfix(&saved, &invalid) == -1 && Error() == Einval); + Require(saved.mcontext.len == sizeof(UserMcontext) && saved.mcontext.rip != 0); +} + +void PingPong() { + Require(getcontext_nid_postfix(&g_coroutine) == 0); + g_coroutine.stackPointer = g_stack.bytes; + g_coroutine.stackSize = sizeof(g_stack.bytes); + g_coroutine.link = &g_main; + makecontext_nid_postfix(&g_coroutine, &Coroutine, 0); + Require(g_coroutine.mcontext.len == sizeof(UserMcontext)); + + std::uint32_t block[4] = {1u << (SigUsr1 - 1), 0, 0, 0}; + std::uint32_t previous[4] = {}; + Require(sigprocmask_nid_postfix(SigBlock, block, previous) == 0); + for (int expected = 1; expected <= 3; ++expected) { + Require(SwapKeepingRegisters(&g_main, &g_coroutine) == 0); + Require(g_steps == expected && Usr1Blocked()); + } + Require(!g_coroutineSawBlocked); + Require(SwapKeepingRegisters(&g_main, &g_coroutine) == 0); + Require(g_steps == 3 && Usr1Blocked()); + Require(sigprocmask_nid_postfix(SigSetmask, previous, nullptr) == 0); +} + +} + +int main() { + Arguments(); + PingPong(); + std::puts("guest_kernel_sys_swapcontext passed"); + return 0; +} diff --git a/core/libs/tests/GuestKernelSysThreadDefaults.cpp b/core/libs/tests/GuestKernelSysThreadDefaults.cpp index 18a48b8f15..f38f272d56 100644 --- a/core/libs/tests/GuestKernelSysThreadDefaults.cpp +++ b/core/libs/tests/GuestKernelSysThreadDefaults.cpp @@ -1,23 +1,11 @@ +#include "prx/libkernel/KernelErrors.hpp" +#include "prx/libkernel_sys/include/Api.hpp" +#include "prx/libkernel/include/Api.hpp" #include "SceTypes.hpp" #include #include #include -extern "C" { -int APS5_VABI pthread_set_defaultstacksize_np_nid_postfix(std::size_t size); -int APS5_VABI scePthreadSetDefaultstacksize(std::size_t size); -void APS5_VABI scePthreadSetName(Pthread thread, const char* name); -int APS5_VABI scePthreadCreate(Pthread* thread, const PthreadAttr* attr, PthreadEntry entry, void* arg, const char* name); -int APS5_VABI scePthreadJoin(Pthread thread, void** retval); -Pthread APS5_VABI scePthreadSelf(void); -int APS5_VABI scePthreadGetname(Pthread thread, char* name); -int APS5_VABI scePthreadAttrInit(PthreadAttr* attr); -int APS5_VABI scePthreadAttrDestroy(PthreadAttr* attr); -int APS5_VABI scePthreadAttrGet(Pthread thread, PthreadAttr* attr); -int APS5_VABI scePthreadAttrGetstacksize(const PthreadAttr* attr, std::size_t* stackSize); -} - -static constexpr int SCE_KERNEL_ERROR_EINVAL = static_cast(0x80020016); static constexpr int POSIX_EINVAL = 22; static constexpr std::size_t INITIAL_DEFAULT = 1u << 20; @@ -70,9 +58,11 @@ static void CheckDefaultStackSize() { static void CheckSetName() { char name[32] = {}; scePthreadSetName(scePthreadSelf(), "renamed main"); + Require(scePthreadGetname(scePthreadSelf(), name) == 0); Require(std::strcmp(name, "renamed main") == 0); scePthreadSetName(scePthreadSelf(), nullptr); + Require(scePthreadGetname(scePthreadSelf(), name) == 0); Require(name[0] == '\0'); } diff --git a/core/libs/tests/GuestKernelSysThreads.cpp b/core/libs/tests/GuestKernelSysThreads.cpp new file mode 100644 index 0000000000..b15c2a7bb6 --- /dev/null +++ b/core/libs/tests/GuestKernelSysThreads.cpp @@ -0,0 +1,95 @@ +#include "prx/libc/include/general/VabiMacros.hpp" +#include "prx/libkernel/File/include/FileFlags.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef _WIN32 +#ifndef NOMINMAX +#define NOMINMAX +#endif +#include +#include +#else +#include +#endif + +static void Require(bool value, std::source_location location = std::source_location::current()) { + if (!value) { + std::fprintf(stderr, "Kernel sys API check failed at line %u\n", location.line()); + std::abort(); + } +} + +static void* LoadLibraryFile(const std::filesystem::path& path) { +#ifdef _WIN32 + auto* module = reinterpret_cast(LoadLibraryExW(path.c_str(), nullptr, LOAD_WITH_ALTERED_SEARCH_PATH)); +#else + auto* module = dlopen(path.c_str(), RTLD_NOW | RTLD_LOCAL); + if (!module) std::fprintf(stderr, "%s\n", dlerror()); +#endif + Require(module != nullptr); +#ifdef _WIN32 + std::wstring loaded(32768, L'\0'); + const auto length = GetModuleFileNameW(static_cast(module), loaded.data(), static_cast(loaded.size())); + Require(length != 0 && length < loaded.size()); + loaded.resize(length); + Require(std::filesystem::equivalent(path, std::filesystem::path(loaded))); +#endif + return module; +} + +template +static Function LoadFunction(void* module, const char* name, bool patched, const char* unpatched = nullptr) { + const auto symbol = patched ? Nid::ComputeNid(name, "") : unpatched ? std::string(unpatched) : std::string(name) + "_nid_postfix"; +#ifdef _WIN32 + const auto function = reinterpret_cast(reinterpret_cast(GetProcAddress(static_cast(module), symbol.c_str()))); +#else + const auto function = reinterpret_cast(dlsym(module, symbol.c_str())); +#endif + if (!function) std::fprintf(stderr, "Missing symbol %s\n", symbol.c_str()); + Require(function != nullptr); + return function; +} + + +int main(int argc, char** argv) { + Require(argc == 4); + const auto directory = std::filesystem::absolute(argv[1]); + const bool patched = std::strcmp(argv[2], "patched") == 0; + const std::string test = argv[3]; +#ifdef __linux__ + if (test == "main_late_load") { + int (APS5_VABI* isMain)() = nullptr; + int other = -1; + std::thread loader([&] { + auto* module = LoadLibraryFile(directory / "libkernel_sys.prx"); + isMain = LoadFunction(module, "pthread_main_np", patched); + other = isMain(); + }); + loader.join(); + Require(other == 0 && isMain() == 1); + return 0; + } +#endif + Require(test == "main"); + auto* sys = LoadLibraryFile(directory / "libkernel_sys.prx"); + LoadLibraryFile(directory / "libkernel.prx"); + auto* libc = LoadLibraryFile(directory / "libc.prx"); + const auto error = LoadFunction(libc, "__error", patched); + const auto isMain = LoadFunction(sys, "pthread_main_np", patched); + *error() = 71; + int other = -1; + std::thread worker([&] { other = isMain(); }); + worker.join(); + Require(other == 0 && isMain() == 1 && *error() == 71); + return 0; +} diff --git a/core/libs/tests/GuestKill.cpp b/core/libs/tests/GuestKill.cpp index 7b75694ea5..162e1b47ed 100644 --- a/core/libs/tests/GuestKill.cpp +++ b/core/libs/tests/GuestKill.cpp @@ -1,16 +1,12 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include #include #include using Handler = void (APS5_VABI *)(int); -extern "C" { -Handler APS5_VABI signal_nid_postfix(int, Handler); -int APS5_VABI kill_nid_postfix(int, int); -int APS5_VABI killpg_nid_postfix(int, int); -int APS5_VABI getpid_nid_postfix(void); -int* APS5_VABI __error_nid_postfix(); -} + volatile std::sig_atomic_t received = 0; void APS5_VABI Callback(int value) { received = value; } static void Require(bool value) { if (!value) std::abort(); } diff --git a/core/libs/tests/GuestKqueue.cpp b/core/libs/tests/GuestKqueue.cpp index 3289a4276a..12afea42a1 100644 --- a/core/libs/tests/GuestKqueue.cpp +++ b/core/libs/tests/GuestKqueue.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "SceTypes.hpp" #include #include @@ -22,33 +24,6 @@ #include #endif -extern "C" { -int APS5_VABI kqueue_nid_postfix(); -int APS5_VABI kevent_nid_postfix(int, const KernelEvent*, int, KernelEvent*, int, const KernelTimespec*); -int APS5_VABI close_nid_postfix(int); -int APS5_VABI dup_nid_postfix(int); -int APS5_VABI pipe_nid_postfix(int*); -int APS5_VABI fcntl_nid_postfix(int, int, ...); -int APS5_VABI socketpair_nid_postfix(int, int, int, int*); -std::int64_t APS5_VABI send_nid_postfix(int, const void*, std::uint64_t, int); -std::int64_t APS5_VABI recv_nid_postfix(int, void*, std::uint64_t, int); -std::int64_t APS5_VABI read_nid_postfix(int, void*, std::uint64_t); -int APS5_VABI open_nid_postfix(const char*, int, int); -int APS5_VABI mkdir_nid_postfix(const char*, unsigned short); -int APS5_VABI rmdir_nid_postfix(const char*); -std::int64_t APS5_VABI write_nid_postfix(int, const char*, std::int64_t); -int APS5_VABI ftruncate_nid_postfix(int, std::int64_t); -int APS5_VABI unlink_nid_postfix(const char*); -int APS5_VABI getpid_nid_postfix(void); -int APS5_VABI sceKernelRename(const char*, const char*); -int APS5_VABI sceKernelCreateEqueue(KernelEqueue* eq, const char* name); -int APS5_VABI sceKernelDeleteEqueue(KernelEqueue eq); -int APS5_VABI sceKernelWaitEqueue(KernelEqueue eq, KernelEvent* ev, int num, int* out, const KernelUseconds* timo); -int APS5_VABI sceKernelAddFileEvent(KernelEqueue eq, int fd, int watch, void* udata); -int APS5_VABI sceKernelDeleteFileEvent(KernelEqueue eq, int fd); -int* APS5_VABI __error_nid_postfix(); -} - static constexpr int GuestEperm = 1; static constexpr int GuestEnoent = 2; static constexpr int GuestEbadf = 9; @@ -1221,6 +1196,102 @@ static void DeniedParentWatch() { Require(std::filesystem::remove_all(path) == 2); } #endif + +#ifdef __linux__ +static std::size_t InotifyWatchCount() { + std::size_t count = 0; + std::error_code error; + for (const auto& entry : std::filesystem::directory_iterator("/proc/self/fd", error)) { + std::error_code linkError; + const auto target = std::filesystem::read_symlink(entry.path(), linkError); + if (!linkError && target.string().find("inotify") != std::string::npos) ++count; + } + return count; +} +#endif + +static void VnodeOneshotWatchStops() { + const auto path = TemporaryName("oneshot"); + const int file = open_nid_postfix(path.c_str(), ReadWrite | Create, 0644); + Require(file >= 0); + const int kq = kqueue_nid_postfix(); + int marker = 0; + KernelEvent events[4]{}; + const auto ident = static_cast(file); +#ifdef __linux__ + auto watchesBefore = InotifyWatchCount(); + for (int attempt = 0; attempt < 100; ++attempt) { + std::this_thread::sleep_for(std::chrono::milliseconds(20)); + const auto settled = InotifyWatchCount(); + if (settled == watchesBefore) break; + watchesBefore = settled; + } +#endif + Require(Apply(kq, Change(ident, EvfiltVnode, EvAdd | EvOneshot, NoteDelete | NoteWrite, 0, &marker)) == 0); + Require(write_nid_postfix(file, "abc", 3) == 3); + Require(Wait(kq, events, 4) == 1); + Require(events[0].ident == ident && events[0].filter == EvfiltVnode && (events[0].flags & EvOneshot) != 0 && events[0].udata == &marker); + Require(write_nid_postfix(file, "def", 3) == 3); + std::this_thread::sleep_for(std::chrono::milliseconds(300)); + Require(Poll(kq, events, 4) == 0); + RequireFailure(Apply(kq, Change(ident, EvfiltVnode, EvDelete)), GuestEnoent); +#ifdef __linux__ + for (int attempt = 0; attempt < 100 && InotifyWatchCount() > watchesBefore; ++attempt) std::this_thread::sleep_for(std::chrono::milliseconds(20)); + Require(InotifyWatchCount() <= watchesBefore); +#endif + Require(close_nid_postfix(file) == 0); + Require(close_nid_postfix(kq) == 0); + Require(std::filesystem::remove(path)); +} + +static void TimerDisableEnableRearm() { + const int kq = kqueue_nid_postfix(); + int marker = 0; + KernelEvent events[4]{}; + Require(Apply(kq, Change(1, EvfiltTimer, EvAdd, NoteUseconds, 50000, &marker)) == 0); + Require(Apply(kq, Change(1, EvfiltTimer, EvDisable, 0, 0, &marker)) == 0); + std::this_thread::sleep_for(std::chrono::milliseconds(150)); + Require(Apply(kq, Change(1, EvfiltTimer, EvEnable, 0, 0, &marker)) == 0); + Require(Wait(kq, events, 4) == 1); + Require(events[0].ident == 1 && events[0].filter == EvfiltTimer && events[0].udata == &marker); + Require(events[0].data >= 2 && events[0].data <= 6); + Require(Wait(kq, events, 4) == 1); + Require(events[0].data >= 1 && events[0].data <= 2); + Require(Throws([kq] { Apply(kq, Change(1, EvfiltTimer, EvAdd | EvEnable)); })); + Require(Apply(kq, Change(1, EvfiltTimer, EvDelete)) == 0); + Require(close_nid_postfix(kq) == 0); +} + +static void PeriodicTimerFiresTwice() { + const int kq = kqueue_nid_postfix(); + KernelEvent events[4]{}; + Require(Apply(kq, Change(1, EvfiltTimer, EvAdd, NoteUseconds, 50000)) == 0); + Require(Wait(kq, events, 4) == 1); + Require(Wait(kq, events, 4) == 1); + Require(Apply(kq, Change(1, EvfiltTimer, EvDelete)) == 0); + Require(close_nid_postfix(kq) == 0); +} + +#ifdef _WIN32 +static void RecycleBinDeleteWatchedFile() { + const auto directory = TemporaryName("deleted"); + std::filesystem::create_directories(directory + "\\$Extend\\$Deleted"); + const auto path = directory + "\\watched"; + const int file = open_nid_postfix(path.c_str(), ReadWrite | Create, 0644); + Require(file >= 0); + const int kq = kqueue_nid_postfix(); + KernelEvent events[4]{}; + const auto ident = static_cast(file); + Require(Apply(kq, Change(ident, EvfiltVnode, EvAdd | EvClear, NoteDelete | NoteRename)) == 0); + Require(sceKernelRename(path.c_str(), (directory + "\\$Extend\\$Deleted\\moved").c_str()) == SceOk); + std::this_thread::sleep_for(std::chrono::milliseconds(300)); + Require(Poll(kq, events, 4) == 1 && events[0].ident == ident && (events[0].fflags & NoteDelete) != 0); + Require(close_nid_postfix(file) == 0); + Require(close_nid_postfix(kq) == 0); + std::filesystem::remove_all(directory); +} +#endif + static void Timeout() { const int kq = kqueue_nid_postfix(); KernelEvent event{}; @@ -1271,7 +1342,6 @@ static void StandardInputReplacement() { Require(StandardInputAtEnd()); } - static void StandardInput() { ReplaceStandardInputWithNull(); const int copy = dup_nid_postfix(0); @@ -1322,6 +1392,12 @@ int main() { FileWatch(); #ifndef _WIN32 RenameAndDeleteWatchedFile(); + VnodeOneshotWatchStops(); + PeriodicTimerFiresTwice(); + TimerDisableEnableRearm(); +#endif +#ifdef _WIN32 + RecycleBinDeleteWatchedFile(); #endif #if !defined(_WIN32) && !defined(__APPLE__) MoveDirectoryEntries(); diff --git a/core/libs/tests/GuestLibcCndInitDefaultName.cpp b/core/libs/tests/GuestLibcCndInitDefaultName.cpp index 6d5d046398..582215e686 100644 --- a/core/libs/tests/GuestLibcCndInitDefaultName.cpp +++ b/core/libs/tests/GuestLibcCndInitDefaultName.cpp @@ -1,13 +1,8 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include -extern "C" { -int APS5_VABI _Cnd_init_with_default_name_override_nid_postfix(void** handle, const char* name); -void APS5_VABI _Cnd_destroy_nid_postfix(void** handle); -int APS5_VABI _Cnd_signal_nid_postfix(void** handle); -} - static void Require(bool value) { if (!value) std::abort(); } template @@ -28,6 +23,7 @@ int main() { Require(condition != nullptr); Require(_Cnd_signal_nid_postfix(&condition) == success); _Cnd_destroy_nid_postfix(&condition); + Require(condition == nullptr); void* unnamed = nullptr; @@ -37,6 +33,7 @@ int main() { RequireThrows([] { _Cnd_init_with_default_name_override_nid_postfix(nullptr, "NullHandle"); + }); return 0; } diff --git a/core/libs/tests/GuestLibcCndTimedWait.cpp b/core/libs/tests/GuestLibcCndTimedWait.cpp index e85144f158..da073cf4f1 100644 --- a/core/libs/tests/GuestLibcCndTimedWait.cpp +++ b/core/libs/tests/GuestLibcCndTimedWait.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -14,23 +15,6 @@ #include #endif -struct Xtime { - std::int64_t sec; - std::int64_t nsec; -}; - -extern "C" { -int APS5_VABI _Mtx_init_nid_postfix(void** handle, int type); -void APS5_VABI _Mtx_destroy_nid_postfix(void** handle); -int APS5_VABI _Mtx_lock_nid_postfix(void** handle); -int APS5_VABI _Mtx_unlock_nid_postfix(void** handle); -int APS5_VABI _Cnd_init_nid_postfix(void** handle); -void APS5_VABI _Cnd_destroy_nid_postfix(void** handle); -int APS5_VABI _Cnd_wait_nid_postfix(void** condition, void** mutex); -int APS5_VABI _Cnd_broadcast_nid_postfix(void** handle); -int APS5_VABI _Cnd_timedwait_nid_postfix(void** condition, void** mutex, const Xtime* target); -} - static void Require(bool value) { if (!value) std::abort(); } #ifdef _WIN32 @@ -181,4 +165,5 @@ int main() { RequireThrows([&] { _Cnd_timedwait_nid_postfix(&condition, &mutex, &overflowSecTime); }); _Cnd_destroy_nid_postfix(&condition); _Mtx_destroy_nid_postfix(&mutex); + } diff --git a/core/libs/tests/GuestLibcFilesystem.cpp b/core/libs/tests/GuestLibcFilesystem.cpp index 903fc8b603..fe53b7ff63 100644 --- a/core/libs/tests/GuestLibcFilesystem.cpp +++ b/core/libs/tests/GuestLibcFilesystem.cpp @@ -1,3 +1,6 @@ +#include "prx/libSceLibcInternal/include/Api.hpp" +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "SceTypes.hpp" #include #include @@ -10,23 +13,6 @@ #include #include -extern "C" { -int APS5_VABI _ZNSt10filesystem5_StatEPKcPNS_5permsEPi_nid_postfix(const char* path, int* perms, int* error); -int APS5_VABI _ZNSt10filesystem6_LstatEPKcPNS_5permsEPi_nid_postfix(const char* path, int* perms, int* error); -std::uint64_t APS5_VABI _ZNSt10filesystem10_File_sizeEPKcPi_nid_postfix(const char* path, int* error); -int APS5_VABI _ZNSt10filesystem16_Last_write_timeEPKcPlS2__nid_postfix(const char* path, std::int64_t* seconds, std::int64_t* nanoseconds); -int APS5_VABI _ZNSt10filesystem9_Make_dirEPKcS1__nid_postfix(const char* path, const char* existing); -bool APS5_VABI _ZNSt10filesystem11_Remove_dirEPKc_nid_postfix(const char* path); -int APS5_VABI _ZNSt10filesystem7_UnlinkEPKc_nid_postfix(const char* path); -int APS5_VABI _ZNSt10filesystem6_ChmodEPKcNS_5permsE_nid_postfix(const char* path, int perms); -bool APS5_VABI _ZNSt10filesystem12_Current_getERA260_c_nid_postfix(char* target); -void* APS5_VABI _ZNSt10filesystem9_Open_dirERA260_cPKcRiRNS_9file_typeE_nid_postfix(char* target, const char* path, int* error, int* type); -char* APS5_VABI _ZNSt10filesystem9_Read_dirERA260_cPvRNS_9file_typeE_nid_postfix(char* target, void* handle, int* type); -int APS5_VABI _ZNSt10filesystem10_Close_dirEPv_nid_postfix(void* handle); -int APS5_VABI stat_nid_postfix(const char* path, FileStat* sb); -char* APS5_VABI getcwd_nid_postfix(char* buffer, std::size_t size); -} - namespace { constexpr int NoSuchFile = 2; diff --git a/core/libs/tests/GuestLibcMutexInitWithName.cpp b/core/libs/tests/GuestLibcMutexInitWithName.cpp index 2501aef36b..a3faa64d90 100644 --- a/core/libs/tests/GuestLibcMutexInitWithName.cpp +++ b/core/libs/tests/GuestLibcMutexInitWithName.cpp @@ -1,14 +1,8 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include -extern "C" { -int APS5_VABI _Mtx_init_with_name_nid_postfix(void** handle, int type, const char* name); -void APS5_VABI _Mtx_destroy_nid_postfix(void** handle); -int APS5_VABI _Mtx_lock_nid_postfix(void** handle); -int APS5_VABI _Mtx_unlock_nid_postfix(void** handle); -} - static void Require(bool value) { if (!value) std::abort(); } template @@ -33,9 +27,11 @@ int main() { Require(_Mtx_lock_nid_postfix(&mutex) == busy); Require(_Mtx_unlock_nid_postfix(&mutex) == success); _Mtx_destroy_nid_postfix(&mutex); + Require(mutex == nullptr); RequireThrows([] { _Mtx_init_with_name_nid_postfix(nullptr, plain, "NullHandle"); + }); } diff --git a/core/libs/tests/GuestLibcRandomSeeding.cpp b/core/libs/tests/GuestLibcRandomSeeding.cpp index 0e1ed63a76..33e46f6781 100644 --- a/core/libs/tests/GuestLibcRandomSeeding.cpp +++ b/core/libs/tests/GuestLibcRandomSeeding.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -7,13 +8,6 @@ #include #include -extern "C" { -std::int64_t APS5_VABI random_nid_postfix(); -void APS5_VABI srandom_nid_postfix(std::uint64_t); -char* APS5_VABI initstate_nid_postfix(std::uint64_t, char*, std::int64_t); -char* APS5_VABI setstate_nid_postfix(char*); -} - static int failures = 0; static void Require(bool condition, const char* message) { diff --git a/core/libs/tests/GuestLibcStaticImports.cpp b/core/libs/tests/GuestLibcStaticImports.cpp index a8068575dd..ff0cc2a7fc 100644 --- a/core/libs/tests/GuestLibcStaticImports.cpp +++ b/core/libs/tests/GuestLibcStaticImports.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -8,21 +9,6 @@ #include #include -struct Xtime { - std::int64_t sec; - std::int64_t nsec; -}; - -extern "C" { -float APS5_VABI nearbyintf_nid_postfix(float x); -int APS5_VABI _Mtx_init_nid_postfix(void** handle, int type); -void APS5_VABI _Mtx_destroy_nid_postfix(void** handle); -int APS5_VABI _Mtx_lock_nid_postfix(void** handle); -int APS5_VABI _Mtx_unlock_nid_postfix(void** handle); -int APS5_VABI _Mtx_trylock_nid_postfix(void** handle); -int APS5_VABI _Thrd_sleep_nid_postfix(const Xtime* target, Xtime* remaining); -} - namespace { void Require(bool value) { @@ -156,6 +142,7 @@ void TestThrdSleep() { RequireThrows([] { _Thrd_sleep_nid_postfix(nullptr, nullptr); + }); } diff --git a/core/libs/tests/GuestLibcThreads.cpp b/core/libs/tests/GuestLibcThreads.cpp index 7536f444aa..1d2b3d7dff 100644 --- a/core/libs/tests/GuestLibcThreads.cpp +++ b/core/libs/tests/GuestLibcThreads.cpp @@ -1,3 +1,7 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libkernel/Pthread/include/Mutex.hpp" +#include "prx/libkernel/Pthread/include/Cond.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -8,73 +12,7 @@ #include extern "C" { -int APS5_VABI _Mtx_init_nid_postfix(void** handle, int type); -void APS5_VABI _Mtx_destroy_nid_postfix(void** handle); -int APS5_VABI _Mtx_lock_nid_postfix(void** handle); -int APS5_VABI _Mtx_unlock_nid_postfix(void** handle); -int APS5_VABI _Cnd_init_nid_postfix(void** handle); -void APS5_VABI _Cnd_destroy_nid_postfix(void** handle); -int APS5_VABI _Cnd_wait_nid_postfix(void** condition, void** mutex); -int APS5_VABI _Cnd_broadcast_nid_postfix(void** handle); -int APS5_VABI _Cnd_signal_nid_postfix(void** handle); -struct GuestPad { - unsigned (APS5_VABI* const* vtable)(GuestPad*); - void* condition; - void* mutex; - bool started; -}; - -void APS5_VABI _ZNSt4_PadC2Ev_nid_postfix(GuestPad* pad); -void APS5_VABI _ZNSt4_PadD2Ev_nid_postfix(GuestPad* pad); -void APS5_VABI _ZNSt4_Pad8_ReleaseEv_nid_postfix(GuestPad* pad); -void APS5_VABI _ZNSt4_Pad7_LaunchEPP7pthread_nid_postfix(GuestPad* pad, void** thread); -int APS5_VABI _Thrd_join_nid_postfix(void* thread, int* code); -int APS5_VABI _Thrd_detach_nid_postfix(void* thread); -void RegisterPthreadCreate_nid_no_patch(int (APS5_VABI* fn)(void**, const void*, void* (APS5_VABI*)(void*), void*)); -void RegisterPthreadJoin_nid_no_patch(int (APS5_VABI* fn)(void*, void**)); -void RegisterPthreadDetach_nid_no_patch(int (APS5_VABI* fn)(void*)); - -struct ThreadForwards { - int (APS5_VABI* once)(std::int32_t*, void (APS5_VABI*)(void)); - int (APS5_VABI* keyCreate)(int*, void (APS5_VABI*)(void*)); - int (APS5_VABI* keyDelete)(int); - void* (APS5_VABI* getSpecific)(int); - int (APS5_VABI* setSpecific)(int, void*); - int (APS5_VABI* equal)(void*, void*); - void* (APS5_VABI* self)(); - void (APS5_VABI* exit)(void*); -}; -void RegisterThreadForwards_nid_no_patch(const ThreadForwards* forwards); -void APS5_VABI _Call_once_nid_postfix(std::int32_t* flag, void (APS5_VABI* function)(void)); -int APS5_VABI _Tss_create_nid_postfix(int* key, void (APS5_VABI* destructor)(void*)); -int APS5_VABI _Tss_delete_nid_postfix(int key); -void* APS5_VABI _Tss_get_nid_postfix(int key); -int APS5_VABI _Tss_set_nid_postfix(int key, void* value); -int APS5_VABI _Thrd_equal_nid_postfix(void* first, void* second); -void* APS5_VABI _Thrd_current_nid_postfix(void); -int APS5_VABI _Mtx_current_owns_nid_postfix(void** handle); -int APS5_VABI _ZNSt8__sce_v29_Mtx_initEPP13pthread_mutexi_nid_postfix(void** mutex, int type); -int APS5_VABI _ZNSt8__sce_v219_Mtx_init_with_nameEPP13pthread_mutexiPKc_nid_postfix(void** mutex, int type, const char* name); -int APS5_VABI _ZNSt8__sce_v212_Mtx_destroyEPP13pthread_mutex_nid_postfix(void** mutex); -int APS5_VABI _ZNSt8__sce_v29_Mtx_lockEPP13pthread_mutex_nid_postfix(void** mutex); -int APS5_VABI _ZNSt8__sce_v212_Mtx_trylockEPP13pthread_mutex_nid_postfix(void** mutex); -int APS5_VABI _ZNSt8__sce_v211_Mtx_unlockEPP13pthread_mutex_nid_postfix(void** mutex); -int APS5_VABI _ZNSt8__sce_v29_Cnd_initEPP12pthread_cond_nid_postfix(void** condition); -int APS5_VABI _ZNSt8__sce_v219_Cnd_init_with_nameEPP12pthread_condPKc_nid_postfix(void** condition, const char* name); -int APS5_VABI _ZNSt8__sce_v212_Cnd_destroyEPP12pthread_cond_nid_postfix(void** condition); -int APS5_VABI _ZNSt8__sce_v29_Cnd_waitEPP12pthread_condPP13pthread_mutex_nid_postfix(void** condition, void** mutex); -int APS5_VABI _ZNSt8__sce_v211_Cnd_signalEPP12pthread_cond_nid_postfix(void** condition); -int APS5_VABI _ZNSt8__sce_v214_Cnd_broadcastEPP12pthread_cond_nid_postfix(void** condition); -int APS5_VABI _ZNSt8__sce_v212_Thrd_detachEP7pthread_nid_postfix(void* thread); -int APS5_VABI _ZNSt8__sce_v210_Thrd_joinEP7pthreadPi_nid_postfix(void* thread, int* code); -void APS5_VABI _ZNSt8__sce_v211_Thrd_yieldEv_nid_postfix(); -void* APS5_VABI _ZNSt8__sce_v28_Thrd_idEv_nid_postfix(); -int APS5_VABI scePthreadCreate(void** thread, const void* attr, void* (APS5_VABI* entry)(void*), void* argument, const char* name); -int APS5_VABI scePthreadMutexUnlock(void** mutex); -int APS5_VABI scePthreadCondWait(void** condition, void** mutex); -void* APS5_VABI scePthreadSelf(); -int APS5_VABI _Thrd_yield_nid_postfix(); } static void Require(bool value) { if (!value) std::abort(); } @@ -118,10 +56,12 @@ static void MutexBasics() { RequireThrows([&] { _Mtx_lock_nid_postfix(&foreignMutex); }); _Cnd_destroy_nid_postfix(&foreignCondition); _Mtx_destroy_nid_postfix(&mutex); + Require(mutex == nullptr); RequireThrows([&] { _Mtx_lock_nid_postfix(&mutex); }); void* emptyMutex = nullptr; _Mtx_destroy_nid_postfix(&emptyMutex); + RequireThrows([] { _Mtx_destroy_nid_postfix(nullptr); }); void* plainMutex = CreateMutex(plain); @@ -139,11 +79,13 @@ static void MutexBasics() { Require(_Mtx_lock_nid_postfix(&defaultMutex) == success && _Mtx_lock_nid_postfix(&defaultMutex) == busy); Require(_Mtx_unlock_nid_postfix(&defaultMutex) == success); _Mtx_destroy_nid_postfix(&defaultMutex); + void* unknownBitsMutex = nullptr; Require(_Mtx_init_nid_postfix(&unknownBitsMutex, tryable | 0x8) == success && unknownBitsMutex != nullptr); Require(_Mtx_lock_nid_postfix(&unknownBitsMutex) == success && _Mtx_lock_nid_postfix(&unknownBitsMutex) == busy); Require(_Mtx_unlock_nid_postfix(&unknownBitsMutex) == success); _Mtx_destroy_nid_postfix(&unknownBitsMutex); + RequireThrows([] { _Mtx_init_nid_postfix(nullptr, tryable); }); RequireThrows([] { _Mtx_lock_nid_postfix(nullptr); }); RequireThrows([] { _Mtx_unlock_nid_postfix(nullptr); }); @@ -165,6 +107,7 @@ static void RecursiveMutex() { other.join(); Require(acquired); _Mtx_destroy_nid_postfix(&mutex); + } static void MutualExclusion() { @@ -181,6 +124,7 @@ static void MutualExclusion() { for (auto& worker : workers) worker.join(); Require(counter == 80000); _Mtx_destroy_nid_postfix(&mutex); + } static void ConditionBroadcast() { @@ -226,12 +170,15 @@ static void ConditionBroadcast() { RequireThrows([] { _Cnd_broadcast_nid_postfix(nullptr); }); RequireThrows([] { _Cnd_init_nid_postfix(nullptr); }); _Cnd_destroy_nid_postfix(&condition); + Require(condition == nullptr); RequireThrows([&] { _Cnd_broadcast_nid_postfix(&condition); }); void* emptyCondition = nullptr; _Cnd_destroy_nid_postfix(&emptyCondition); + RequireThrows([] { _Cnd_destroy_nid_postfix(nullptr); }); _Mtx_destroy_nid_postfix(&mutex); + } static void ConditionSignal() { @@ -239,6 +186,7 @@ static void ConditionSignal() { Require(_Cnd_init_nid_postfix(&condition) == success); Require(_Cnd_signal_nid_postfix(&condition) == success); _Cnd_destroy_nid_postfix(&condition); + } struct TestPad { @@ -280,6 +228,7 @@ static unsigned APS5_VABI TestPadGo(GuestPad* base) { auto* pad = reinterpret_cast(base); pad->ran.store(true); _ZNSt4_Pad8_ReleaseEv_nid_postfix(base); + return 42; } @@ -288,15 +237,18 @@ static void PadLaunchAndJoin() { TestPad unregPad{}; unregPad.vtable = vtable; _ZNSt4_PadC2Ev_nid_postfix(reinterpret_cast(&unregPad)); + RegisterPthreadCreate_nid_no_patch(nullptr); RegisterPthreadJoin_nid_no_patch(nullptr); void* unregThread = nullptr; RequireThrows([&] { _ZNSt4_Pad7_LaunchEPP7pthread_nid_postfix(reinterpret_cast(&unregPad), &unregThread); + }); RequireThrows([&] { int code = 0; _Thrd_join_nid_postfix(&unregPad, &code); + }); _ZNSt4_PadD2Ev_nid_postfix(reinterpret_cast(&unregPad)); @@ -306,10 +258,13 @@ static void PadLaunchAndJoin() { TestPad pad{}; pad.vtable = vtable; _ZNSt4_PadC2Ev_nid_postfix(reinterpret_cast(&pad)); + void* thread = nullptr; _ZNSt4_Pad7_LaunchEPP7pthread_nid_postfix(reinterpret_cast(&pad), &thread); + Require(thread != nullptr && pad.started && pad.ran.load()); _ZNSt4_PadD2Ev_nid_postfix(reinterpret_cast(&pad)); + int code = 0; Require(_Thrd_join_nid_postfix(thread, &code) == success && code == 42); Require(_Thrd_join_nid_postfix(nullptr, &code) == 4); @@ -329,10 +284,13 @@ static void PadDetach() { TestPad pad{}; pad.vtable = vtable; _ZNSt4_PadC2Ev_nid_postfix(reinterpret_cast(&pad)); + void* thread = nullptr; _ZNSt4_Pad7_LaunchEPP7pthread_nid_postfix(reinterpret_cast(&pad), &thread); + Require(thread != nullptr && pad.ran.load()); _ZNSt4_PadD2Ev_nid_postfix(reinterpret_cast(&pad)); + Require(_Thrd_detach_nid_postfix(thread) == success); Require(_Thrd_detach_nid_postfix(nullptr) == 4); @@ -375,10 +333,11 @@ static void APS5_VABI FakeExit(void*) { std::abort(); } static void APS5_VABI OnceTarget() {} static void ForwardedCalls() { - static const ThreadForwards fakes{FakeOnce, FakeKeyCreate, FakeKeyDelete, FakeGetSpecific, FakeSetSpecific, FakeEqual, FakeSelf, FakeExit}; + static const ThreadForwards_nid_no_patch fakes{FakeOnce, FakeKeyCreate, FakeKeyDelete, FakeGetSpecific, FakeSetSpecific, FakeEqual, FakeSelf, FakeExit}; RegisterThreadForwards_nid_no_patch(&fakes); std::int32_t flag = 0; _Call_once_nid_postfix(&flag, OnceTarget); + Require(forwardLog.flag == &flag && forwardLog.function == OnceTarget); int key = 0; Require(_Tss_create_nid_postfix(&key, nullptr) == static_cast(0x80020016) && key == 41); @@ -395,74 +354,75 @@ static void ForwardedCalls() { } struct VersionedShared { - void* mutex = nullptr; - void* condition = nullptr; + PthreadMutex mutex = nullptr; + PthreadCond condition = nullptr; std::atomic stage{0}; int tryResult = -1; }; static void* APS5_VABI VersionedWorker(void* argument) { auto* shared = static_cast(argument); - shared->tryResult = _ZNSt8__sce_v212_Mtx_trylockEPP13pthread_mutex_nid_postfix(&shared->mutex); + shared->tryResult = _ZNSt8__sce_v212_Mtx_trylockEPP13pthread_mutex_nid_postfix(reinterpret_cast(&shared->mutex)); shared->stage = 1; - Require(_ZNSt8__sce_v29_Mtx_lockEPP13pthread_mutex_nid_postfix(&shared->mutex) == success); + Require(_ZNSt8__sce_v29_Mtx_lockEPP13pthread_mutex_nid_postfix(reinterpret_cast(&shared->mutex)) == success); shared->stage = 2; - Require(_ZNSt8__sce_v211_Cnd_signalEPP12pthread_cond_nid_postfix(&shared->condition) == success); - Require(_ZNSt8__sce_v211_Mtx_unlockEPP13pthread_mutex_nid_postfix(&shared->mutex) == success); + Require(_ZNSt8__sce_v211_Cnd_signalEPP12pthread_cond_nid_postfix(reinterpret_cast(&shared->condition)) == success); + Require(_ZNSt8__sce_v211_Mtx_unlockEPP13pthread_mutex_nid_postfix(reinterpret_cast(&shared->mutex)) == success); return reinterpret_cast(std::intptr_t{42}); } static void* APS5_VABI DetachedWorker(void*) { return nullptr; } static void VersionedSync() { - void* recursiveMutex = reinterpret_cast(std::uintptr_t{1}); - Require(_ZNSt8__sce_v29_Mtx_initEPP13pthread_mutexi_nid_postfix(&recursiveMutex, plain | recursive) == success && recursiveMutex != nullptr); - Require(_ZNSt8__sce_v29_Mtx_lockEPP13pthread_mutex_nid_postfix(&recursiveMutex) == success); - Require(_ZNSt8__sce_v29_Mtx_lockEPP13pthread_mutex_nid_postfix(&recursiveMutex) == success); - Require(_ZNSt8__sce_v212_Mtx_trylockEPP13pthread_mutex_nid_postfix(&recursiveMutex) == success); - for (int unlock = 0; unlock < 3; ++unlock) Require(_ZNSt8__sce_v211_Mtx_unlockEPP13pthread_mutex_nid_postfix(&recursiveMutex) == success); - Require(_ZNSt8__sce_v212_Mtx_destroyEPP13pthread_mutex_nid_postfix(&recursiveMutex) == success); + PthreadMutex recursiveMutex = reinterpret_cast(std::uintptr_t{1}); + Require(_ZNSt8__sce_v29_Mtx_initEPP13pthread_mutexi_nid_postfix(reinterpret_cast(&recursiveMutex), plain | recursive) == success && recursiveMutex != nullptr); + Require(_ZNSt8__sce_v29_Mtx_lockEPP13pthread_mutex_nid_postfix(reinterpret_cast(&recursiveMutex)) == success); + Require(_ZNSt8__sce_v29_Mtx_lockEPP13pthread_mutex_nid_postfix(reinterpret_cast(&recursiveMutex)) == success); + Require(_ZNSt8__sce_v212_Mtx_trylockEPP13pthread_mutex_nid_postfix(reinterpret_cast(&recursiveMutex)) == success); + for (int unlock = 0; unlock < 3; ++unlock) Require(_ZNSt8__sce_v211_Mtx_unlockEPP13pthread_mutex_nid_postfix(reinterpret_cast(&recursiveMutex)) == success); + Require(_ZNSt8__sce_v212_Mtx_destroyEPP13pthread_mutex_nid_postfix(reinterpret_cast(&recursiveMutex)) == success); - void* plainMutex = nullptr; - Require(_ZNSt8__sce_v219_Mtx_init_with_nameEPP13pthread_mutexiPKc_nid_postfix(&plainMutex, plain, "") == success); - Require(_ZNSt8__sce_v29_Mtx_lockEPP13pthread_mutex_nid_postfix(&plainMutex) == success); - Require(_ZNSt8__sce_v29_Mtx_lockEPP13pthread_mutex_nid_postfix(&plainMutex) == busy); - Require(_ZNSt8__sce_v211_Mtx_unlockEPP13pthread_mutex_nid_postfix(&plainMutex) == success); - void* unownedCondition = nullptr; - Require(_ZNSt8__sce_v29_Cnd_initEPP12pthread_cond_nid_postfix(&unownedCondition) == success); + PthreadMutex plainMutex = nullptr; + Require(_ZNSt8__sce_v219_Mtx_init_with_nameEPP13pthread_mutexiPKc_nid_postfix(reinterpret_cast(&plainMutex), plain, "") == success); + Require(_ZNSt8__sce_v29_Mtx_lockEPP13pthread_mutex_nid_postfix(reinterpret_cast(&plainMutex)) == success); + Require(_ZNSt8__sce_v29_Mtx_lockEPP13pthread_mutex_nid_postfix(reinterpret_cast(&plainMutex)) == busy); + Require(_ZNSt8__sce_v211_Mtx_unlockEPP13pthread_mutex_nid_postfix(reinterpret_cast(&plainMutex)) == success); + PthreadCond unownedCondition = nullptr; + Require(_ZNSt8__sce_v29_Cnd_initEPP12pthread_cond_nid_postfix(reinterpret_cast(&unownedCondition)) == success); Require(scePthreadMutexUnlock(&plainMutex) != 0); Require(scePthreadCondWait(&unownedCondition, &plainMutex) != 0); - Require(_ZNSt8__sce_v211_Mtx_unlockEPP13pthread_mutex_nid_postfix(&plainMutex) == success); - Require(_ZNSt8__sce_v29_Cnd_waitEPP12pthread_condPP13pthread_mutex_nid_postfix(&unownedCondition, &plainMutex) == success); - Require(_ZNSt8__sce_v212_Cnd_destroyEPP12pthread_cond_nid_postfix(&unownedCondition) == success); - Require(_ZNSt8__sce_v212_Mtx_destroyEPP13pthread_mutex_nid_postfix(&plainMutex) == success); + Require(_ZNSt8__sce_v211_Mtx_unlockEPP13pthread_mutex_nid_postfix(reinterpret_cast(&plainMutex)) == success); + Require(_ZNSt8__sce_v29_Cnd_waitEPP12pthread_condPP13pthread_mutex_nid_postfix(reinterpret_cast(&unownedCondition), reinterpret_cast(&plainMutex)) == success); + Require(_ZNSt8__sce_v212_Cnd_destroyEPP12pthread_cond_nid_postfix(reinterpret_cast(&unownedCondition)) == success); + Require(_ZNSt8__sce_v212_Mtx_destroyEPP13pthread_mutex_nid_postfix(reinterpret_cast(&plainMutex)) == success); VersionedShared shared; - Require(_ZNSt8__sce_v29_Mtx_initEPP13pthread_mutexi_nid_postfix(&shared.mutex, plain) == success); - Require(_ZNSt8__sce_v219_Cnd_init_with_nameEPP12pthread_condPKc_nid_postfix(&shared.condition, "versioned") == success); - Require(_ZNSt8__sce_v29_Mtx_lockEPP13pthread_mutex_nid_postfix(&shared.mutex) == success); - void* thread = nullptr; + Require(_ZNSt8__sce_v29_Mtx_initEPP13pthread_mutexi_nid_postfix(reinterpret_cast(&shared.mutex), plain) == success); + Require(_ZNSt8__sce_v219_Cnd_init_with_nameEPP12pthread_condPKc_nid_postfix(reinterpret_cast(&shared.condition), "versioned") == success); + Require(_ZNSt8__sce_v29_Mtx_lockEPP13pthread_mutex_nid_postfix(reinterpret_cast(&shared.mutex)) == success); + Pthread thread = nullptr; Require(scePthreadCreate(&thread, nullptr, VersionedWorker, &shared, "versioned") == 0); while (shared.stage.load() == 0) std::this_thread::yield(); - while (shared.stage.load() == 1) Require(_ZNSt8__sce_v29_Cnd_waitEPP12pthread_condPP13pthread_mutex_nid_postfix(&shared.condition, &shared.mutex) == success); + while (shared.stage.load() == 1) Require(_ZNSt8__sce_v29_Cnd_waitEPP12pthread_condPP13pthread_mutex_nid_postfix(reinterpret_cast(&shared.condition), reinterpret_cast(&shared.mutex)) == success); Require(shared.tryResult == busy); - Require(_ZNSt8__sce_v211_Mtx_unlockEPP13pthread_mutex_nid_postfix(&shared.mutex) == success); + Require(_ZNSt8__sce_v211_Mtx_unlockEPP13pthread_mutex_nid_postfix(reinterpret_cast(&shared.mutex)) == success); int code = 0; Require(_ZNSt8__sce_v210_Thrd_joinEP7pthreadPi_nid_postfix(thread, &code) == success && code == 42); Require(_ZNSt8__sce_v210_Thrd_joinEP7pthreadPi_nid_postfix(thread, &code) == 4); - Require(_ZNSt8__sce_v214_Cnd_broadcastEPP12pthread_cond_nid_postfix(&shared.condition) == success); - Require(_ZNSt8__sce_v212_Cnd_destroyEPP12pthread_cond_nid_postfix(&shared.condition) == success); - Require(_ZNSt8__sce_v212_Mtx_destroyEPP13pthread_mutex_nid_postfix(&shared.mutex) == success); + Require(_ZNSt8__sce_v214_Cnd_broadcastEPP12pthread_cond_nid_postfix(reinterpret_cast(&shared.condition)) == success); + Require(_ZNSt8__sce_v212_Cnd_destroyEPP12pthread_cond_nid_postfix(reinterpret_cast(&shared.condition)) == success); + Require(_ZNSt8__sce_v212_Mtx_destroyEPP13pthread_mutex_nid_postfix(reinterpret_cast(&shared.mutex)) == success); - void* condition = nullptr; - Require(_ZNSt8__sce_v29_Cnd_initEPP12pthread_cond_nid_postfix(&condition) == success); - Require(_ZNSt8__sce_v212_Cnd_destroyEPP12pthread_cond_nid_postfix(&condition) == success); + PthreadCond condition = nullptr; + Require(_ZNSt8__sce_v29_Cnd_initEPP12pthread_cond_nid_postfix(reinterpret_cast(&condition)) == success); + Require(_ZNSt8__sce_v212_Cnd_destroyEPP12pthread_cond_nid_postfix(reinterpret_cast(&condition)) == success); - void* detached = nullptr; + Pthread detached = nullptr; Require(scePthreadCreate(&detached, nullptr, DetachedWorker, nullptr, "detached") == 0); Require(_ZNSt8__sce_v212_Thrd_detachEP7pthread_nid_postfix(detached) == success); Require(_ZNSt8__sce_v212_Thrd_detachEP7pthread_nid_postfix(nullptr) == 4); _ZNSt8__sce_v211_Thrd_yieldEv_nid_postfix(); + Require(_ZNSt8__sce_v28_Thrd_idEv_nid_postfix() != nullptr); } diff --git a/core/libs/tests/GuestLibreSsl3Digest.cpp b/core/libs/tests/GuestLibreSsl3Digest.cpp index 19f6f8cb2b..dcddacf406 100644 --- a/core/libs/tests/GuestLibreSsl3Digest.cpp +++ b/core/libs/tests/GuestLibreSsl3Digest.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceLibreSsl3/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -7,11 +8,6 @@ #include #include -extern "C" { -unsigned char* APS5_VABI MD5_nid_postfix(const unsigned char*, std::size_t, unsigned char*); -unsigned char* APS5_VABI SHA1_nid_postfix(const unsigned char*, std::size_t, unsigned char*); -} - static void Require(bool condition, std::source_location location = std::source_location::current()) { if (condition) return; std::fprintf(stderr, "LibreSSL3 digest check failed at line %u\n", location.line()); diff --git a/core/libs/tests/GuestLibreSslAes.cpp b/core/libs/tests/GuestLibreSslAes.cpp index 4146b14b36..e36afbc5d8 100644 --- a/core/libs/tests/GuestLibreSslAes.cpp +++ b/core/libs/tests/GuestLibreSslAes.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceLibreSsl/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -8,22 +9,6 @@ #include #include -struct AesKey { - std::uint32_t roundKeys[60]; - std::int32_t rounds; -}; - -extern "C" { -int APS5_VABI AES_set_encrypt_key_nid_postfix(const unsigned char*, int, AesKey*); -int APS5_VABI AES_set_decrypt_key_nid_postfix(const unsigned char*, int, AesKey*); -void APS5_VABI AES_encrypt_nid_postfix(const unsigned char*, unsigned char*, const AesKey*); -void APS5_VABI AES_decrypt_nid_postfix(const unsigned char*, unsigned char*, const AesKey*); -void APS5_VABI AES_ecb_encrypt_nid_postfix(const unsigned char*, unsigned char*, const AesKey*, int); -void APS5_VABI AES_cbc_encrypt_nid_postfix(const unsigned char*, unsigned char*, std::size_t, const AesKey*, unsigned char*, int); -void APS5_VABI AES_cfb128_encrypt_nid_postfix(const unsigned char*, unsigned char*, std::size_t, const AesKey*, unsigned char*, int*, int); -void APS5_VABI AES_ctr128_encrypt_nid_postfix(const unsigned char*, unsigned char*, std::size_t, const AesKey*, unsigned char*, unsigned char*, unsigned*); -} - static void Require(bool value, const char* what) { if (value) return; std::fprintf(stderr, "failed: %s\n", what); @@ -104,12 +89,16 @@ int main() { const int last = 4 * encrypt.rounds; Require(!std::memcmp(decrypt.roundKeys, encrypt.roundKeys + last, 16) && !std::memcmp(decrypt.roundKeys + last, encrypt.roundKeys, 16), "decrypt key reverses the round keys"); AES_encrypt_nid_postfix(plain.data(), out, &encrypt); + Require(Hex(out, 16) == ciphers[i], "FIPS-197 appendix C cipher"); AES_decrypt_nid_postfix(out, back, &decrypt); + Require(!std::memcmp(back, plain.data(), 16), "FIPS-197 appendix C inverse cipher"); AES_ecb_encrypt_nid_postfix(plain.data(), out, &encrypt, 1); + Require(Hex(out, 16) == ciphers[i], "ECB encrypt"); AES_ecb_encrypt_nid_postfix(out, out, &decrypt, 0); + Require(!std::memcmp(out, plain.data(), 16), "ECB decrypt in place"); } @@ -167,36 +156,44 @@ int main() { AesKey encrypt {}, decrypt {}; AES_set_encrypt_key_nid_postfix(key.data(), 128, &encrypt); AES_set_decrypt_key_nid_postfix(key.data(), 128, &decrypt); + std::vector out(message.size() + 16), back(message.size() + 16); auto iv = Bytes("000102030405060708090a0b0c0d0e0f"); AES_cbc_encrypt_nid_postfix(message.data(), out.data(), 64, &encrypt, iv.data(), 1); + Require(Hex(out.data(), 64) == "7649abac8119b246cee98e9b12e9197d5086cb9b507219ee95db113a917678b273bed6b8e3c1743b7116e69e222295163ff1caa1681fac09120eca307586e1a7", "SP 800-38A F.2.1 CBC encrypt"); Require(Hex(iv.data(), 16) == "3ff1caa1681fac09120eca307586e1a7", "CBC encrypt returns the last cipher block as iv"); iv = Bytes("000102030405060708090a0b0c0d0e0f"); std::memcpy(back.data(), out.data(), 64); AES_cbc_encrypt_nid_postfix(back.data(), back.data(), 32, &decrypt, iv.data(), 0); AES_cbc_encrypt_nid_postfix(back.data() + 32, back.data() + 32, 32, &decrypt, iv.data(), 0); + Require(!std::memcmp(back.data(), message.data(), 64) && Hex(iv.data(), 16) == "3ff1caa1681fac09120eca307586e1a7", "SP 800-38A F.2.2 CBC decrypt in place across calls"); iv = Bytes("000102030405060708090a0b0c0d0e0f"); std::vector partial(32, 0xee); AES_cbc_encrypt_nid_postfix(message.data(), partial.data(), 20, &encrypt, iv.data(), 1); + Require(Hex(partial.data(), 16) == "7649abac8119b246cee98e9b12e9197d" && partial[31] != 0xee && Hex(iv.data(), 16) == Hex(partial.data() + 16, 16), "CBC encrypt pads a partial block with the iv and writes the whole block"); iv = Bytes("000102030405060708090a0b0c0d0e0f"); std::vector plainPartial(32, 0xee); AES_cbc_encrypt_nid_postfix(partial.data(), plainPartial.data(), 20, &decrypt, iv.data(), 0); + Require(!std::memcmp(plainPartial.data(), message.data(), 20) && plainPartial[20] == 0xee && Hex(iv.data(), 16) == Hex(partial.data() + 16, 16), "CBC decrypt writes only the requested length"); iv = Bytes("000102030405060708090a0b0c0d0e0f"); int num = 0; AES_cfb128_encrypt_nid_postfix(message.data(), out.data(), 5, &encrypt, iv.data(), &num, 1); AES_cfb128_encrypt_nid_postfix(message.data() + 5, out.data() + 5, 32, &encrypt, iv.data(), &num, 1); + Require(num == 5, "CFB128 keeps the block position"); AES_cfb128_encrypt_nid_postfix(message.data() + 37, out.data() + 37, 27, &encrypt, iv.data(), &num, 1); + Require(Hex(out.data(), 64) == "3b3fd92eb72dad20333449f8e83cfb4ac8a64537a0b3a93fcde3cdad9f1ce58b26751f67a3cbb140b1808cf187a4f4dfc04b05357c5d1c0eeac4c66f9ff7f2e6" && num == 0, "SP 800-38A F.3.13 CFB128 encrypt in pieces"); iv = Bytes("000102030405060708090a0b0c0d0e0f"); num = 0; AES_cfb128_encrypt_nid_postfix(out.data(), back.data(), 64, &encrypt, iv.data(), &num, 0); + Require(!std::memcmp(back.data(), message.data(), 64), "SP 800-38A F.3.14 CFB128 decrypt"); num = 16; RequireThrows([&] { AES_cfb128_encrypt_nid_postfix(message.data(), out.data(), 1, &encrypt, iv.data(), &num, 1); }, "CFB128 position out of range"); @@ -206,11 +203,13 @@ int main() { unsigned position = 0; AES_ctr128_encrypt_nid_postfix(message.data(), out.data(), 7, &encrypt, counter.data(), keystream, &position); AES_ctr128_encrypt_nid_postfix(message.data() + 7, out.data() + 7, 57, &encrypt, counter.data(), keystream, &position); + Require(Hex(out.data(), 64) == "874d6191b620e3261bef6864990db6ce9806f66b7970fdff8617187bb9fffdff5ae4df3edbd5d35e5b4f09020db03eab1e031dda2fbe03d1792170a0f3009cee", "SP 800-38A F.5.1 CTR encrypt in pieces"); Require(position == 0 && Hex(counter.data(), 16) == "f0f1f2f3f4f5f6f7f8f9fafbfcfdff03", "CTR advances the counter per block"); counter = Bytes("ffffffffffffffffffffffffffffffff"); position = 0; AES_ctr128_encrypt_nid_postfix(message.data(), out.data(), 37, &encrypt, counter.data(), keystream, &position); + Require(Hex(out.data(), 37) == "e13338e36cb71962e00d020b4cedbd86d3dae15b04bb352fa0f59febfcb4da3e67da610697", "CTR counter wraps across all 128 bits"); Require(position == 5 && Hex(counter.data(), 16) == "00000000000000000000000000000002", "CTR position and counter after a partial block"); position = 16; diff --git a/core/libs/tests/GuestLibreSslCipher.cpp b/core/libs/tests/GuestLibreSslCipher.cpp new file mode 100644 index 0000000000..366264cc99 --- /dev/null +++ b/core/libs/tests/GuestLibreSslCipher.cpp @@ -0,0 +1,97 @@ +#include "prx/libSceLibreSsl/libSceLibreSsl.hpp" +#include +#include +#include +#include +#include +#include +#include + +struct alignas(8) RawCipher { + std::array prefix; + std::int32_t strength; + std::int32_t algorithm; +}; + +static_assert(sizeof(RawCipher) == 88); +static_assert(offsetof(RawCipher, strength) == 80); +static_assert(offsetof(RawCipher, algorithm) == 84); + +static void Require(bool value, const char* message) { + if (value) return; + std::fprintf(stderr, "failed: %s\n", message); + std::abort(); +} + +static void RequireString(const char* actual, const char* expected) { + Require(actual && std::strcmp(actual, expected) == 0, expected); +} + +int main() { + struct { std::int32_t before, bits, after; } output {0x12345678, -777, 0x23456789}; + Require(SSL_CIPHER_get_bits_nid_postfix(nullptr, &output.bits) == 0, "null cipher has zero strength"); + Require(output.bits == -777, "null cipher leaves the optional output untouched"); + Require(SSL_CIPHER_get_bits_nid_postfix(nullptr, nullptr) == 0, "both pointers may be null"); + RequireString(SSL_CIPHER_get_name_nid_postfix(nullptr), "(NONE)"); + RequireString(SSL_CIPHER_get_version_nid_postfix(nullptr), "(NONE)"); + + struct { std::uint64_t before; RawCipher cipher; std::uint64_t after; } guarded; + std::memset(&guarded, 0xa5, sizeof(guarded)); + RawCipher& cipher = guarded.cipher; + const char customName[] = "arbitrary caller-provided cipher"; + const char* name = customName; + std::memcpy(cipher.prefix.data() + 8, &name, sizeof(name)); + Require(SSL_CIPHER_get_name_nid_postfix(&cipher) == name, "name pointer is returned without copying or a registry lookup"); + name = nullptr; + std::memcpy(cipher.prefix.data() + 8, &name, sizeof(name)); + Require(SSL_CIPHER_get_name_nid_postfix(&cipher) == nullptr, "null name field is preserved"); + name = customName; + std::memcpy(cipher.prefix.data() + 8, &name, sizeof(name)); + + constexpr std::int32_t bitPairs[][2] { + {0, 0}, {40, 128}, {56, 64}, {112, 168}, {128, 128}, {192, 192}, {256, 256}, + {-1, -2}, {std::numeric_limits::min(), std::numeric_limits::max()}, + {std::numeric_limits::max(), std::numeric_limits::min()}, + }; + for (const auto& pair : bitPairs) { + cipher.strength = pair[0]; + cipher.algorithm = pair[1]; + const auto snapshot = guarded; + output.bits = -777; + Require(SSL_CIPHER_get_bits_nid_postfix(&cipher, &output.bits) == pair[0], "effective strength is distinct from algorithm bits"); + Require(output.bits == pair[1], "algorithm bits use the 32-bit field at guest offset 84"); + Require(output.before == 0x12345678 && output.after == 0x23456789, "output writes exactly four bytes"); + Require(SSL_CIPHER_get_bits_nid_postfix(&cipher, nullptr) == pair[0], "optional output may be omitted"); + Require(std::memcmp(&guarded, &snapshot, sizeof(guarded)) == 0, "queries preserve the cipher and its guards"); + } + + constexpr std::uint64_t lowIds[] {0, 1, 0x35, 0xc02f, 0xffffff}; + for (std::uint64_t version = 0; version < 256; ++version) { + for (const auto low : lowIds) { + const std::uint64_t id = (version << 24) | low; + std::memcpy(cipher.prefix.data() + 16, &id, sizeof(id)); + RequireString(SSL_CIPHER_get_version_nid_postfix(&cipher), version == 3 ? "TLSv1/SSLv3" : "unknown"); + } + } + constexpr std::uint64_t wideIds[] {0x103000035ULL, 0x800000000300c02fULL, 0xffffffff03000000ULL, + std::numeric_limits::max()}; + for (const auto id : wideIds) { + std::memcpy(cipher.prefix.data() + 16, &id, sizeof(id)); + RequireString(SSL_CIPHER_get_version_nid_postfix(&cipher), "unknown"); + } + + cipher.strength = 40; + cipher.algorithm = 128; + Require(SSL_CIPHER_get_bits_nid_postfix(&cipher, &cipher.algorithm) == 40, "output may alias the algorithm field"); + Require(cipher.algorithm == 128, "self-alias preserves algorithm bits"); + Require(SSL_CIPHER_get_bits_nid_postfix(&cipher, &cipher.strength) == 128, "algorithm output is written before strength is read"); + Require(cipher.strength == 128, "aliased output receives algorithm bits"); + + const auto snapshot = guarded; + const std::int32_t valid = 0; + std::memcpy(cipher.prefix.data(), &valid, sizeof(valid)); + Require(SSL_CIPHER_get_name_nid_postfix(&cipher) == customName, "valid flag does not gate name access"); + Require(SSL_CIPHER_get_bits_nid_postfix(&cipher, nullptr) == 128, "valid flag does not gate strength access"); + Require(guarded.before == snapshot.before && guarded.after == snapshot.after, "input guards remain intact"); + return 0; +} diff --git a/core/libs/tests/GuestLibreSslDes.cpp b/core/libs/tests/GuestLibreSslDes.cpp index 630f2601ed..6191facec5 100644 --- a/core/libs/tests/GuestLibreSslDes.cpp +++ b/core/libs/tests/GuestLibreSslDes.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceLibreSsl/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -10,12 +11,6 @@ using DesBlock = std::array; using DesSchedule = std::array; -extern "C" { -void APS5_VABI DES_ecb_encrypt_nid_postfix(const unsigned char*, unsigned char*, const unsigned char*, int); -int APS5_VABI DES_set_key_nid_postfix(const unsigned char*, unsigned char*); -void APS5_VABI DES_set_odd_parity_nid_postfix(unsigned char*); -} - static void Require(bool value) { if (!value) std::abort(); } template @@ -38,22 +33,27 @@ static void CheckVector(std::uint64_t key, std::uint64_t plain, std::uint64_t ci const auto plainBlock = Block(plain); DesBlock output{}; DES_ecb_encrypt_nid_postfix(plainBlock.data(), output.data(), schedule.data(), 1); + Require(output == Block(cipher)); DES_ecb_encrypt_nid_postfix(output.data(), output.data(), schedule.data(), 0); + Require(output == plainBlock); DesBlock again{}; DES_ecb_encrypt_nid_postfix(plainBlock.data(), again.data(), schedule.data(), 7); + Require(again == Block(cipher)); } static void CheckParity() { DesBlock key{0x00, 0x01, 0x02, 0x03, 0x12, 0x13, 0xfe, 0xff}; DES_set_odd_parity_nid_postfix(key.data()); + Require(key == (DesBlock{0x01, 0x01, 0x02, 0x02, 0x13, 0x13, 0xfe, 0xfe})); for (int value = 0; value < 256; ++value) { DesBlock single{}; single.fill(static_cast(value)); DES_set_odd_parity_nid_postfix(single.data()); + Require((single[0] & 0xfe) == (value & 0xfe) && std::popcount(single[0]) % 2 == 1); } } diff --git a/core/libs/tests/GuestLibreSslDigest.cpp b/core/libs/tests/GuestLibreSslDigest.cpp index 8b9ba6183b..ba0ae9d3e0 100644 --- a/core/libs/tests/GuestLibreSslDigest.cpp +++ b/core/libs/tests/GuestLibreSslDigest.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceLibreSsl/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -9,35 +10,19 @@ #include #include -extern "C" { -int APS5_VABI MD4_Init_nid_postfix(void*); -int APS5_VABI MD4_Update_nid_postfix(void*, const void*, std::size_t); -int APS5_VABI MD4_Final_nid_postfix(unsigned char*, void*); -int APS5_VABI MD5_Init_nid_postfix(void*); -int APS5_VABI MD5_Update_nid_postfix(void*, const void*, std::size_t); -int APS5_VABI MD5_Final_nid_postfix(unsigned char*, void*); -int APS5_VABI SHA1_Init_nid_postfix(void*); -int APS5_VABI SHA1_Update_nid_postfix(void*, const void*, std::size_t); -int APS5_VABI SHA1_Final_nid_postfix(unsigned char*, void*); -int APS5_VABI SHA224_Init_nid_postfix(void*); -int APS5_VABI SHA224_Update_nid_postfix(void*, const void*, std::size_t); -int APS5_VABI SHA224_Final_nid_postfix(unsigned char*, void*); -int APS5_VABI SHA256_Init_nid_postfix(void*); -int APS5_VABI SHA256_Update_nid_postfix(void*, const void*, std::size_t); -int APS5_VABI SHA256_Final_nid_postfix(unsigned char*, void*); -unsigned char* APS5_VABI SHA256_nid_postfix(const unsigned char*, std::size_t, unsigned char*); -int APS5_VABI SHA384_Init_nid_postfix(void*); -int APS5_VABI SHA384_Update_nid_postfix(void*, const void*, std::size_t); -int APS5_VABI SHA384_Final_nid_postfix(unsigned char*, void*); -int APS5_VABI SHA512_Init_nid_postfix(void*); -int APS5_VABI SHA512_Update_nid_postfix(void*, const void*, std::size_t); -int APS5_VABI SHA512_Final_nid_postfix(unsigned char*, void*); -} - using InitFunction = int (APS5_VABI*)(void*); using UpdateFunction = int (APS5_VABI*)(void*, const void*, std::size_t); using FinalFunction = int (APS5_VABI*)(unsigned char*, void*); +template +int APS5_VABI Initialize(void* context) { return TFunction(static_cast(context)); } + +template +int APS5_VABI Update(void* context, const void* data, std::size_t size) { return TFunction(static_cast(context), data, size); } + +template +int APS5_VABI Finalize(unsigned char* digest, void* context) { return TFunction(digest, static_cast(context)); } + struct Algorithm { const char* name; InitFunction init; @@ -92,31 +77,31 @@ int main() { std::string(1000000, 'a'), }; const Algorithm algorithms[] { - {"MD4", MD4_Init_nid_postfix, MD4_Update_nid_postfix, MD4_Final_nid_postfix, 92, 64, 16, { + {"MD4", Initialize, Update, Finalize, 92, 64, 16, { "31d6cfe0d16ae931b73c59d7e0c089c0", "a448017aaf21d8525fc10ae87aa6729d", "4691a9ec81b1a6bd1ab8557240b245c5", nullptr, "e33b4ddc9c38f2199c3e7b164fcc0536", nullptr}}, - {"MD5", MD5_Init_nid_postfix, MD5_Update_nid_postfix, MD5_Final_nid_postfix, 92, 64, 16, { + {"MD5", Initialize, Update, Finalize, 92, 64, 16, { "d41d8cd98f00b204e9800998ecf8427e", "900150983cd24fb0d6963f7d28e17f72", "8215ef0796a20bcaaae116d3876c664a", "03dd8807a93175fb062dfb55dc7d359c", "57edf4a22be3c955ac49da2e2107b67a", "7707d6ae4e027c70eea2a935c2296f21"}}, - {"SHA1", SHA1_Init_nid_postfix, SHA1_Update_nid_postfix, SHA1_Final_nid_postfix, 96, 64, 20, { + {"SHA1", Initialize, Update, Finalize, 96, 64, 20, { "da39a3ee5e6b4b0d3255bfef95601890afd80709", "a9993e364706816aba3e25717850c26c9cd0d89d", "84983e441c3bd26ebaae4aa1f95129e5e54670f1", "a49b2446a02c645bf419f995b67091253a04a259", "50abf5706a150990a08b2c5ea40fa0e585554732", "34aa973cd4c4daa4f61eeb2bdbad27316534016f"}}, - {"SHA224", SHA224_Init_nid_postfix, SHA224_Update_nid_postfix, SHA224_Final_nid_postfix, 112, 64, 28, { + {"SHA224", Initialize, Update, Finalize, 112, 64, 28, { "d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f", "23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7", "75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525", "c97ca9a559850ce97a04a96def6d99a9e0e0e2ab14e6b8df265fc0b3", "b50aecbe4e9bb0b57bc5f3ae760a8e01db24f203fb3cdcd13148046e", "20794655980c91d8bbb4c1ea97618a4bf03f42581948b2ee4ee7ad67"}}, - {"SHA256", SHA256_Init_nid_postfix, SHA256_Update_nid_postfix, SHA256_Final_nid_postfix, 112, 64, 32, { + {"SHA256", Initialize, Update, Finalize, 112, 64, 32, { "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad", "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1", "cf5b16a778af8380036ce59e7b0492370b249b11e8f07a51afac45037afee9d1", "f371bc4a311f2b009eef952dd83ca80e2b60026c8e935592d0f9c308453c813e", "cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0"}}, - {"SHA384", SHA384_Init_nid_postfix, SHA384_Update_nid_postfix, SHA384_Final_nid_postfix, 216, 128, 48, { + {"SHA384", Initialize, Update, Finalize, 216, 128, 48, { "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b", "cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7", "3391fdddfc8dc7393707a65b1b4709397cf8b1d162af05abfe8f450de5f36bc6b0455a8520bc4e6f5fe95b1fe3c8452b", "09330c33f71147e83d192fc782cd1b4753111b173b3b05d22fa08086e3b0f712fcc7c71a557e2db966c3e9fa91746039", "b12932b0627d1c060942f5447764155655bd4da0c9afa6dd9b9ef53129af1b8fb0195996d2de9ca0df9d821ffee67026", "9d0e1809716474cb086e834e310a4a1ced149e9c00f248527972cec5704c2a5b07b8b3dc38ecc4ebae97ddd87f3d8985"}}, - {"SHA512", SHA512_Init_nid_postfix, SHA512_Update_nid_postfix, SHA512_Final_nid_postfix, 216, 128, 64, { + {"SHA512", Initialize, Update, Finalize, 216, 128, 64, { "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e", "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f", "204a8fc6dda82f0a0ced7beb8e08a41657c16ef468b228a8279be331a703c33596fd15c13b1b07f9aa1d3bea57789ca031ad85c7a71dd70354ec631238ca3445", @@ -168,24 +153,28 @@ int main() { alignas(16) unsigned char context[256] {}; unsigned char digest[64] {}; - Require(SHA512_Init_nid_postfix(context) == 1 && SHA512_Final_nid_postfix(nullptr, context) == 0, "SHA512_Final without a digest buffer"); - SHA256_Init_nid_postfix(context); + Require(SHA512_Init_nid_postfix(reinterpret_cast(context)) == 1 && SHA512_Final_nid_postfix(nullptr, reinterpret_cast(context)) == 0, "SHA512_Final without a digest buffer"); + SHA256_Init_nid_postfix(reinterpret_cast(context)); + std::uint32_t length = 33; std::memcpy(context + 108, &length, 4); - Require(SHA256_Final_nid_postfix(digest, context) == 0, "SHA256_Final with an oversized digest length"); - SHA256_Init_nid_postfix(context); + Require(SHA256_Final_nid_postfix(digest, reinterpret_cast(context)) == 0, "SHA256_Final with an oversized digest length"); + SHA256_Init_nid_postfix(reinterpret_cast(context)); + length = 16; std::memcpy(context + 108, &length, 4); std::memset(digest, 0xee, sizeof(digest)); - Require(SHA256_Final_nid_postfix(digest, context) == 1 && Hex(digest, 16) == "e3b0c44298fc1c149afbf4c8996fb924" && digest[16] == 0xee, "SHA256_Final truncates to the digest length"); - SHA512_Init_nid_postfix(context); + Require(SHA256_Final_nid_postfix(digest, reinterpret_cast(context)) == 1 && Hex(digest, 16) == "e3b0c44298fc1c149afbf4c8996fb924" && digest[16] == 0xee, "SHA256_Final truncates to the digest length"); + SHA512_Init_nid_postfix(reinterpret_cast(context)); + length = 32; std::memcpy(context + 212, &length, 4); - RequireThrows([&] { SHA512_Final_nid_postfix(digest, context); }, "SHA-512/256 digest length"); - SHA256_Init_nid_postfix(context); + RequireThrows([&] { SHA512_Final_nid_postfix(digest, reinterpret_cast(context)); }, "SHA-512/256 digest length"); + SHA256_Init_nid_postfix(reinterpret_cast(context)); + length = 64; std::memcpy(context + 104, &length, 4); - RequireThrows([&] { SHA256_Update_nid_postfix(context, "a", 1); }, "corrupt buffered count"); + RequireThrows([&] { SHA256_Update_nid_postfix(reinterpret_cast(context), "a", 1); }, "corrupt buffered count"); const auto* abc = reinterpret_cast("abc"); Require(SHA256_nid_postfix(abc, 3, digest) == digest && Hex(digest, 32) == "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad", "SHA256 one-shot"); diff --git a/core/libs/tests/GuestLibreSslError.cpp b/core/libs/tests/GuestLibreSslError.cpp new file mode 100644 index 0000000000..f81ec64d6b --- /dev/null +++ b/core/libs/tests/GuestLibreSslError.cpp @@ -0,0 +1,69 @@ +#include "prx/libSceLibreSsl/include/Api.hpp" +#include "prx/libSceLibreSsl/include/Error.hpp" +#include "prx/libc/include/general/VabiMacros.hpp" +#include +#include +#include +#include + +static void Require(bool value, const char* what) { + if (value) return; + std::fprintf(stderr, "failed: %s\n", what); + std::abort(); +} + +static std::uint64_t Pack(std::uint64_t library, std::uint64_t function, std::uint64_t reason) { + return library << 24 | function << 12 | reason; +} + +int main() { + Require(ERR_get_error_nid_postfix() == 0, "empty queue get"); + Require(ERR_peek_error_nid_postfix() == 0, "empty queue peek"); + + LibreSslPutError_nid_no_patch(3, 100, 65); + LibreSslPutError_nid_no_patch(4, 101, 66); + LibreSslPutError_nid_no_patch(20, 102, 67); + Require(ERR_peek_error_nid_postfix() == Pack(3, 100, 65), "peek returns the earliest error"); + Require(ERR_peek_error_nid_postfix() == Pack(3, 100, 65), "peek keeps the earliest error"); + Require(ERR_get_error_nid_postfix() == Pack(3, 100, 65), "get returns the earliest error"); + Require(ERR_get_error_nid_postfix() == Pack(4, 101, 66), "get returns the second error"); + Require(ERR_peek_error_nid_postfix() == Pack(20, 102, 67), "peek follows get"); + Require(ERR_get_error_nid_postfix() == Pack(20, 102, 67), "get returns the third error"); + Require(ERR_get_error_nid_postfix() == 0, "drained queue get"); + Require(ERR_peek_error_nid_postfix() == 0, "drained queue peek"); + + for (int i = 1; i <= 16; ++i) LibreSslPutError_nid_no_patch(i, 0, i); + for (int i = 2; i <= 16; ++i) Require(ERR_get_error_nid_postfix() == Pack(i, 0, i), "full queue drops the oldest error"); + Require(ERR_get_error_nid_postfix() == 0, "full queue holds 15 errors"); + + LibreSslPutError_nid_no_patch(0x1ff, 0x1fff, 0x1fff); + Require(ERR_get_error_nid_postfix() == 0xFFFFFFFFu, "fields are masked and the code keeps 32 bits"); + + LibreSslPutError_nid_no_patch(5, 1, 2); + LibreSslPutError_nid_no_patch(6, 1, 2); + ERR_clear_error_nid_postfix(); + Require(ERR_peek_error_nid_postfix() == 0, "clear empties the queue"); + LibreSslPutError_nid_no_patch(7, 1, 2); + Require(ERR_get_error_nid_postfix() == Pack(7, 1, 2), "queue works after clear"); + + LibreSslPutError_nid_no_patch(8, 1, 2); + bool otherEmpty = false; + bool otherOwn = false; + std::thread other([&] { + otherEmpty = ERR_peek_error_nid_postfix() == 0; + LibreSslPutError_nid_no_patch(9, 1, 2); + otherOwn = ERR_get_error_nid_postfix() == Pack(9, 1, 2); + }); + other.join(); + Require(otherEmpty, "another thread starts with an empty queue"); + Require(otherOwn, "another thread reads its own error"); + Require(ERR_get_error_nid_postfix() == Pack(8, 1, 2), "this thread keeps its error"); + Require(ERR_get_error_nid_postfix() == 0, "the other thread's error stays on that thread"); + + LibreSslPutError_nid_no_patch(10, 1, 2); + ERR_remove_thread_state_nid_postfix(nullptr); + Require(ERR_peek_error_nid_postfix() == 0, "removing the thread state empties the queue"); + + std::puts("guest_libressl_error: ok"); + return 0; +} diff --git a/core/libs/tests/GuestLibreSslRuntime.cpp b/core/libs/tests/GuestLibreSslRuntime.cpp index 937036d5fd..7a67fb61ea 100644 --- a/core/libs/tests/GuestLibreSslRuntime.cpp +++ b/core/libs/tests/GuestLibreSslRuntime.cpp @@ -1,3 +1,5 @@ +#include "prx/libc/include/Api.hpp" +#include "prx/libSceLibreSsl/include/Api.hpp" #include "prx/libc/include/ApplicationHeap.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -10,19 +12,6 @@ #include #include -extern "C" { -void APS5_VABI RAND_add_nid_postfix(const void*, int, double); -int APS5_VABI RAND_status_nid_postfix(void); -int APS5_VABI RAND_bytes_nid_postfix(unsigned char*, int); -int APS5_VABI RAND_load_file_nid_postfix(const char*, std::int64_t); -const char* APS5_VABI RAND_file_name_nid_postfix(char*, std::size_t); -void* APS5_VABI CRYPTO_malloc_nid_postfix(int, const char*, int); -void APS5_VABI CRYPTO_free_nid_postfix(void*); -int APS5_VABI CRYPTO_set_mem_functions_nid_postfix(void*, void*, void*); -void APS5_VABI free_nid_postfix(void*); -void* APS5_VABI malloc_nid_postfix(std::size_t); -} - static void Require(bool condition, std::source_location location = std::source_location::current()) { if (condition) return; std::fprintf(stderr, "LibreSSL runtime check failed at line %u\n", location.line()); @@ -80,12 +69,15 @@ int main() { Require(block != nullptr); std::memset(block, 0x5a, 64); CRYPTO_free_nid_postfix(block); + block = static_cast(CRYPTO_malloc_nid_postfix(32, nullptr, 0)); Require(block != nullptr); free_nid_postfix(block); + block = static_cast(malloc_nid_postfix(16)); CRYPTO_free_nid_postfix(block); CRYPTO_free_nid_postfix(nullptr); + Require(CRYPTO_malloc_nid_postfix(0, nullptr, 0) == nullptr); Require(CRYPTO_malloc_nid_postfix(-1, nullptr, 0) == nullptr); Require(CRYPTO_set_mem_functions_nid_postfix(reinterpret_cast(&std::malloc), reinterpret_cast(&std::realloc), reinterpret_cast(&std::free)) == 0); diff --git a/core/libs/tests/GuestLibreSslX509Errors.cpp b/core/libs/tests/GuestLibreSslX509Errors.cpp index 7a53a5e582..4b68ca300b 100644 --- a/core/libs/tests/GuestLibreSslX509Errors.cpp +++ b/core/libs/tests/GuestLibreSslX509Errors.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceLibreSsl/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -6,8 +7,6 @@ #include #include -extern "C" const char* APS5_VABI X509_verify_cert_error_string_nid_postfix(std::int64_t); - static constexpr std::uint64_t ExpectedHashes[] { 0x8b05d07b5566befULL, 0, 0x708834e4234778b5ULL, 0xefb3526cbf8b4d8fULL, 0xf9c246e135cdbad1ULL, 0xd42f63e9d35f4aa1ULL, 0xcccbec8974d6af08ULL, 0x8d443856acab19a4ULL, diff --git a/core/libs/tests/GuestLifecycle.cpp b/core/libs/tests/GuestLifecycle.cpp index 11cb61e1ec..ccdf3cc1df 100644 --- a/core/libs/tests/GuestLifecycle.cpp +++ b/core/libs/tests/GuestLifecycle.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -10,19 +11,6 @@ #include #endif -struct InitEnvParams { - int argc; - std::uint32_t pad; - const char* argv[3]; -}; - -extern "C" { -int APS5_VABI cxa_atexit_nid_postfix(void (APS5_VABI *)(void*), void*, void*); -void APS5_VABI cxa_finalize_nid_postfix(void*); -int APS5_VABI LibcInternalExtCxaThreadAtexit_nid_postfix(void (APS5_VABI *)(void*), void*, void*); -void APS5_VABI init_env_nid_postfix(const InitEnvParams*); -} - namespace { void Require(bool value) { @@ -54,10 +42,13 @@ int main() { Require(cxa_atexit_nid_postfix(Second, nullptr, first) == 0); Require(cxa_atexit_nid_postfix(Other, nullptr, second) == 0); cxa_finalize_nid_postfix(first); + Require(secondAt == 0 && firstAt == 1 && otherAt == -1); cxa_finalize_nid_postfix(reinterpret_cast(3)); + Require(otherAt == -1); cxa_finalize_nid_postfix(second); + Require(otherAt == 2); std::thread worker([] { @@ -79,6 +70,7 @@ int main() { try { init_env_nid_postfix(nullptr); + } catch (const std::runtime_error& error) { Require(std::strstr(error.what(), "not implemented") == nullptr); return 0; diff --git a/core/libs/tests/GuestLoadExecHost.cpp b/core/libs/tests/GuestLoadExecHost.cpp index bba40568d0..618d8f5ebf 100644 --- a/core/libs/tests/GuestLoadExecHost.cpp +++ b/core/libs/tests/GuestLoadExecHost.cpp @@ -1,3 +1,6 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" +#include "prx/libSceSystemService/include/SystemService.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libc/include/Shutdown.hpp" #include "prx/libc/include/General.hpp" @@ -17,11 +20,6 @@ #include #endif -extern "C" int APS5_VABI sceSystemServiceLoadExec(const char*, const char* const*); -extern "C" int APS5_VABI __cxa_atexit_nid_postfix(void (APS5_VABI*)(void*), void*, void*); -extern "C" int APS5_VABI getargc_nid_postfix(); -extern "C" const char** APS5_VABI getargv_nid_postfix(); - namespace { bool cleaned = false; diff --git a/core/libs/tests/GuestLocale.cpp b/core/libs/tests/GuestLocale.cpp index 506939f2da..3baacd92f3 100644 --- a/core/libs/tests/GuestLocale.cpp +++ b/core/libs/tests/GuestLocale.cpp @@ -1,4 +1,5 @@ #include "prx/libc/include/ApplicationHeap.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/GuestLocale.hpp" #include #include @@ -13,39 +14,13 @@ extern "C" { extern GuestLocale::Implementation* _ZSt21_sceLibcClassicLocale_nid_postfix; -GuestLocale::Implementation* APS5_VABI _ZNSt6locale16_GetgloballocaleEv_nid_postfix(); -GuestLocale::Implementation* APS5_VABI _ZNSt6locale5_InitEv_nid_postfix(); -struct GuestLocaleFacade { GuestLocale::Implementation* implementation; }; -GuestLocaleFacade* APS5_VABI _ZNSt6locale7classicEv_nid_postfix(); -void APS5_VABI _ZNSt6locale5facet9_RegisterEv_nid_postfix(GuestLocale::Facet* self); -void APS5_VABI _ZNSt8_LocinfoC1EPKc_nid_postfix(GuestLocale::LocinfoStorage* self, const char* localeName); -void APS5_VABI _ZNSt8_LocinfoD1Ev_nid_postfix(GuestLocale::LocinfoStorage* self); -void APS5_VABI _ZNSt8ios_baseD2Ev_nid_postfix(GuestLocale::IosBase* self); -struct StreamManipulator { - GuestLocale::IosBase* (APS5_VABI* function)(GuestLocale::IosBase*, std::int32_t); - std::int32_t argument; -}; -StreamManipulator APS5_VABI _ZSt4setwi_nid_postfix(std::int32_t width); -void APS5_VABI _ZNSt8ios_base7_AddstdEPS__nid_postfix(GuestLocale::IosBase* self); -const short* APS5_VABI _Getpctype_nid_postfix(); -const short* APS5_VABI _Getptolower_nid_postfix(); -const short* APS5_VABI _Getptoupper_nid_postfix(); -int APS5_VABI _Mbtowcx_nid_postfix(std::uint16_t* dst, const char* src, std::size_t count, std::mbstate_t* st); -int APS5_VABI _Wctombx_nid_postfix(char* dst, std::uint16_t src, std::mbstate_t* st); -void APS5_VABI _Locksyslock_nid_postfix(); -void APS5_VABI _Unlocksyslock_nid_postfix(); -std::uint32_t APS5_VABI _Towctrans_nid_postfix(std::uint32_t wc, std::uint64_t desc); -int* APS5_VABI __error_nid_postfix(); + extern std::uint64_t _ZNSt7num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE2idE_nid_postfix; extern std::uint64_t _ZNSt8time_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE2idE_nid_postfix; extern std::uint64_t _ZNSt8time_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE2idE_nid_postfix; extern std::uintptr_t _ZTVSt7num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE_nid_postfix[17]; extern std::uintptr_t _ZTVSt7codecvtIwc9_MbstatetE_nid_postfix[13]; extern std::uintptr_t _ZTVSt7num_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE_nid_postfix[14]; -std::size_t APS5_VABI _ZNSt7codecvtIcc9_MbstatetE7_GetcatEPPKNSt6locale5facetEPKS2__nid_postfix(GuestLocale::Facet** facet, const GuestLocale::Implementation* const* locale); -std::size_t APS5_VABI _ZNSt8numpunctIcE7_GetcatEPPKNSt6locale5facetEPKS1__nid_postfix(GuestLocale::Facet** facet, const GuestLocale::Implementation* const* locale); -std::size_t APS5_VABI _ZNSt7num_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE7_GetcatEPPKNSt6locale5facetEPKS5__nid_postfix(GuestLocale::Facet** facet, const GuestLocale::Implementation* const* locale); -std::size_t APS5_VABI _ZNSt8time_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE7_GetcatEPPKNSt6locale5facetEPKS5__nid_postfix(GuestLocale::Facet** facet, const GuestLocale::Implementation* const* locale); extern std::uintptr_t _ZTVSt7collateIcE_nid_postfix[9]; } @@ -147,8 +122,10 @@ static void CheckLocinfoAlignment() { bytes.fill(std::byte{0x5a}); auto* storage = reinterpret_cast(bytes.data() + 8); _ZNSt8_LocinfoC1EPKc_nid_postfix(storage, "C"); + for (std::size_t index = 0; index < bytes.size(); ++index) Require(bytes[index] == (index >= 8 && index < 72 ? std::byte{} : std::byte{0x5a})); _ZNSt8_LocinfoD1Ev_nid_postfix(storage); + RequireException([&] { _ZNSt8_LocinfoC1EPKc_nid_postfix(storage, "unknown-locale"); }); RequireException([] { _ZNSt8_LocinfoC1EPKc_nid_postfix(nullptr, "C"); }); } @@ -203,6 +180,7 @@ static void CheckStreamDestruction() { } object; object.stream.locale = &_ZSt21_sceLibcClassicLocale_nid_postfix; _ZNSt8ios_baseD2Ev_nid_postfix(&object.stream); + Require(object.stream.locale == nullptr && object.before == 0x12345678 && object.after == 0x87654321); object.stream.locale = &_ZSt21_sceLibcClassicLocale_nid_postfix; object.stream.callbacks = &object; @@ -240,31 +218,42 @@ static void CheckStandardStreams() { RequireException([&] { _ZNSt8ios_base7_AddstdEPS__nid_postfix(nullptr); }); _ZNSt8ios_base7_AddstdEPS__nid_postfix(&streams[0].stream); _ZNSt8ios_base7_AddstdEPS__nid_postfix(&streams[1].stream); + Require(streams[0].stream.standardStream == 1 && streams[1].stream.standardStream == 2); _ZNSt8ios_base7_AddstdEPS__nid_postfix(&streams[0].stream); + Require(streams[0].stream.standardStream == 1); _ZNSt8ios_baseD2Ev_nid_postfix(&streams[0].stream); + Require(streams[0].stream.locale == classic && streams[0].stream.standardStream == 1); _ZNSt8ios_baseD2Ev_nid_postfix(&streams[0].stream); + Require(streams[0].stream.locale == nullptr && streams[0].stream.standardStream == 1); streams[0].stream.locale = classic; _ZNSt8ios_base7_AddstdEPS__nid_postfix(&streams[0].stream); + Require(streams[0].stream.standardStream == 1); _ZNSt8ios_baseD2Ev_nid_postfix(&streams[1].stream); + Require(streams[1].stream.locale == nullptr && streams[1].stream.standardStream == 2); for (int index = 2; index < 7; ++index) { _ZNSt8ios_base7_AddstdEPS__nid_postfix(&streams[index].stream); + Require(streams[index].stream.standardStream == index + 1); } _ZNSt8ios_base7_AddstdEPS__nid_postfix(&streams[7].stream); _ZNSt8ios_base7_AddstdEPS__nid_postfix(&streams[8].stream); + Require(streams[7].stream.standardStream == 8 && streams[8].stream.standardStream == 8); _ZNSt8ios_baseD2Ev_nid_postfix(&streams[7].stream); + Require(streams[7].stream.locale == classic); _ZNSt8ios_baseD2Ev_nid_postfix(&streams[8].stream); + Require(streams[8].stream.locale == nullptr); for (int index = 2; index < 7; ++index) { _ZNSt8ios_baseD2Ev_nid_postfix(&streams[index].stream); + Require(streams[index].stream.locale == nullptr && streams[index].stream.standardStream == index + 1); } for (auto& object : streams) Require(object.before == 0x12345678 && object.after == 0x87654321); @@ -372,5 +361,6 @@ int main() { _Locksyslock_nid_postfix(); _Unlocksyslock_nid_postfix(); _Unlocksyslock_nid_postfix(); + std::cout << "Guest locale checks passed\n"; } diff --git a/core/libs/tests/GuestLoginDialog.cpp b/core/libs/tests/GuestLoginDialog.cpp index 09e5d52663..6f919c7cc8 100644 --- a/core/libs/tests/GuestLoginDialog.cpp +++ b/core/libs/tests/GuestLoginDialog.cpp @@ -1,18 +1,9 @@ +#include "prx/libSceLoginDialog/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include #include "prx/libSceCommonDialog/CommonDialog.hpp" -extern "C" { -int APS5_VABI sceLoginDialogInitialize(void); -int APS5_VABI sceLoginDialogOpen(const LoginDialogParam* param); -int APS5_VABI sceLoginDialogUpdateStatus(void); -int APS5_VABI sceLoginDialogGetStatus(void); -int APS5_VABI sceLoginDialogGetResult(LoginDialogResult* result); -int APS5_VABI sceLoginDialogClose(void); -int APS5_VABI sceLoginDialogTerminate(void); -} - namespace { void Require(bool value) { if (!value) std::abort(); } diff --git a/core/libs/tests/GuestLoginService.cpp b/core/libs/tests/GuestLoginService.cpp index a1fa20d143..dfee6d6f6c 100644 --- a/core/libs/tests/GuestLoginService.cpp +++ b/core/libs/tests/GuestLoginService.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceLoginService/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -5,12 +6,6 @@ #include #include -extern "C" { -int APS5_VABI sceLoginServiceInitialize(void); -int APS5_VABI sceLoginServiceTerminate(void); -int APS5_VABI sceLoginServiceRequestDevices(void* param); -} - static void Require(bool value) { if (!value) std::abort(); } @@ -20,7 +15,8 @@ int main() { Require(sceLoginServiceTerminate() == 0); unsigned char buffer[0x80]{}; try { - sceLoginServiceRequestDevices(buffer); + sceLoginServiceRequestDevices(reinterpret_cast(buffer)); + } catch (const std::runtime_error& error) { if (std::string(error.what()) == "sceLoginServiceRequestDevices not implemented") return 0; std::fprintf(stderr, "sceLoginServiceRequestDevices threw: %s\n", error.what()); diff --git a/core/libs/tests/GuestLowAddressMemory.cpp b/core/libs/tests/GuestLowAddressMemory.cpp index 8627e2bf2d..3af824dcac 100644 --- a/core/libs/tests/GuestLowAddressMemory.cpp +++ b/core/libs/tests/GuestLowAddressMemory.cpp @@ -1,3 +1,4 @@ +#include "prx/libkernel/include/Api.hpp" #include "SceTypes.hpp" #include "prx/libc/include/GuestArena.hpp" #include @@ -6,13 +7,6 @@ #include #include -extern "C" { -void* APS5_VABI mmap_nid_postfix(void*, std::size_t, int, int, int, std::int64_t) noexcept; -int APS5_VABI munmap_nid_postfix(void*, std::size_t) noexcept; -int APS5_VABI mprotect_nid_postfix(void*, std::size_t, int) noexcept; -int APS5_VABI sceKernelVirtualQuery(const void*, int, VirtualQueryInfo*, std::uint64_t); -} - static void Require(bool condition, std::source_location location = std::source_location::current()) { if (!condition) { std::fprintf(stderr, "Low guest memory check failed at line %u\n", static_cast(location.line())); diff --git a/core/libs/tests/GuestM4aacEnc.cpp b/core/libs/tests/GuestM4aacEnc.cpp index d9f6f00888..0db4db35fa 100644 --- a/core/libs/tests/GuestM4aacEnc.cpp +++ b/core/libs/tests/GuestM4aacEnc.cpp @@ -1,28 +1,9 @@ +#include "prx/libSceM4aacEnc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include #include -extern "C" { -int32_t APS5_VABI sceM4aacEncClearContext(int32_t m4aacEncHandle); -int APS5_VABI sceM4aacEncClearContextEx(); -int32_t APS5_VABI sceM4aacEncCreateEncoder(int32_t channels, int32_t samplingRate, int32_t bitRate, int32_t inputFormat, int32_t outputFormat, int32_t* pInternalError); -int APS5_VABI sceM4aacEncCreateEncoderEx(); -int32_t APS5_VABI sceM4aacEncDeleteEncoder(int32_t m4aacEncHandle, int32_t* pInternalError); -int APS5_VABI sceM4aacEncDeleteEncoderEx(); -int32_t APS5_VABI sceM4aacEncEncode(int32_t m4aacEncHandle, void* pInput, uint32_t inputByte, void* pOutput, uint32_t* pOutputByte, int32_t* pInternalError); -int APS5_VABI sceM4aacEncEncodeEx(); -int APS5_VABI sceM4aacEncEncodeWithPriority(); -int APS5_VABI sceM4aacEncEncodeWithPriorityEx(); -int32_t APS5_VABI sceM4aacEncFlush(int32_t m4aacEncHandle, void* pOutput, uint32_t* pOutputByte, int32_t* pInternalError); -int APS5_VABI sceM4aacEncFlushEx(); -int APS5_VABI sceM4aacEncFlushWithPriority(); -int APS5_VABI sceM4aacEncFlushWithPriorityEx(); -int APS5_VABI sceM4aacEncGetContext(); -int APS5_VABI sceM4aacEncInitialize(); -int APS5_VABI sceM4aacEncTerminate(); -} - namespace { void Require(bool value) { if (!value) std::abort(); } diff --git a/core/libs/tests/GuestMath.cpp b/core/libs/tests/GuestMath.cpp index c82fef2a8a..7c6bd1e44e 100644 --- a/core/libs/tests/GuestMath.cpp +++ b/core/libs/tests/GuestMath.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -13,50 +14,10 @@ #include #include #include -struct GuestFloatingPointEnvironment { - std::uint32_t control; - std::uint32_t status; - std::uint32_t tag; - unsigned char other[16]; - std::uint32_t mxcsr; -}; + static_assert(sizeof(GuestFloatingPointEnvironment) == 32); extern "C" { -int APS5_VABI fegetenv_nid_postfix(GuestFloatingPointEnvironment*); -double APS5_VABI atof_nid_postfix(const char*); -double APS5_VABI strtod_nid_postfix(const char*, char**); -double APS5_VABI wcstod_nid_postfix(const char16_t*, char16_t**); -float APS5_VABI wcstof_nid_postfix(const char16_t*, char16_t**); -long double APS5_VABI wcstold_nid_postfix(const char16_t*, char16_t**); -float APS5_VABI strtof_nid_postfix(const char*, char**); -long double APS5_VABI strtold_nid_postfix(const char*, char**); -std::int64_t APS5_VABI strtol_nid_postfix(const char*, char**, int); -std::uint64_t APS5_VABI strtoul_nid_postfix(const char*, char**, int); -std::intmax_t APS5_VABI strtoimax_nid_postfix(const char*, char**, int); -long long APS5_VABI strtoll_nid_postfix(const char*, char**, int); -unsigned long long APS5_VABI strtoull_nid_postfix(const char*, char**, int); -std::uintmax_t APS5_VABI strtoumax_nid_postfix(const char*, char**, int); -unsigned long long APS5_VABI _Stoull_nid_postfix(const char*, char**, int); -std::uint64_t APS5_VABI _Stoul_nid_postfix(const char*, char**, int); -int APS5_VABI atoi_nid_postfix(const char*); -std::int64_t APS5_VABI atol_nid_postfix(const char*); -long long APS5_VABI atoll_nid_postfix(const char*); -int* APS5_VABI __error_nid_postfix(); -double APS5_VABI sqrt_nid_postfix(double); -float APS5_VABI sqrtf_nid_postfix(float); -double APS5_VABI fabs_nid_postfix(double); -int APS5_VABI abs_nid_postfix(int); -double APS5_VABI trunc_nid_postfix(double); -double APS5_VABI ceil_nid_postfix(double); -double APS5_VABI floor_nid_postfix(double); -float APS5_VABI truncf_nid_postfix(float); -float APS5_VABI ceilf_nid_postfix(float); -float APS5_VABI floorf_nid_postfix(float); -double APS5_VABI nearbyint_nid_postfix(double); -double APS5_VABI fma_nid_postfix(double, double, double); -long double APS5_VABI acosl_nid_postfix(long double); -long double APS5_VABI asinl_nid_postfix(long double); -long double APS5_VABI frexpl_nid_postfix(long double, int*); + struct LibcFloatConstant { std::uint32_t bits[4]; }; extern LibcFloatConstant _FInf_nid_postfix; extern LibcFloatConstant _FNan_nid_postfix; @@ -72,143 +33,9 @@ extern SonyDconst _LDenorm_nid_postfix; extern SonyDconst _LInf_nid_postfix; extern SonyDconst _LNan_nid_postfix; extern SonyDconst _LSnan_nid_postfix; -short APS5_VABI _FDtest_nid_postfix(const float*); -short APS5_VABI _Dtest_nid_postfix(const double*); -int APS5_VABI __fpclassifyf_nid_postfix(float); -int APS5_VABI isnanf_nid_postfix(float); -int APS5_VABI __signbitl_nid_postfix(long double); -float APS5_VABI fmodf_nid_postfix(float, float); -double APS5_VABI fmod_nid_postfix(double, double); -float APS5_VABI asinf_nid_postfix(float); -float APS5_VABI acosf_nid_postfix(float); -double APS5_VABI asin_nid_postfix(double); -float APS5_VABI atan2f_nid_postfix(float, float); -float APS5_VABI atanf_nid_postfix(float); -float APS5_VABI hypotf_nid_postfix(float, float); -double APS5_VABI hypot_nid_postfix(double, double); -double APS5_VABI fdim_nid_postfix(double, double); -float APS5_VABI fdimf_nid_postfix(float, float); -float APS5_VABI fabsf_nid_postfix(float); -long double APS5_VABI fabsl_nid_postfix(long double); -double APS5_VABI copysign_nid_postfix(double, double); -float APS5_VABI copysignf_nid_postfix(float, float); -double APS5_VABI remquo_nid_postfix(double, double, int*); -float APS5_VABI remquof_nid_postfix(float, float, int*); -float APS5_VABI fmaf_nid_postfix(float, float, float); -long double APS5_VABI ceill_nid_postfix(long double); -long double APS5_VABI floorl_nid_postfix(long double); -float APS5_VABI cbrtf_nid_postfix(float); -float APS5_VABI tanf_nid_postfix(float); -float APS5_VABI sinf_nid_postfix(float); -float APS5_VABI cosf_nid_postfix(float); -void APS5_VABI sincosf_nid_postfix(float, float*, float*); -int APS5_VABI rand_nid_postfix(); -void APS5_VABI srand_nid_postfix(unsigned int); -int APS5_VABI rand_r_nid_postfix(unsigned int*); -float APS5_VABI log10f_nid_postfix(float); -float APS5_VABI powf_nid_postfix(float, float); -double APS5_VABI log1p_nid_postfix(double); -float APS5_VABI log1pf_nid_postfix(float); -double APS5_VABI expm1_nid_postfix(double); -float APS5_VABI expm1f_nid_postfix(float); -float APS5_VABI erff_nid_postfix(float); -double APS5_VABI erf_nid_postfix(double); -double APS5_VABI erfc_nid_postfix(double); -float APS5_VABI erfcf_nid_postfix(float); -double APS5_VABI lgamma_nid_postfix(double); + extern int signgam_nid_postfix; -float APS5_VABI logbf_nid_postfix(float); -int APS5_VABI ilogb_nid_postfix(double); -int APS5_VABI ilogbf_nid_postfix(float); -double APS5_VABI exp2_nid_postfix(double); -float APS5_VABI __powisf2_nid_postfix(float, int); -double APS5_VABI __powidf2_nid_postfix(double, int); -double APS5_VABI ldexp_nid_postfix(double, int); -double APS5_VABI scalbn_nid_postfix(double, int); -float APS5_VABI scalbnf_nid_postfix(float, int); -float APS5_VABI nextafterf_nid_postfix(float, float); -double APS5_VABI nextafter_nid_postfix(double, double); -double APS5_VABI frexp_nid_postfix(double, int*); -float APS5_VABI frexpf_nid_postfix(float, int*); -float APS5_VABI logf_nid_postfix(float); -std::int64_t APS5_VABI lround_nid_postfix(double); -std::div_t APS5_VABI div_nid_postfix(int, int); -double APS5_VABI sinh_nid_postfix(double); -double APS5_VABI cosh_nid_postfix(double); -double APS5_VABI _Cosh_nid_postfix(double, double); -float APS5_VABI coshf_nid_postfix(float); -float APS5_VABI sinhf_nid_postfix(float); -float APS5_VABI _FSinh_nid_postfix(float, float); -float APS5_VABI _FCosh_nid_postfix(float, float); -double APS5_VABI asinh_nid_postfix(double); -float APS5_VABI asinhf_nid_postfix(float); -double APS5_VABI acosh_nid_postfix(double); -float APS5_VABI acoshf_nid_postfix(float); -double APS5_VABI atanh_nid_postfix(double); -float APS5_VABI atanhf_nid_postfix(float); -std::int64_t APS5_VABI lroundf_nid_postfix(float); -std::int64_t APS5_VABI llround_nid_postfix(double); -std::int64_t APS5_VABI llroundf_nid_postfix(float); -std::int64_t APS5_VABI llroundl_nid_postfix(long double); -int APS5_VABI __isfinitef_nid_postfix(float); -int APS5_VABI __isfinitel_nid_postfix(long double); -int APS5_VABI __isnormal_nid_postfix(double); -int APS5_VABI __isnormalf_nid_postfix(float); -int APS5_VABI __isinff_nid_postfix(float); -int APS5_VABI __isinf_nid_postfix(double); -int APS5_VABI isnan_nid_postfix(double); -int APS5_VABI isinf_nid_postfix(double); -std::lldiv_t APS5_VABI lldiv_nid_postfix(long long, long long); -std::lldiv_t APS5_VABI imaxdiv_nid_postfix(std::int64_t, std::int64_t); -std::int64_t APS5_VABI labs_nid_postfix(std::int64_t); -std::int64_t APS5_VABI llabs_nid_postfix(std::int64_t); -std::int64_t APS5_VABI imaxabs_nid_postfix(std::int64_t); -long double APS5_VABI scalbnl_nid_postfix(long double, int); -float APS5_VABI significandf_nid_postfix(float); -double APS5_VABI significand_nid_postfix(double); -long double APS5_VABI acoshl_nid_postfix(long double); -long double APS5_VABI asinhl_nid_postfix(long double); -long double APS5_VABI atanhl_nid_postfix(long double); -long double APS5_VABI atan2l_nid_postfix(long double, long double); -long double APS5_VABI cbrtl_nid_postfix(long double); -long double APS5_VABI erfl_nid_postfix(long double); -long double APS5_VABI erfcl_nid_postfix(long double); -long double APS5_VABI expm1l_nid_postfix(long double); -long double APS5_VABI log1pl_nid_postfix(long double); -long double APS5_VABI log2l_nid_postfix(long double); -long double APS5_VABI lgammal_nid_postfix(long double); -long double APS5_VABI tgammal_nid_postfix(long double); -float APS5_VABI tgammaf_nid_postfix(float); -long double APS5_VABI hypotl_nid_postfix(long double, long double); -float APS5_VABI hypot3f_nid_postfix(float, float, float); -double APS5_VABI hypot3_nid_postfix(double, double, double); -long double APS5_VABI hypot3l_nid_postfix(long double, long double, long double); -float APS5_VABI j0f_nid_postfix(float); -float APS5_VABI j1f_nid_postfix(float); -float APS5_VABI jnf_nid_postfix(int, float); -float APS5_VABI y0f_nid_postfix(float); -float APS5_VABI y1f_nid_postfix(float); -float APS5_VABI ynf_nid_postfix(int, float); -std::lldiv_t APS5_VABI ldiv_nid_postfix(std::int64_t, std::int64_t); -float APS5_VABI nanf_nid_postfix(const char*); -double APS5_VABI nan_nid_postfix(const char*); -long double APS5_VABI atanl_nid_postfix(long double); -long double APS5_VABI sinl_nid_postfix(long double); -long double APS5_VABI cosl_nid_postfix(long double); -long double APS5_VABI tanl_nid_postfix(long double); -long double APS5_VABI sinhl_nid_postfix(long double); -long double APS5_VABI coshl_nid_postfix(long double); -long double APS5_VABI tanhl_nid_postfix(long double); -long double APS5_VABI expl_nid_postfix(long double); -long double APS5_VABI exp2l_nid_postfix(long double); -long double APS5_VABI logl_nid_postfix(long double); -long double APS5_VABI log10l_nid_postfix(long double); -long double APS5_VABI powl_nid_postfix(long double, long double); -long double APS5_VABI ldexpl_nid_postfix(long double, int); -long double APS5_VABI truncl_nid_postfix(long double); -long double APS5_VABI nearbyintl_nid_postfix(long double); -double APS5_VABI logb_nid_postfix(double); -double APS5_VABI remainder_nid_postfix(double, double); + struct DinkumwareFloatCharacteristics { int digits; int mantissaDigits; @@ -715,6 +542,35 @@ static void CheckExpm1ConsoleBits() { } } +static void CheckLog1pConsoleBits() { + constexpr struct { + std::uint64_t input; + std::uint64_t expected; + int error; + } cases[] = { + {0x0000000000000000ull, 0x0000000000000000ull, 0}, {0x8000000000000000ull, 0x8000000000000000ull, 0}, + {0x3c8fffffffffffffull, 0x3c8fffffffffffffull, 0}, {0x3c90000000000000ull, 0x3c90000000000000ull, 0}, + {0x3e1fffffffffffffull, 0x3e1fffffff7fffffull, 0}, {0x3e20000000000000ull, 0x3e1fffffff800000ull, 0}, + {0xbe20000000000000ull, 0xbe20000000400000ull, 0}, {0x3fda8279ffffffffull, 0x3fd62e43471c5d9dull, 0}, + {0x3fda827a00000000ull, 0x3fd62e43471c5d9eull, 0}, {0xbfd2bec400000000ull, 0xbfd62e4420e1ff10ull, 0}, + {0xbfd2bec3ffffffffull, 0xbfd62e4420e1ff0full, 0}, {0x3ff0000000000000ull, 0x3fe62e42fefa39efull, 0}, + {0xbfe0000000000000ull, 0xbfe62e42fefa39efull, 0}, {0xbfefffffffffffffull, 0xc0425e4f7b2737faull, 0}, + {0xbff0000000000000ull, 0xfff0000000000000ull, 0}, {0xbff0000000000001ull, 0xfff8000000000000ull, EDOM}, + {0xc000000000000000ull, 0xfff8000000000000ull, EDOM}, {0x433fffffffffffffull, 0x40425e4f7b2737faull, 0}, + {0x4340000000000000ull, 0x40425e4f7b2737faull, 0}, {0x7fefffffffffffffull, 0x40862e42fefa39efull, 0}, + {0x7ff0000000000000ull, 0x7ff0000000000000ull, 0}, {0xfff0000000000000ull, 0xfff8000000000000ull, EDOM}, + {0x7ff8000000000001ull, 0x7ff8000000000001ull, 0}, {0xfff8000000000002ull, 0xfff8000000000002ull, EDOM}, + {0x3f0f5ab6d3865ccaull, 0x3f0f5a7962a0216cull, 0}, {0x3fe8683f0ace287cull, 0x3fe223b9ede79242ull, 0}, + {0x3f5f8cd247124706ull, 0x3f5f850e039f6187ull, 0}, {0x40298faede87074bull, 0x4004fc71ddb00cc0ull, 0}, + {0x404b621796f08648ull, 0x401015adbb851c70ull, 0}, {0x3f21ecf9339d7420ull, 0x3f21eca8e0601790ull, 0}, + }; + for (const auto& item : cases) { + errno = 1234; + Require(std::bit_cast(log1p_nid_postfix(std::bit_cast(item.input))) == item.expected); + Require(errno == (item.error != 0 ? item.error : 1234)); + } +} + static void CheckAsinl() { const struct { std::uint64_t inputMantissa; std::uint16_t inputSignExponent; std::uint64_t outputMantissa; std::uint16_t outputSignExponent; } cases[] = { {0, 0x0000, 0, 0x0000}, {0, 0x8000, 0, 0x8000}, @@ -938,10 +794,12 @@ static void CheckAsin() { std::feclearexcept(FE_ALL_EXCEPT); errno = 0; asin_nid_postfix(2.0); + Require(std::fetestexcept(FE_INVALID)); Require(errno == 0); std::feclearexcept(FE_ALL_EXCEPT); asin_nid_postfix(nan); + Require(!std::fetestexcept(FE_INVALID)); } @@ -977,6 +835,7 @@ static void CheckTrigfConsoleBits() { float sine = 0.0f; float cosine = 0.0f; sincosf_nid_postfix(x, &sine, &cosine); + Require(std::bit_cast(sine) == item.sine && std::bit_cast(cosine) == item.cosine); } } @@ -1015,6 +874,26 @@ static void CheckExtendedMath() { Require(std::isnan(remainder_nid_postfix(1.0, 0.0)) && std::isnan(remainder_nid_postfix(INFINITY, 1.0))); } +static void CheckExp2fConsoleBits() { + constexpr struct { + std::uint32_t input; + std::uint32_t expected; + int error; + } cases[] = { + {0x3d00010bu, 0x3f82cd8du, 0}, {0x3f000303u, 0x3fb5066du, 0}, {0x40a0051bu, 0x42000e29u, 0}, {0x42f0070cu, 0x7b813a1bu, 0}, + {0xbf400909u, 0x3f183437u, 0}, {0xc2f00b14u, 0x037c3073u, 0}, {0x00000000u, 0x3f800000u, 0}, {0x80000000u, 0x3f800000u, 0}, + {0x33000000u, 0x3f800000u, 0}, {0x3f800000u, 0x40000000u, 0}, {0x42fe0000u, 0x7f000000u, 0}, {0x42ffffffu, 0x7f7fffa7u, 0}, + {0x43000000u, 0x7f800000u, ERANGE}, {0x7f7fffffu, 0x7f800000u, ERANGE}, {0x7f800000u, 0x7f800000u, 0}, {0xff800000u, 0x00000000u, 0}, + {0xc2fc0000u, 0x00800000u, 0}, {0xc3150000u, 0x00000001u, 0}, {0xc315ffffu, 0x00000001u, 0}, {0xc3160000u, 0x00000000u, ERANGE}, + {0xc3160001u, 0x00000000u, ERANGE}, {0xff7fffffu, 0x00000000u, ERANGE}, {0x7fc00001u, 0x7fc00001u, 0}, {0xffc00002u, 0xffc00002u, 0}, + }; + for (const auto& item : cases) { + errno = 1234; + Require(std::bit_cast(exp2f_nid_postfix(std::bit_cast(item.input))) == item.expected); + Require(errno == (item.error != 0 ? item.error : 1234)); + } +} + static void CheckHyperbolic() { const double infinity = std::numeric_limits::infinity(); Require(_Cosh_nid_postfix(0.0, 2.0) == 2.0); @@ -1608,6 +1487,7 @@ int main() { Require(rand_r_nid_postfix(&randomState) == 16806 && randomState == 16806u); for (const unsigned int seed : {0u, 1u, 12345u, 0x7ffffffeu, 0xffffffffu}) { srand_nid_postfix(seed); + randomState = seed; for (int step = 0; step < 8; ++step) Require(rand_r_nid_postfix(&randomState) == rand_nid_postfix()); } @@ -1674,6 +1554,7 @@ int main() { const auto gammaSign = [](double x) { signgam_nid_postfix = 7; lgamma_nid_postfix(x); + return signgam_nid_postfix; }; Require(gammaSign(0.5) == 1 && gammaSign(10.) == 1 && gammaSign(0.) == 1 && gammaSign(-0.) == -1); @@ -1724,6 +1605,7 @@ int main() { CheckLongDouble(); CheckNearbyintl(); CheckExpm1ConsoleBits(); + CheckLog1pConsoleBits(); CheckAsinl(); Require(scalbn_nid_postfix(0.75, -2) == 0.1875); Require(scalbnf_nid_postfix(0.75f, 4) == 12.f); @@ -1848,6 +1730,7 @@ int main() { CheckHyperbolic(); CheckAcoshfMsunBoundaries(); CheckCoshfMsunBoundaries(); + CheckExp2fConsoleBits(); CheckScaledHyperbolic(); CheckSinhf(); CheckAtanhf(); diff --git a/core/libs/tests/GuestMathExact.cpp b/core/libs/tests/GuestMathExact.cpp index e601e88973..db7361070f 100644 --- a/core/libs/tests/GuestMathExact.cpp +++ b/core/libs/tests/GuestMathExact.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -7,35 +8,6 @@ #include #include -extern "C" { -long double APS5_VABI fdiml_nid_postfix(long double, long double); -long double APS5_VABI fmodl_nid_postfix(long double, long double); -long double APS5_VABI remquol_nid_postfix(long double, long double, int*); -int APS5_VABI ilogbl_nid_postfix(long double); -long double APS5_VABI roundl_nid_postfix(long double); -long double APS5_VABI modfl_nid_postfix(long double, long double*); -long double APS5_VABI nanl_nid_postfix(const char*); -long double APS5_VABI scalblnl_nid_postfix(long double, std::int64_t); -long double APS5_VABI fmal_nid_postfix(long double, long double, long double); -double APS5_VABI scalb_nid_postfix(double, double); -double APS5_VABI scalbln_nid_postfix(double, std::int64_t); -long double APS5_VABI remainderl_nid_postfix(long double, long double); -double APS5_VABI drem_nid_postfix(double, double); -float APS5_VABI dremf_nid_postfix(float, float); -std::int64_t APS5_VABI lrint_nid_postfix(double); -double APS5_VABI rint_nid_postfix(double); -float APS5_VABI rintf_nid_postfix(float); -long double APS5_VABI rintl_nid_postfix(long double); -long long APS5_VABI llrint_nid_postfix(double); -int APS5_VABI finite_nid_postfix(double); -int APS5_VABI __fpclassifyl_nid_postfix(long double); -int APS5_VABI __isnanl_nid_postfix(long double); -int APS5_VABI __isnormall_nid_postfix(long double); -short APS5_VABI _LDtest_nid_postfix(const long double*); -int APS5_VABI _Dclass_nid_postfix(double); -short APS5_VABI _LDsign_nid_postfix(long double); -} - static void Require(bool value) { if (!value) std::abort(); } static long double Extended(std::uint16_t signExponent, std::uint64_t mantissa) { @@ -49,6 +21,40 @@ static long double Extended(std::uint16_t signExponent, std::uint64_t mantissa) static bool SameBits(long double left, long double right) { return std::memcmp(&left, &right, 10) == 0; } +static void CheckRoundingAndScaling() { + Require(copysignl_nid_postfix(3.0L, -1.0L) == -3.0L && copysignl_nid_postfix(-3.0L, 0.0L) == 3.0L); + Require(std::signbit(copysignl_nid_postfix(0.0L, -0.0L)) && !std::signbit(copysignl_nid_postfix(-0.0L, 2.0L))); + Require(sqrtl_nid_postfix(6.25L) == 2.5L && std::isnan(sqrtl_nid_postfix(-1.0L))); + Require(sqrtl_nid_postfix(-0.0L) == 0.0L && std::signbit(sqrtl_nid_postfix(-0.0L))); + + const int saved = std::fegetround(); + const struct { + int mode; + long long half; + long long negativeHalf; + } modes[] = {{FE_TONEAREST, 2, -2}, {FE_UPWARD, 3, -2}, {FE_DOWNWARD, 2, -3}, {FE_TOWARDZERO, 2, -2}}; + for (const auto& mode : modes) { + Require(std::fesetround(mode.mode) == 0); + errno = 0; + Require(lrintl_nid_postfix(2.5L) == mode.half && lrintl_nid_postfix(-2.5L) == mode.negativeHalf); + Require(llrintl_nid_postfix(2.5L) == mode.half && llrintl_nid_postfix(-2.5L) == mode.negativeHalf); + Require(lrintf_nid_postfix(2.5f) == mode.half && lrintf_nid_postfix(-2.5f) == mode.negativeHalf); + Require(llrintf_nid_postfix(2.5f) == mode.half && llrintf_nid_postfix(-2.5f) == mode.negativeHalf); + Require(errno == 0); + } + std::fesetround(saved); + Require(llrintl_nid_postfix(3.5L) == 4 && lrintf_nid_postfix(16777216.0f) == 16777216); + + Require(scalbf_nid_postfix(1.5f, 3.0f) == 12.0f && scalbf_nid_postfix(12.0f, -2.0f) == 3.0f); + Require(std::isnan(scalbf_nid_postfix(1.0f, 0.5f)) && std::isnan(scalbf_nid_postfix(NAN, 1.0f))); + Require(std::isinf(scalbf_nid_postfix(1.0f, INFINITY)) && scalbf_nid_postfix(8.0f, -INFINITY) == 0.0f); + Require(scalblnf_nid_postfix(1.0f, 10) == 1024.0f && scalblnf_nid_postfix(1024.0f, -10) == 1.0f); + Require(std::isinf(scalblnf_nid_postfix(1.0f, INT64_MAX)) && scalblnf_nid_postfix(1.0f, INT64_MIN) == 0.0f); + + Require(__isinfl_nid_postfix(static_cast(INFINITY)) == 1 && __isinfl_nid_postfix(-static_cast(INFINITY)) == 1); + Require(__isinfl_nid_postfix(1.0L) == 0 && __isinfl_nid_postfix(static_cast(NAN)) == 0 && __isinfl_nid_postfix(0.0L) == 0); +} + static void CheckSignalingNanPassThrough() { const long double signaling = Extended(0x7fff, 0x8000000000001234ull); Require(SameBits(fdiml_nid_postfix(signaling, 1.0L), signaling)); @@ -70,6 +76,7 @@ static void CheckErrno() { Require(std::isnan(remquol_nid_postfix(1.0L, 0.0L, "ient)) && errno == EDOM); errno = 0; remquol_nid_postfix(NAN, 0.0L, "ient); + Require(errno == 0); Require(remquol_nid_postfix(-7.0L, 2.0L, "ient) == 1.0L && quotient == -4); errno = 0; @@ -133,6 +140,7 @@ static void CheckClassification() { } int main() { + CheckRoundingAndScaling(); CheckSignalingNanPassThrough(); CheckErrno(); CheckConsoleQuirks(); diff --git a/core/libs/tests/GuestMbus.cpp b/core/libs/tests/GuestMbus.cpp index e867068157..4050f1d452 100644 --- a/core/libs/tests/GuestMbus.cpp +++ b/core/libs/tests/GuestMbus.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceMbus/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -6,26 +7,6 @@ #include #include -struct DeviceServiceThreadParam; -struct DeviceServiceInitParam { - std::uint32_t size; - std::uint32_t reserved; - const DeviceServiceThreadParam* threadParam; -}; -struct DeviceServiceUsageFilter { - std::uint16_t usagePage; - std::uint16_t minimumUsage; - std::uint16_t maximumUsage; -}; - -extern "C" { -std::int32_t APS5_VABI sceDeviceServiceInitialize(std::int32_t mode, const DeviceServiceInitParam* param); -std::int32_t APS5_VABI sceDeviceServiceTerminate(); -std::int32_t APS5_VABI sceDeviceServiceGetEventState(std::int32_t clear); -std::int32_t APS5_VABI sceDeviceServiceQueryDeviceInfo_(std::int32_t deviceClass, const DeviceServiceUsageFilter* filter, std::int32_t arg2, void* infos, std::int32_t maxInfos, std::int32_t* count, std::int32_t* reserved, std::uint32_t infoSize); -std::int32_t APS5_VABI sceDeviceServiceGetGeneration(); -} - namespace { void Require(bool condition, const char* message) { diff --git a/core/libs/tests/GuestMemory.cpp b/core/libs/tests/GuestMemory.cpp index bb7246740c..66cb09290a 100644 --- a/core/libs/tests/GuestMemory.cpp +++ b/core/libs/tests/GuestMemory.cpp @@ -1,3 +1,6 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libkernel/File/include/File.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libc/include/GuestAllocations.hpp" #include "prx/libc/include/GuestHeap.hpp" @@ -42,55 +45,6 @@ #include #endif -extern "C" { -void* APS5_VABI mmap_nid_postfix(void*, std::size_t, int, int, int, std::int64_t) noexcept; -int APS5_VABI munmap_nid_postfix(void*, std::size_t) noexcept; -int APS5_VABI sceKernelMmap(void*, std::size_t, int, int, int, std::int64_t, void**); -int APS5_VABI mprotect_nid_postfix(void*, std::size_t, int) noexcept; -int APS5_VABI madvise_nid_postfix(void*, std::size_t, int); -int APS5_VABI mincore_nid_postfix(const void*, std::size_t, char*); -int* APS5_VABI __error_nid_postfix(); -int APS5_VABI sceKernelMapNamedFlexibleMemory(void**, std::size_t, int, int, const char*); -int APS5_VABI sceKernelMapNamedFlexibleMemoryInternal(void**, std::size_t, int, int, const char*); -int APS5_VABI sceKernelAvailableFlexibleMemorySize(std::size_t*); -int APS5_VABI sceKernelInternalMemoryGetAvailableSize(std::size_t*); -int APS5_VABI sceKernelMapFlexibleMemory(void**, std::size_t, int, int); -int APS5_VABI sceKernelMunmap(void*, std::size_t); -int APS5_VABI sceKernelReleaseFlexibleMemory(void*, std::size_t); -int APS5_VABI sceKernelMprotect(const void*, std::size_t, int); -int APS5_VABI sceKernelMtypeprotect(const void*, std::size_t, int, int); -int APS5_VABI sceKernelBatchMap2(KernelBatchMapEntry*, int, int*, int); -int APS5_VABI sceKernelMemoryPoolBatch(const KernelMemoryPoolBatchEntry*, int, int*, int); -int APS5_VABI sceKernelVirtualQuery(const void*, int, VirtualQueryInfo*, std::uint64_t); -int APS5_VABI sceKernelSetVirtualRangeName(const void*, std::uint64_t, const char*); -int APS5_VABI sceKernelClearVirtualRangeName(const void*, std::uint64_t); -int APS5_VABI sceKernelGetPageTableStats(int*, int*, int*, int*); -int APS5_VABI sceKernelAllocateDirectMemory(std::int64_t, std::int64_t, std::size_t, std::size_t, int, std::int64_t*); -int APS5_VABI sceKernelMapDirectMemory(void**, std::size_t, int, int, std::int64_t, std::size_t); -int APS5_VABI sceKernelEnableDmemAliasing(); -int APS5_VABI sceKernelReleaseDirectMemory(std::int64_t, std::size_t); -int APS5_VABI sceKernelAvailableDirectMemorySize(std::int64_t, std::int64_t, std::size_t, std::int64_t*, std::size_t*); -int APS5_VABI sceKernelCheckedReleaseDirectMemory(std::int64_t, std::size_t); -int APS5_VABI sceKernelReserveVirtualRange(void**, std::size_t, int, std::size_t); -int APS5_VABI sceKernelMemoryPoolReserve(void*, std::size_t, std::size_t, int, void**); -int APS5_VABI sceKernelMemoryPoolCommit(void*, std::size_t, int, int, int); -int APS5_VABI sceKernelOpen(const char*, int, std::uint16_t); -int APS5_VABI sceKernelClose(int); -std::int64_t APS5_VABI sceKernelRead(int, void*, std::size_t); -std::int64_t APS5_VABI sceKernelPread(int, void*, std::size_t, std::int64_t); -std::int64_t APS5_VABI sceKernelPwrite(int, const void*, std::size_t, std::int64_t); -int APS5_VABI sceKernelAioInitializeImpl(void*, std::int32_t); -int APS5_VABI sceKernelAioSubmitReadCommands(KernelAioRwRequest*, std::int32_t, std::int32_t, std::int32_t*); -int APS5_VABI sceKernelAioWaitRequest(std::int32_t, std::int32_t*, std::uint32_t*); -int APS5_VABI sceKernelAioDeleteRequest(std::int32_t, std::int32_t*); -int APS5_VABI sceKernelMlock_nid_postfix(void*, std::uint64_t); -int APS5_VABI sceKernelGetDirectMemoryType(std::int64_t, int*, std::int64_t*, std::int64_t*); -int APS5_VABI sceKernelBatchMap2(KernelBatchMapEntry*, int, int*, int); -void* APS5_VABI dlopen_nid_postfix(const char*, int); -void* APS5_VABI dlsym_nid_postfix(void*, const char*); -int APS5_VABI dlclose_nid_postfix(void*); -} - static void Require(bool condition, std::source_location location = std::source_location::current()) { if (!condition) { std::fprintf(stderr, "Guest memory check failed at %s:%u\n", location.file_name(), static_cast(location.line())); @@ -139,7 +93,7 @@ static void CheckReleaseFlexibleMemory() { Require(sceKernelMapFlexibleMemory(&again, length, 3, 0x10) == 0 && again == mapped); Require(static_cast(again)[length - 1] == 0); Require(sceKernelAvailableFlexibleMemorySize(&available) == 0 && available == before - length); - Require(sceKernelMunmap(again, length) == 0); + Require(sceKernelMunmap(reinterpret_cast(again), length) == 0); } static void CheckFlexibleMappingIgnoresFlag8000() { @@ -151,11 +105,11 @@ static void CheckFlexibleMappingIgnoresFlag8000() { Require(sceKernelMapFlexibleMemory(&mapped, length, 3, 0x8000) == 0 && mapped != nullptr); static_cast(mapped)[length - 1] = 1; Require(sceKernelAvailableFlexibleMemorySize(&available) == 0 && available == before - length); - Require(sceKernelMunmap(mapped, length) == 0); + Require(sceKernelMunmap(reinterpret_cast(mapped), length) == 0); void* again = mapped; Require(sceKernelMapFlexibleMemory(&again, length, 3, 0x8090) == 0 && again == mapped); Require(static_cast(again)[length - 1] == 0); - Require(sceKernelMunmap(again, length) == 0); + Require(sceKernelMunmap(reinterpret_cast(again), length) == 0); Require(sceKernelAvailableFlexibleMemorySize(&available) == 0 && available == before); bool rejected = false; void* unknown = nullptr; @@ -181,6 +135,7 @@ static void CheckInternalMemoryAvailableSize() { bool threw = false; try { sceKernelInternalMemoryGetAvailableSize(&available); + } catch (const std::logic_error&) { threw = true; } @@ -207,13 +162,13 @@ static void CheckNamedAndHintedMappings() { void* overwrite = first; Require(sceKernelMapFlexibleMemory(&overwrite, 0x4000, 3, 0x90) == static_cast(0x8002000cu)); Require(overwrite == first); - Require(sceKernelMunmap(hinted, length) == 0); + Require(sceKernelMunmap(reinterpret_cast(hinted), length) == 0); void* exclusive = hinted; Require(sceKernelMapFlexibleMemory(&exclusive, length, 3, 0x90) == 0); Require(exclusive == hinted); static_cast(exclusive)[0] = 1; - Require(sceKernelMunmap(exclusive, length) == 0); - Require(sceKernelMunmap(first, length) == 0); + Require(sceKernelMunmap(reinterpret_cast(exclusive), length) == 0); + Require(sceKernelMunmap(reinterpret_cast(first), length) == 0); } static void CheckAudioCoprocessorProtection() { @@ -226,7 +181,7 @@ static void CheckAudioCoprocessorProtection() { Require(static_cast(writable)[length - 1] == 7); Require(sceKernelMprotect(writable, length, 0x3f2) == 0); static_cast(writable)[0] = 9; - Require(sceKernelMunmap(writable, length) == 0); + Require(sceKernelMunmap(reinterpret_cast(writable), length) == 0); bool rejected = false; void* undefined = nullptr; try { sceKernelMapFlexibleMemory(&undefined, length, 0x400, 0); } catch (const std::invalid_argument&) { rejected = true; } @@ -262,7 +217,7 @@ static void CheckMprotectIgnoresUndefinedBits() { for (const auto undefined : {0u, 8u, 0x400u, 0x80000000u, 0xfffffc08u}) check(mapping, static_cast(static_cast(protection) | undefined)); } - Require(sceKernelMunmap(mapping, length) == 0); + Require(sceKernelMunmap(reinterpret_cast(mapping), length) == 0); std::int64_t physical = 0; Require(sceKernelAllocateDirectMemory(0, 0x7fffffffffll, length, 0, 0, &physical) == 0); mapping = nullptr; @@ -272,7 +227,7 @@ static void CheckMprotectIgnoresUndefinedBits() { check(mapping, 0x100); check(mapping, 0x200); check(mapping, 0x3f7); - Require(sceKernelMunmap(mapping, length) == 0); + Require(sceKernelMunmap(reinterpret_cast(mapping), length) == 0); Require(sceKernelReleaseDirectMemory(physical, length) == 0); } @@ -310,7 +265,7 @@ static void CheckStrictMemoryProtectionBits() { Require(sceKernelGetDirectMemoryType(physical, &type, &start, &end) == 0 && type == 0); Require(bytes[0] == 5 && bytes[length - 1] == 7); } - Require(sceKernelMunmap(mapping, length) == 0); + Require(sceKernelMunmap(reinterpret_cast(mapping), length) == 0); Require(sceKernelReleaseDirectMemory(physical, length) == 0); } @@ -334,14 +289,14 @@ static void CheckInternalNamedFlexibleMapping() { Require(sceKernelMapNamedFlexibleMemoryInternal(&mapped, length, 3, 0, "internal mapping") == 0 && mapped != nullptr); Require(std::strcmp(NameAt(mapped), "internal mapping") == 0); Require(sceKernelAvailableFlexibleMemorySize(&available) == 0 && available == before - length); - Require(sceKernelMunmap(mapped, length) == 0); + Require(sceKernelMunmap(reinterpret_cast(mapped), length) == 0); Require(sceKernelAvailableFlexibleMemorySize(&available) == 0 && available == before); void* flagged = nullptr; Require(sceKernelMapNamedFlexibleMemoryInternal(&flagged, length, 3, 0x8000, "internal flag") == 0 && flagged != nullptr); Require(std::strcmp(NameAt(flagged), "internal flag") == 0); static_cast(flagged)[length - 1] = 1; Require(sceKernelAvailableFlexibleMemorySize(&available) == 0 && available == before - length); - Require(sceKernelMunmap(flagged, length) == 0); + Require(sceKernelMunmap(reinterpret_cast(flagged), length) == 0); bool rejected = false; void* unknown = nullptr; try { sceKernelMapNamedFlexibleMemoryInternal(&unknown, length, 3, 0x20000, "internal mapping"); } catch (const std::exception&) { rejected = true; } @@ -364,7 +319,7 @@ static void CheckFlexibleFixedReplacement() { Require(sceKernelMapFlexibleMemory(&replacement, page, 3, 0x10) == 0 && replacement == middle); Require(bytes[0] == 17 && bytes[page] == 0 && bytes[page * 2] == 19 && bytes[page * 3] == 20); Require(sceKernelAvailableFlexibleMemorySize(&available) == 0 && available == before - page * 4); - Require(sceKernelMunmap(base, page * 4) == 0); + Require(sceKernelMunmap(reinterpret_cast(base), page * 4) == 0); Require(sceKernelAvailableFlexibleMemorySize(&available) == 0 && available == before); } @@ -382,23 +337,23 @@ static void CheckMunmapScopedFlexibleRelease() { Require(sceKernelMapDirectMemory(&direct, page, 3, 0x10, phys, 0) == 0 && direct == static_cast(base) + page); std::size_t mid = 0; Require(sceKernelAvailableFlexibleMemorySize(&mid) == 0); - Require(sceKernelMunmap(direct, page) == 0); + Require(sceKernelMunmap(reinterpret_cast(direct), page) == 0); Require(sceKernelAvailableFlexibleMemorySize(&available) == 0 && available == mid); void* reserved = nullptr; Require(sceKernelReserveVirtualRange(&reserved, page * 2, 0, 0) == 0 && reserved != nullptr); Require(sceKernelAvailableFlexibleMemorySize(&available) == 0 && available == mid); - Require(sceKernelMunmap(reserved, page * 2) == 0); + Require(sceKernelMunmap(reinterpret_cast(reserved), page * 2) == 0); Require(sceKernelAvailableFlexibleMemorySize(&available) == 0 && available == mid); - Require(sceKernelMunmap(base, page) == 0); + Require(sceKernelMunmap(reinterpret_cast(base), page) == 0); Require(sceKernelAvailableFlexibleMemorySize(&available) == 0 && available == mid + page); Require(sceKernelReleaseDirectMemory(phys, page) == 0); void* fresh = nullptr; Require(sceKernelMapFlexibleMemory(&fresh, page * 4, 3, 0) == 0 && fresh != nullptr); Require(sceKernelAvailableFlexibleMemorySize(&available) == 0 && available == before - page * 4); - Require(sceKernelMunmap(static_cast(fresh) + page, page * 2) == 0); + Require(sceKernelMunmap(reinterpret_cast(static_cast(fresh) + page), page * 2) == 0); Require(sceKernelAvailableFlexibleMemorySize(&available) == 0 && available == before - page * 2); - Require(sceKernelMunmap(fresh, page) == 0); - Require(sceKernelMunmap(static_cast(fresh) + page * 3, page) == 0); + Require(sceKernelMunmap(reinterpret_cast(fresh), page) == 0); + Require(sceKernelMunmap(reinterpret_cast(static_cast(fresh) + page * 3), page) == 0); Require(sceKernelAvailableFlexibleMemorySize(&available) == 0 && available == before); } @@ -430,7 +385,7 @@ static void CheckBatchMapStopsAtInvalidEntry() { Require(sceKernelBatchMap2(entries, 3, &processed, 0) == SCE_KERNEL_ERROR_EINVAL); Require(processed == 1); Require(entries[0].start != nullptr && entries[1].start == nullptr && entries[2].start == nullptr); - Require(sceKernelMunmap(entries[0].start, page) == 0); + Require(sceKernelMunmap(reinterpret_cast(entries[0].start), page) == 0); } KernelBatchMapEntry entries[3] = {flexible(), flexible(), flexible()}; entries[1].operation = protect; @@ -446,7 +401,7 @@ static void CheckBatchMapStopsAtInvalidEntry() { processed = -1; Require(sceKernelBatchMap2(unmaps, 2, &processed, 0) == SCE_KERNEL_ERROR_EINVAL && processed == 1); Require(sceKernelBatchMap2(entries, 1, &processed, 0) == 0 && processed == 1); - Require(sceKernelMunmap(entries[0].start, page) == 0); + Require(sceKernelMunmap(reinterpret_cast(entries[0].start), page) == 0); } static void CheckVirtualQueryFindsNeighbours() { @@ -464,14 +419,14 @@ static void CheckVirtualQueryFindsNeighbours() { Require(info.start == reinterpret_cast(low) + page && info.end == reinterpret_cast(low) + page * 2 && info.protection == 1); Require(sceKernelVirtualQuery(lowBytes + page * 2, 0, &info, sizeof(info)) == 0); Require(info.start == reinterpret_cast(low) + page * 2 && info.end == reinterpret_cast(low) + page * 4 && info.protection == 3); - Require(sceKernelMunmap(lowBytes + page * 2, page) == 0); + Require(sceKernelMunmap(reinterpret_cast(lowBytes + page * 2), page) == 0); Require(sceKernelVirtualQuery(lowBytes + page * 2, 0, &info, sizeof(info)) != 0); Require(sceKernelVirtualQuery(lowBytes + page * 2, 1, &info, sizeof(info)) == 0); Require(info.start == reinterpret_cast(low) + page * 3 && info.end == reinterpret_cast(low) + page * 4); Require(sceKernelVirtualQuery(lowBytes + page * 3, 0, &info, sizeof(info)) == 0 && info.start == reinterpret_cast(low) + page * 3); - Require(sceKernelMunmap(low, page * 2) == 0); - Require(sceKernelMunmap(lowBytes + page * 3, page) == 0); - Require(sceKernelMunmap(high, page) == 0); + Require(sceKernelMunmap(reinterpret_cast(low), page * 2) == 0); + Require(sceKernelMunmap(reinterpret_cast(lowBytes + page * 3), page) == 0); + Require(sceKernelMunmap(reinterpret_cast(high), page) == 0); } static void CheckReleaseFindsEveryDirectMapping() { @@ -527,7 +482,7 @@ static void CheckCheckedReleaseDirectMemory() { Require(sceKernelCheckedReleaseDirectMemory(phys, page * 3) == SCE_KERNEL_ERROR_ENOENT); void* mapped = nullptr; Require(sceKernelMapDirectMemory(&mapped, page * 2, 3, 0, phys, 0) == 0); - Require(sceKernelMunmap(mapped, page * 2) == 0); + Require(sceKernelMunmap(reinterpret_cast(mapped), page * 2) == 0); Require(sceKernelCheckedReleaseDirectMemory(phys + page, page) == 0); Require(sceKernelCheckedReleaseDirectMemory(phys, page * 2) == SCE_KERNEL_ERROR_ENOENT); Require(sceKernelCheckedReleaseDirectMemory(phys, page) == 0); @@ -556,9 +511,9 @@ static void CheckDirectMemoryFollowsPhysicalPages() { Require(sceKernelMprotect(alias, page, 3) == 0); static_cast(alias)[5] = 22; Require(static_cast(first)[page + 5] == 22); - Require(sceKernelMunmap(alias, page) == 0); + Require(sceKernelMunmap(reinterpret_cast(alias), page) == 0); static_cast(first)[page + 5] = 22; - Require(sceKernelMunmap(first, page * 2) == 0); + Require(sceKernelMunmap(reinterpret_cast(first), page * 2) == 0); void* filler = nullptr; Require(sceKernelMapFlexibleMemory(&filler, page * 2, 3, 0) == 0); void* second = nullptr; @@ -569,16 +524,16 @@ static void CheckDirectMemoryFollowsPhysicalPages() { void* fixed = reserved; Require(sceKernelMapDirectMemory(&fixed, page, 1, 0x10, phys, 0) == 0); Require(fixed == reserved && static_cast(fixed)[0] == 11); - Require(sceKernelMunmap(fixed, page) == 0); - Require(sceKernelMunmap(second, page) == 0); + Require(sceKernelMunmap(reinterpret_cast(fixed), page) == 0); + Require(sceKernelMunmap(reinterpret_cast(second), page) == 0); Require(sceKernelReleaseDirectMemory(phys, page * 2) == 0); std::int64_t again = 0; Require(sceKernelAllocateDirectMemory(0, 0x7fffffffffll, page * 2, 0, 0, &again) == 0 && again == phys); void* fresh = nullptr; Require(sceKernelMapDirectMemory(&fresh, page * 2, 3, 0, again, 0) == 0); Require(static_cast(fresh)[0] == 0 && static_cast(fresh)[page + 5] == 0); - Require(sceKernelMunmap(fresh, page * 2) == 0); - Require(sceKernelMunmap(filler, page * 2) == 0); + Require(sceKernelMunmap(reinterpret_cast(fresh), page * 2) == 0); + Require(sceKernelMunmap(reinterpret_cast(filler), page * 2) == 0); Require(sceKernelReleaseDirectMemory(again, page * 2) == 0); } @@ -602,11 +557,11 @@ static void CheckSparseDirectMemoryBacking() { Require(aliasBytes[page - 1] == 29 && aliasBytes[0] == 0); aliasBytes[page - 1] = 41; Require(lastBytes[page - 1] == 41 && firstBytes[0] == 17); - Require(sceKernelMunmap(last, page) == 0 && sceKernelMunmap(alias, page) == 0); + Require(sceKernelMunmap(reinterpret_cast(last), page) == 0 && sceKernelMunmap(reinterpret_cast(alias), page) == 0); last = nullptr; Require(sceKernelMapDirectMemory(&last, page, 3, 0, physical + size - page, 0) == 0); Require(static_cast(last)[page - 1] == 41); - Require(sceKernelMunmap(first, page) == 0 && sceKernelMunmap(last, page) == 0); + Require(sceKernelMunmap(reinterpret_cast(first), page) == 0 && sceKernelMunmap(reinterpret_cast(last), page) == 0); Require(sceKernelReleaseDirectMemory(physical, size) == 0); } @@ -619,7 +574,7 @@ static void CheckSavedDirectMemorySurvivesCachePressure() { void* mapped = nullptr; Require(sceKernelMapDirectMemory(&mapped, bytes, 3, 0, retained[index], bytes) == 0); std::memset(mapped, static_cast(index + 1), bytes); - Require(sceKernelMunmap(mapped, bytes) == 0); + Require(sceKernelMunmap(reinterpret_cast(mapped), bytes) == 0); } const auto temporary = [] { constexpr std::size_t small = 0x10000; @@ -632,12 +587,12 @@ static void CheckSavedDirectMemorySurvivesCachePressure() { Require(std::all_of(data, data + small, [](unsigned char value) { return value == 0; })); data[7] = round; data[small - 1] = static_cast(round + 0x40); - Require(sceKernelMunmap(mapped, small) == 0); + Require(sceKernelMunmap(reinterpret_cast(mapped), small) == 0); mapped = nullptr; Require(sceKernelMapDirectMemory(&mapped, small, 3, 0, physical, 0) == 0); data = static_cast(mapped); for (std::size_t at = 0; at < small; ++at) Require(data[at] == (at == 7 ? round : at == small - 1 ? static_cast(round + 0x40) : 0)); - Require(sceKernelMunmap(mapped, small) == 0); + Require(sceKernelMunmap(reinterpret_cast(mapped), small) == 0); Require(sceKernelReleaseDirectMemory(physical, small) == 0); } }; @@ -647,7 +602,7 @@ static void CheckSavedDirectMemorySurvivesCachePressure() { Require(sceKernelMapDirectMemory(&mapped, bytes, 3, 0, retained[index], bytes) == 0); const auto* data = static_cast(mapped); Require(std::all_of(data, data + bytes, [&](unsigned char value) { return value == index + 1; })); - Require(sceKernelMunmap(mapped, bytes) == 0); + Require(sceKernelMunmap(reinterpret_cast(mapped), bytes) == 0); Require(sceKernelReleaseDirectMemory(retained[index], bytes) == 0); } temporary(); @@ -678,7 +633,7 @@ static void CheckReusedDirectMemorySections() { auto physical = allocate(); auto* data = map(physical); std::memset(data, 0x5a, bytes); - Require(sceKernelMunmap(data, bytes) == 0); + Require(sceKernelMunmap(reinterpret_cast(data), bytes) == 0); auto before = handles(); Require(sceKernelReleaseDirectMemory(physical, bytes) == 0); const auto released = handles(); @@ -697,12 +652,12 @@ static void CheckReusedDirectMemorySections() { Require(data[page + 3] == 41); data[page * 2] = 53; Require(alias[page * 2] == 53); - Require(sceKernelMunmap(alias, bytes) == 0); + Require(sceKernelMunmap(reinterpret_cast(alias), bytes) == 0); Require(data[5] == 17 && data[page + 3] == 41 && data[page * 2] == 53); - Require(sceKernelMunmap(data, bytes) == 0); + Require(sceKernelMunmap(reinterpret_cast(data), bytes) == 0); data = map(physical); Require(data[5] == 17 && data[page + 3] == 41 && data[page * 2] == 53 && data[bytes - 1] == 29); - Require(sceKernelMunmap(data, bytes) == 0); + Require(sceKernelMunmap(reinterpret_cast(data), bytes) == 0); before = handles(); Require(sceKernelReleaseDirectMemory(physical, bytes) == 0); Require(handles() == before - 1); @@ -715,9 +670,9 @@ static void CheckReusedDirectMemorySections() { second = nullptr; Require(sceKernelMapDirectMemory(&second, page, 3, 0, physical + static_cast(page), 0) == 0); Require(static_cast(second)[page - 1] == round); - Require(sceKernelMunmap(second, page) == 0); + Require(sceKernelMunmap(reinterpret_cast(second), page) == 0); } - Require(sceKernelMunmap(data, bytes) == 0); + Require(sceKernelMunmap(reinterpret_cast(data), bytes) == 0); Require(sceKernelReleaseDirectMemory(physical, bytes) == 0); } #endif @@ -769,7 +724,7 @@ static void CheckFixedMappingReplacesPartialOverlap() { Require(sceKernelAllocateDirectMemory(0, 0x7fffffffffll, page * 3, 0, 0, &phys) == 0); void* reserved = nullptr; Require(sceKernelMapDirectMemory(&reserved, page * 3, 3, 0, phys, 0) == 0); - Require(sceKernelMunmap(reserved, page * 3) == 0); + Require(sceKernelMunmap(reinterpret_cast(reserved), page * 3) == 0); void* head = reserved; Require(sceKernelMapDirectMemory(&head, page, 3, 0x10, phys, 0) == 0 && head == reserved); void* fixed = reserved; @@ -780,7 +735,7 @@ static void CheckFixedMappingReplacesPartialOverlap() { Require(sceKernelVirtualQuery(fixed, 0, &info, sizeof(info)) == 0); Require(info.is_direct && info.offset == static_cast(phys)); Require(static_cast(fixed)[page * 2 + 7] == 0x5c); - Require(sceKernelMunmap(fixed, page * 3) == 0); + Require(sceKernelMunmap(reinterpret_cast(fixed), page * 3) == 0); Require(sceKernelReleaseDirectMemory(phys, page * 3) == 0); } @@ -793,14 +748,14 @@ static void CheckFixedMappingOverHoleInsideAllocation() { auto* bytes = static_cast(mapped); bytes[7] = 0x11; bytes[page * 3 + 7] = 0x44; - Require(sceKernelMunmap(bytes + page, page) == 0); + Require(sceKernelMunmap(reinterpret_cast(bytes + page), page) == 0); void* fixed = bytes + page; Require(sceKernelMapDirectMemory(&fixed, page * 2, 3, 0x10, phys + static_cast(page), 0) == 0); Require(fixed == bytes + page); bytes[page * 2 + 7] = 0x33; Require(bytes[7] == 0x11 && bytes[page * 2 + 7] == 0x33 && bytes[page * 3 + 7] == 0x44); - Require(sceKernelMunmap(bytes + page * 2, page * 2) == 0); - Require(sceKernelMunmap(mapped, page * 4) == 0); + Require(sceKernelMunmap(reinterpret_cast(bytes + page * 2), page * 2) == 0); + Require(sceKernelMunmap(reinterpret_cast(mapped), page * 4) == 0); Require(sceKernelReleaseDirectMemory(phys, page * 4) == 0); } @@ -901,7 +856,7 @@ static void CheckMtypeprotect() { std::int64_t start = -1; std::int64_t end = -1; Require(sceKernelGetDirectMemoryType(phys + static_cast(page * 2), &type, &start, &end) == 0 && type == 2); - Require(sceKernelMunmap(mapped, page * 3) == 0); + Require(sceKernelMunmap(reinterpret_cast(mapped), page * 3) == 0); Require(sceKernelReleaseDirectMemory(phys, page * 3) == 0); } @@ -913,7 +868,7 @@ static void CheckDirectMemoryGpuProtBits() { Require(sceKernelMapDirectMemory(&mapping, page, 0x3f2, 0, phys, 0) == 0); static_cast(mapping)[0] = 11; Require(static_cast(mapping)[0] == 11); - Require(sceKernelMunmap(mapping, page) == 0); + Require(sceKernelMunmap(reinterpret_cast(mapping), page) == 0); Require(sceKernelReleaseDirectMemory(phys, page) == 0); } @@ -947,16 +902,16 @@ static void CheckGpuAccessFollowsProtection() { const auto image = std::find_if(lease.begin(), lease.end(), [&](const auto& range) { return probe >= range->address && probe - range->address < range->bytes; }); Require(image != lease.end() && !(*image)->releasable && !(*image)->gpu); } - Require(sceKernelMunmap(cpu, page) == 0); - Require(sceKernelMunmap(gpu, page) == 0); + Require(sceKernelMunmap(reinterpret_cast(cpu), page) == 0); + Require(sceKernelMunmap(reinterpret_cast(gpu), page) == 0); Require(sceKernelReleaseDirectMemory(phys, page * 2) == 0); void* flexible = nullptr; Require(sceKernelMapNamedFlexibleMemory(&flexible, page, 3, 0, "cpu") == 0); Require(!GpuMapped(flexible)); - Require(sceKernelMunmap(flexible, page) == 0); + Require(sceKernelMunmap(reinterpret_cast(flexible), page) == 0); Require(sceKernelMapNamedFlexibleMemory(&flexible, page, 0x33, 0, "gpu") == 0); Require(GpuMapped(flexible)); - Require(sceKernelMunmap(flexible, page) == 0); + Require(sceKernelMunmap(reinterpret_cast(flexible), page) == 0); } static std::vector> gpuMapped; @@ -979,7 +934,7 @@ static void CheckClearingTheObserverWaitsForItsCalls() { GuestAllocations::GuestAllocationsSetGpuMapObserver_nid_postfix(nullptr); Require(observerDone); mapper.join(); - Require(sceKernelMunmap(gpu, page) == 0); + Require(sceKernelMunmap(reinterpret_cast(gpu), page) == 0); Require(sceKernelReleaseDirectMemory(phys, page) == 0); } @@ -1019,10 +974,10 @@ static void CheckGpuMapsAreObserved() { Require(sceKernelMapDirectMemory(&gpuRemap, page, 0x32, 0x10, remapPhys + static_cast(page), 0) == 0 && gpuRemap == gpuTarget); Require(gpuMapped.size() == 2 && gpuMapped.back().first == reinterpret_cast(gpuTarget) && gpuMapped.back().second == page); GuestAllocations::GuestAllocationsSetGpuMapObserver_nid_postfix(nullptr); - Require(sceKernelMunmap(reserved, page * 2) == 0); + Require(sceKernelMunmap(reinterpret_cast(reserved), page * 2) == 0); Require(sceKernelReleaseDirectMemory(remapPhys, page * 2) == 0); - Require(sceKernelMunmap(cpu, page) == 0); - Require(sceKernelMunmap(gpu, page) == 0); + Require(sceKernelMunmap(reinterpret_cast(cpu), page) == 0); + Require(sceKernelMunmap(reinterpret_cast(gpu), page) == 0); Require(sceKernelReleaseDirectMemory(phys, page * 2) == 0); } @@ -1030,7 +985,7 @@ static void CheckHintedVirtualReservation() { constexpr std::size_t page = 0x4000; void* probe = nullptr; Require(sceKernelReserveVirtualRange(&probe, page * 8, 0, 0) == 0); - Require(sceKernelMunmap(probe, page * 8) == 0); + Require(sceKernelMunmap(reinterpret_cast(probe), page * 8) == 0); void* const hint = static_cast(probe) + page * 2; void* placed = hint; Require(sceKernelReserveVirtualRange(&placed, page * 2, 0, 0) == 0); @@ -1038,8 +993,8 @@ static void CheckHintedVirtualReservation() { void* above = hint; Require(sceKernelReserveVirtualRange(&above, page * 2, 0, 0) == 0); Require(above > hint); - Require(sceKernelMunmap(above, page * 2) == 0); - Require(sceKernelMunmap(placed, page * 2) == 0); + Require(sceKernelMunmap(reinterpret_cast(above), page * 2) == 0); + Require(sceKernelMunmap(reinterpret_cast(placed), page * 2) == 0); } static void CheckReservationHintWithoutRoomAbove() { @@ -1055,15 +1010,15 @@ static void CheckReservationHintWithoutRoomAbove() { void* belowTheHint = lastPage; Require(sceKernelReserveVirtualRange(&belowTheHint, page * 2, 0, 0) == 0); Require(belowTheHint < lastPage && GuestArena::GuestArenaContains_nid_postfix(belowTheHint, page * 2)); - Require(sceKernelMunmap(belowTheHint, page * 2) == 0); - Require(sceKernelMunmap(aboveTheArena, page * 2) == 0); + Require(sceKernelMunmap(reinterpret_cast(belowTheHint), page * 2) == 0); + Require(sceKernelMunmap(reinterpret_cast(aboveTheArena), page * 2) == 0); } static void CheckFixedVirtualReservation() { constexpr std::size_t page = 0x4000; void* probe = nullptr; Require(sceKernelReserveVirtualRange(&probe, page * 4, 0, 0) == 0); - Require(sceKernelMunmap(probe, page * 4) == 0); + Require(sceKernelMunmap(reinterpret_cast(probe), page * 4) == 0); void* const requested = static_cast(probe) + page; void* fixed = requested; Require(sceKernelReserveVirtualRange(&fixed, page * 2, 0x400010, 0) == 0); @@ -1095,16 +1050,17 @@ static void CheckFixedVirtualReservation() { bool refused = false; try { sceKernelReserveVirtualRange(&reserved, page * 2, 0x90, 0); + } catch (const std::exception&) { refused = true; } Require(refused); - Require(sceKernelMunmap(reserved, page * 2) == 0); + Require(sceKernelMunmap(reinterpret_cast(reserved), page * 2) == 0); Require(sceKernelReleaseDirectMemory(phys, page * 2) == 0); void* pooled = nullptr; Require(sceKernelMemoryPoolReserve(requested, page * 2, 0, 0x10, &pooled) == 0); Require(pooled == requested); - Require(sceKernelMunmap(pooled, page * 2) == 0); + Require(sceKernelMunmap(reinterpret_cast(pooled), page * 2) == 0); } static void CheckHintInsideReservation() { @@ -1133,8 +1089,8 @@ static void CheckHintInsideReservation() { Require(sceKernelMapDirectMemory(&overlapping, page * 2, 3, 0, phys + page, 0) == 0); Require(overlapping != base + page); Require(static_cast(direct)[0] == 21 && static_cast(flexible)[0] == 22); - Require(sceKernelMunmap(overlapping, page * 2) == 0); - Require(sceKernelMunmap(reserved, page * 4) == 0); + Require(sceKernelMunmap(reinterpret_cast(overlapping), page * 2) == 0); + Require(sceKernelMunmap(reinterpret_cast(reserved), page * 4) == 0); Require(sceKernelReleaseDirectMemory(phys, page * 3) == 0); } @@ -1159,7 +1115,7 @@ static void CheckReservedRangeIsNotCommitted() { Require(sceKernelVirtualQuery(static_cast(reserved) + page, 0, &info, sizeof(info)) == 0); Require(!info.is_committed && info.protection == 0); Require(info.start == start + page && info.end == start + page * 2); - Require(sceKernelMunmap(reserved, page * 2) == 0); + Require(sceKernelMunmap(reinterpret_cast(reserved), page * 2) == 0); Require(sceKernelReleaseDirectMemory(phys, page) == 0); } @@ -1180,7 +1136,7 @@ static void CheckNoOverwriteRefusesLiveMapping() { VirtualQueryInfo info{}; Require(sceKernelVirtualQuery(mapped, 0, &info, sizeof(info)) == 0); Require(info.is_direct && info.offset == static_cast(phys)); - Require(sceKernelMunmap(mapped, page) == 0); + Require(sceKernelMunmap(reinterpret_cast(mapped), page) == 0); Require(sceKernelReleaseDirectMemory(phys, page * 2) == 0); } @@ -1194,7 +1150,7 @@ static void CheckNoOverwriteRejectsHostOccupiedMapping() { constexpr std::size_t page = 0x4000; void* reservation = nullptr; Require(sceKernelReserveVirtualRange(&reservation, page * 4, 0, 0) == 0); - Require(sceKernelMunmap(reservation, page * 4) == 0); + Require(sceKernelMunmap(reinterpret_cast(reservation), page * 4) == 0); void* target = static_cast(reservation) + page; GuestArena::GuestArenaCommit_nid_postfix(target, page, ReadWriteProtection, page); std::int64_t phys = 0; @@ -1255,6 +1211,7 @@ static void CheckGuestModuleImageProtection() { bool failed = false; try { dlclose_nid_postfix(module); + } catch (const std::runtime_error&) { failed = true; } @@ -1295,6 +1252,7 @@ static void CheckGuestModuleImageProtection() { bool rejected = false; try { sceKernelMprotect(GetModuleHandleA("kernel32.dll"), page, 1); + } catch (const std::invalid_argument&) { rejected = true; } @@ -1305,6 +1263,7 @@ static void CheckGuestModuleImageProtection() { const auto libkernel = GetModuleHandleA("libkernel.prx"); Require(libkernel != nullptr); sceKernelMprotect(libkernel, page, 1); + } catch (const std::invalid_argument&) { rejected = true; } @@ -1332,6 +1291,7 @@ static void CheckGuestModuleImageProtection() { rejected = false; try { sceKernelMprotect(plainTarget, page, 1); + } catch (const std::invalid_argument&) { rejected = true; } @@ -1382,6 +1342,7 @@ static void CheckGuestModuleImageProtection() { bool rejected = false; try { sceKernelMprotect(reinterpret_cast(&::getpid), page, 1); + } catch (const std::invalid_argument&) { rejected = true; } @@ -1409,8 +1370,8 @@ static void CheckUnhintedKernelMappingsLandInTheWindow() { const auto flexibleAddress = reinterpret_cast(flexible); Require(flexibleAddress >= windowStart); Require(flexibleAddress + page <= windowEnd); - Require(sceKernelMunmap(direct, page) == 0); - Require(sceKernelMunmap(flexible, page) == 0); + Require(sceKernelMunmap(reinterpret_cast(direct), page) == 0); + Require(sceKernelMunmap(reinterpret_cast(flexible), page) == 0); Require(sceKernelReleaseDirectMemory(phys, page) == 0); } @@ -1420,13 +1381,13 @@ static void CheckUnmappedArenaRangeStaysReserved() { void* address = nullptr; Require(sceKernelMapNamedFlexibleMemory(&address, page, 3, 0, "reserved-after-unmap") == 0); Require(address != nullptr); - Require(sceKernelMunmap(address, page) == 0); + Require(sceKernelMunmap(reinterpret_cast(address), page) == 0); void* hostile = mmap(address, page, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED_NOREPLACE, -1, 0); Require(hostile == MAP_FAILED && errno == EEXIST); void* again = nullptr; Require(sceKernelMapNamedFlexibleMemory(&again, page, 3, 0, "reserved-after-unmap-2") == 0); Require(again != nullptr); - Require(sceKernelMunmap(again, page) == 0); + Require(sceKernelMunmap(reinterpret_cast(again), page) == 0); } #endif @@ -1506,8 +1467,8 @@ static void CheckFixedMappingsReachTheApplicationAreaEnd() { refused = true; } Require(refused && beyond == reinterpret_cast(applicationAreaEnd)); - Require(sceKernelMunmap(alias, page) == 0); - Require(sceKernelMunmap(mapped, page * 2) == 0); + Require(sceKernelMunmap(reinterpret_cast(alias), page) == 0); + Require(sceKernelMunmap(reinterpret_cast(mapped), page * 2) == 0); Require(sceKernelReleaseDirectMemory(phys, page * 2) == 0); } #ifdef _WIN32 @@ -1533,7 +1494,7 @@ static void CheckAliasOfReorderedSharedPages() { Require(bytes[6] == 0x33 && bytes[page + 6] == 0x44); GuestArena::GuestArenaUnmapAlias_nid_postfix(const_cast(alias)); Require(bytes[5] == 0x22 && bytes[page + 5] == 0x11); - Require(sceKernelMunmap(mapped, page * 2) == 0); + Require(sceKernelMunmap(reinterpret_cast(mapped), page * 2) == 0); Require(sceKernelReleaseDirectMemory(phys, page * 2) == 0); } @@ -1564,7 +1525,7 @@ static void CheckAliasAcrossDirectAllocations() { Require(VirtualQuery(alias + offset, &released, sizeof(released)) == sizeof(released) && released.State == MEM_FREE); } Require(bytes[5] == 0x11 && bytes[page + 5] == 0x22 && bytes[page * 2 + 5] == 0x33); - Require(sceKernelMunmap(mapped, page * 3) == 0); + Require(sceKernelMunmap(reinterpret_cast(mapped), page * 3) == 0); Require(sceKernelReleaseDirectMemory(first, page * 3) == 0); } @@ -1586,7 +1547,7 @@ static void CheckAliasLeavesResidentRunsUnderAHostWrite() { Require(alias != nullptr && alias[5] == 0x11 && alias[page + 5] == 0x22); GuestArena::GuestArenaUnmapAlias_nid_postfix(const_cast(alias)); Require(bytes[5] == 0x11 && bytes[page + 5] == 0x22); - Require(sceKernelMunmap(mapped, page * 2) == 0); + Require(sceKernelMunmap(reinterpret_cast(mapped), page * 2) == 0); Require(sceKernelReleaseDirectMemory(phys, page * 2) == 0); } @@ -1603,7 +1564,7 @@ static void CheckAliasRefusesPagesThatAreNotSharedViews() { bool refused = false; try { GuestArena::GuestArenaMapAlias_nid_postfix(reinterpret_cast(reserved), page * 2); } catch (const std::runtime_error&) { refused = true; } Require(refused); - Require(sceKernelMunmap(reserved, page * 2) == 0); + Require(sceKernelMunmap(reinterpret_cast(reserved), page * 2) == 0); Require(sceKernelReleaseDirectMemory(phys, page) == 0); } #endif @@ -1655,8 +1616,8 @@ static void CheckMlock() { #ifndef ANYPS5_ENABLE_ASAN Require(sceKernelMlock_nid_postfix(reserved, page) == outOfMemory); #endif - Require(sceKernelMunmap(reserved, page) == 0); - Require(sceKernelMunmap(mapped, length) == 0); + Require(sceKernelMunmap(reinterpret_cast(reserved), page) == 0); + Require(sceKernelMunmap(reinterpret_cast(mapped), length) == 0); #ifndef ANYPS5_ENABLE_ASAN Require(sceKernelMlock_nid_postfix(mapped, page) == outOfMemory); #endif @@ -1684,8 +1645,8 @@ static void CheckSharedDirectMemoryLifecycle() { left[page] = 48; Require(sceKernelMprotect(inaccessible, page, 1) == 0); Require(static_cast(inaccessible)[0] == 48); - Require(sceKernelMunmap(inaccessible, page) == 0); - Require(sceKernelMunmap(left + page, page) == 0); + Require(sceKernelMunmap(reinterpret_cast(inaccessible), page) == 0); + Require(sceKernelMunmap(reinterpret_cast(left + page), page) == 0); right[page] = 79; Require(left[0] == 31 && left[page * 2] == 63); void* middle = left + page; @@ -1697,9 +1658,9 @@ static void CheckSharedDirectMemoryLifecycle() { left[page] = 95; Require(sceKernelMprotect(second, page * 3, 1) == 0); Require(right[page] == 95); - Require(sceKernelMunmap(first, page) == 0); - Require(sceKernelMunmap(left + page * 2, page) == 0); - Require(sceKernelMunmap(middle, page) == 0); + Require(sceKernelMunmap(reinterpret_cast(first), page) == 0); + Require(sceKernelMunmap(reinterpret_cast(left + page * 2), page) == 0); + Require(sceKernelMunmap(reinterpret_cast(middle), page) == 0); Require(sceKernelMprotect(second, page * 3, 3) == 0); right[page * 2] = 111; void* reserved = nullptr; @@ -1715,8 +1676,8 @@ static void CheckSharedDirectMemoryLifecycle() { Require(!info.is_direct && info.is_flexible && info.offset == 0); static_cast(fixed)[0] = 143; Require(right[page * 2] == 127); - Require(sceKernelMunmap(reserved, page * 3) == 0); - Require(sceKernelMunmap(second, page * 3) == 0); + Require(sceKernelMunmap(reinterpret_cast(reserved), page * 3) == 0); + Require(sceKernelMunmap(reinterpret_cast(second), page * 3) == 0); Require(sceKernelReleaseDirectMemory(phys + page, page) == 0); std::int64_t replacement = 0; Require(sceKernelAllocateDirectMemory(phys + page, phys + page * 2, page, 0, 0, &replacement) == 0); @@ -1725,7 +1686,7 @@ static void CheckSharedDirectMemoryLifecycle() { Require(sceKernelMapDirectMemory(&mixed, page * 3, 3, 0, phys, 0) == 0); const auto* data = static_cast(mixed); Require(data[0] == 31 && data[page] == 0 && data[page * 2] == 127); - Require(sceKernelMunmap(mixed, page * 3) == 0); + Require(sceKernelMunmap(reinterpret_cast(mixed), page * 3) == 0); Require(sceKernelReleaseDirectMemory(phys, page * 3) == 0); } @@ -1792,7 +1753,7 @@ static void CheckSingleDirectMappingTracksWritesWithoutFaults() { Require(g_accessViolations == 0); Require(collect(mapped, page * 4) == 2); Require(collect(mapped, page * 4) == 0); - Require(sceKernelMunmap(static_cast(mapped) + page * 2, page) == 0); + Require(sceKernelMunmap(reinterpret_cast(static_cast(mapped) + page * 2), page) == 0); Require(bytes[page + 0x1000] == 7 && bytes[page * 3] == 9); bytes[0] = 5; Require(collect(mapped, page * 2) != 0); @@ -1803,19 +1764,19 @@ static void CheckSingleDirectMappingTracksWritesWithoutFaults() { static_cast(second)[0x1001] = 11; Require(bytes[page + 0x1001] == 11); Require(collect(mapped, page * 2) != 0); - Require(sceKernelMunmap(second, page) == 0); - Require(sceKernelMunmap(mapped, page * 2) == 0); - Require(sceKernelMunmap(static_cast(mapped) + page * 3, page) == 0); + Require(sceKernelMunmap(reinterpret_cast(second), page) == 0); + Require(sceKernelMunmap(reinterpret_cast(mapped), page * 2) == 0); + Require(sceKernelMunmap(reinterpret_cast(static_cast(mapped) + page * 3), page) == 0); void* again = nullptr; Require(sceKernelMapDirectMemory(&again, page * 4, 3, 0, phys, 0) == 0); const auto* data = static_cast(again); Require(data[0] == 5 && data[page + 0x1000] == 7 && data[page + 0x1001] == 11 && data[page * 2] == 0 && data[page * 3] == 9); - Require(sceKernelMunmap(again, page * 4) == 0); + Require(sceKernelMunmap(reinterpret_cast(again), page * 4) == 0); Require(sceKernelReleaseDirectMemory(phys, page * 4) == 0); #endif } -static void CheckLargeResidentWritesStopFaulting() { +static void CheckLargeResidentWritesDoNotFault() { #ifdef _WIN32 constexpr std::size_t bytes = 0x200000; std::int64_t physical = 0; @@ -1831,7 +1792,7 @@ static void CheckLargeResidentWritesStopFaulting() { Require(collect() == bytes / 4096); Require(collect() == 0 && collect() == 0); MEMORY_BASIC_INFORMATION memory{}; - Require(VirtualQuery(mapped, &memory, sizeof(memory)) == sizeof(memory) && memory.Protect == PAGE_READONLY); + Require(VirtualQuery(mapped, &memory, sizeof(memory)) == sizeof(memory) && memory.Protect == PAGE_READWRITE); auto* data = static_cast(mapped); const auto path = std::filesystem::path("anyps5-resident-read-" + std::to_string(std::chrono::steady_clock::now().time_since_epoch().count()) + ".bin"); @@ -1859,7 +1820,7 @@ static void CheckLargeResidentWritesStopFaulting() { Require(collect() == 1 && collect() == 0); } for (unsigned int round = 0; round < 16; ++round) Require(collect() == 0); - Require(VirtualQuery(mapped, &memory, sizeof(memory)) == sizeof(memory) && memory.Protect == PAGE_READONLY); + Require(VirtualQuery(mapped, &memory, sizeof(memory)) == sizeof(memory) && memory.Protect == PAGE_READWRITE); const auto before = g_accessViolations; const auto handler = AddVectoredExceptionHandler(1, CountAccessViolations); Require(handler != nullptr); @@ -1868,14 +1829,14 @@ static void CheckLargeResidentWritesStopFaulting() { Require(collect() == bytes / 4096 && collect() == 0); } Require(RemoveVectoredExceptionHandler(handler)); - Require(g_accessViolations == before + 1); + Require(g_accessViolations == before); Require(VirtualQuery(mapped, &memory, sizeof(memory)) == sizeof(memory) && memory.Protect == PAGE_READWRITE); Require(mprotect_nid_postfix(mapped, bytes, 1) == 0); Require(collect() == 0 && collect() == 0); Require(mprotect_nid_postfix(mapped, bytes, 3) == 0); data[0x10000] = 97; Require(collect() == 1 && collect() == 0); - Require(sceKernelMunmap(mapped, bytes) == 0); + Require(sceKernelMunmap(reinterpret_cast(mapped), bytes) == 0); Require(sceKernelReleaseDirectMemory(physical, bytes) == 0); #endif } @@ -1911,8 +1872,8 @@ static void CheckImportAccessDoesNotInventSharedWrites() { } Require(static_cast(second)[4097] == 73); Require(collect(first) == 0 && collect(second) == 0); - Require(sceKernelMunmap(first, bytes) == 0); - Require(sceKernelMunmap(second, bytes) == 0); + Require(sceKernelMunmap(reinterpret_cast(first), bytes) == 0); + Require(sceKernelMunmap(reinterpret_cast(second), bytes) == 0); Require(sceKernelReleaseDirectMemory(physical, bytes) == 0); #endif } @@ -1952,7 +1913,7 @@ static void CheckResidentCollectPreservesPartialWrites() { Require(collect(small, bytes - small, 1, true, false) == std::vector{small}); Require(collect(small * 2, bytes - small * 2, bytes / small, true, true) == std::vector{0x200000}); Require(collect(0, bytes, bytes / small, true, false).empty()); - Require(sceKernelMunmap(mapped, bytes) == 0); + Require(sceKernelMunmap(reinterpret_cast(mapped), bytes) == 0); Require(sceKernelReleaseDirectMemory(physical, bytes) == 0); #endif } @@ -2014,8 +1975,8 @@ static void CheckResidentCollectionDuringHostWrites() { Require(data[small + 11] == 4); const auto pages = collect(); Require(std::find(pages.begin(), pages.end(), data + small) != pages.end()); - Require(sceKernelMunmap(alias, 0x4000) == 0); - Require(sceKernelMunmap(mapped, bytes) == 0); + Require(sceKernelMunmap(reinterpret_cast(alias), 0x4000) == 0); + Require(sceKernelMunmap(reinterpret_cast(mapped), bytes) == 0); Require(sceKernelReleaseDirectMemory(physical, bytes) == 0); #endif } @@ -2095,8 +2056,8 @@ static void CheckSecondDirectMappingWaitsForLeases() { static_cast(second)[8] = 3; Require(static_cast(mapped)[page + 8] == 3); static_cast(mapped)[page * 2 + 8] = 4; - Require(sceKernelMunmap(second, page) == 0); - Require(sceKernelMunmap(mapped, page * 4) == 0); + Require(sceKernelMunmap(reinterpret_cast(second), page) == 0); + Require(sceKernelMunmap(reinterpret_cast(mapped), page * 4) == 0); Require(sceKernelReleaseDirectMemory(phys, page * 4) == 0); #endif } @@ -2149,7 +2110,7 @@ static void CheckBreakingAResidentRunKeepsConcurrentAccesses() { std::array second{}; go = true; for (std::size_t index = 0; index < chunks; ++index) { - if (unmap) Require(sceKernelMunmap(static_cast(mapped) + index * chunk + page, page) == 0); + if (unmap) Require(sceKernelMunmap(reinterpret_cast(static_cast(mapped) + index * chunk + page), page) == 0); else Require(sceKernelMapDirectMemory(&second[index], page, 3, 0, phys + static_cast(index * chunk + page), 0) == 0); } writer.join(); @@ -2162,16 +2123,16 @@ static void CheckBreakingAResidentRunKeepsConcurrentAccesses() { } if (unmap) continue; for (std::size_t offset = 0; offset < page; ++offset) Require(static_cast(second[index])[offset] == value(index * chunk + page + offset)); - Require(sceKernelMunmap(second[index], page) == 0); + Require(sceKernelMunmap(reinterpret_cast(second[index]), page) == 0); } for (std::size_t index = 0; index < chunks; ++index) { auto* base = static_cast(mapped) + index * chunk; if (!unmap) { - Require(sceKernelMunmap(base, chunk) == 0); + Require(sceKernelMunmap(reinterpret_cast(base), chunk) == 0); continue; } - Require(sceKernelMunmap(base, page) == 0); - Require(sceKernelMunmap(base + page * 2, chunk - page * 2) == 0); + Require(sceKernelMunmap(reinterpret_cast(base), page) == 0); + Require(sceKernelMunmap(reinterpret_cast(base + page * 2), chunk - page * 2) == 0); } Require(sceKernelReleaseDirectMemory(phys, chunk * chunks) == 0); } @@ -2196,13 +2157,13 @@ static void CheckRemappedDirectMemoryIsChargedOnce() { Require(sceKernelMapDirectMemory(&mapped, bytes, 3, 0, phys, 0) == 0); RequireResidentMapping(mapped); std::memset(mapped, 0xa5, bytes); - Require(sceKernelMunmap(mapped, bytes) == 0); + Require(sceKernelMunmap(reinterpret_cast(mapped), bytes) == 0); void* again = nullptr; Require(sceKernelMapDirectMemory(&again, bytes, 3, 0, phys, 0) == 0); const auto* data = static_cast(again); Require(data[0] == 0xa5 && data[bytes / 2] == 0xa5 && data[bytes - 1] == 0xa5); once = committed() - before < static_cast(bytes + bytes / 2); - Require(sceKernelMunmap(again, bytes) == 0); + Require(sceKernelMunmap(reinterpret_cast(again), bytes) == 0); Require(sceKernelReleaseDirectMemory(phys, bytes) == 0); } Require(once); @@ -2256,9 +2217,9 @@ static void CheckSharedWriteTracking() { collect(second, page * 3); static_cast(third)[0] = 105; Require(collect(first, page * 3) == 1 && collect(second, page * 3) == 1); - Require(sceKernelMunmap(third, page) == 0); - Require(sceKernelMunmap(first, page * 3) == 0); - Require(sceKernelMunmap(second, page * 3) == 0); + Require(sceKernelMunmap(reinterpret_cast(third), page) == 0); + Require(sceKernelMunmap(reinterpret_cast(first), page * 3) == 0); + Require(sceKernelMunmap(reinterpret_cast(second), page * 3) == 0); Require(sceKernelReleaseDirectMemory(phys, page * 3) == 0); #endif } @@ -2301,7 +2262,7 @@ static void CheckSharedWritePages() { Require(bytes[page + small] == 5 && bytes[page + small * 2 - 1] == 5); Require(collect(page, small) == 0); Require(collect(0, page * 2) == 1); - Require(sceKernelMunmap(mapped, page * 2) == 0); + Require(sceKernelMunmap(reinterpret_cast(mapped), page * 2) == 0); Require(sceKernelReleaseDirectMemory(phys, page * 2) == 0); std::filesystem::remove(path); #endif @@ -2344,8 +2305,8 @@ static void CheckSharedWritesDuringHostWrite() { Require(collect(first).empty() && collect(second).empty()); left[small + 16] = 3; Require(right[small + 16] == 3 && collect(second) == std::vector{small}); - Require(sceKernelMunmap(first, page) == 0); - Require(sceKernelMunmap(second, page) == 0); + Require(sceKernelMunmap(reinterpret_cast(first), page) == 0); + Require(sceKernelMunmap(reinterpret_cast(second), page) == 0); Require(sceKernelReleaseDirectMemory(phys, page) == 0); #endif } @@ -2378,7 +2339,7 @@ static void CheckFailedCollectKeepsWrites() { Require(sceKernelMprotect(const_cast(shared + page), page, 0) == 0); Require(!collect(mapped, page * 2, count)); Require(collect(mapped, page, count) && count == 1); - Require(sceKernelMunmap(mapped, page * 2) == 0); + Require(sceKernelMunmap(reinterpret_cast(mapped), page * 2) == 0); Require(sceKernelReleaseDirectMemory(phys, page * 2) == 0); #endif } @@ -2460,8 +2421,8 @@ static void CheckPinnedSharedPages() { Require(protection(page) == PAGE_READONLY); bytes[page + 8] = 11; Require(collect() == 1); - Require(sceKernelMunmap(alias, page * 3) == 0); - Require(sceKernelMunmap(mapped, page * 3) == 0); + Require(sceKernelMunmap(reinterpret_cast(alias), page * 3) == 0); + Require(sceKernelMunmap(reinterpret_cast(mapped), page * 3) == 0); Require(sceKernelReleaseDirectMemory(phys, page * 3) == 0); #endif } @@ -2521,7 +2482,7 @@ static void CheckReadsIntoSharedWriteTracking() { Require(refusedResult.return_value == static_cast(SCE_KERNEL_ERROR_EFAULT)); Require(sceKernelAioDeleteRequest(id, &deleted) == 0); Require(sceKernelClose(fd) == 0); - Require(sceKernelMunmap(mapped, page * 2) == 0); + Require(sceKernelMunmap(reinterpret_cast(mapped), page * 2) == 0); Require(sceKernelReleaseDirectMemory(phys, page * 2) == 0); std::filesystem::remove(path); #endif @@ -2576,7 +2537,7 @@ static void CheckWriteWatchArmedCollect() { Require(CollectArmedRuns(mapping, 0, length, runs) && runs == PageRuns{{5, 6}}); Require(Written(mapping, length, {{length / small / 2, length / small}})); Require(Written(mapping, length, {})); - Require(sceKernelMunmap(mapping, length) == 0); + Require(sceKernelMunmap(reinterpret_cast(mapping), length) == 0); } static bool CollectFreshRuns(const void* base, std::size_t offset, std::size_t bytes, PageRuns& runs) { @@ -2604,7 +2565,7 @@ static void CheckWriteWatchFreshCollect() { Require(CollectFreshRuns(mapping, 0, length, runs) && runs.empty()); bytes[200 * small] = 1; Require(Written(mapping, length, {{5, 6}, {200, 201}})); - Require(sceKernelMunmap(mapping, length) == 0); + Require(sceKernelMunmap(reinterpret_cast(mapping), length) == 0); } static void CheckWriteWatch() { @@ -2654,7 +2615,7 @@ static void CheckWriteWatch() { Require(Written(mapping, length, {{50, 51}})); constexpr std::size_t guestPage = 0x4000; auto* middle = const_cast(bytes + 4 * guestPage); - Require(sceKernelMunmap(middle, guestPage) == 0); + Require(sceKernelMunmap(reinterpret_cast(middle), guestPage) == 0); Require(!GuestWriteWatch::GuestWriteWatchCovers_nid_postfix(address, length)); Require(!CollectRuns(mapping, 0, length, runs) && runs.empty()); void* fixed = middle; @@ -2664,7 +2625,7 @@ static void CheckWriteWatch() { Require(Written(mapping, length, {})); middle[1] = 1; Require(Written(mapping, length, {{16, 17}})); - Require(sceKernelMunmap(mapping, length) == 0); + Require(sceKernelMunmap(reinterpret_cast(mapping), length) == 0); Require(!GuestWriteWatch::GuestWriteWatchCovers_nid_postfix(address, small)); constexpr std::size_t tableSpan = 0x200000; constexpr std::size_t spanned = 2 * tableSpan; @@ -2704,7 +2665,7 @@ static void CheckDirectMemoryBackingNeedsNoFilesystem() { const auto backing = BackingOf(mapped); if (backing.rfind("/memfd:", 0) != 0) std::fprintf(stderr, "direct memory backing: %s\n", backing.c_str()); Require(backing.rfind("/memfd:", 0) == 0); - Require(sceKernelMunmap(mapped, page) == 0); + Require(sceKernelMunmap(reinterpret_cast(mapped), page) == 0); Require(sceKernelReleaseDirectMemory(phys, page) == 0); } @@ -2747,10 +2708,10 @@ static void CheckDirectMemorySharedBacking() { Require(!GuestArena::GuestArenaSharedBacking_nid_postfix(flexibleAddress, page * 2, &file, &offset)); Require(GuestArena::GuestArenaSharedBacking_nid_postfix(flexibleAddress + page, page, &file, &offset) && offset == base + page * 2); close(file); - Require(sceKernelMunmap(high, page) == 0); + Require(sceKernelMunmap(reinterpret_cast(high), page) == 0); Require(!GuestArena::GuestArenaSharedBacking_nid_postfix(flexibleAddress + page, page, &file, &offset)); - Require(sceKernelMunmap(flexible, page) == 0); - Require(sceKernelMunmap(first, page * 2) == 0); + Require(sceKernelMunmap(reinterpret_cast(flexible), page) == 0); + Require(sceKernelMunmap(reinterpret_cast(first), page * 2) == 0); Require(!GuestArena::GuestArenaSharedBacking_nid_postfix(address, page, &file, &offset)); Require(sceKernelReleaseDirectMemory(phys, page * 3) == 0); @@ -2774,15 +2735,15 @@ static void CheckDirectMemorySharedBacking() { close(leftFile); close(rightFile); std::memset(leftView, 0x77, page); - Require(sceKernelMunmap(leftView, page) == 0); + Require(sceKernelMunmap(reinterpret_cast(leftView), page) == 0); Require(sceKernelReleaseDirectMemory(left, page) == 0); std::int64_t again = 0; Require(sceKernelAllocateDirectMemory(left, left + static_cast(page), page, 0, 0, &again) == 0 && again == left); void* againView = nullptr; Require(sceKernelMapDirectMemory(&againView, page, 3, 0, again, 0) == 0); for (std::size_t i = 0; i < page; ++i) Require(static_cast(againView)[i] == 0); - Require(sceKernelMunmap(againView, page) == 0); - Require(sceKernelMunmap(rightView, page) == 0); + Require(sceKernelMunmap(reinterpret_cast(againView), page) == 0); + Require(sceKernelMunmap(reinterpret_cast(rightView), page) == 0); Require(sceKernelReleaseDirectMemory(again, page) == 0); Require(sceKernelReleaseDirectMemory(right, page) == 0); } @@ -2818,8 +2779,8 @@ static void CheckDirectMemoryWriteWatch() { Require(bytes[page + 7] == 3); Require(CollectRuns(first, 0, page, runs) && runs == PageRuns{{0, 1}}); Require(CollectRuns(first, page * 2, page, runs) && runs.empty()); - Require(sceKernelMunmap(alias, page) == 0); - Require(sceKernelMunmap(first, page * 3) == 0); + Require(sceKernelMunmap(reinterpret_cast(alias), page) == 0); + Require(sceKernelMunmap(reinterpret_cast(first), page * 3) == 0); Require(!GuestWriteWatch::GuestWriteWatchCovers_nid_postfix(address, page)); void* flexible = nullptr; Require(sceKernelMapFlexibleMemory(&flexible, page * 3, 3, 0) == 0); @@ -2833,7 +2794,7 @@ static void CheckDirectMemoryWriteWatch() { Require(Written(flexible, page * 3, {})); static_cast(fixed)[9] = 4; Require(Written(flexible, page * 3, {{page / small, page / small + 1}})); - Require(sceKernelMunmap(flexible, page * 3) == 0); + Require(sceKernelMunmap(reinterpret_cast(flexible), page * 3) == 0); Require(sceKernelReleaseDirectMemory(phys, page * 3) == 0); } @@ -2853,12 +2814,12 @@ static void CheckDirectMemoryWriteWatchFollowsRemovedMappings() { Require(sceKernelMapDirectMemory(&pair, page * 2, 3, 0, phys + page, 0) == 0); Require(watched(whole, 0) && !watched(whole, page) && !watched(whole, page * 2) && watched(whole, page * 3)); Require(!watched(pair, 0) && !watched(pair, page)); - Require(sceKernelMunmap(pair, page) == 0); + Require(sceKernelMunmap(reinterpret_cast(pair), page) == 0); void* single = nullptr; Require(sceKernelMapDirectMemory(&single, page, 3, 0, phys + page, 0) == 0); Require(!watched(single, 0) && watched(whole, 0) && watched(whole, page * 3)); - Require(sceKernelMunmap(single, page) == 0); - Require(sceKernelMunmap(static_cast(pair) + page, page) == 0); + Require(sceKernelMunmap(reinterpret_cast(single), page) == 0); + Require(sceKernelMunmap(reinterpret_cast(static_cast(pair) + page), page) == 0); void* replaced = whole; Require(sceKernelMapDirectMemory(&replaced, page, 3, 0x10, phys + page * 3, 0) == 0 && replaced == whole); Require(!watched(whole, 0) && !watched(whole, page * 3)); @@ -2873,9 +2834,9 @@ static void CheckDirectMemoryWriteWatchFollowsRemovedMappings() { void* again = nullptr; Require(sceKernelMapDirectMemory(&again, page, 3, 0, phys, 0) == 0); Require(!watched(alone, 0) && !watched(again, 0)); - Require(sceKernelMunmap(again, page) == 0); - Require(sceKernelMunmap(alone, page) == 0); - Require(sceKernelMunmap(whole, page * 4) == 0); + Require(sceKernelMunmap(reinterpret_cast(again), page) == 0); + Require(sceKernelMunmap(reinterpret_cast(alone), page) == 0); + Require(sceKernelMunmap(reinterpret_cast(whole), page * 4) == 0); Require(sceKernelReleaseDirectMemory(phys, page * 4) == 0); } @@ -2898,7 +2859,7 @@ static double MapAcrossBackingsSeconds(std::int64_t phys, std::size_t backings) std::uint64_t offset = 0; int type = 0; Require(QueryDirectMapping(last, &start, &end, &offset, &type) && start == last && end == last + page); - Require(sceKernelMunmap(mapped, page * backings) == 0); + Require(sceKernelMunmap(reinterpret_cast(mapped), page * backings) == 0); } return best; } @@ -3039,7 +3000,7 @@ static void CheckVirtualQuerySplitFlexibleRanges() { Require(info.protection == (index == 1 ? 1 : 3)); Require(info.is_committed && info.is_flexible && !info.is_direct); } - Require(sceKernelMunmap(bytes + page, page) == 0); + Require(sceKernelMunmap(reinterpret_cast(bytes + page), page) == 0); for (std::size_t index : {std::size_t{0}, std::size_t{2}}) { VirtualQueryInfo info{}; Require(sceKernelVirtualQuery(bytes + page * index, 0, &info, sizeof(info)) == 0); @@ -3051,8 +3012,8 @@ static void CheckVirtualQuerySplitFlexibleRanges() { Require(next.start == reinterpret_cast(bytes + page * 2)); Require(next.end == next.start + page && next.protection == 3); Require(bytes[0] == 17 && bytes[page * 2] == 29); - Require(sceKernelMunmap(bytes, page) == 0); - Require(sceKernelMunmap(bytes + page * 2, page) == 0); + Require(sceKernelMunmap(reinterpret_cast(bytes), page) == 0); + Require(sceKernelMunmap(reinterpret_cast(bytes + page * 2), page) == 0); } static void CheckVirtualQueryWireLayout() { @@ -3082,7 +3043,7 @@ static void CheckVirtualQueryWireLayout() { Require(std::all_of(result.before.begin(), result.before.end(), [](auto byte) { return byte == 0xa5; })); Require(std::all_of(result.after.begin(), result.after.end(), [](auto byte) { return byte == 0x5a; })); Require(sceKernelClearVirtualRangeName(mapped, page) == 0); - Require(sceKernelMunmap(mapped, page) == 0); + Require(sceKernelMunmap(reinterpret_cast(mapped), page) == 0); } static void CheckVirtualQueryForNonReadableGuestRange() { @@ -3095,7 +3056,7 @@ static void CheckVirtualQueryForNonReadableGuestRange() { Require(sceKernelVirtualQuery(mapped, 0, &info, sizeof(info)) == 0); Require(info.start == reinterpret_cast(mapped)); Require(info.end == info.start + page && info.protection == 0); - Require(sceKernelMunmap(mapped, page) == 0); + Require(sceKernelMunmap(reinterpret_cast(mapped), page) == 0); } static void CheckPosixFixedAnonymousMapping() { @@ -3131,7 +3092,7 @@ static void CheckPosixFixedAnonymousMapping() { memory[page] = 0x51; memory[page * 2 - 1] = 0x52; memory[page * 2] = 0x61; - Require(sceKernelMunmap(memory + page * 3, page) == 0); + Require(sceKernelMunmap(reinterpret_cast(memory + page * 3), page) == 0); Require(mmap_nid_postfix(memory + page * 3, page, 3, exclusive, -1, 0) == memory + page * 3); Require(std::all_of(memory + page * 3, memory + page * 4, [](unsigned char value) { return value == 0; })); memory[page * 4 - 1] = 0x62; @@ -3184,7 +3145,7 @@ static void CheckPosixFixedAnonymousReleasesFlexibleAccounting() { Require(mmap_nid_postfix(bytes + page, page, 3, fixed, -1, 0) == bytes + page); Require(bytes[0] == 0x31 && bytes[page] == 0 && bytes[page * 2] == 0x51); Require(sceKernelAvailableFlexibleMemorySize(&available) == 0 && available == before - page * 2); - Require(sceKernelMunmap(base, page * 3) == 0); + Require(sceKernelMunmap(reinterpret_cast(base), page * 3) == 0); Require(sceKernelAvailableFlexibleMemorySize(&available) == 0 && available == before); } @@ -3213,7 +3174,7 @@ static void CheckPosixFixedFileReleasesFlexibleAccounting() { Require(mmap_nid_postfix(bytes + page, page, 1, fixedShared, fd, 0) == bytes + page); Require(bytes[0] == 0x31 && bytes[page] == 0x6d && bytes[page * 2] == 0x51); Require(sceKernelAvailableFlexibleMemorySize(&available) == 0 && available == before - page * 2); - Require(sceKernelMunmap(base, page * 3) == 0); + Require(sceKernelMunmap(reinterpret_cast(base), page * 3) == 0); Require(sceKernelAvailableFlexibleMemorySize(&available) == 0 && available == before); Require(sceKernelClose(fd) == 0); std::filesystem::remove(path); @@ -3226,7 +3187,7 @@ static void CheckSceKernelMmap() { Require(sceKernelMmap(nullptr, page, 3, 0x1002, -1, 0, &mapped) == 0 && mapped != nullptr); static_cast(mapped)[page - 1] = 7; Require(static_cast(mapped)[page - 1] == 7); - Require(sceKernelMunmap(mapped, page) == 0); + Require(sceKernelMunmap(reinterpret_cast(mapped), page) == 0); void* untouched = &mapped; Require(sceKernelMmap(nullptr, 0, 3, 0x1002, -1, 0, &untouched) == static_cast(0x80020016u)); Require(untouched == &mapped); @@ -3261,7 +3222,6 @@ static void CheckVirtualQueryPartialMunmap() { Require(munmap_nid_postfix(memory + page * 2, page) == 0); } - static void CheckAvailableDirectMemoryIsLargestFreeBlock() { constexpr std::int64_t window = 0x4000000; const std::int64_t top = static_cast(DIRECT_MEMORY_SIZE) - window; @@ -3343,8 +3303,8 @@ static void CheckMunmapOverUnmappedPages() { Require(sceKernelVirtualQuery(memory, 0, &info, sizeof(info)) == SCE_KERNEL_ERROR_EACCES); Require(sceKernelVirtualQuery(memory + page * 2, 0, &info, sizeof(info)) == SCE_KERNEL_ERROR_EACCES); Require(munmap_nid_postfix(memory, page * 3) == 0); - Require(sceKernelMunmap(memory, page * 3) == 0); - Require(sceKernelMunmap(memory, 0) == SCE_KERNEL_ERROR_EINVAL); + Require(sceKernelMunmap(reinterpret_cast(memory), page * 3) == 0); + Require(sceKernelMunmap(reinterpret_cast(memory), 0) == SCE_KERNEL_ERROR_EINVAL); } int main(int argc, char** argv) { @@ -3433,7 +3393,7 @@ int main(int argc, char** argv) { CheckPinnedSharedPages(); CheckFailedCollectKeepsWrites(); CheckSingleDirectMappingTracksWritesWithoutFaults(); - CheckLargeResidentWritesStopFaulting(); + CheckLargeResidentWritesDoNotFault(); CheckImportAccessDoesNotInventSharedWrites(); CheckResidentCollectPreservesPartialWrites(); CheckResidentCollectionDuringHostWrites(); @@ -3543,7 +3503,7 @@ int main(int argc, char** argv) { Require(sceKernelReserveVirtualRange(&mincoreReserved, page, 0, 0) == 0); mincoreVec[0] = 0x55; Require(mincore_nid_postfix(mincoreReserved, page, mincoreVec) == 0 && mincoreVec[0] == 0); - Require(sceKernelMunmap(mincoreReserved, page) == 0); + Require(sceKernelMunmap(reinterpret_cast(mincoreReserved), page) == 0); Require(munmap_nid_postfix(memory + 1, page) == -1 && *__error_nid_postfix() == 22); Require(munmap_nid_postfix(memory, 0) == -1 && *__error_nid_postfix() == 22); Require(memory[0] == 42); diff --git a/core/libs/tests/GuestMemoryPoolStats.cpp b/core/libs/tests/GuestMemoryPoolStats.cpp index 7aec461e18..14d926ca31 100644 --- a/core/libs/tests/GuestMemoryPoolStats.cpp +++ b/core/libs/tests/GuestMemoryPoolStats.cpp @@ -1,3 +1,6 @@ +#include "prx/libSceSsl/include/Ssl.hpp" +#include "prx/libSceNet/include/Net.hpp" +#include "prx/libSceHttp2/include/Http2.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -6,41 +9,19 @@ #include #include -struct PoolStats { - std::size_t pool_size; - std::size_t max_inuse_size; - std::size_t current_inuse_size; - std::int32_t reserved; -}; - -struct NetPoolStats { - std::size_t pool_size; - std::size_t max_inuse_size; - std::size_t current_inuse_size; -}; - -extern "C" { -int APS5_VABI sceSslInit_nid_postfix(std::size_t); -int APS5_VABI sceSslTerm_nid_postfix(int); -int APS5_VABI sceSslGetMemoryPoolStats(int, void*); -int APS5_VABI sceHttp2Init(int, int, std::size_t, int); -int APS5_VABI sceHttp2Term(int); -int APS5_VABI sceHttp2GetMemoryPoolStats(int, void*); -int APS5_VABI sceNetPoolCreate(const char*, int, int); -int APS5_VABI sceNetPoolDestroy(int); -int APS5_VABI sceNetGetMemoryPoolStats(int, void*); -} - static void Require(bool value) { if (!value) std::abort(); } -using StatsCall = int(APS5_VABI*)(int, void*); - -static void CheckRejected(StatsCall call, int id, int expected) { - std::array buffer; - buffer.fill(0x5a); - Require(call(id, buffer.data()) == expected); - for (std::size_t i = 0; i < sizeof(PoolStats); ++i) Require(buffer[i] == 0); - for (std::size_t i = sizeof(PoolStats); i < buffer.size(); ++i) Require(buffer[i] == 0x5a); +template +static void CheckRejected(int (APS5_VABI *call)(int, TStats*), int id, int expected) { + struct { + TStats stats; + std::array guard; + } buffer; + std::memset(&buffer, 0x5a, sizeof(buffer)); + Require(call(id, &buffer.stats) == expected); + const auto* bytes = reinterpret_cast(&buffer.stats); + for (std::size_t i = 0; i < sizeof(TStats); ++i) Require(bytes[i] == 0); + for (const auto byte : buffer.guard) Require(byte == 0x5a); } int main() { @@ -50,12 +31,12 @@ int main() { constexpr int http2NullPointer = static_cast(0x817B1225); constexpr int netBadDescriptor = static_cast(0x80410109); constexpr int netInvalid = static_cast(0x80410116); - static_assert(sizeof(PoolStats) == 0x20 && sizeof(NetPoolStats) == 0x18); + static_assert(sizeof(SceSsl::MemoryPoolStats) == 0x20 && sizeof(Http2MemoryPoolStats) == 0x20 && sizeof(NetMemoryPoolStats) == 0x18); const int ssl = sceSslInit_nid_postfix(0x40000); Require(ssl > 0); - PoolStats stats{}; - Require(sceSslGetMemoryPoolStats(ssl, &stats) == 0 && stats.pool_size == 0x40000); + SceSsl::MemoryPoolStats sslStats{}; + Require(sceSslGetMemoryPoolStats(ssl, &sslStats) == 0 && sslStats.poolSize == 0x40000); Require(sceSslGetMemoryPoolStats(ssl, nullptr) == sslInvalidValue); Require(sceSslGetMemoryPoolStats(12345, nullptr) == sslInvalidValue); CheckRejected(sceSslGetMemoryPoolStats, 12345, sslInvalidId); @@ -63,7 +44,8 @@ int main() { const int http2 = sceHttp2Init(1, ssl, 0x40000, 1); Require(http2 > 0); - Require(sceHttp2GetMemoryPoolStats(http2, &stats) == 0 && stats.pool_size == 0x40000); + Http2MemoryPoolStats http2Stats{}; + Require(sceHttp2GetMemoryPoolStats(http2, &http2Stats) == 0 && http2Stats.pool_size == 0x40000); Require(sceHttp2GetMemoryPoolStats(http2, nullptr) == http2NullPointer); Require(sceHttp2GetMemoryPoolStats(12345, nullptr) == http2NullPointer); CheckRejected(sceHttp2GetMemoryPoolStats, 12345, http2InvalidId); @@ -76,14 +58,17 @@ int main() { const int pool = sceNetPoolCreate("stats", 0x20000, 0); Require(pool > 0); - NetPoolStats netStats{}; + NetMemoryPoolStats netStats{}; Require(sceNetGetMemoryPoolStats(pool, &netStats) == 0 && netStats.pool_size == 0x20000); Require(sceNetGetMemoryPoolStats(pool, nullptr) == netInvalid); Require(sceNetGetMemoryPoolStats(12345, nullptr) == netBadDescriptor); - std::array untouched; - untouched.fill(0x5a); + struct { + NetMemoryPoolStats stats; + std::array guard; + } untouched; + std::memset(&untouched, 0x5a, sizeof(untouched)); auto buffer = untouched; - Require(sceNetGetMemoryPoolStats(12345, buffer.data()) == netBadDescriptor && buffer == untouched); + Require(sceNetGetMemoryPoolStats(12345, &buffer.stats) == netBadDescriptor && std::memcmp(&buffer, &untouched, sizeof(buffer)) == 0); Require(sceNetPoolDestroy(pool) == 0); Require(sceNetGetMemoryPoolStats(pool, nullptr) == netBadDescriptor); return 0; diff --git a/core/libs/tests/GuestMemrchr.cpp b/core/libs/tests/GuestMemrchr.cpp index 8715e30bf2..6f09c1f987 100644 --- a/core/libs/tests/GuestMemrchr.cpp +++ b/core/libs/tests/GuestMemrchr.cpp @@ -1,10 +1,7 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include -extern "C" { -void* APS5_VABI memrchr_nid_postfix(const void*, int, std::size_t); -} - int main() { const unsigned char bytes[] = {0xff, 0x01, 0xff, 0x00}; const auto* found = static_cast(memrchr_nid_postfix(bytes, 0xff, sizeof(bytes))); diff --git a/core/libs/tests/GuestMessageDestructorAbi.cpp b/core/libs/tests/GuestMessageDestructorAbi.cpp index 8c55dbc490..90d524adf0 100644 --- a/core/libs/tests/GuestMessageDestructorAbi.cpp +++ b/core/libs/tests/GuestMessageDestructorAbi.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/exceptions/Runtime.hpp" #include #include @@ -10,10 +11,10 @@ using GuestDestroy = void (APS5_VABI *)(void*); using HostDestroy = void (*)(void*); using GuestThrowFunction = void (APS5_VABI *)(std::uintptr_t); struct TypeRecord { const void* vtable; const char* name; const TypeRecord* base; }; -struct Object { const void* vtable; const char* message; }; + struct Table { std::ptrdiff_t offset; const TypeRecord* type; GuestDestroy destroy; GuestDestroy deleteObject; GuestWhat what; }; struct Message { std::size_t length; std::size_t capacity; std::atomic references; }; -static_assert(sizeof(Object) == 16); +static_assert(sizeof(LibcException::ExceptionObject) == 16); extern "C" { extern const unsigned char _ZTVN10__cxxabiv117__class_type_infoE_nid_postfix[]; @@ -22,22 +23,12 @@ extern const unsigned char _ZTISt12out_of_range_nid_postfix[]; extern const unsigned char _ZTISt11regex_error_nid_postfix[]; extern const unsigned char _ZTISt13runtime_error_nid_postfix[]; extern const unsigned char _ZTISt11logic_error_nid_postfix[]; -void APS5_VABI _ZNSt12out_of_rangeC1EPKc_nid_postfix(Object*, const char*); -void APS5_VABI _ZNSt12out_of_rangeC1ERKS__nid_postfix(Object*, const Object*); -void APS5_VABI _ZNSt12out_of_rangeD1Ev_nid_postfix(Object*); -void APS5_VABI _ZNSt11logic_errorC1EPKc_nid_postfix(Object*, const char*); -void APS5_VABI _ZNSt11logic_errorD1Ev_nid_postfix(Object*); -[[noreturn]] void APS5_VABI _ZSt14_Xout_of_rangePKc_nid_postfix(const char*); -[[noreturn]] void APS5_VABI _ZSt15_Xruntime_errorPKc_nid_postfix(const char*); -[[noreturn]] void APS5_VABI _ZNKSt11logic_error8_DoraiseEv_nid_postfix(const Object*); -[[noreturn]] void APS5_VABI _ZSt13_Xregex_errorNSt15regex_constants10error_typeE_nid_postfix(std::regex_constants::error_type); + int APS5_VABI GuestOuter(); void APS5_VABI GuestCleanup(); void APS5_VABI GuestStdCapture(); void APS5_VABI ProbeDestroy(GuestDestroy, void*, void*); const char* APS5_VABI ProbeWhat(GuestWhat, const void*, const void*); -void APS5_VABI _ZNSt8bad_castC1Ev_nid_postfix(Object*); -void APS5_VABI _ZNSt9bad_allocC1Ev_nid_postfix(Object*); TypeRecord FixtureBaseType{_ZTVN10__cxxabiv117__class_type_infoE_nid_postfix + 16, "11FixtureBase", nullptr}; TypeRecord FixtureErrorType{_ZTVN10__cxxabiv120__si_class_type_infoE_nid_postfix + 16, "12FixtureError", &FixtureBaseType}; @@ -56,7 +47,7 @@ unsigned FixtureWhatChecked = 0; std::fprintf(stderr, "guest exception failure %u\n", code); ExitProcess(code); } -const char* APS5_VABI FixtureWhat(const void* object) { return static_cast(object)->message; } +const char* APS5_VABI FixtureWhat(const void* object) { return static_cast(object)->message; } void APS5_VABI FixtureDestroy(void* object) { if (object != FixtureLastObject) FixtureFail(11); ++FixtureDestroyed; @@ -68,7 +59,7 @@ void APS5_VABI FixtureCheckWhat(const char* message) { } } -static Object decoy{}, retained{}; +static LibcException::ExceptionObject decoy{}, retained{}; static GuestDestroy registeredDestructor; static void* expectedObject; static void* poison; @@ -129,18 +120,20 @@ static int TestVtable(const char* mode) { const bool plain = std::strstr(mode, "plain") != nullptr; const bool deleting = std::strstr(mode, "delete") != nullptr; const bool destroying = deleting || std::strstr(mode, "destroy") != nullptr; - auto* actual = static_cast(std::malloc(sizeof(Object))); - auto* other = static_cast(std::malloc(sizeof(Object))); + auto* actual = static_cast(std::malloc(sizeof(LibcException::ExceptionObject))); + auto* other = static_cast(std::malloc(sizeof(LibcException::ExceptionObject))); if (!actual || !other) FixtureFail(57); actual->message = other->message = nullptr; if (plain) { _ZNSt9bad_allocC1Ev_nid_postfix(actual); _ZNSt8bad_castC1Ev_nid_postfix(other); + } else { _ZNSt12out_of_rangeC1EPKc_nid_postfix(actual, "actual virtual message"); _ZNSt12out_of_rangeC1EPKc_nid_postfix(other, "unrelated virtual message"); + } - const Object originalOther = *other; + const LibcException::ExceptionObject originalOther = *other; watchedObject = actual; watchedMessage = plain ? nullptr : reinterpret_cast(const_cast(actual->message)) - 1; foreignObject = other; @@ -168,20 +161,21 @@ static int TestVtable(const char* mode) { if (!plain) { if (!deleting) _ZNSt12out_of_rangeD1Ev_nid_postfix(actual); _ZNSt12out_of_rangeD1Ev_nid_postfix(other); + } if (!deleting) std::free(actual); std::free(other); return 0; } -static Message* MessageHeader(const Object& object) { +static Message* MessageHeader(const LibcException::ExceptionObject& object) { return reinterpret_cast(const_cast(object.message)) - 1; } extern "C" void APS5_VABI ObserveDestroy(void* pointer) { if (pointer != expectedObject || ++callbacks != 1) FixtureFail(40); ProbeDestroy(registeredDestructor, pointer, poison); - if (static_cast(pointer)->message != nullptr || + if (static_cast(pointer)->message != nullptr || !decoy.message || std::strcmp(decoy.message, "unrelated message") || (keepMessage && MessageHeader(retained)->references.load() != 0)) FixtureFail(41); } @@ -191,12 +185,13 @@ extern "C" void APS5_VABI FixtureInspect(void* pointer) { if (header->_pad != 0 || !header->destructor) FixtureFail(42); expectedObject = pointer; GuestWhat what; - std::memcpy(&what, static_cast(static_cast(pointer)->vtable) + + std::memcpy(&what, static_cast(static_cast(pointer)->vtable) + 2 * sizeof(void*), sizeof(what)); const char* message = ProbeWhat(what, pointer, poison); if (!message || std::strcmp(message, expectedMessage)) FixtureFail(62); if (keepMessage) { - _ZNSt12out_of_rangeC1ERKS__nid_postfix(&retained, static_cast(pointer)); + _ZNSt12out_of_rangeC1ERKS__nid_postfix(&retained, static_cast(pointer)); + if (MessageHeader(retained)->references.load() != 1) FixtureFail(43); } registeredDestructor = reinterpret_cast(header->destructor); @@ -255,7 +250,7 @@ int main(int argc, char** argv) { regularRelease = std::strcmp(argv[1], "release") == 0; keepMessage = std::strstr(argv[1], "unshared") == nullptr; FixtureArgument = reinterpret_cast(FixtureMessage); - Object raised{}; + LibcException::ExceptionObject raised{}; if (regex) { expectedMessage = "regular expression error"; FixtureStdOutType = _ZTISt11regex_error_nid_postfix; @@ -267,12 +262,14 @@ int main(int argc, char** argv) { FixtureThrow = reinterpret_cast(_ZSt15_Xruntime_errorPKc_nid_postfix); } else if (doraise) { _ZNSt11logic_errorC1EPKc_nid_postfix(&raised, FixtureMessage); + expectedMessage = FixtureMessage; FixtureStdOutType = _ZTISt11logic_error_nid_postfix; FixtureThrow = reinterpret_cast(_ZNKSt11logic_error8_DoraiseEv_nid_postfix); FixtureArgument = reinterpret_cast(&raised); } _ZNSt12out_of_rangeC1EPKc_nid_postfix(&decoy, "unrelated message"); + poison = std::strstr(argv[1], "zero") ? nullptr : &decoy; GuestStdCapture(); const char* expected = regex ? "regular expression error" : FixtureMessage; @@ -282,6 +279,7 @@ int main(int argc, char** argv) { !decoy.message || std::strcmp(decoy.message, "unrelated message")) return 44; _ZNSt12out_of_rangeD1Ev_nid_postfix(&retained); _ZNSt12out_of_rangeD1Ev_nid_postfix(&decoy); + if (doraise) _ZNSt11logic_errorD1Ev_nid_postfix(&raised); if (retained.message || decoy.message || (doraise && raised.message)) return 45; std::puts("guest message callback, retained ownership and release: PASS"); diff --git a/core/libs/tests/GuestMktime.cpp b/core/libs/tests/GuestMktime.cpp index 97d72aeaa9..f3e74a4a6b 100644 --- a/core/libs/tests/GuestMktime.cpp +++ b/core/libs/tests/GuestMktime.cpp @@ -1,3 +1,5 @@ +#include "prx/libc/include/SonyCrt.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/GuestTime.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -8,14 +10,6 @@ #include #include -extern "C" { -std::int64_t APS5_VABI libc_mktime_nid_postfix(GuestTm*); -std::int64_t APS5_VABI mktime_nid_postfix(GuestTm*); -GuestTm* APS5_VABI localtime_s_nid_postfix(const std::int64_t*, GuestTm*); -void APS5_VABI tzset_nid_postfix(); -int APS5_VABI setenv_nid_postfix(const char*, const char*, int); -} - using Converter = std::int64_t (APS5_VABI *)(GuestTm*); static void Require(bool value, const char* message) { @@ -67,6 +61,7 @@ static void CheckFailure(Converter convert) { static void CheckZone(const char* zone) { Require(setenv_nid_postfix("TZ", zone, 1) == 0, "Could not set the time zone"); tzset_nid_postfix(); + constexpr std::array converters{libc_mktime_nid_postfix, mktime_nid_postfix}; constexpr std::array timers{-86401, -2, -1, 0, 1, 59, 60, 86400}; for (auto convert : converters) { diff --git a/core/libs/tests/GuestMlock.cpp b/core/libs/tests/GuestMlock.cpp index 79b571e9b2..71883b2b4c 100644 --- a/core/libs/tests/GuestMlock.cpp +++ b/core/libs/tests/GuestMlock.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -15,17 +17,6 @@ #include #endif -extern "C" { -int APS5_VABI sceKernelMapFlexibleMemory(void**, std::size_t, int, int); -int APS5_VABI sceKernelReserveVirtualRange(void**, std::size_t, int, std::size_t); -int APS5_VABI sceKernelMunmap(void*, std::size_t); -int APS5_VABI mlock_nid_postfix(const void*, std::size_t); -int APS5_VABI munlock_nid_postfix(const void*, std::size_t); -int APS5_VABI mlockall_nid_postfix(int); -int APS5_VABI munlockall_nid_postfix(); -int* APS5_VABI __error_nid_postfix(); -} - static void Require(bool value) { if (!value) std::abort(); } static void RequireLockAllInvalid(int flags) { @@ -37,6 +28,7 @@ static void RequireLockAllUnsupported(int flags) { bool rejected = false; try { mlockall_nid_postfix(flags); + } catch (const std::runtime_error&) { rejected = true; } @@ -140,9 +132,9 @@ int main() { *__error_nid_postfix() = untouched; Require(munlock_nid_postfix(reserved, page) == 0); Require(*__error_nid_postfix() == untouched); - Require(sceKernelMunmap(reserved, page) == 0); + Require(sceKernelMunmap(reinterpret_cast(reserved), page) == 0); - Require(sceKernelMunmap(mapped, length) == 0); + Require(sceKernelMunmap(reinterpret_cast(mapped), length) == 0); #ifndef ANYPS5_ENABLE_ASAN *__error_nid_postfix() = 0; Require(mlock_nid_postfix(mapped, page) == -1 && *__error_nid_postfix() == 12); diff --git a/core/libs/tests/GuestModuleInfo.cpp b/core/libs/tests/GuestModuleInfo.cpp index a9419b03f3..85dd43c3fb 100644 --- a/core/libs/tests/GuestModuleInfo.cpp +++ b/core/libs/tests/GuestModuleInfo.cpp @@ -1,3 +1,4 @@ +#include "prx/libkernel/include/Api.hpp" #include "SceTypes.hpp" #include "prx/libkernel/KernelErrors.hpp" #include @@ -11,18 +12,7 @@ #include #include #include -extern "C" { -void* APS5_VABI dlopen_nid_postfix(const char*, int); -void* APS5_VABI dlsym_nid_postfix(void*, const char*); -int APS5_VABI dlclose_nid_postfix(void*); -int APS5_VABI sceKernelGetModuleInfoFromAddr(std::uint64_t, int, ModuleInfoEx*); -int APS5_VABI sceKernelGetModuleList(KernelModule*, std::size_t, std::size_t*); -int APS5_VABI sceKernelGetModuleInfo(KernelModule, ModuleInfo*); -int APS5_VABI sceKernelGetModuleList2(KernelModule*, std::size_t, std::size_t*); -int APS5_VABI sceKernelGetModuleInfo2(KernelModule, ModuleInfo*); -std::int32_t APS5_VABI sceKernelGetLibkernelTextLocation_nid_postfix(void**, std::size_t*); -std::int32_t APS5_VABI sceKernelInternalMemoryGetModuleSegmentInfo_nid_postfix(InternalSegmentInfo*); -} + static void Require(bool value, const std::source_location& location = std::source_location::current()) { if (!value) { std::fprintf(stderr, "module info check failed at line %u\n", location.line()); diff --git a/core/libs/tests/GuestMove.cpp b/core/libs/tests/GuestMove.cpp index ad027c999f..98d1e59b72 100644 --- a/core/libs/tests/GuestMove.cpp +++ b/core/libs/tests/GuestMove.cpp @@ -1,23 +1,10 @@ +#include "prx/libSceMove/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include #include #include -extern "C" { -int APS5_VABI sceMoveInit(void); -int APS5_VABI sceMoveTerm(void); -int APS5_VABI sceMoveOpen(std::int32_t userId, std::int32_t type, std::int32_t index); -int APS5_VABI sceMoveClose(std::int32_t handle); -int APS5_VABI sceMoveGetDeviceInfo(std::int32_t handle, void* info); -int APS5_VABI sceMoveGetExtensionPortInfo(std::int32_t handle, void* data); -int APS5_VABI sceMoveReadStateLatest(std::int32_t handle, void* data); -int APS5_VABI sceMoveReadStateRecent(std::int32_t handle, std::int64_t timestamp, void* data, std::int32_t* outCount); -int APS5_VABI sceMoveSetVibration(std::int32_t handle, std::uint8_t motor); -int APS5_VABI sceMoveSetLightSphere(std::int32_t handle, std::uint8_t red, std::uint8_t green, std::uint8_t blue); -int APS5_VABI sceMoveResetLightSphere(std::int32_t handle); -} - namespace { void Require(bool value) { if (!value) std::abort(); } diff --git a/core/libs/tests/GuestMprotectUnmapped.cpp b/core/libs/tests/GuestMprotectUnmapped.cpp index 8a4ed05199..326051d6ab 100644 --- a/core/libs/tests/GuestMprotectUnmapped.cpp +++ b/core/libs/tests/GuestMprotectUnmapped.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libkernel/KernelErrors.hpp" #include "SceTypes.hpp" @@ -6,16 +8,6 @@ #include #include -extern "C" { -void* APS5_VABI mmap_nid_postfix(void*, std::size_t, int, int, int, std::int64_t) noexcept; -int APS5_VABI munmap_nid_postfix(void*, std::size_t) noexcept; -int APS5_VABI mprotect_nid_postfix(void*, std::size_t, int) noexcept; -int APS5_VABI sceKernelMprotect(const void*, std::size_t, int); -int APS5_VABI sceKernelMtypeprotect(const void*, std::size_t, int, int); -int APS5_VABI sceKernelVirtualQuery(const void*, int, VirtualQueryInfo*, std::uint64_t); -int* APS5_VABI __error_nid_postfix(); -} - namespace { constexpr std::size_t Page = 0x4000; diff --git a/core/libs/tests/GuestMsgDialogNative.cpp b/core/libs/tests/GuestMsgDialogNative.cpp index 8842c84299..21383b3c87 100644 --- a/core/libs/tests/GuestMsgDialogNative.cpp +++ b/core/libs/tests/GuestMsgDialogNative.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceMsgDialog.native/libSceMsgDialog.native.hpp" #include "SceTypes.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -5,16 +6,7 @@ extern "C" { extern int SceMsgDialogNativeModuleLoaded_nid_no_patch; -int APS5_VABI sceMsgDialogInitialize(void); -int APS5_VABI sceMsgDialogOpen(const void* param); -int APS5_VABI sceMsgDialogGetStatus(void); -int APS5_VABI sceMsgDialogUpdateStatus(void); -int APS5_VABI sceMsgDialogGetResult(MsgDialogResult* result); -int APS5_VABI sceMsgDialogClose(void); -int APS5_VABI sceMsgDialogTerminate(void); -int APS5_VABI sceMsgDialogProgressBarInc(int target, std::uint32_t delta); -int APS5_VABI sceMsgDialogProgressBarSetMsg(int target, const char* msg); -int APS5_VABI sceMsgDialogProgressBarSetValue(int target, std::uint32_t rate); + } namespace { diff --git a/core/libs/tests/GuestMsync.cpp b/core/libs/tests/GuestMsync.cpp index 1f23ef02ad..e5dc64d5ce 100644 --- a/core/libs/tests/GuestMsync.cpp +++ b/core/libs/tests/GuestMsync.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -5,14 +7,6 @@ #include #include -extern "C" { -void* APS5_VABI mmap_nid_postfix(void*, std::size_t, int, int, int, std::int64_t) noexcept; -int APS5_VABI munmap_nid_postfix(void*, std::size_t) noexcept; -int APS5_VABI msync_nid_postfix(void*, std::size_t, int); -int APS5_VABI sceKernelReserveVirtualRange(void**, std::size_t, int, std::size_t); -int* APS5_VABI __error_nid_postfix(); -} - namespace { constexpr std::size_t Page = 0x4000; constexpr int ReadWrite = 3; diff --git a/core/libs/tests/GuestMultibyteLocale.cpp b/core/libs/tests/GuestMultibyteLocale.cpp index 60a4a52808..682521486d 100644 --- a/core/libs/tests/GuestMultibyteLocale.cpp +++ b/core/libs/tests/GuestMultibyteLocale.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -5,21 +6,6 @@ #include #include -extern "C" { -std::size_t APS5_VABI mbrtowc_nid_postfix(std::uint16_t*, const char*, std::size_t, void*); -std::size_t APS5_VABI mbrlen_nid_postfix(const char*, std::size_t, void*); -int APS5_VABI mbtowc_nid_postfix(std::uint16_t*, const char*, std::size_t); -int APS5_VABI mblen_nid_postfix(const char*, std::size_t); -std::size_t APS5_VABI wcrtomb_nid_postfix(char*, std::uint16_t, void*); -int APS5_VABI wctomb_nid_postfix(char*, std::uint16_t); -int APS5_VABI mbsinit_nid_postfix(const void*); -int APS5_VABI _Getmbcurmax_nid_postfix(); -std::size_t APS5_VABI mbstowcs_nid_postfix(std::uint16_t*, const char*, std::size_t); -std::size_t APS5_VABI wcstombs_nid_postfix(char*, const std::uint16_t*, std::size_t); -std::size_t APS5_VABI mbsrtowcs_nid_postfix(std::uint16_t*, const char**, std::size_t, void*); -int* APS5_VABI __error_nid_postfix(); -} - constexpr auto Invalid = static_cast(-1); constexpr auto Incomplete = static_cast(-2); @@ -83,6 +69,7 @@ static void CheckState() { Require(mbtowc_nid_postfix(&value, "\xa9", 1) == 1 && value == 0xe9, "mbtowc keeps the partial character"); Require(mbtowc_nid_postfix(&value, "\xe2\x82\xac", 8) == 3 && value == 0x20ac, "mbtowc limits the count to three bytes"); mbtowc_nid_postfix(&value, "\xc3", 1); + Require(mbtowc_nid_postfix(nullptr, nullptr, 0) == 0 && mbtowc_nid_postfix(&value, "A", 1) == 1, "a null string resets mbtowc"); Require(mblen_nid_postfix("\xc3", 1) == -1 && mblen_nid_postfix("\xa9", 1) == -1, "mblen keeps no state"); Require(mblen_nid_postfix("\xe2\x82\xac", 3) == 3 && mblen_nid_postfix(nullptr, 0) == 0, "mblen"); diff --git a/core/libs/tests/GuestMutexContention.cpp b/core/libs/tests/GuestMutexContention.cpp index dbb0da5e2f..648e403aa7 100644 --- a/core/libs/tests/GuestMutexContention.cpp +++ b/core/libs/tests/GuestMutexContention.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libkernel/Pthread/include/Mutex.hpp" #include "SceTypes.hpp" #include #include @@ -11,19 +13,6 @@ #include #include -extern "C" { -int APS5_VABI scePthreadCreate(Pthread*, const PthreadAttr*, PthreadEntry, void*, const char*); -int APS5_VABI scePthreadJoin(Pthread, void**); -int APS5_VABI scePthreadMutexattrInit(PthreadMutexattr*); -int APS5_VABI scePthreadMutexattrSettype(PthreadMutexattr*, int); -int APS5_VABI scePthreadMutexattrDestroy(PthreadMutexattr*); -int APS5_VABI scePthreadMutexInit(PthreadMutex*, const PthreadMutexattr*, const char*); -int APS5_VABI scePthreadMutexDestroy(PthreadMutex*); -int APS5_VABI scePthreadMutexLock(PthreadMutex*); -int APS5_VABI scePthreadMutexTimedlock(PthreadMutex*, KernelUseconds); -int APS5_VABI scePthreadMutexUnlock(PthreadMutex*); -} - namespace { using Clock = std::chrono::steady_clock; diff --git a/core/libs/tests/GuestMutexRaiseException.cpp b/core/libs/tests/GuestMutexRaiseException.cpp index ecdd471b4e..6bfa05b6ac 100644 --- a/core/libs/tests/GuestMutexRaiseException.cpp +++ b/core/libs/tests/GuestMutexRaiseException.cpp @@ -1,52 +1,42 @@ -#include "SceTypes.hpp" -#include -#include -#include -#include -#include - -extern "C" { -int APS5_VABI scePthreadCreate(Pthread*, const PthreadAttr*, PthreadEntry, void*, const char*); -int APS5_VABI scePthreadJoin(Pthread, void**); -int APS5_VABI scePthreadMutexInit(PthreadMutex*, const PthreadMutexattr*, const char*); -int APS5_VABI scePthreadMutexDestroy(PthreadMutex*); -int APS5_VABI scePthreadMutexLock(PthreadMutex*); -int APS5_VABI scePthreadMutexUnlock(PthreadMutex*); -int APS5_VABI sceKernelInstallExceptionHandler(int, void*); -int APS5_VABI sceKernelRemoveExceptionHandler(int); -int APS5_VABI sceKernelRaiseException(Pthread, int); -} - -static constexpr int SigUsr1 = 30; -static void Require(bool value) { if (!value) std::abort(); } -static std::atomic deliveries{0}; -static void APS5_VABI Handler(int, void*) { deliveries.fetch_add(1); } - -struct Context { PthreadMutex mutex = nullptr; std::atomic started{false}; std::atomic acquired{false}; }; -static void* APS5_VABI Worker(void* opaque) { - auto& context = *static_cast(opaque); - context.started.store(true); - Require(scePthreadMutexLock(&context.mutex) == 0); - context.acquired.store(true); - Require(scePthreadMutexUnlock(&context.mutex) == 0); - return nullptr; -} - -int main() { - Require(sceKernelInstallExceptionHandler(SigUsr1, reinterpret_cast(&Handler)) == 0); - Context context; - Require(scePthreadMutexInit(&context.mutex, nullptr, nullptr) == 0); - Require(scePthreadMutexLock(&context.mutex) == 0); - Pthread worker = nullptr; - Require(scePthreadCreate(&worker, nullptr, Worker, &context, "mutex wait") == 0); - while (!context.started.load()) std::this_thread::yield(); - std::this_thread::sleep_for(std::chrono::milliseconds(10)); - Require(sceKernelRaiseException(worker, SigUsr1) == 0); - for (int i = 0; i < 5000 && deliveries.load() == 0; ++i) std::this_thread::sleep_for(std::chrono::milliseconds(1)); - Require(deliveries.load() == 1); - Require(scePthreadMutexUnlock(&context.mutex) == 0); - Require(scePthreadJoin(worker, nullptr) == 0); - Require(context.acquired.load()); - Require(scePthreadMutexDestroy(&context.mutex) == 0); - Require(sceKernelRemoveExceptionHandler(SigUsr1) == 0); -} \ No newline at end of file +#include "prx/libkernel/include/Api.hpp" +#include "prx/libkernel/Pthread/include/Mutex.hpp" +#include "SceTypes.hpp" +#include +#include +#include +#include +#include + +static constexpr int SigUsr1 = 30; +static void Require(bool value) { if (!value) std::abort(); } +static std::atomic deliveries{0}; +static void APS5_VABI Handler(int, void*) { deliveries.fetch_add(1); } + +struct Context { PthreadMutex mutex = nullptr; std::atomic started{false}; std::atomic acquired{false}; }; +static void* APS5_VABI Worker(void* opaque) { + auto& context = *static_cast(opaque); + context.started.store(true); + Require(scePthreadMutexLock(&context.mutex) == 0); + context.acquired.store(true); + Require(scePthreadMutexUnlock(&context.mutex) == 0); + return nullptr; +} + +int main() { + Require(sceKernelInstallExceptionHandler(SigUsr1, reinterpret_cast(&Handler)) == 0); + Context context; + Require(scePthreadMutexInit(&context.mutex, nullptr, nullptr) == 0); + Require(scePthreadMutexLock(&context.mutex) == 0); + Pthread worker = nullptr; + Require(scePthreadCreate(&worker, nullptr, Worker, &context, "mutex wait") == 0); + while (!context.started.load()) std::this_thread::yield(); + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + Require(sceKernelRaiseException(worker, SigUsr1) == 0); + for (int i = 0; i < 5000 && deliveries.load() == 0; ++i) std::this_thread::sleep_for(std::chrono::milliseconds(1)); + Require(deliveries.load() == 1); + Require(scePthreadMutexUnlock(&context.mutex) == 0); + Require(scePthreadJoin(worker, nullptr) == 0); + Require(context.acquired.load()); + Require(scePthreadMutexDestroy(&context.mutex) == 0); + Require(sceKernelRemoveExceptionHandler(SigUsr1) == 0); +} diff --git a/core/libs/tests/GuestNamedShmConcurrency.cpp b/core/libs/tests/GuestNamedShmConcurrency.cpp index 5dc2e7e350..da44c93dba 100644 --- a/core/libs/tests/GuestNamedShmConcurrency.cpp +++ b/core/libs/tests/GuestNamedShmConcurrency.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "SceTypes.hpp" #include "nid/Sha1.hpp" #include "prx/libc/include/general/VabiMacros.hpp" @@ -14,16 +16,6 @@ #include #include -extern "C" { -int APS5_VABI shm_open_nid_postfix(const char*, int, int); -int APS5_VABI ftruncate_nid_postfix(int, std::int64_t); -std::int64_t APS5_VABI pwrite_nid_disambig1_nid_postfix(int, const void*, std::size_t, std::int64_t); -std::int64_t APS5_VABI fstat_nid_disambig1_nid_postfix(int, FileStat*); -int APS5_VABI fchmod_nid_postfix(int, int); -int APS5_VABI close_nid_postfix(int); -int* APS5_VABI __error_nid_postfix(); -} - namespace { using Unlink = int (*)(const char*); constexpr std::int64_t Page = 0x4000; diff --git a/core/libs/tests/GuestNamedShmDescriptorReuse.cpp b/core/libs/tests/GuestNamedShmDescriptorReuse.cpp index e2b7263e23..6af68772cb 100644 --- a/core/libs/tests/GuestNamedShmDescriptorReuse.cpp +++ b/core/libs/tests/GuestNamedShmDescriptorReuse.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "SceTypes.hpp" #include "nid/Sha1.hpp" #include "prx/libc/include/general/VabiMacros.hpp" @@ -15,17 +17,6 @@ #include #include -extern "C" { -int APS5_VABI shm_open_nid_postfix(const char*, int, int); -int APS5_VABI close_nid_postfix(int); -int APS5_VABI ftruncate_nid_postfix(int, std::int64_t); -std::int64_t APS5_VABI pread_nid_postfix(int, void*, std::size_t, std::int64_t); -std::int64_t APS5_VABI pwrite_nid_disambig1_nid_postfix(int, const void*, std::size_t, std::int64_t); -void* APS5_VABI mmap_nid_postfix(void*, std::size_t, int, int, int, std::int64_t) noexcept; -int APS5_VABI munmap_nid_postfix(void*, std::size_t) noexcept; -int* APS5_VABI __error_nid_postfix(); -} - namespace { constexpr int ReadWrite = 2; constexpr int Create = 0x200; diff --git a/core/libs/tests/GuestNamedShmIoDescriptorReuse.cpp b/core/libs/tests/GuestNamedShmIoDescriptorReuse.cpp index 8de714aa88..088119df94 100644 --- a/core/libs/tests/GuestNamedShmIoDescriptorReuse.cpp +++ b/core/libs/tests/GuestNamedShmIoDescriptorReuse.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "nid/Sha1.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -14,19 +16,6 @@ #include #include -struct GuestIovec { void* base; std::size_t length; }; -extern "C" { -int APS5_VABI shm_open_nid_postfix(const char*, int, int); -int APS5_VABI close_nid_postfix(int); -int APS5_VABI dup2_nid_postfix(int, int); -int APS5_VABI ftruncate_nid_postfix(int, std::int64_t); -std::int64_t APS5_VABI write_nid_postfix(int, const char*, std::int64_t); -std::int64_t APS5_VABI pwrite_nid_disambig1_nid_postfix(int, const void*, std::size_t, std::int64_t); -std::int64_t APS5_VABI lseek_nid_postfix(int, std::int64_t, int); -std::int64_t APS5_VABI writev_nid_postfix(int, const GuestIovec*, int); -std::int64_t APS5_VABI pwritev_nid_postfix(int, const GuestIovec*, int, std::int64_t); -int* APS5_VABI __error_nid_postfix(); -} namespace { int original = -1; int replacement = -1; @@ -76,7 +65,7 @@ void Run(int operation, int boundary) { swapped = false; armed = true; char payload[] = "bad!"; - GuestIovec vector{payload, 4}; + KernelIovec vector{payload, 4}; std::int64_t result = 0; switch (operation) { case 0: result = write_nid_postfix(original, payload, 4); break; diff --git a/core/libs/tests/GuestNamedShmLifecycle.cpp b/core/libs/tests/GuestNamedShmLifecycle.cpp index a5c26b8bee..4c14b9cc3c 100644 --- a/core/libs/tests/GuestNamedShmLifecycle.cpp +++ b/core/libs/tests/GuestNamedShmLifecycle.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "SceTypes.hpp" #include "nid/Sha1.hpp" #include "prx/libc/include/GuestWriteWatch.hpp" @@ -15,31 +17,6 @@ #include #include -extern "C" { -int APS5_VABI shm_open_nid_postfix(const char*, int, int); -int APS5_VABI close_nid_postfix(int); -int APS5_VABI ftruncate_nid_postfix(int, std::int64_t); -std::int64_t APS5_VABI fstat_nid_disambig1_nid_postfix(int, FileStat*); -std::int64_t APS5_VABI pread_nid_postfix(int, void*, std::size_t, std::int64_t); -std::int64_t APS5_VABI pwrite_nid_disambig1_nid_postfix(int, const void*, std::size_t, std::int64_t); -std::int64_t APS5_VABI read_nid_postfix(int, void*, std::uint64_t); -std::int64_t APS5_VABI write_nid_postfix(int, const char*, std::int64_t); -std::int64_t APS5_VABI lseek_nid_postfix(int, std::int64_t, int); -int APS5_VABI dup2_nid_postfix(int, int); -void* APS5_VABI mmap_nid_postfix(void*, std::size_t, int, int, int, std::int64_t) noexcept; -int APS5_VABI munmap_nid_postfix(void*, std::size_t) noexcept; -int APS5_VABI mprotect_nid_postfix(void*, std::size_t, int); -int APS5_VABI open_nid_postfix(const char*, int, int); -std::int64_t APS5_VABI writev_nid_postfix(int, const struct GuestIovec*, int); -std::int64_t APS5_VABI pwritev_nid_postfix(int, const struct GuestIovec*, int, std::int64_t); -int* APS5_VABI __error_nid_postfix(); -} - -struct GuestIovec { - void* base; - std::size_t length; -}; - namespace { constexpr int ReadOnly = 0; constexpr int ReadWrite = 2; @@ -115,7 +92,7 @@ void Run() { Require(write_nid_postfix(descriptor, "xy", 2) == 1, "cross-EOF write did not return its short length"); Require(lseek_nid_postfix(descriptor, 0, SEEK_END) == static_cast(Page), "cross-EOF write changed object size"); char vectorBytes[] = "uv"; - GuestIovec vectorWrite{vectorBytes, 2}; + KernelIovec vectorWrite{vectorBytes, 2}; Require(pwritev_nid_postfix(descriptor, nullptr, 0, Page) == 0, "zero-vector positioned write on a writable descriptor failed"); Require(pwritev_nid_postfix(descriptor, &vectorWrite, 1, Page) == 0, "positioned vector write at EOF grew the object"); Require(pwritev_nid_postfix(descriptor, &vectorWrite, 1, Page - 1) == 1, "positioned vector write past EOF was not short"); diff --git a/core/libs/tests/GuestNamedShmOpen.cpp b/core/libs/tests/GuestNamedShmOpen.cpp index dc6cebf447..82abbb8a07 100644 --- a/core/libs/tests/GuestNamedShmOpen.cpp +++ b/core/libs/tests/GuestNamedShmOpen.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "nid/Sha1.hpp" #include @@ -10,9 +12,6 @@ #include #include -extern "C" int APS5_VABI shm_open_nid_postfix(const char*, int, int); -extern "C" int* APS5_VABI __error_nid_postfix(); - static void Require(bool value, const char* message) { if (!value) { throw std::runtime_error(std::string(message) + " (guest errno=" + std::to_string(*__error_nid_postfix()) + ")"); diff --git a/core/libs/tests/GuestNamedShmPermissions.cpp b/core/libs/tests/GuestNamedShmPermissions.cpp index c6f8d4c1bf..332d7f6441 100644 --- a/core/libs/tests/GuestNamedShmPermissions.cpp +++ b/core/libs/tests/GuestNamedShmPermissions.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel_sys/include/Api.hpp" +#include "prx/libkernel/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "nid/Sha1.hpp" #include @@ -9,9 +11,6 @@ #include #include -extern "C" int APS5_VABI shm_open_nid_postfix(const char*, int, int); -extern "C" std::uint16_t APS5_VABI umask_nid_postfix(std::uint16_t); - static void Require(bool condition, const char* message) { if (!condition) throw std::runtime_error(message); } diff --git a/core/libs/tests/GuestNamedShmWindows.cpp b/core/libs/tests/GuestNamedShmWindows.cpp index f159ac1ee8..401ac8df2e 100644 --- a/core/libs/tests/GuestNamedShmWindows.cpp +++ b/core/libs/tests/GuestNamedShmWindows.cpp @@ -1,3 +1,5 @@ +#include "prx/libc/include/Api.hpp" +#include "prx/libkernel/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libkernel/File/include/SharedMemory.hpp" #include "nid/Sha1.hpp" @@ -21,19 +23,6 @@ #include #include -extern "C" { -int APS5_VABI shm_open_nid_postfix(const char*, int, int); -int APS5_VABI shm_unlink_nid_postfix(const char*); -int APS5_VABI close_nid_postfix(int); -int APS5_VABI dup_nid_postfix(int); -int APS5_VABI dup2_nid_postfix(int, int); -std::int64_t APS5_VABI lseek_nid_postfix(int, std::int64_t, int); -int APS5_VABI ftruncate_nid_postfix(int, std::int64_t); -int APS5_VABI fchmod_nid_postfix(int, int); -std::int64_t APS5_VABI pread_nid_postfix(int, void*, std::size_t, std::int64_t); -std::int64_t APS5_VABI pwrite_nid_disambig1_nid_postfix(int, const void*, std::size_t, std::int64_t); -int* APS5_VABI __error_nid_postfix(); -} namespace { constexpr int ReadOnly = 0; diff --git a/core/libs/tests/GuestNanosleep.cpp b/core/libs/tests/GuestNanosleep.cpp index c97b6c1f13..6ae6cbbd17 100644 --- a/core/libs/tests/GuestNanosleep.cpp +++ b/core/libs/tests/GuestNanosleep.cpp @@ -1,20 +1,14 @@ +#include "prx/libkernel/KernelErrors.hpp" +#include "prx/libkernel/include/Api.hpp" +#include "prx/libkernel/Time/include/Time.hpp" +#include "prx/libc/include/Api.hpp" #include "SceTypes.hpp" #include #include -extern "C" { -int APS5_VABI nanosleep_nid_postfix(const KernelTimespec* rqtp, KernelTimespec* rmtp); -int APS5_VABI _nanosleep_nid_postfix(const KernelTimespec* rqtp, KernelTimespec* rmtp); -int APS5_VABI sceKernelNanosleep(const KernelTimespec* rqtp, KernelTimespec* rmtp); -int APS5_VABI clock_gettime_nid_postfix(int clockId, KernelTimespec* tp); -int* APS5_VABI __error_nid_postfix(); -} - using Nanosleep = int (APS5_VABI *)(const KernelTimespec*, KernelTimespec*); static constexpr int SCE_OK = 0; -static constexpr int SCE_KERNEL_ERROR_EFAULT = static_cast(0x8002000E); -static constexpr int SCE_KERNEL_ERROR_EINVAL = static_cast(0x80020016); static constexpr int GUEST_EACCES = 13; static constexpr int GUEST_EFAULT = 14; diff --git a/core/libs/tests/GuestNanosleepLongRequest.cpp b/core/libs/tests/GuestNanosleepLongRequest.cpp index b2b6ec9cd6..c68722401f 100644 --- a/core/libs/tests/GuestNanosleepLongRequest.cpp +++ b/core/libs/tests/GuestNanosleepLongRequest.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libkernel/Time/include/Time.hpp" #include "SceTypes.hpp" #include "prx/libkernel/Pthread/include/Pthread.hpp" #include @@ -8,12 +10,6 @@ #include #include -extern "C" { -int APS5_VABI scePthreadCreate(Pthread* thread, const PthreadAttr* attr, PthreadEntry entry, void* arg, const char* name); -int APS5_VABI nanosleep_nid_postfix(const KernelTimespec* rqtp, KernelTimespec* rmtp); -int APS5_VABI sceKernelNanosleep(const KernelTimespec* rqtp, KernelTimespec* rmtp); -} - static void Require(bool value, std::source_location location = std::source_location::current()) { if (value) return; std::fprintf(stderr, "%s:%u: requirement failed\n", location.file_name(), location.line()); diff --git a/core/libs/tests/GuestNetBufferValidation.cpp b/core/libs/tests/GuestNetBufferValidation.cpp index 4b2c66402d..cf734de324 100644 --- a/core/libs/tests/GuestNetBufferValidation.cpp +++ b/core/libs/tests/GuestNetBufferValidation.cpp @@ -1,3 +1,6 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" +#include "prx/libSceNet/include/Net.hpp" #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN #include @@ -12,17 +15,6 @@ #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libkernel/Socket/include/SocketPoll.hpp" -extern "C" { -int APS5_VABI sceNetInit_nid_postfix(); -int APS5_VABI sceNetSocket(const char*, int, int, int); -int APS5_VABI sceNetSocketClose(int); -int APS5_VABI sceNetSetsockopt(int, int, int, const void*, std::uint32_t); -int APS5_VABI sceNetGetsockopt(int, int, int, void*, std::uint32_t*); -int* APS5_VABI sceNetErrnoLoc(); -int APS5_VABI setsockopt_nid_postfix(int, int, int, const void*, std::uint32_t); -int* APS5_VABI __error_nid_postfix(); -} - static void Require(bool condition, std::source_location location = std::source_location::current()) { if (!condition) { std::fprintf(stderr, "check failed at line %u\n", location.line()); diff --git a/core/libs/tests/GuestNetCtl.cpp b/core/libs/tests/GuestNetCtl.cpp index 9b900f4bd4..9a0e595f2b 100644 --- a/core/libs/tests/GuestNetCtl.cpp +++ b/core/libs/tests/GuestNetCtl.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNetCtl/include/NetCtl.hpp" #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN #include @@ -31,29 +32,13 @@ struct NetCtlDefaultRoute { }; #endif -union NetCtlInfoV6; extern "C" { -int APS5_VABI sceNetCtlInit(void); -int APS5_VABI sceNetCtlCheckCallback(void); -int APS5_VABI sceNetCtlGetInfo(int, NetCtlInfo*); -int APS5_VABI sceNetCtlGetNatInfo(NetCtlNatInfo*); -int APS5_VABI sceNetCtlGetState(int*); -int APS5_VABI sceNetCtlGetStateV6(int*); -int APS5_VABI sceNetCtlGetInfoV6(std::uint32_t, NetCtlInfoV6*); -int APS5_VABI sceNetCtlGetResult(int, int*); -int APS5_VABI sceNetCtlGetResultV6(int, int*); + #ifdef __APPLE__ std::size_t NetCtlDefaultRoutes_nid_no_patch(const char*, std::size_t, NetCtlDefaultRoute*, std::size_t); #endif -int APS5_VABI sceNetCtlRegisterCallback(NetCtlCallback, void*, int*); -int APS5_VABI sceNetCtlRegisterCallbackV6(NetCtlCallback, void*, int*); -void APS5_VABI sceNetCtlTerm(void); -int APS5_VABI sceNetCtlUnregisterCallback(int); -int APS5_VABI sceNetCtlUnregisterCallbackV6(int); -int APS5_VABI sceNetCtlRegisterCallbackForNpToolkit(NetCtlCallback, void*, int*); -int APS5_VABI sceNetCtlUnregisterCallbackForNpToolkit(int); -int APS5_VABI sceNetCtlCheckCallbackForNpToolkit(void); + } namespace { diff --git a/core/libs/tests/GuestNetCtlAp.cpp b/core/libs/tests/GuestNetCtlAp.cpp index cc7dfda6a9..d9db3b4796 100644 --- a/core/libs/tests/GuestNetCtlAp.cpp +++ b/core/libs/tests/GuestNetCtlAp.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNetCtlAp/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -5,20 +6,6 @@ #include #include -extern "C" { -int APS5_VABI sceNetCtlApInit(void); -void APS5_VABI sceNetCtlApTerm(void); -int APS5_VABI sceNetCtlApCheckCallback(void); -int APS5_VABI sceNetCtlApClearEvent(int eventType); -int APS5_VABI sceNetCtlApRegisterCallback(void (APS5_VABI *func)(int, void*), void* arg, int* cid); -int APS5_VABI sceNetCtlApUnregisterCallback(int cid); -int APS5_VABI sceNetCtlApGetResult(int eventType, int* errorCode); -int APS5_VABI sceNetCtlApGetInfo(void* info); -int APS5_VABI sceNetCtlApGetState(int* state); -int APS5_VABI sceNetCtlApStop(void); -int APS5_VABI sceNetCtlApGetConnectInfo(const char* optStr, void* connectInfo); -} - namespace { void Require(bool value) { if (!value) std::abort(); } @@ -123,6 +110,7 @@ int main() { bool threw = false; try { sceNetCtlApInit(); + } catch (const std::runtime_error&) { threw = true; } @@ -136,5 +124,6 @@ int main() { Require(sceNetCtlApGetState(&state) == 0 && state == 0); sceNetCtlApTerm(); sceNetCtlApTerm(); + RequireUninitialized(); } diff --git a/core/libs/tests/GuestNetCtlApDialog.cpp b/core/libs/tests/GuestNetCtlApDialog.cpp index f17c171e56..82b0318b87 100644 --- a/core/libs/tests/GuestNetCtlApDialog.cpp +++ b/core/libs/tests/GuestNetCtlApDialog.cpp @@ -1,19 +1,10 @@ +#include "prx/libSceNetCtlApDialog/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include #include #include "prx/libSceCommonDialog/CommonDialog.hpp" -extern "C" { -int APS5_VABI sceNetCtlApDialogInitialize(void); -int APS5_VABI sceNetCtlApDialogTerminate(void); -int APS5_VABI sceNetCtlApDialogOpen(const NetCtlApDialogParam* param); -int APS5_VABI sceNetCtlApDialogClose(void); -int APS5_VABI sceNetCtlApDialogUpdateStatus(void); -int APS5_VABI sceNetCtlApDialogGetStatus(void); -int APS5_VABI sceNetCtlApDialogGetResult(void* result); -} - namespace { void Require(bool value) { if (!value) std::abort(); } @@ -48,7 +39,7 @@ int main() { Require(sceNetCtlApDialogTerminate() == kErrNotInitialized); Require(sceNetCtlApDialogOpen(¶m) == kErrNotInitialized); Require(sceNetCtlApDialogClose() == kErrNotInitialized); - Require(sceNetCtlApDialogGetResult(result) == kErrNotInitialized); + Require(sceNetCtlApDialogGetResult(reinterpret_cast(result)) == kErrNotInitialized); Require(sceNetCtlApDialogGetStatus() == kStatusNone); Require(sceNetCtlApDialogUpdateStatus() == kStatusNone); @@ -59,9 +50,9 @@ int main() { Require(sceNetCtlApDialogOpen(nullptr) == kErrArgNull); Require(sceNetCtlApDialogGetStatus() == kStatusInitialized); - Require(sceNetCtlApDialogGetResult(result) == static_cast(0x80B8000Au)); + Require(sceNetCtlApDialogGetResult(reinterpret_cast(result)) == static_cast(0x80B8000Au)); std::memset(result + 4, 0, 36); - Require(sceNetCtlApDialogGetResult(result) == kErrNotFinished); + Require(sceNetCtlApDialogGetResult(reinterpret_cast(result)) == kErrNotFinished); param.size = 103; Require(sceNetCtlApDialogOpen(¶m) == static_cast(0x80B8000Au)); @@ -80,7 +71,7 @@ int main() { Require(sceNetCtlApDialogUpdateStatus() == kStatusFinished); Require(sceNetCtlApDialogGetResult(nullptr) == kErrArgNull); - Require(sceNetCtlApDialogGetResult(result) == kResultUserCanceled); + Require(sceNetCtlApDialogGetResult(reinterpret_cast(result)) == kResultUserCanceled); RequireCanceled(result); Require(sceNetCtlApDialogOpen(¶m) == 0); @@ -92,6 +83,6 @@ int main() { Require(sceNetCtlApDialogInitialize() == 0); Require(sceNetCtlApDialogClose() == static_cast(0x80B8000Bu)); Require(sceNetCtlApDialogGetStatus() == kStatusInitialized); - Require(sceNetCtlApDialogGetResult(result) == kErrNotFinished); + Require(sceNetCtlApDialogGetResult(reinterpret_cast(result)) == kErrNotFinished); Require(sceNetCtlApDialogTerminate() == 0); } diff --git a/core/libs/tests/GuestNetNodelayReadback.cpp b/core/libs/tests/GuestNetNodelayReadback.cpp new file mode 100644 index 0000000000..ad296cdba6 --- /dev/null +++ b/core/libs/tests/GuestNetNodelayReadback.cpp @@ -0,0 +1,77 @@ +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#else +#include +#include +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include "prx/libSceNet/libSceNet.hpp" +#include "prx/libkernel/Socket/include/SocketPoll.hpp" + + +static void Require(bool condition, std::source_location where = std::source_location::current()) { + if (!condition) { + std::fprintf(stderr, "check failed at line %u\n", where.line()); + std::abort(); + } +} + +static void CheckValue(int socket, int expected) { + for (const std::uint32_t capacity : {0u, 1u, 2u, 3u, 4u, 8u}) { + std::array bytes; + bytes.fill(0xa5); + auto size = capacity; + Require(sceNetGetsockopt(socket, 6, 1, bytes.data(), &size) == 0); + Require(size == std::min(capacity, 4u)); + Require(std::memcmp(bytes.data(), &expected, size) == 0); + Require(std::all_of(bytes.begin() + size, bytes.end(), [](auto value) { return value == 0xa5; })); + } +} + +int main() { + Require(sceNetInit_nid_postfix() == 0); + for (const int family : {2, 28}) { + const int socket = sceNetSocket("nodelay", family, 1, 6); + const int other = sceNetSocket("nodelay-other", family, 1, 0); + const int datagram = sceNetSocket("nodelay-datagram", family, 2, 17); + Require(socket >= 0 && other >= 0 && datagram >= 0); + CheckValue(socket, 0); + for (const int requested : {1, 0, -1, 256, 0}) { + Require(sceNetSetsockopt(socket, 6, 1, &requested, sizeof(requested)) == 0); + CheckValue(socket, requested != 0 ? 4 : 0); + CheckValue(other, 0); + } + std::shared_ptr owner; + std::uintptr_t native = 0; + Require(KernelFindSocketNative_nid_no_patch(socket, &owner, &native)); + const int enabled = 1; + Require(::setsockopt(native, IPPROTO_TCP, TCP_NODELAY, + reinterpret_cast(&enabled), sizeof(enabled)) == 0); + CheckValue(socket, 4); + std::uint32_t size = 0; + int value = 99; + Require(sceNetGetsockopt(socket, 6, 1, nullptr, &size) < 0 && *sceNetErrnoLoc() == 22); + Require(sceNetGetsockopt(socket, 6, 1, &value, nullptr) < 0 && *sceNetErrnoLoc() == 22); + for (const std::uint32_t capacity : {0u, 3u, 4u}) { + size = capacity; + Require(sceNetGetsockopt(datagram, 6, 1, &value, &size) < 0 && *sceNetErrnoLoc() == 22); + Require(size == capacity && value == 99); + Require(sceNetGetsockopt(socket, 6, 0x7fffffff, &value, &size) < 0); + Require(*sceNetErrnoLoc() == (capacity < 4 ? 22 : 42)); + Require(size == capacity && value == 99); + } + owner.reset(); + for (const int descriptor : {socket, other, datagram}) Require(sceNetSocketClose(descriptor) == 0); + size = 0; + Require(sceNetGetsockopt(socket, 6, 1, &value, &size) < 0 && *sceNetErrnoLoc() == 9); + Require(size == 0 && value == 99); + } +} diff --git a/core/libs/tests/GuestNetProtocol.cpp b/core/libs/tests/GuestNetProtocol.cpp new file mode 100644 index 0000000000..038c59f77d --- /dev/null +++ b/core/libs/tests/GuestNetProtocol.cpp @@ -0,0 +1,71 @@ +#include +#include +#include +#include +#include +#include +#include +#include "prx/libSceNet/libSceNet.hpp" + + +static void Require(bool condition, std::source_location where = std::source_location::current()) { + if (!condition) { + std::fprintf(stderr, "check failed at line %u\n", where.line()); + std::abort(); + } +} + +static void CheckProtocol(int socket, int expected) { + for (const std::uint32_t capacity : {0u, 1u, 3u, 4u, 8u}) { + std::array bytes; + bytes.fill(0xa5); + auto size = capacity; + Require(sceNetGetsockopt(socket, 0xffff, 0x1016, bytes.data(), &size) == 0); + Require(size == std::min(capacity, 4u)); + Require(std::memcmp(bytes.data(), &expected, size) == 0); + Require(std::all_of(bytes.begin() + size, bytes.end(), [](auto value) { return value == 0xa5; })); + } +} + +int main() { + Require(sceNetInit_nid_postfix() == 0); + for (const int family : {2, 28}) { + for (const int type : {1, 2}) { + const int expected = type == 1 ? 6 : 17; + for (const int protocol : {0, expected}) { + const int socket = sceNetSocket("protocol", family, type, protocol); + Require(socket >= 0); + CheckProtocol(socket, expected); + std::uint32_t size = 4; + int value = 99; + Require(sceNetGetsockopt(socket, 0xffff, 0x1016, nullptr, &size) < 0 && *sceNetErrnoLoc() == 22); + Require(sceNetGetsockopt(socket, 0xffff, 0x1016, &value, nullptr) < 0 && *sceNetErrnoLoc() == 22); + Require(value == 99 && size == 4); + Require(sceNetSetsockopt(socket, 0xffff, 0x1016, &value, sizeof(value)) < 0); + CheckProtocol(socket, expected); + Require(sceNetSocketClose(socket) == 0); + Require(sceNetGetsockopt(socket, 0xffff, 0x1016, &value, &size) < 0 && *sceNetErrnoLoc() == 9); + Require(value == 99 && size == 4); + } + } + const int listener = sceNetSocket("protocol-listener", family, 1, 0); + const int client = sceNetSocket("protocol-client", family, 1, 6); + Require(listener >= 0 && client >= 0); + std::array address{}; + std::uint32_t size = family == 2 ? 16 : 28; + address[0] = size; + address[1] = family; + if (family == 2) { address[4] = 127; address[7] = 1; } + else address[23] = 1; + Require(sceNetBind_nid_postfix(listener, address.data(), size) == 0); + Require(sceNetListen(listener, 1) == 0); + CheckProtocol(listener, 6); + Require(sceNetGetsockname(listener, address.data(), &size) == 0); + Require(sceNetConnect(client, address.data(), size) == 0); + const int accepted = sceNetAccept(listener, nullptr, nullptr); + Require(accepted >= 0); + CheckProtocol(accepted, 6); + CheckProtocol(client, 6); + for (const int socket : {accepted, client, listener}) Require(sceNetSocketClose(socket) == 0); + } +} diff --git a/core/libs/tests/GuestNetThread.cpp b/core/libs/tests/GuestNetThread.cpp index 27f3b16a11..abdc2c22d8 100644 --- a/core/libs/tests/GuestNetThread.cpp +++ b/core/libs/tests/GuestNetThread.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNet/include/Net.hpp" #include "SceTypes.hpp" #include #include @@ -6,27 +7,13 @@ #include #include -extern "C" { -int APS5_VABI sceNetThreadCreate(Pthread*, void*, const char*); -void APS5_VABI sceNetThreadExit(); -int APS5_VABI sceNetThreadJoin(Pthread); -int APS5_VABI sceNetEmulationGet(); -int APS5_VABI sceNetEmulationSet(); -int* APS5_VABI sceNetErrnoLoc(); -} - namespace { constexpr int Einval = 22; constexpr int Eopnotsupp = 45; constexpr int NetError = static_cast(0x80410100u); -struct ThreadParam { - void (APS5_VABI *entry)(void*); - void* arg; - std::uint64_t reserved; - std::uint32_t flags; -}; + struct Run { std::atomic started{0}; @@ -55,7 +42,7 @@ void APS5_VABI ExitEarly(void* arg) { } int main() { - ThreadParam counting{Count, &run, 0, 0}; + NetThreadParameter counting{Count, &run, 0, 0}; Pthread thread = nullptr; Require(sceNetThreadCreate(&thread, &counting, "anyps5-net-thread") == 0 && thread != nullptr, "sceNetThreadCreate failed"); Require(sceNetThreadJoin(thread) == 0, "sceNetThreadJoin failed"); @@ -66,21 +53,21 @@ int main() { Require(sceNetThreadCreate(&untouched, nullptr, "anyps5-net-thread") == (NetError | Einval), "a null parameter was not refused with EINVAL"); Require(*sceNetErrnoLoc() == Einval && untouched == reinterpret_cast(&run), "a refused create set no errno or wrote the thread"); - ThreadParam exiting{ExitEarly, &run, 0, 1}; + NetThreadParameter exiting{ExitEarly, &run, 0, 1}; Require(sceNetThreadCreate(&thread, &exiting, nullptr) == 0, "sceNetThreadCreate failed without a name"); Require(sceNetThreadJoin(thread) == 0, "joining an exited thread failed"); Require(run.started == 2 && !run.pastExit, "sceNetThreadExit did not end the thread"); - static ThreadParam detached{Count, &run, 0, 0}; + static NetThreadParameter detached{Count, &run, 0, 0}; Require(sceNetThreadCreate(nullptr, &detached, "anyps5-net-thread") == 0, "a null thread output was refused"); const auto deadline = std::chrono::steady_clock::now() + std::chrono::seconds(5); while (run.started != 3 && std::chrono::steady_clock::now() < deadline) std::this_thread::sleep_for(std::chrono::milliseconds(1)); Require(run.started == 3, "the thread created without an output did not run"); *sceNetErrnoLoc() = 0; - Require(sceNetEmulationGet() == (NetError | Eopnotsupp) && *sceNetErrnoLoc() == Eopnotsupp, "sceNetEmulationGet did not return EOPNOTSUPP"); + Require(sceNetEmulationGet(nullptr, 0) == (NetError | Eopnotsupp) && *sceNetErrnoLoc() == Eopnotsupp, "sceNetEmulationGet did not return EOPNOTSUPP"); *sceNetErrnoLoc() = 0; - Require(sceNetEmulationSet() == (NetError | Eopnotsupp) && *sceNetErrnoLoc() == Eopnotsupp, "sceNetEmulationSet did not return EOPNOTSUPP"); + Require(sceNetEmulationSet(nullptr, 0) == (NetError | Eopnotsupp) && *sceNetErrnoLoc() == Eopnotsupp, "sceNetEmulationSet did not return EOPNOTSUPP"); std::puts("net thread tests passed"); return 0; } diff --git a/core/libs/tests/GuestNewHandler.cpp b/core/libs/tests/GuestNewHandler.cpp index 6229ada261..29b5acfc3c 100644 --- a/core/libs/tests/GuestNewHandler.cpp +++ b/core/libs/tests/GuestNewHandler.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/ApplicationHeap.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -11,16 +12,7 @@ extern "C" { using Handler = void (APS5_VABI*)(); -Handler APS5_VABI _ZSt15set_new_handlerPFvvE_nid_postfix(Handler); -Handler APS5_VABI _ZSt15get_new_handlerv_nid_postfix(); -void* APS5_VABI _Znwm_nid_postfix(std::size_t); -void* APS5_VABI _Znam_nid_postfix(std::size_t); -void* APS5_VABI _ZnwmSt11align_val_t_nid_postfix(std::size_t, std::size_t); -void* APS5_VABI _ZnwmRKSt9nothrow_t_nid_postfix(std::size_t, const void*) noexcept; -void* APS5_VABI _ZnamRKSt9nothrow_t_nid_postfix(std::size_t, const void*) noexcept; -void APS5_VABI _ZdlPv_nid_postfix(void*); -void APS5_VABI _ZdlPvRKSt9nothrow_t_nid_postfix(void*, const void*) noexcept; -void APS5_VABI _ZdlPvSt11align_val_t_nid_postfix(void*, std::size_t); + } namespace { @@ -146,8 +138,10 @@ int main(int argc, char** argv) { const int nothrowTag = 0; REQUIRE(nothrowPointer == storage.data() && releases == 0); _ZdlPvRKSt9nothrow_t_nid_postfix(nothrowPointer, ¬hrowTag); + REQUIRE(releases == 1); _ZdlPvRKSt9nothrow_t_nid_postfix(nullptr, ¬hrowTag); + REQUIRE(releases == 1); Reset(1); @@ -198,6 +192,7 @@ int main(int argc, char** argv) { void* aligned = _ZnwmSt11align_val_t_nid_postfix(24, 16); REQUIRE(aligned == storage.data() && lastSize == 24 && lastAlignment == 16 && allocations == 1); _ZdlPvSt11align_val_t_nid_postfix(aligned, 16); + Reset(1); REQUIRE(Throws([] { _ZnwmSt11align_val_t_nid_postfix(8, 32); }) && handlerCalls == 0 && allocations == 1); @@ -205,6 +200,7 @@ int main(int argc, char** argv) { REQUIRE(_ZnwmSt11align_val_t_nid_postfix(0, 16) == storage.data() && lastSize == 1 && lastAlignment == 16); Reset(2); _ZSt15set_new_handlerPFvvE_nid_postfix(&countingHandler); + REQUIRE(_ZnwmSt11align_val_t_nid_postfix(8, 16) == storage.data() && handlerCalls == 2 && allocations == 3); _ZSt15set_new_handlerPFvvE_nid_postfix(nullptr); diff --git a/core/libs/tests/GuestNpAuth.cpp b/core/libs/tests/GuestNpAuth.cpp index 695d37a67d..a1920ceb5c 100644 --- a/core/libs/tests/GuestNpAuth.cpp +++ b/core/libs/tests/GuestNpAuth.cpp @@ -1,26 +1,10 @@ +#include "prx/libSceNpAuth/include/Api.hpp" #include "SceTypes.hpp" #include #include #include -extern "C" { -int APS5_VABI sceNpAuthAbortRequest(int req_id); -int APS5_VABI sceNpAuthCreateAsyncRequest(const void* param); -int APS5_VABI sceNpAuthCreateRequest(void); -int APS5_VABI sceNpAuthDeleteRequest(int req_id); -int APS5_VABI sceNpAuthGetAuthorizationCode(int req_id, const void* param, void* auth_code); -int APS5_VABI sceNpAuthGetAuthorizationCodeA(int req_id, const void* param, void* auth_code, int* issuer_id); -int APS5_VABI sceNpAuthGetAuthorizationCodeV3(int req_id, const void* param, void* auth_code, int* issuer_id); -int APS5_VABI sceNpAuthGetAuthorizedAppCode(std::int32_t, const NpAuthAuthorizedAppCodeParameter*, char*, std::int32_t*, bool*); -int APS5_VABI sceNpAuthGetIdToken(int req_id, const void* param, void* id_token); -int APS5_VABI sceNpAuthGetIdTokenA(int req_id, const void* param, void* id_token); -int APS5_VABI sceNpAuthGetIdTokenV3(int req_id, const void* param, void* id_token); -int APS5_VABI sceNpAuthPollAsync(int req_id, int* result); -int APS5_VABI sceNpAuthSetTimeout(int req_id, int resolve_retry, uint32_t resolve_timeout, uint32_t connect_timeout, uint32_t send_timeout, uint32_t receive_timeout); -int APS5_VABI sceNpAuthWaitAsync(int req_id, int* result); -} - static void Require(bool condition) { if (!condition) { std::abort(); diff --git a/core/libs/tests/GuestNpAuthAuthorizedAppCode.cpp b/core/libs/tests/GuestNpAuthAuthorizedAppCode.cpp index a5d7f6fe17..b644c62ed3 100644 --- a/core/libs/tests/GuestNpAuthAuthorizedAppCode.cpp +++ b/core/libs/tests/GuestNpAuthAuthorizedAppCode.cpp @@ -1,14 +1,9 @@ +#include "prx/libSceNpAuth/include/Api.hpp" #include "SceTypes.hpp" #include #include #include -extern "C" { -int APS5_VABI sceNpAuthCreateRequest(); -int APS5_VABI sceNpAuthDeleteRequest(int); -int APS5_VABI sceNpAuthGetAuthorizedAppCode(std::int32_t, const NpAuthAuthorizedAppCodeParameter*, char*, std::int32_t*, bool*); -} - static void Require(bool condition) { if (!condition) std::abort(); } @@ -41,6 +36,7 @@ int main() { bool threw = false; try { sceNpAuthGetAuthorizedAppCode(requestId, ¶meter, code.data(), nullptr, &authorizationRequired); + } catch (const std::logic_error&) { threw = true; } diff --git a/core/libs/tests/GuestNpAuthAuthorizedAppDialog.cpp b/core/libs/tests/GuestNpAuthAuthorizedAppDialog.cpp index aedef7375a..a8fecd529b 100644 --- a/core/libs/tests/GuestNpAuthAuthorizedAppDialog.cpp +++ b/core/libs/tests/GuestNpAuthAuthorizedAppDialog.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNpAuthAuthorizedAppDialog/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -5,18 +6,6 @@ #include "prx/libSceCommonDialog/CommonDialog.hpp" #include "prx/libSceUserService/UserService.hpp" -extern "C" { -int APS5_VABI sceUserServiceInitialize(const UserServiceInitParam* param); -int APS5_VABI sceUserServiceTerminate(); -int APS5_VABI sceNpAuthAuthorizedAppDialogInitialize(void); -int APS5_VABI sceNpAuthAuthorizedAppDialogOpen(const NpAuthAuthorizedAppDialogParam* param); -int APS5_VABI sceNpAuthAuthorizedAppDialogUpdateStatus(void); -int APS5_VABI sceNpAuthAuthorizedAppDialogGetStatus(void); -int APS5_VABI sceNpAuthAuthorizedAppDialogGetResult(std::int32_t* result); -int APS5_VABI sceNpAuthAuthorizedAppDialogClose(void); -int APS5_VABI sceNpAuthAuthorizedAppDialogTerminate(void); -} - namespace { void Require(bool value) { if (!value) std::abort(); } diff --git a/core/libs/tests/GuestNpCommerceDialog.cpp b/core/libs/tests/GuestNpCommerceDialog.cpp index 3db9b4c3b3..58383cb878 100644 --- a/core/libs/tests/GuestNpCommerceDialog.cpp +++ b/core/libs/tests/GuestNpCommerceDialog.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNpCommerce/include/Api.hpp" #include "ProcessParametersFixture.hpp" #include "prx/libSceUserService/UserService.hpp" #include @@ -9,20 +10,6 @@ #include #include -extern "C" { -int APS5_VABI sceUserServiceInitialize(const UserServiceInitParam* param); -int APS5_VABI sceUserServiceTerminate(); -int APS5_VABI sceNpCommerceDialogInitialize(); -int APS5_VABI sceNpCommerceDialogInitializeInternal(); -int APS5_VABI sceNpCommerceDialogOpen(const NpCommerceDialogParam* param); -int APS5_VABI sceNpCommerceDialogOpen2(const NpCommerceDialogParam2* param); -int APS5_VABI sceNpCommerceDialogUpdateStatus(void); -int APS5_VABI sceNpCommerceDialogGetStatus(void); -int APS5_VABI sceNpCommerceDialogGetResult(NpCommerceDialogResult* result); -int APS5_VABI sceNpCommerceDialogClose(void); -int APS5_VABI sceNpCommerceDialogTerminate(); -} - namespace { void Require(bool value) { if (!value) std::abort(); } @@ -157,6 +144,7 @@ int main() { bool threw = false; try { sceNpCommerceDialogOpen2(¶m2); + } catch (const std::runtime_error&) { threw = true; } diff --git a/core/libs/tests/GuestNpCommon.cpp b/core/libs/tests/GuestNpCommon.cpp index c3d964f7ea..fc8817dbf1 100644 --- a/core/libs/tests/GuestNpCommon.cpp +++ b/core/libs/tests/GuestNpCommon.cpp @@ -1,41 +1,11 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libSceNpCommon/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "SceTypes.hpp" #include #include #include -struct NpIdFull { - NpOnlineId handle; - std::uint8_t opt[8]; - std::uint8_t reserved[8]; -}; - -extern "C" { -int APS5_VABI sceNpCmpOnlineId(const NpOnlineId* onlineId1, const NpOnlineId* onlineId2); -int APS5_VABI sceNpCmpNpIdInOrder(const NpIdFull* npId1, const NpIdFull* npId2, std::int32_t* order); -int APS5_VABI sceNpGetPlatformType(const NpIdFull* npId); -int APS5_VABI sceNpIntIsValidOnlineId(const NpOnlineId* onlineId); -int APS5_VABI sceNpMutexInit(PthreadMutex* mutex, const char* name, std::uint64_t flags); -int APS5_VABI sceNpMutexDestroy(PthreadMutex* mutex); -int APS5_VABI sceNpMutexLock(PthreadMutex* mutex); -int APS5_VABI sceNpMutexTryLock(PthreadMutex* mutex); -int APS5_VABI sceNpMutexUnlock(PthreadMutex* mutex); -int APS5_VABI sceNpLwMutexInit(PthreadMutex* mutex, const char* name, std::uint64_t flags); -int APS5_VABI sceNpLwMutexTryLock(PthreadMutex* mutex); -int APS5_VABI sceNpLwMutexUnlock(PthreadMutex* mutex); -int APS5_VABI sceNpLwMutexDestroy(PthreadMutex* mutex); -int APS5_VABI sceNpLwMutexLock(PthreadMutex* mutex); -int APS5_VABI sceNpCondInit(PthreadCond* cond, const char* name, std::uint64_t flags); -int APS5_VABI sceNpCondDestroy(PthreadCond* cond); -int APS5_VABI sceNpCondSignal(PthreadCond* cond); -int APS5_VABI sceNpCondTimedwait(PthreadCond* cond, PthreadMutex* mutex, std::uint32_t usec); -int APS5_VABI sceNpJoinThread(Pthread thread, void** retval); -int APS5_VABI sceNpGetSystemClockUsec(std::int64_t* usec); -void APS5_VABI sceNpGetSdkVersion(char* version); -int APS5_VABI sceKernelClockGettime(KernelClockid clockId, KernelTimespec* tp); -int APS5_VABI scePthreadCreate(Pthread* thread, const PthreadAttr* attr, PthreadEntry entry, void* arg, const char* name); -} - static constexpr int INVALID_ARGUMENT = static_cast(0x80550003); static constexpr int INVALID_PLATFORM_TYPE = static_cast(0x80550004); static constexpr int NOT_MATCH = static_cast(0x80550609); @@ -153,12 +123,15 @@ static int testClock() { KernelTimespec after{}; std::int64_t usec = -1; sceKernelClockGettime(4, &before); + bool ok = expect(sceNpGetSystemClockUsec(&usec) == 0, "the clock was not read"); sceKernelClockGettime(4, &after); + ok &= expect(usec >= before.tv_sec * 1000000 + before.tv_nsec / 1000 && usec <= after.tv_sec * 1000000 + after.tv_nsec / 1000, "the clock is not the monotonic kernel clock in microseconds"); char version[12]; std::memset(version, 'x', sizeof(version)); sceNpGetSdkVersion(version); + ok &= expect(std::strcmp(version, "1.00") == 0, "the version is not 1.00"); ok &= expect(version[8] == 'x', "the version was written past 8 bytes"); return ok ? 0 : 1; diff --git a/core/libs/tests/GuestNpCommonRuntime.cpp b/core/libs/tests/GuestNpCommonRuntime.cpp index ff9f9aa995..1747776629 100644 --- a/core/libs/tests/GuestNpCommonRuntime.cpp +++ b/core/libs/tests/GuestNpCommonRuntime.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNpCommon/include/Api.hpp" #include "SceTypes.hpp" #include @@ -9,133 +10,6 @@ #include #include -extern "C" { -int APS5_VABI sceNpAtomicCas32(std::int32_t* value, std::int32_t expected, std::int32_t desired); -int APS5_VABI sceNpAtomicInc32(std::int32_t* value); -int APS5_VABI sceNpAtomicDec32(std::int32_t* value); -int APS5_VABI sceNpCreateSema(KernelSema* sema, std::uint32_t flags, int initial, int maximum, const char* name); -int APS5_VABI sceNpDeleteSema(KernelSema sema); -int APS5_VABI sceNpPollSema(KernelSema sema); -int APS5_VABI sceNpSignalSema(KernelSema sema); -int APS5_VABI sceNpCreateEventFlag(KernelEventFlag* flag, const char* name, std::uint32_t attr, std::uint64_t pattern); -int APS5_VABI sceNpDeleteEventFlag(KernelEventFlag flag); -int APS5_VABI sceNpSetEventFlag(KernelEventFlag flag, std::uint64_t pattern); -int APS5_VABI sceNpPollEventFlag(KernelEventFlag flag, std::uint64_t pattern, std::uint32_t mode, std::uint64_t* result); -int APS5_VABI sceNpCreateThread(Pthread* thread, PthreadEntry entry, void* arg, int priority, std::size_t stackSize, KernelCpumask affinity, const char* name); -int APS5_VABI sceNpJoinThread(Pthread thread, void** value); -int APS5_VABI sceNpThreadGetId(Pthread* thread); - -struct NpHeap { - void* mspace; -}; - -struct NpHeapStat { - std::uint64_t maxSystemSize; - std::uint64_t maxInuseSize; - std::uint64_t currentInuseSize; -}; - -struct NpKernelMemory { - std::uint64_t size; - std::uint64_t reserved; - void* address; -}; - -struct NpMemoryHeap { - NpKernelMemory memory; - NpHeap heap; -}; - -struct NpAllocator { - void* (APS5_VABI *allocate)(std::size_t size, void* context); - void* (APS5_VABI *reallocate)(void* pointer, std::size_t size, void* context); - void (APS5_VABI *release)(void* pointer, void* context); - void* context; -}; - -struct NpAllocatorEx { - NpAllocator allocator; - int outOfMemoryError; -}; - -int APS5_VABI sceNpHeapInit(NpHeap* heap, void* base, std::size_t size, const char* name); -void APS5_VABI sceNpHeapDestroy(NpHeap* heap); -void APS5_VABI sceNpHeapGetAllocator(NpHeap* heap, NpAllocator* allocator); -int APS5_VABI sceNpHeapGetStat(const NpHeap* heap, NpHeapStat* stat); -int APS5_VABI sceNpMemoryHeapInit(NpMemoryHeap* heap, std::uint64_t size, const char* name); -void APS5_VABI sceNpMemoryHeapDestroy(NpMemoryHeap* heap); -void APS5_VABI sceNpMemoryHeapGetAllocatorEx(NpMemoryHeap* heap, int outOfMemoryError, NpAllocatorEx* allocator); -int APS5_VABI sceNpArchInit(void); -int APS5_VABI sceNpIpc2ClientInit(void); -int APS5_VABI sceNpIpc2ClientTerm(void); -void APS5_VABI sceNpArchTerm(void); -NpAllocatorEx* APS5_VABI sceNpGlobalHeapGetAllocatorExPtr(void); -int APS5_VABI sceNpAllocateKernelMemoryWithAlignment(std::uint64_t size, const char* name, void** address, NpKernelMemory* memory); -int APS5_VABI sceNpFreeKernelMemory(NpKernelMemory* memory); -struct NpCallout { - NpCallout* next; - void (APS5_VABI *handler)(void* arg); - std::uint64_t deadline; - void* arg; - std::uint64_t reserved; -}; - -struct NpCalloutContext { - Pthread thread; - PthreadMutex mutex; - PthreadCond cond; - int initialized; - int stopping; - NpCallout* pending; -}; - -int APS5_VABI sceNpCalloutInitCtx(NpCalloutContext* context, const char* name, std::size_t stackSize, int priority, KernelCpumask affinity); -void APS5_VABI sceNpCalloutTermCtx(NpCalloutContext* context); -int APS5_VABI sceNpCalloutStartOnCtx(NpCalloutContext* context, NpCallout* callout, std::uint32_t usec, void (APS5_VABI *handler)(void* arg), void* arg); -int APS5_VABI sceNpCalloutStopOnCtx(NpCalloutContext* context, NpCallout* callout, int* wasPending); -int APS5_VABI sceNpUtilCmpAccountId(std::uint64_t left, std::uint64_t right); -int APS5_VABI sceNpCmpNpId(const void* npId1, const void* npId2); -bool APS5_VABI sceNpIntIsOnlineIdString(const char* text); -int APS5_VABI sceNpUtilGetNpLanguageCode(int language, char* code); -int APS5_VABI sceNpUtilGetNpLanguageCode2(int language, char* tag); -const char* APS5_VABI sceNpUtilGetNpLanguageCodeStr(int language); -const char* APS5_VABI sceNpUtilGetNpLanguageCode2Str(int language); -std::uint32_t APS5_VABI sceNpDbgAssignDebugId(void); -int APS5_VABI sceNpUtilJsonEscape(char* dst, std::size_t dstSize, const char* src, std::size_t srcLength); -int APS5_VABI sceNpUtilJsonUnescape(char* dst, std::size_t dstSize, const char* src, std::size_t srcLength, std::size_t* dstLength); -int APS5_VABI sceNpUtilJsonGetOneChar(char* dst, std::size_t dstSize, const char* src, std::size_t srcLength, std::size_t* dstLength, std::size_t* consumed); -int APS5_VABI sceNpUtilGetNthChar(std::size_t index, const char* text, const char** character); -int APS5_VABI sceNpUtilHttpUrlEncode(char* dst, std::size_t dstSize, const char* src, std::size_t srcLength, std::size_t* dstLength); -struct NpTitleIdParts { - char id[9]; - char reserved; - std::uint8_t index; -}; - -int APS5_VABI sceNpUtilBuildTitleId(const NpTitleIdParts* parts, char* titleId, std::size_t size); -int APS5_VABI sceNpBase64GetDecodeSize(const char* src, std::size_t length); -int APS5_VABI sceNpBase64Decoder(const char* src, std::size_t length, void* dst, std::size_t capacity); -int APS5_VABI sceNpBase64Encoder(const void* src, char* dst, std::size_t length); -int APS5_VABI sceNpBase64UrlGetDecodeSize(const char* src, std::size_t length); -int APS5_VABI sceNpBase64UrlDecoder(const char* src, std::size_t length, void* dst, std::size_t capacity); -int APS5_VABI sceNpBase64UrlEncoder(const void* src, char* dst, std::size_t length); -int APS5_VABI sceNpHexToInt(int c); -int APS5_VABI sceNpIntToHex(std::uint32_t value, bool uppercase); -int APS5_VABI sceNpUInt32ToStr(char* buf, std::size_t size, std::uint32_t value, std::uint32_t radix, std::uint32_t flags, std::size_t* length); -int APS5_VABI sceNpUInt64ToStr(char* buf, std::size_t size, std::uint64_t value, std::uint32_t radix, std::uint32_t flags, std::size_t* length); -int APS5_VABI sceNpInt32ToStr(char* buf, std::size_t size, std::int32_t value, std::uint32_t radix, std::uint32_t flags, std::size_t* length); -int APS5_VABI sceNpInt64ToStr(char* buf, std::size_t size, std::int64_t value, std::uint32_t radix, std::uint32_t flags, std::size_t* length); -int APS5_VABI sceNpStrToInt32(const char* str, std::int32_t* value, int base, std::size_t* parsedLength); -int APS5_VABI sceNpStrToInt64(const char* str, std::int64_t* value, int base, std::size_t* parsedLength); -int APS5_VABI sceNpStrToUInt32(const char* str, std::uint32_t* value, int base, std::size_t* parsedLength); -int APS5_VABI sceNpStrToUInt64(const char* str, std::uint64_t* value, int base, std::size_t* parsedLength); -int APS5_VABI sceNpStrBuildHex(char* dst, std::size_t size, const void* src, std::size_t length, bool uppercase); -int APS5_VABI sceNpStrParseHex(const char* hex, void* out, std::size_t capacity); -int APS5_VABI sceNpStrnParseHex(const char* hex, std::size_t length, void* out, std::size_t capacity); -int APS5_VABI sceNpStrcpyToBuf(char* dst, std::size_t size, const char* src); -int APS5_VABI sceNpStrncpyToBuf(char* dst, std::size_t size, const char* src, std::size_t maxLength); -} - namespace { constexpr int NpIpcAlreadyInitialized = static_cast(0x80559D00); @@ -156,7 +30,10 @@ constexpr int NpOutOfRange = static_cast(0x8055800E); constexpr int NpInvalidArgument = static_cast(0x80558009); constexpr int NpEventFlagBusy = static_cast(0x8055800C); constexpr int NpSemaBusy = static_cast(0x8055800D); +constexpr int KernelNotPermitted = static_cast(0x80020001); +constexpr int KernelNoSuchObject = static_cast(0x80020003); constexpr std::uint32_t EventFlagWaitAnd = 1; +constexpr std::uint32_t EventFlagShared = 0x100; void Require(bool value, const char* message) { if (value) return; @@ -193,6 +70,20 @@ void TestSemaphoresAndFlags() { Require(sceNpDeleteEventFlag(flag) == 0, "the event flag is deleted"); } +void TestSharedEventFlags() { + KernelEventFlag creator {}; + Require(sceNpCreateEventFlag(&creator, "NpSharedFlag", EventFlagShared, 0) == 0, "a shared event flag is created"); + KernelEventFlag opened {}; + Require(sceNpOpenEventFlag(&opened, "NpSharedFlag") == 0 && opened != creator, "the shared event flag is opened by name"); + std::uint64_t result = 0; + Require(sceNpSetEventFlag(opened, 2) == 0 && sceNpPollEventFlag(creator, 2, EventFlagWaitAnd, &result) == 0 && result == 2, + "a bit set through the opened handle is polled through the creator"); + Require(sceNpCloseEventFlag(creator) == KernelNotPermitted, "the creator handle is not closed"); + Require(sceNpCloseEventFlag(opened) == 0, "the opened handle is closed"); + Require(sceNpCloseEventFlag(opened) == KernelNoSuchObject, "a closed handle is gone"); + Require(sceNpDeleteEventFlag(creator) == 0, "the creator deletes the shared event flag"); +} + void TestThreads() { Require(sceNpThreadGetId(nullptr) == NpInvalidArgument, "a null thread id output is refused"); Pthread thread {}; @@ -220,10 +111,12 @@ void TestHeaps() { "the memory heap size is rounded up to 16 KiB"); NpAllocatorEx allocatorEx {}; sceNpMemoryHeapGetAllocatorEx(&memoryHeap, 0x1234, &allocatorEx); + Require(allocatorEx.allocator.context == &memoryHeap && allocatorEx.outOfMemoryError == 0x1234, "the extended allocator carries the caller's error code"); UseAllocator(allocatorEx.allocator); sceNpMemoryHeapDestroy(&memoryHeap); + Require(memoryHeap.memory.address == nullptr && memoryHeap.heap.mspace == nullptr, "destroying clears the memory heap"); NpKernelMemory memory {}; @@ -237,11 +130,13 @@ void TestHeaps() { Require(sceNpHeapInit(&heap, memory.address, memory.size, "np-test") == 0 && heap.mspace != nullptr, "a heap is created"); NpAllocator allocator {}; sceNpHeapGetAllocator(&heap, &allocator); + Require(allocator.context == &heap, "the heap allocator uses the heap as its context"); UseAllocator(allocator); NpHeapStat stat {}; Require(sceNpHeapGetStat(&heap, &stat) == 0 && stat.maxInuseSize >= stat.currentInuseSize, "heap statistics are reported"); sceNpHeapDestroy(&heap); + Require(heap.mspace == nullptr, "destroying clears the heap"); Require(sceNpFreeKernelMemory(&memory) == 0 && memory.address == nullptr, "kernel memory is released"); Require(sceNpFreeKernelMemory(nullptr) == NpNullObject, "freeing needs an object"); @@ -251,6 +146,7 @@ void TestHeaps() { Require(global->outOfMemoryError == NpOutOfMemory, "the global allocator reports the library's out-of-memory error"); UseAllocator(global->allocator); sceNpArchTerm(); + UseAllocator(sceNpGlobalHeapGetAllocatorExPtr()->allocator); sceNpArchTerm(); @@ -313,8 +209,10 @@ void TestCallouts() { for (int i = 0; i < 2000 && g_callouts.second == 0; ++i) std::this_thread::sleep_for(std::chrono::milliseconds(1)); Require(g_callouts.first == 1 && g_callouts.second == 2, "callouts run in deadline order"); sceNpCalloutTermCtx(&context); + Require(context.initialized == 0, "terminating clears the context"); sceNpCalloutTermCtx(&context); + } bool Equals(const char* actual, const char* expected) { @@ -519,6 +417,7 @@ void TestHexAndCopies() { int main() { TestAtomics(); TestSemaphoresAndFlags(); + TestSharedEventFlags(); TestThreads(); TestHeaps(); TestBase64(); diff --git a/core/libs/tests/GuestNpCppWebApiIntrusivePtr.cpp b/core/libs/tests/GuestNpCppWebApiIntrusivePtr.cpp index 93ee41cd7a..13cc9a8491 100644 --- a/core/libs/tests/GuestNpCppWebApiIntrusivePtr.cpp +++ b/core/libs/tests/GuestNpCppWebApiIntrusivePtr.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNpCppWebApi/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -7,102 +8,11 @@ using Deleter = void (APS5_VABI*)(void*); -struct IntrusivePtr { - void* object; - Deleter deleter; - void* libContext; -}; - using Construct = void (APS5_VABI*)(IntrusivePtr*); using Copy = void (APS5_VABI*)(IntrusivePtr*, const IntrusivePtr*); using Destroy = void (APS5_VABI*)(IntrusivePtr*); using Access = void* (APS5_VABI*)(const IntrusivePtr*); -extern "C" { -void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V121GetRankingRequestBodyEEC1Ev(IntrusivePtr*); -void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V122GetRankingResponseBodyEEC1Ev(IntrusivePtr*); -void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V122RecordScoreRequestBodyEEC1Ev(IntrusivePtr*); -void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V123RecordScoreResponseBodyEEC1Ev(IntrusivePtr*); -void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V130GetBoardDefinitionResponseBodyEEC1Ev(IntrusivePtr*); -void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V14UserEEC1Ev(IntrusivePtr*); -void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V19RecordApi26RecordScoreResponseHeadersEEC1Ev(IntrusivePtr*); - -void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V121GetRankingRequestBodyEEC1ERS7_(IntrusivePtr*, const IntrusivePtr*); -void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V122RecordScoreRequestBodyEEC1ERS7_(IntrusivePtr*, const IntrusivePtr*); - -void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V121GetRankingRequestBodyEED1Ev(IntrusivePtr*); -void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V122GetRankingResponseBodyEED1Ev(IntrusivePtr*); -void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V122RecordScoreRequestBodyEED1Ev(IntrusivePtr*); -void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V123RecordScoreResponseBodyEED1Ev(IntrusivePtr*); -void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V130GetBoardDefinitionResponseBodyEED1Ev(IntrusivePtr*); -void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V14UserEED1Ev(IntrusivePtr*); -void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V19RecordApi26RecordScoreResponseHeadersEED1Ev(IntrusivePtr*); -void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS3_INS1_12Leaderboards2V15EntryEEEEEED1Ev(IntrusivePtr*); - -void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V121GetRankingRequestBodyEEptEv(const IntrusivePtr*); -void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V122GetRankingResponseBodyEEptEv(const IntrusivePtr*); -void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V122RecordScoreRequestBodyEEptEv(const IntrusivePtr*); -void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V123RecordScoreResponseBodyEEptEv(const IntrusivePtr*); -void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V130GetBoardDefinitionResponseBodyEEptEv(const IntrusivePtr*); -void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V14UserEEptEv(const IntrusivePtr*); -void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V15EntryEEptEv(const IntrusivePtr*); -void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V19RecordApi26RecordScoreResponseHeadersEEptEv(const IntrusivePtr*); -void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6BinaryEEptEv(const IntrusivePtr*); -void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS3_INS1_12Leaderboards2V15EntryEEEEEEdeEv(const IntrusivePtr*); - -void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_14SessionManager2V126RequestPlayerSessionPlayerEED1Ev(IntrusivePtr*); -void APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_14SessionManager2V126RequestPlayerSessionPlayerEEEEC1EPNS2_10LibContextE(IntrusivePtr*, void*); -void APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_14SessionManager2V126RequestPlayerSessionPlayerEEEED1Ev(IntrusivePtr*); -int APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_14SessionManager2V126RequestPlayerSessionPlayerEEEE8pushBackERKS8_(IntrusivePtr*, const IntrusivePtr*); -void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS2_6StringEEEEC1EPS6_PFvS8_EPNS2_10LibContextE(IntrusivePtr*, void*, Deleter, void*); -void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS2_6StringEEEED1Ev(IntrusivePtr*); - -void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_15ProfanityFilter2V219WebApiFilterRequestEEC1Ev(IntrusivePtr*); -void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS2_18ResponseHeaderBaseEEC1Ev(IntrusivePtr*); -void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6StringEEC1Ev(IntrusivePtr*); -void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_15ProfanityFilter2V219WebApiFilterRequestEEC1ERS7_(IntrusivePtr*, const IntrusivePtr*); -void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_15ProfanityFilter2V219WebApiFilterRequestEED1Ev(IntrusivePtr*); -void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS2_18ResponseHeaderBaseEED1Ev(IntrusivePtr*); -void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6StringEED1Ev(IntrusivePtr*); -void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS3_INS1_11UserProfile2V113BasicPresenceEEEEEED1Ev(IntrusivePtr*); -void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_11UserProfile2V113BasicPresenceEEptEv(const IntrusivePtr*); -void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_11UserProfile2V118GetFriendsResponseEEptEv(const IntrusivePtr*); -void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_11UserProfile2V124GetBlockingUsersResponseEEptEv(const IntrusivePtr*); -void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_11UserProfile2V125GetBasicPresencesResponseEEptEv(const IntrusivePtr*); -void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_15ProfanityFilter2V223FilterProfanityResponseEEptEv(const IntrusivePtr*); -void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_30CommunicationRestrictionStatus2V338CommunicationRestrictionStatusResponseEEptEv(const IntrusivePtr*); -void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS2_18ResponseHeaderBaseEE3getEv(const IntrusivePtr*); -void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS2_18ResponseHeaderBaseEEptEv(const IntrusivePtr*); -void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6StringEE3getEv(const IntrusivePtr*); -void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6StringEEptEv(const IntrusivePtr*); -void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS3_INS1_11UserProfile2V113BasicPresenceEEEEEEdeEv(const IntrusivePtr*); -void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS3_INS1_11UserProfile2V113BasicPresenceEEEEEEptEv(const IntrusivePtr*); -void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorImEEEdeEv(const IntrusivePtr*); -void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorImEEEptEv(const IntrusivePtr*); -void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_17TitleCloudStorage2V132GetMultiDataStatusesResponseBodyEEC1Ev(IntrusivePtr*); -void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS3_INS1_13InGameCatalog2V59ContainerEEEEEEC1Ev(IntrusivePtr*); -void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_13InGameCatalog2V57ProductEEptEv(const IntrusivePtr*); -void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_13InGameCatalog2V59ContainerEEptEv(const IntrusivePtr*); -void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_17TitleCloudStorage2V110DataStatusEEptEv(const IntrusivePtr*); -void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_17TitleCloudStorage2V132GetMultiDataStatusesResponseBodyEEptEv(const IntrusivePtr*); -void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_17TitleCloudStorage2V15OwnerEEptEv(const IntrusivePtr*); -void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS3_INS1_13InGameCatalog2V53SkuEEEEEEptEv(const IntrusivePtr*); -void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS3_INS1_13InGameCatalog2V57ProductEEEEEEptEv(const IntrusivePtr*); -void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS3_INS1_13InGameCatalog2V59ContainerEEEEEEdeEv(const IntrusivePtr*); -void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS3_INS1_13InGameCatalog2V59ContainerEEEEEEptEv(const IntrusivePtr*); -void* APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS3_INS1_17TitleCloudStorage2V110DataStatusEEEEEEdeEv(const IntrusivePtr*); -void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_13InGameCatalog2V57ProductEEC1ERS7_(IntrusivePtr*, const IntrusivePtr*); -void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_13InGameCatalog2V59ContainerEEC1ERS7_(IntrusivePtr*, const IntrusivePtr*); -void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_13InGameCatalog2V57ProductEED1Ev(IntrusivePtr*); -void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_13InGameCatalog2V59ContainerEED1Ev(IntrusivePtr*); -void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_17TitleCloudStorage2V132GetMultiDataStatusesResponseBodyEED1Ev(IntrusivePtr*); -void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_17TitleCloudStorage2V15OwnerEED1Ev(IntrusivePtr*); -void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS3_INS1_13InGameCatalog2V53SkuEEEEEED1Ev(IntrusivePtr*); -void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS3_INS1_13InGameCatalog2V57ProductEEEEEED1Ev(IntrusivePtr*); -void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS3_INS1_13InGameCatalog2V59ContainerEEEEEED1Ev(IntrusivePtr*); -void APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS3_INS1_17TitleCloudStorage2V110DataStatusEEEEEED1Ev(IntrusivePtr*); -} - static void Require(bool value) { if (!value) std::abort(); } static constexpr std::size_t ObjectSize = 0x40; @@ -238,11 +148,13 @@ static void TestSharedOwnership() { IntrusivePtr owner; _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V122RecordScoreRequestBodyEEC1Ev(&owner); + owner.object = object; owner.deleter = RecordDelete; IntrusivePtr argument; _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V122RecordScoreRequestBodyEEC1ERS7_(&argument, &owner); + Require(_ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V122RecordScoreRequestBodyEEptEv(&argument) == object); Require(ReadCount(object, 0) == 2); @@ -267,6 +179,7 @@ static void TestVectorPushBackReleasesElements() { IntrusivePtr vector; _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_14SessionManager2V126RequestPlayerSessionPlayerEEEEC1EPNS2_10LibContextE(&vector, &context); + Require(vector.object == nullptr); Require(vector.deleter == nullptr); Require(vector.libContext == &context); @@ -302,6 +215,7 @@ static void TestAdoptedVectorBodyDestroyedThroughDeleter() { IntrusivePtr vector; _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS2_6StringEEEEC1EPS6_PFvS8_EPNS2_10LibContextE(&vector, body, RecordDelete, &context); + Require(vector.object == body); Require(vector.deleter == RecordDelete); Require(vector.libContext == &context); diff --git a/core/libs/tests/GuestNpCppWebApiOffline.cpp b/core/libs/tests/GuestNpCppWebApiOffline.cpp index 32a7b48145..ed22df2b30 100644 --- a/core/libs/tests/GuestNpCppWebApiOffline.cpp +++ b/core/libs/tests/GuestNpCppWebApiOffline.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNpCppWebApi/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -5,11 +6,6 @@ using SelfCall = int (APS5_VABI*)(void*); -extern "C" { -int APS5_VABI _ZN3sce2Np9CppWebApi6Common13ConstIteratorINS2_12IntrusivePtrINS1_13InGameCatalog2V57ProductEEEED2Ev(void*); -int APS5_VABI _ZN3sce2Np9CppWebApi6Common13ConstIteratorINS2_12IntrusivePtrINS1_17TitleCloudStorage2V110DataStatusEEEED2Ev(void*); -} - static void Require(bool value, const char* what) { if (value) return; std::fprintf(stderr, "%s\n", what); diff --git a/core/libs/tests/GuestNpCppWebApiSignedOut.cpp b/core/libs/tests/GuestNpCppWebApiSignedOut.cpp index 455bc254b0..826ceb8fa0 100644 --- a/core/libs/tests/GuestNpCppWebApiSignedOut.cpp +++ b/core/libs/tests/GuestNpCppWebApiSignedOut.cpp @@ -1,72 +1,9 @@ +#include "prx/libSceNpCppWebApi/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include #include -extern "C" { -int APS5_VABI _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_11UserProfile2V118GetFriendsResponseEEENS4_INS2_18ResponseHeaderBaseEEEEC1Ev(void*); -int APS5_VABI _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_11UserProfile2V118GetFriendsResponseEEENS4_INS2_18ResponseHeaderBaseEEEED1Ev(void*); -int APS5_VABI _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_11UserProfile2V118GetFriendsResponseEEENS4_INS2_18ResponseHeaderBaseEEEE21setOnFinishedCallbackEPFvliS8_PvEPFvliSC_ESC_(); -int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_11UserProfile2V118GetFriendsResponseEEENS4_INS2_18ResponseHeaderBaseEEEE28setResponseInformationOptionEP37SceNpWebApi2ResponseInformationOption(); -int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_11UserProfile2V118GetFriendsResponseEEENS4_INS2_18ResponseHeaderBaseEEEE5startEPNS2_10LibContextE(); -int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_11UserProfile2V118GetFriendsResponseEEENS4_INS2_18ResponseHeaderBaseEEEE6finishEv(); -int APS5_VABI _ZNK3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_11UserProfile2V118GetFriendsResponseEEENS4_INS2_18ResponseHeaderBaseEEEE18getResponseHeadersERSA_(); -int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V110FriendsApi21ParameterToGetFriendsC1Ev(void*); -int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V110FriendsApi21ParameterToGetFriendsD1Ev(void*); -int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V110FriendsApi21ParameterToGetFriends10initializeEPNS1_6Common10LibContextEPKc(); -int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V110FriendsApi21ParameterToGetFriends9terminateEv(); -int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V110FriendsApi10getFriendsEiRKNS4_21ParameterToGetFriendsERNS1_6Common11TransactionINS8_12IntrusivePtrINS3_18GetFriendsResponseEEENSA_INS8_18ResponseHeaderBaseEEEEE(); -int APS5_VABI _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_11UserProfile2V124GetBlockingUsersResponseEEENS4_INS2_18ResponseHeaderBaseEEEEC1Ev(void*); -int APS5_VABI _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_11UserProfile2V124GetBlockingUsersResponseEEENS4_INS2_18ResponseHeaderBaseEEEED1Ev(void*); -int APS5_VABI _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_11UserProfile2V124GetBlockingUsersResponseEEENS4_INS2_18ResponseHeaderBaseEEEE21setOnFinishedCallbackEPFvliS8_PvEPFvliSC_ESC_(); -int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_11UserProfile2V124GetBlockingUsersResponseEEENS4_INS2_18ResponseHeaderBaseEEEE28setResponseInformationOptionEP37SceNpWebApi2ResponseInformationOption(); -int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_11UserProfile2V124GetBlockingUsersResponseEEENS4_INS2_18ResponseHeaderBaseEEEE5startEPNS2_10LibContextE(); -int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_11UserProfile2V124GetBlockingUsersResponseEEENS4_INS2_18ResponseHeaderBaseEEEE6finishEv(); -int APS5_VABI _ZNK3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_11UserProfile2V124GetBlockingUsersResponseEEENS4_INS2_18ResponseHeaderBaseEEEE18getResponseHeadersERSA_(); -int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V19BlocksApi27ParameterToGetBlockingUsersC1Ev(void*); -int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V19BlocksApi27ParameterToGetBlockingUsersD1Ev(void*); -int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V19BlocksApi27ParameterToGetBlockingUsers10initializeEPNS1_6Common10LibContextE(); -int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V19BlocksApi27ParameterToGetBlockingUsers9terminateEv(); -int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V19BlocksApi16getBlockingUsersEiRKNS4_27ParameterToGetBlockingUsersERNS1_6Common11TransactionINS8_12IntrusivePtrINS3_24GetBlockingUsersResponseEEENSA_INS8_18ResponseHeaderBaseEEEEE(); -int APS5_VABI _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_11UserProfile2V125GetBasicPresencesResponseEEENS4_INS2_18ResponseHeaderBaseEEEEC1Ev(void*); -int APS5_VABI _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_11UserProfile2V125GetBasicPresencesResponseEEENS4_INS2_18ResponseHeaderBaseEEEED1Ev(void*); -int APS5_VABI _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_11UserProfile2V125GetBasicPresencesResponseEEENS4_INS2_18ResponseHeaderBaseEEEE21setOnFinishedCallbackEPFvliS8_PvEPFvliSC_ESC_(); -int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_11UserProfile2V125GetBasicPresencesResponseEEENS4_INS2_18ResponseHeaderBaseEEEE28setResponseInformationOptionEP37SceNpWebApi2ResponseInformationOption(); -int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_11UserProfile2V125GetBasicPresencesResponseEEENS4_INS2_18ResponseHeaderBaseEEEE5startEPNS2_10LibContextE(); -int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_11UserProfile2V125GetBasicPresencesResponseEEENS4_INS2_18ResponseHeaderBaseEEEE6finishEv(); -int APS5_VABI _ZNK3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_11UserProfile2V125GetBasicPresencesResponseEEENS4_INS2_18ResponseHeaderBaseEEEE18getResponseHeadersERSA_(); -int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V111PresenceApi28ParameterToGetBasicPresencesC1Ev(void*); -int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V111PresenceApi28ParameterToGetBasicPresencesD1Ev(void*); -int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V111PresenceApi28ParameterToGetBasicPresences10initializeEPNS1_6Common10LibContextEPKc(); -int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V111PresenceApi28ParameterToGetBasicPresences9terminateEv(); -int APS5_VABI _ZN3sce2Np9CppWebApi11UserProfile2V111PresenceApi17getBasicPresencesEiRKNS4_28ParameterToGetBasicPresencesERNS1_6Common11TransactionINS8_12IntrusivePtrINS3_25GetBasicPresencesResponseEEENSA_INS8_18ResponseHeaderBaseEEEEE(); -int APS5_VABI _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_15ProfanityFilter2V223FilterProfanityResponseEEENS4_INS2_18ResponseHeaderBaseEEEEC1Ev(void*); -int APS5_VABI _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_15ProfanityFilter2V223FilterProfanityResponseEEENS4_INS2_18ResponseHeaderBaseEEEED1Ev(void*); -int APS5_VABI _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_15ProfanityFilter2V223FilterProfanityResponseEEENS4_INS2_18ResponseHeaderBaseEEEE21setOnFinishedCallbackEPFvliS8_PvEPFvliSC_ESC_(); -int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_15ProfanityFilter2V223FilterProfanityResponseEEENS4_INS2_18ResponseHeaderBaseEEEE28setResponseInformationOptionEP37SceNpWebApi2ResponseInformationOption(); -int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_15ProfanityFilter2V223FilterProfanityResponseEEENS4_INS2_18ResponseHeaderBaseEEEE5startEPNS2_10LibContextE(); -int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_15ProfanityFilter2V223FilterProfanityResponseEEENS4_INS2_18ResponseHeaderBaseEEEE6finishEv(); -int APS5_VABI _ZNK3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_15ProfanityFilter2V223FilterProfanityResponseEEENS4_INS2_18ResponseHeaderBaseEEEE18getResponseHeadersERSA_(); -int APS5_VABI _ZN3sce2Np9CppWebApi15ProfanityFilter2V212ProfanityApi26ParameterToFilterProfanityC1Ev(void*); -int APS5_VABI _ZN3sce2Np9CppWebApi15ProfanityFilter2V212ProfanityApi26ParameterToFilterProfanityD1Ev(void*); -int APS5_VABI _ZN3sce2Np9CppWebApi15ProfanityFilter2V212ProfanityApi26ParameterToFilterProfanity10initializeEPNS1_6Common10LibContextEPKcSA_NS6_12IntrusivePtrINS3_19WebApiFilterRequestEEE(); -int APS5_VABI _ZN3sce2Np9CppWebApi15ProfanityFilter2V212ProfanityApi26ParameterToFilterProfanity9terminateEv(); -int APS5_VABI _ZN3sce2Np9CppWebApi15ProfanityFilter2V212ProfanityApi15filterProfanityEiRKNS4_26ParameterToFilterProfanityERNS1_6Common11TransactionINS8_12IntrusivePtrINS3_23FilterProfanityResponseEEENSA_INS8_18ResponseHeaderBaseEEEEE(); -int APS5_VABI _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_30CommunicationRestrictionStatus2V338CommunicationRestrictionStatusResponseEEENS4_INS2_18ResponseHeaderBaseEEEEC1Ev(void*); -int APS5_VABI _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_30CommunicationRestrictionStatus2V338CommunicationRestrictionStatusResponseEEENS4_INS2_18ResponseHeaderBaseEEEED1Ev(void*); -int APS5_VABI _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_30CommunicationRestrictionStatus2V338CommunicationRestrictionStatusResponseEEENS4_INS2_18ResponseHeaderBaseEEEE21setOnFinishedCallbackEPFvliS8_PvEPFvliSC_ESC_(); -int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_30CommunicationRestrictionStatus2V338CommunicationRestrictionStatusResponseEEENS4_INS2_18ResponseHeaderBaseEEEE28setResponseInformationOptionEP37SceNpWebApi2ResponseInformationOption(); -int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_30CommunicationRestrictionStatus2V338CommunicationRestrictionStatusResponseEEENS4_INS2_18ResponseHeaderBaseEEEE5startEPNS2_10LibContextE(); -int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_30CommunicationRestrictionStatus2V338CommunicationRestrictionStatusResponseEEENS4_INS2_18ResponseHeaderBaseEEEE6finishEv(); -int APS5_VABI _ZNK3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_30CommunicationRestrictionStatus2V338CommunicationRestrictionStatusResponseEEENS4_INS2_18ResponseHeaderBaseEEEE18getResponseHeadersERSA_(); -int APS5_VABI _ZN3sce2Np9CppWebApi30CommunicationRestrictionStatus2V333CommunicationRestrictionStatusApi44ParameterToGetCommunicationRestrictionStatusC1Ev(void*); -int APS5_VABI _ZN3sce2Np9CppWebApi30CommunicationRestrictionStatus2V333CommunicationRestrictionStatusApi44ParameterToGetCommunicationRestrictionStatusD1Ev(void*); -int APS5_VABI _ZN3sce2Np9CppWebApi30CommunicationRestrictionStatus2V333CommunicationRestrictionStatusApi44ParameterToGetCommunicationRestrictionStatus10initializeEPNS1_6Common10LibContextEm(); -int APS5_VABI _ZN3sce2Np9CppWebApi30CommunicationRestrictionStatus2V333CommunicationRestrictionStatusApi44ParameterToGetCommunicationRestrictionStatus9terminateEv(); -int APS5_VABI _ZN3sce2Np9CppWebApi30CommunicationRestrictionStatus2V333CommunicationRestrictionStatusApi33getCommunicationRestrictionStatusEiRKNS4_44ParameterToGetCommunicationRestrictionStatusERNS1_6Common11TransactionINS8_12IntrusivePtrINS3_38CommunicationRestrictionStatusResponseEEENSA_INS8_18ResponseHeaderBaseEEEEE(); -int APS5_VABI _ZN3sce2Np9CppWebApi15ProfanityFilter2V226WebApiFilterRequestFactory6createEPNS1_6Common10LibContextEPKcPNS5_12IntrusivePtrINS3_19WebApiFilterRequestEEE(); -} - static void Require(bool value) { if (!value) std::abort(); } static constexpr int NotSignedIn = static_cast(0x80552907); diff --git a/core/libs/tests/GuestNpCppWebApiString.cpp b/core/libs/tests/GuestNpCppWebApiString.cpp index eb127730a9..6d50a21eb3 100644 --- a/core/libs/tests/GuestNpCppWebApiString.cpp +++ b/core/libs/tests/GuestNpCppWebApiString.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNpCppWebApi/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -5,24 +6,6 @@ #include #include -extern "C" { -void APS5_VABI _ZN3sce2Np9CppWebApi6Common6StringC1EPNS2_10LibContextE(void* self, void* libContext); -void APS5_VABI _ZN3sce2Np9CppWebApi6Common6StringD1Ev(void* self); -int APS5_VABI _ZN3sce2Np9CppWebApi6Common6String6appendEPKc(void* self, const char* text); -const char* APS5_VABI _ZNK3sce2Np9CppWebApi6Common6String5c_strEv(const void* self); -void APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_6StringEEC1EPNS2_10LibContextE(void* self, void* libContext); -void APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_6StringEED1Ev(void* self); -int APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_6StringEE8pushBackERKS4_(void* self, const void* element); -int APS5_VABI _ZNK3sce2Np9CppWebApi6Common6String5emptyEv(const void* self); -int APS5_VABI _ZN3sce2Np9CppWebApi6Common6StringeqEPKc(const void* self, const char* other); -void APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_14SessionManager2V112JoinableUserEEEEC1EPNS2_10LibContextE(void* self, void* libContext); -void APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_14SessionManager2V112JoinableUserEEEED1Ev(void* self); -int APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_14SessionManager2V112JoinableUserEEEE8pushBackERKS8_(void* self, const void* element); -int APS5_VABI _ZNK3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_14SessionManager2V130PostPlayerSessionsResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEE11hasResponseEv(); -int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V117PlayerSessionsApi17getPlayerSessionsEiRKNS4_28ParameterToGetPlayerSessionsERNS1_6Common11TransactionINS8_12IntrusivePtrINS3_29GetPlayerSessionsResponseBodyEEENSA_INS8_18ResponseHeaderBaseEEEEE(); -int APS5_VABI _ZN3sce2Np9CppWebApi14SessionManager2V117PlayerSessionsApi26setPlayerSessionPropertiesEiRKNS4_37ParameterToSetPlayerSessionPropertiesERNS1_6Common11TransactionINS8_15DefaultResponseENS8_12IntrusivePtrINS8_18ResponseHeaderBaseEEEEE(); -} - namespace { void Require(bool value) { if (!value) std::abort(); } @@ -89,18 +72,17 @@ void TestConstructedStringIsEmpty() { Storage storage; std::memset(storage.bytes, kFill, sizeof(storage.bytes)); - _ZN3sce2Np9CppWebApi6Common6StringC1EPNS2_10LibContextE(storage.bytes, &libContext); - + _ZN3sce2Np9CppWebApi6Common6StringC1EPNS2_10LibContextE(reinterpret_cast(storage.bytes), &libContext); Require(Load(storage, kReferenceCountOffset) == 0); Require(Load(storage, kBufferOffset) == nullptr); Require(Load(storage, kBufferSizeOffset) == 0); Require(Load(storage, kLibContextOffset) == &libContext); Require(GuardIntact(storage)); - const char* text = _ZNK3sce2Np9CppWebApi6Common6String5c_strEv(storage.bytes); + const char* text = _ZNK3sce2Np9CppWebApi6Common6String5c_strEv(reinterpret_cast(storage.bytes)); Require(text != nullptr && text[0] == '\0'); - _ZN3sce2Np9CppWebApi6Common6StringD1Ev(storage.bytes); + _ZN3sce2Np9CppWebApi6Common6StringD1Ev(reinterpret_cast(storage.bytes)); Require(Load(storage, kBufferOffset) == nullptr); Require(Load(storage, kBufferSizeOffset) == 0); Require(GuardIntact(storage)); @@ -110,29 +92,28 @@ void TestNullLibContextIsStored() { Storage storage; std::memset(storage.bytes, kFill, sizeof(storage.bytes)); - _ZN3sce2Np9CppWebApi6Common6StringC1EPNS2_10LibContextE(storage.bytes, nullptr); - + _ZN3sce2Np9CppWebApi6Common6StringC1EPNS2_10LibContextE(reinterpret_cast(storage.bytes), nullptr); Require(Load(storage, kLibContextOffset) == nullptr); Require(Load(storage, kBufferOffset) == nullptr); - Require(_ZNK3sce2Np9CppWebApi6Common6String5c_strEv(storage.bytes)[0] == '\0'); - _ZN3sce2Np9CppWebApi6Common6StringD1Ev(storage.bytes); + Require(_ZNK3sce2Np9CppWebApi6Common6String5c_strEv(reinterpret_cast(storage.bytes))[0] == '\0'); + _ZN3sce2Np9CppWebApi6Common6StringD1Ev(reinterpret_cast(storage.bytes)); + } void TestAppendBuildsAndClearsBuffer() { std::uint64_t libContext = 1; Storage storage; std::memset(storage.bytes, kFill, sizeof(storage.bytes)); + _ZN3sce2Np9CppWebApi6Common6StringC1EPNS2_10LibContextE(reinterpret_cast(storage.bytes), &libContext); - _ZN3sce2Np9CppWebApi6Common6StringC1EPNS2_10LibContextE(storage.bytes, &libContext); - - Require(_ZN3sce2Np9CppWebApi6Common6String6appendEPKc(storage.bytes, "rank") == 0); - Require(std::strcmp(_ZNK3sce2Np9CppWebApi6Common6String5c_strEv(storage.bytes), "rank") == 0); - Require(_ZN3sce2Np9CppWebApi6Common6String6appendEPKc(storage.bytes, "ing") == 0); - Require(std::strcmp(_ZNK3sce2Np9CppWebApi6Common6String5c_strEv(storage.bytes), "ranking") == 0); + Require(_ZN3sce2Np9CppWebApi6Common6String6appendEPKc(reinterpret_cast(storage.bytes), "rank") == 0); + Require(std::strcmp(_ZNK3sce2Np9CppWebApi6Common6String5c_strEv(reinterpret_cast(storage.bytes)), "rank") == 0); + Require(_ZN3sce2Np9CppWebApi6Common6String6appendEPKc(reinterpret_cast(storage.bytes), "ing") == 0); + Require(std::strcmp(_ZNK3sce2Np9CppWebApi6Common6String5c_strEv(reinterpret_cast(storage.bytes)), "ranking") == 0); Require(Load(storage, kBufferOffset) != nullptr); Require(GuardIntact(storage)); - _ZN3sce2Np9CppWebApi6Common6StringD1Ev(storage.bytes); + _ZN3sce2Np9CppWebApi6Common6StringD1Ev(reinterpret_cast(storage.bytes)); Require(Load(storage, kBufferOffset) == nullptr); Require(Load(storage, kBufferSizeOffset) == 0); Require(GuardIntact(storage)); @@ -143,11 +124,12 @@ void TestAppendNullKeepsEmpty() { Storage storage; std::memset(storage.bytes, kFill, sizeof(storage.bytes)); - _ZN3sce2Np9CppWebApi6Common6StringC1EPNS2_10LibContextE(storage.bytes, &libContext); - Require(_ZN3sce2Np9CppWebApi6Common6String6appendEPKc(storage.bytes, nullptr) == 0); + _ZN3sce2Np9CppWebApi6Common6StringC1EPNS2_10LibContextE(reinterpret_cast(storage.bytes), &libContext); + Require(_ZN3sce2Np9CppWebApi6Common6String6appendEPKc(reinterpret_cast(storage.bytes), nullptr) == 0); Require(Load(storage, kBufferOffset) == nullptr); - Require(_ZNK3sce2Np9CppWebApi6Common6String5c_strEv(storage.bytes)[0] == '\0'); - _ZN3sce2Np9CppWebApi6Common6StringD1Ev(storage.bytes); + Require(_ZNK3sce2Np9CppWebApi6Common6String5c_strEv(reinterpret_cast(storage.bytes))[0] == '\0'); + _ZN3sce2Np9CppWebApi6Common6StringD1Ev(reinterpret_cast(storage.bytes)); + } void TestVectorPushBackCopiesStringContent() { @@ -157,15 +139,15 @@ void TestVectorPushBackCopiesStringContent() { std::memset(vector.bytes, kFill, sizeof(vector.bytes)); std::memset(element.bytes, kFill, sizeof(element.bytes)); - _ZN3sce2Np9CppWebApi6Common6VectorINS2_6StringEEC1EPNS2_10LibContextE(vector.bytes, &libContext); + _ZN3sce2Np9CppWebApi6Common6VectorINS2_6StringEEC1EPNS2_10LibContextE(reinterpret_cast(vector.bytes), &libContext); Require(VectorGuardIntact(vector)); - _ZN3sce2Np9CppWebApi6Common6StringC1EPNS2_10LibContextE(element.bytes, &libContext); - Require(_ZN3sce2Np9CppWebApi6Common6String6appendEPKc(element.bytes, "privilege") == 0); + _ZN3sce2Np9CppWebApi6Common6StringC1EPNS2_10LibContextE(reinterpret_cast(element.bytes), &libContext); + Require(_ZN3sce2Np9CppWebApi6Common6String6appendEPKc(reinterpret_cast(element.bytes), "privilege") == 0); char* elementBuffer = Load(element, kBufferOffset); Require(elementBuffer != nullptr); - Require(_ZN3sce2Np9CppWebApi6Common6VectorINS2_6StringEE8pushBackERKS4_(vector.bytes, element.bytes) == 0); + Require(_ZN3sce2Np9CppWebApi6Common6VectorINS2_6StringEE8pushBackERKS4_(reinterpret_cast(vector.bytes), element.bytes) == 0); void* body; std::memcpy(&body, vector.bytes + kObjectOffset, sizeof(body)); @@ -181,10 +163,10 @@ void TestVectorPushBackCopiesStringContent() { Require(storedBuffer != elementBuffer); Require(std::strcmp(storedBuffer, "privilege") == 0); - _ZN3sce2Np9CppWebApi6Common6StringD1Ev(element.bytes); + _ZN3sce2Np9CppWebApi6Common6StringD1Ev(reinterpret_cast(element.bytes)); Require(std::strcmp(storedBuffer, "privilege") == 0); - _ZN3sce2Np9CppWebApi6Common6VectorINS2_6StringEED1Ev(vector.bytes); + _ZN3sce2Np9CppWebApi6Common6VectorINS2_6StringEED1Ev(reinterpret_cast(vector.bytes)); Require(VectorGuardIntact(vector)); } @@ -193,18 +175,18 @@ void TestStringEmptyAndEquals() { Storage storage; std::memset(storage.bytes, kFill, sizeof(storage.bytes)); - _ZN3sce2Np9CppWebApi6Common6StringC1EPNS2_10LibContextE(storage.bytes, &libContext); - Require(_ZNK3sce2Np9CppWebApi6Common6String5emptyEv(storage.bytes) == 1); - Require(_ZN3sce2Np9CppWebApi6Common6StringeqEPKc(storage.bytes, "rank") == 0); + _ZN3sce2Np9CppWebApi6Common6StringC1EPNS2_10LibContextE(reinterpret_cast(storage.bytes), &libContext); + Require(_ZNK3sce2Np9CppWebApi6Common6String5emptyEv(reinterpret_cast(storage.bytes)) == 1); + Require(_ZN3sce2Np9CppWebApi6Common6StringeqEPKc(reinterpret_cast(storage.bytes), "rank") == 0); - Require(_ZN3sce2Np9CppWebApi6Common6String6appendEPKc(storage.bytes, "rank") == 0); - Require(_ZNK3sce2Np9CppWebApi6Common6String5emptyEv(storage.bytes) == 0); - Require(_ZN3sce2Np9CppWebApi6Common6StringeqEPKc(storage.bytes, "rank") == 1); - Require(_ZN3sce2Np9CppWebApi6Common6StringeqEPKc(storage.bytes, "rank2") == 0); - Require(_ZN3sce2Np9CppWebApi6Common6StringeqEPKc(storage.bytes, nullptr) == 0); + Require(_ZN3sce2Np9CppWebApi6Common6String6appendEPKc(reinterpret_cast(storage.bytes), "rank") == 0); + Require(_ZNK3sce2Np9CppWebApi6Common6String5emptyEv(reinterpret_cast(storage.bytes)) == 0); + Require(_ZN3sce2Np9CppWebApi6Common6StringeqEPKc(reinterpret_cast(storage.bytes), "rank") == 1); + Require(_ZN3sce2Np9CppWebApi6Common6StringeqEPKc(reinterpret_cast(storage.bytes), "rank2") == 0); + Require(_ZN3sce2Np9CppWebApi6Common6StringeqEPKc(reinterpret_cast(storage.bytes), nullptr) == 0); Require(GuardIntact(storage)); - _ZN3sce2Np9CppWebApi6Common6StringD1Ev(storage.bytes); + _ZN3sce2Np9CppWebApi6Common6StringD1Ev(reinterpret_cast(storage.bytes)); } int g_elementDeleterCalls = 0; @@ -227,10 +209,10 @@ void TestIntrusivePtrVectorPushBack() { std::memcpy(element + 0x08, &deleter, sizeof(void*)); std::memcpy(element + 0x10, &libContext, sizeof(void*)); - _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_14SessionManager2V112JoinableUserEEEEC1EPNS2_10LibContextE(vector.bytes, &libContext); + _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_14SessionManager2V112JoinableUserEEEEC1EPNS2_10LibContextE(reinterpret_cast(vector.bytes), &libContext); Require(VectorGuardIntact(vector)); - Require(_ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_14SessionManager2V112JoinableUserEEEE8pushBackERKS8_(vector.bytes, element) == 0); + Require(_ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_14SessionManager2V112JoinableUserEEEE8pushBackERKS8_(reinterpret_cast(vector.bytes), element) == 0); void* body; std::memcpy(&body, vector.bytes + kObjectOffset, sizeof(body)); @@ -240,7 +222,7 @@ void TestIntrusivePtrVectorPushBack() { Require(LoadBody(body, kBodySizeOffset) == 1); Require(*reinterpret_cast(elementObject) == 1); - _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_14SessionManager2V112JoinableUserEEEED1Ev(vector.bytes); + _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_14SessionManager2V112JoinableUserEEEED1Ev(reinterpret_cast(vector.bytes)); Require(g_elementDeleterCalls == 1); Require(VectorGuardIntact(vector)); } diff --git a/core/libs/tests/GuestNpFriendListDialog.cpp b/core/libs/tests/GuestNpFriendListDialog.cpp index 70385c595c..f06898db7b 100644 --- a/core/libs/tests/GuestNpFriendListDialog.cpp +++ b/core/libs/tests/GuestNpFriendListDialog.cpp @@ -1,17 +1,8 @@ +#include "prx/libSceNpFriendListDialog/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include -extern "C" { -int APS5_VABI sceNpFriendListDialogInitialize(void); -int APS5_VABI sceNpFriendListDialogOpenA(const void* param); -int APS5_VABI sceNpFriendListDialogUpdateStatus(void); -int APS5_VABI sceNpFriendListDialogGetStatus(void); -int APS5_VABI sceNpFriendListDialogGetResultA(void* result); -int APS5_VABI sceNpFriendListDialogClose(void); -int APS5_VABI sceNpFriendListDialogTerminate(void); -} - namespace { void Require(bool value) { if (!value) std::abort(); } diff --git a/core/libs/tests/GuestNpGameIntent.cpp b/core/libs/tests/GuestNpGameIntent.cpp index dbf030f79e..dd362cdad4 100644 --- a/core/libs/tests/GuestNpGameIntent.cpp +++ b/core/libs/tests/GuestNpGameIntent.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNpGameIntent/include/Api.hpp" #include "SceTypes.hpp" #include "prx/libc/include/general/VabiMacros.hpp" @@ -5,20 +6,6 @@ #include #include -extern "C" { -int APS5_VABI sceNpGameIntentInitParamInit(NpGameIntentInitParam* param); -int APS5_VABI sceNpGameIntentInfoInit(NpGameIntentInfo* info); -int APS5_VABI sceNpGameIntentInitialize(const void* initParam); -int APS5_VABI sceNpGameIntentReceiveIntent(NpGameIntentInfo* intentInfo); -int APS5_VABI sceNpGameIntentGetPropertyValueString(const NpGameIntentData* intentData, const char* key, char* valueBuf, size_t bufSize); -int APS5_VABI sceNpGameIntentVshInitialize(void); -int APS5_VABI sceNpGameIntentVshTerminate(void); -int APS5_VABI sceNpGameIntentTerminate(void); -int APS5_VABI sceNpAppLauncherInitialize(const void* initParam); -int APS5_VABI sceNpAppLauncherLaunchApp(void); -int APS5_VABI sceNpAppLauncherTerminate(void); -} - static void Require(bool value, const char* what) { if (value) return; std::printf("NpGameIntent: %s\n", what); diff --git a/core/libs/tests/GuestNpManager.cpp b/core/libs/tests/GuestNpManager.cpp index ef285cab3a..43c844bb62 100644 --- a/core/libs/tests/GuestNpManager.cpp +++ b/core/libs/tests/GuestNpManager.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNpManager/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "SceTypes.hpp" #include @@ -7,59 +8,6 @@ #include #include -extern "C" { -int APS5_VABI sceNpGetAccountCountryA(int user_id, void* country_code); -int APS5_VABI sceNpGetNpId(int user_id, NpId* np_id); -int APS5_VABI sceNpGetOnlineId(int user_id, NpOnlineId* online_id); -int APS5_VABI sceNpGetUserIdByAccountId(std::uint64_t account_id, int* user_id); -int APS5_VABI sceNpUnknown_8weiQyIdI3A(int userId, const NpOnlineId* buffer); -int APS5_VABI sceNpUnknown_WxLcN76q19o(void); -int APS5_VABI sceNpGetAccountCountry(const NpOnlineId* online_id, void* country_code); -int APS5_VABI sceNpGetAccountDateOfBirth(const NpOnlineId* online_id, void* date_of_birth); -int APS5_VABI sceNpGetAccountLanguage(int req_id, const NpOnlineId* online_id, void* language); -int APS5_VABI sceNpGetParentalControlInfo(int req_id, const NpOnlineId* online_id, std::int8_t* age, void* info); -int APS5_VABI sceNpGetUserIdByOnlineId(const NpOnlineId* online_id, int* user_id); -int APS5_VABI sceNpCheckPlus(int req_id, const void* param, void* result); -int APS5_VABI sceNpNotifyPlusFeature(const void* param); -int APS5_VABI sceNpGetAccountId(const NpOnlineId* online_id, std::uint64_t* account_id); -int APS5_VABI sceNpSetGamePresenceOnline(int req_id, const NpOnlineId* online_id, std::uint32_t presence); -int APS5_VABI sceNpRegisterPlusEventCallback(void* callback, void* userdata); -int APS5_VABI sceNpUnregisterPlusEventCallback(void); -int APS5_VABI sceNpIsPlusMember(int user_id, bool* is_member); -int APS5_VABI sceNpSetContentRestriction(const NpContentRestriction* restriction); -} - -extern "C" { -int APS5_VABI sceNpCreateRequest(void); -int APS5_VABI sceNpCreateAsyncRequest(const NpCreateAsyncRequestParameter* param); -int APS5_VABI sceNpDeleteRequest(int reqId); -int APS5_VABI sceNpAbortRequest(int reqId); -int APS5_VABI sceNpPollAsync(int reqId, int* result); -int APS5_VABI sceNpSetTimeout(int reqId, std::int32_t resolveRetry, std::uint32_t resolveTimeout, - std::uint32_t connTimeout, std::uint32_t sendTimeout, std::uint32_t recvTimeout); -} - -extern "C" { -int APS5_VABI sceNpCheckCallback(void); -int APS5_VABI sceNpCheckCallbackForLib(void); -int APS5_VABI sceNpRegisterStateCallback(void* callback, void* userdata); -int APS5_VABI sceNpUnregisterStateCallback(void); -int APS5_VABI sceNpRegisterStateCallbackA(void* callback, void* userdata); -int APS5_VABI sceNpUnregisterStateCallbackA(int callbackId); -int APS5_VABI sceNpRegisterNpReachabilityStateCallback(void* callback, void* userdata); -void APS5_VABI sceNpRegisterGamePresenceCallback(void* callback, void* userdata); -int APS5_VABI sceNpUnregisterNpReachabilityStateCallback(void); -} - -extern "C" { -int APS5_VABI sceNpCheckNpAvailabilityA(int reqId, int userId); -int APS5_VABI sceNpGetAccountDateOfBirthA(int userId, void* dateOfBirth); -int APS5_VABI sceNpGetAccountLanguageA(int reqId, int userId, void* language); -int APS5_VABI sceNpGetGamePresenceStatus(const NpOnlineId* onlineId, std::uint32_t* status); -int APS5_VABI sceNpGetGamePresenceStatusA(int userId, std::uint32_t* status); -int APS5_VABI sceNpGetParentalControlInfoA(int reqId, int userId, std::int8_t* age, void* info); -} - namespace { constexpr int InvalidArgument = static_cast(0x80550003u); @@ -137,27 +85,28 @@ void CheckStateCallbacksA() { int userdata[9]{}; Require(sceNpRegisterStateCallbackA(nullptr, &userdata[0]) == InvalidArgument, "null state callback"); int ids[8]{}; - ids[0] = sceNpRegisterStateCallbackA(callbacks[0], &userdata[0]); + ids[0] = sceNpRegisterStateCallbackA(reinterpret_cast(callbacks[0]), &userdata[0]); Require(ids[0] >= 1 && ids[0] <= 8, "state callback id outside 1..8"); - Require(sceNpRegisterStateCallbackA(callbacks[0], &userdata[1]) == AlreadyRegistered, "duplicate state callback"); + Require(sceNpRegisterStateCallbackA(reinterpret_cast(callbacks[0]), &userdata[1]) == AlreadyRegistered, "duplicate state callback"); Require(stateCallsA[0].calls == 0, "registering calls the state callback"); Require(sceNpRegisterNpReachabilityStateCallback(reinterpret_cast(&AbortingReachabilityCallback), nullptr) == 0, "registering the reachability callback"); sceNpRegisterGamePresenceCallback(nullptr, nullptr); sceNpRegisterGamePresenceCallback(reinterpret_cast(&AbortingGamePresenceCallback), &userdata[0]); + Require(sceNpCheckCallback() == 0, "sceNpCheckCallback failed"); Require(SignedOutOnce(stateCallsA[0], &userdata[0]), "sceNpCheckCallback must deliver SIGNED_OUT once"); Require(sceNpUnregisterNpReachabilityStateCallback() == 0, "unregistering the reachability callback"); Require(sceNpCheckCallback() == 0, "second sceNpCheckCallback failed"); Require(stateCallsA[0].calls == 1, "the second sceNpCheckCallback delivered the state again"); for (int index = 1; index < 8; ++index) { - ids[index] = sceNpRegisterStateCallbackA(callbacks[index], &userdata[index]); + ids[index] = sceNpRegisterStateCallbackA(reinterpret_cast(callbacks[index]), &userdata[index]); Require(ids[index] >= 1 && ids[index] <= 8, "state callback id outside 1..8"); for (int other = 0; other < index; ++other) { Require(ids[index] != ids[other], "two state callbacks got the same id"); } } - Require(sceNpRegisterStateCallbackA(callbacks[8], &userdata[8]) == CallbackMax, "ninth state callback"); + Require(sceNpRegisterStateCallbackA(reinterpret_cast(callbacks[8]), &userdata[8]) == CallbackMax, "ninth state callback"); Require(sceNpCheckCallback() == 0, "sceNpCheckCallback failed with eight callbacks"); for (int index = 0; index < 8; ++index) { Require(SignedOutOnce(stateCallsA[index], &userdata[index]), "each callback gets SIGNED_OUT once"); @@ -168,10 +117,10 @@ void CheckStateCallbacksA() { Require(sceNpUnregisterStateCallbackA(ids[3]) == 0, "unregistering one state callback"); for (int index = 0; index < 8; ++index) { if (index == 3) continue; - Require(sceNpRegisterStateCallbackA(callbacks[index], &userdata[index]) == AlreadyRegistered, + Require(sceNpRegisterStateCallbackA(reinterpret_cast(callbacks[index]), &userdata[index]) == AlreadyRegistered, "unregistering one id removed another callback"); } - Require(sceNpRegisterStateCallbackA(callbacks[3], &userdata[3]) == ids[3], "registering again takes the freed slot"); + Require(sceNpRegisterStateCallbackA(reinterpret_cast(callbacks[3]), &userdata[3]) == ids[3], "registering again takes the freed slot"); Require(sceNpCheckCallbackForLib() == 0, "sceNpCheckCallbackForLib failed after registering again"); for (int index = 0; index < 8; ++index) { Require(stateCallsA[index].calls == (index == 3 ? 2 : 1), "only the registration made again gets SIGNED_OUT"); @@ -184,13 +133,13 @@ void CheckStateCallbacksA() { Require(sceNpUnregisterStateCallbackA(ids[index]) == 0, "unregistering a state callback"); } Require(sceNpUnregisterStateCallbackA(ids[0]) == NotRegistered, "unregistering a state callback twice"); - const int removed = sceNpRegisterStateCallbackA(callbacks[8], &userdata[8]); + const int removed = sceNpRegisterStateCallbackA(reinterpret_cast(callbacks[8]), &userdata[8]); Require(removed >= 1 && removed <= 8, "a freed slot is reused"); Require(sceNpUnregisterStateCallbackA(removed) == 0, "unregistering before sceNpCheckCallback"); Require(sceNpCheckCallback() == 0, "sceNpCheckCallback failed with no callbacks"); Require(stateCallsA[8].calls == 0, "an unregistered callback was called"); SelfUnregister self{}; - self.id = sceNpRegisterStateCallbackA(reinterpret_cast(&SelfUnregisteringCallback), &self); + self.id = sceNpRegisterStateCallbackA(reinterpret_cast(reinterpret_cast(&SelfUnregisteringCallback)), &self); Require(self.id >= 1 && self.id <= 8, "state callback id outside 1..8"); Require(sceNpCheckCallback() == 0, "sceNpCheckCallback failed with a callback that unregisters itself"); Require(self.calls == 1 && self.result == 0, "a state callback must be able to unregister itself"); @@ -203,8 +152,8 @@ void CheckLegacyStateCallback() { auto* callback = reinterpret_cast(&LegacyStateCallback); Require(sceNpUnregisterStateCallback() == NotRegistered, "unregistering with no legacy callback"); Require(sceNpRegisterStateCallback(nullptr, &userdata) == InvalidArgument, "null legacy callback"); - Require(sceNpRegisterStateCallback(callback, &userdata) == 0, "registering the legacy callback"); - Require(sceNpRegisterStateCallback(callback, nullptr) == AlreadyRegistered, "duplicate legacy callback"); + Require(sceNpRegisterStateCallback(reinterpret_cast(callback), &userdata) == 0, "registering the legacy callback"); + Require(sceNpRegisterStateCallback(reinterpret_cast(callback), nullptr) == AlreadyRegistered, "duplicate legacy callback"); legacyStateCall.npId = &sentinel; Require(sceNpCheckCallback() == 0, "sceNpCheckCallback failed with the legacy callback"); Require(SignedOutOnce(legacyStateCall, &userdata), "the legacy callback must get SIGNED_OUT with no NpId"); @@ -313,6 +262,7 @@ void CheckOnlineIdQueries() { Require(std::memcmp(output, untouched, sizeof(output)) == 0 && age == 0x5a && userId == 0x5a5a && accountId == 0x5a5a, "a failed query wrote its output"); try { sceNpNotifyPlusFeature(output); + Require(false, "sceNpNotifyPlusFeature must report that it is not implemented"); } catch (const std::runtime_error& error) { Require(std::string(error.what()) == "sceNpNotifyPlusFeature not implemented", "sceNpNotifyPlusFeature threw"); @@ -454,6 +404,7 @@ int main() { NpOnlineId buffer{}; try { sceNpUnknown_8weiQyIdI3A(0x10000, &buffer); + Require(false, "sceNpUnknown_8weiQyIdI3A must report that it is not implemented"); } catch (const std::runtime_error& error) { Require(std::string(error.what()) == "sceNpUnknown_8weiQyIdI3A not implemented", @@ -461,6 +412,7 @@ int main() { } try { sceNpUnknown_WxLcN76q19o(); + Require(false, "sceNpUnknown_WxLcN76q19o must report that it is not implemented"); } catch (const std::runtime_error& error) { Require(std::string(error.what()) == "sceNpUnknown_WxLcN76q19o not implemented", diff --git a/core/libs/tests/GuestNpMatching2Offline.cpp b/core/libs/tests/GuestNpMatching2Offline.cpp index 7435757a21..796c217bdf 100644 --- a/core/libs/tests/GuestNpMatching2Offline.cpp +++ b/core/libs/tests/GuestNpMatching2Offline.cpp @@ -1,38 +1,11 @@ +#include "prx/libSceNpMatching2/include/Api.hpp" #include "SceTypes.hpp" #include #include -struct InitializeParameter { - std::uint64_t poolSize; - std::uint64_t reserved; - std::int32_t priority; - std::uint8_t padding[4]; - std::uint64_t stackSize; - std::uint64_t size; - std::uint64_t sslPoolSize; -}; -struct CreateContextParameter { - const void* npId; - const void* npCommunicationId; - const void* npPassphrase; - std::uint32_t serviceLabel; - std::uint64_t size; -}; -extern "C" { -int APS5_VABI sceNpMatching2Initialize(const InitializeParameter* param); -int APS5_VABI sceNpMatching2Terminate(); -int APS5_VABI sceNpMatching2CreateContext(const CreateContextParameter* param, std::uint16_t* ctxId); -int APS5_VABI sceNpMatching2DestroyContext(std::uint16_t ctxId); -int APS5_VABI sceNpMatching2ContextStart(std::uint16_t ctxId, std::uint64_t timeout); -int APS5_VABI sceNpMatching2ContextStop(std::uint16_t ctxId); -int APS5_VABI sceNpMatching2RegisterContextCallback(void* callback, void* userdata); -int APS5_VABI sceNpMatching2RegisterRoomEventCallback(std::uint16_t ctxId, void* callback, void* userdata); -int APS5_VABI sceNpMatching2RegisterRoomMessageCallback(std::uint16_t ctxId, void* callback, void* userdata); -int APS5_VABI sceNpMatching2RegisterSignalingCallback(std::uint16_t ctxId, void* callback, void* userdata); -int APS5_VABI sceNpMatching2SetDefaultRequestOptParam(std::uint16_t ctxId, const void* requestOpt); -} + namespace { @@ -54,8 +27,8 @@ void Require(bool value, const char* name, const char* what) { } int main() { - InitializeParameter init{}; - CreateContextParameter create{}; + NpMatching2InitializeParameter init{}; + NpMatching2CreateContextParameter create{}; create.size = 0x28; unsigned char requestOpt[24] = {}; std::uint16_t context = 77; diff --git a/core/libs/tests/GuestNpPartner.cpp b/core/libs/tests/GuestNpPartner.cpp index 700570470a..e57e29c5c5 100644 --- a/core/libs/tests/GuestNpPartner.cpp +++ b/core/libs/tests/GuestNpPartner.cpp @@ -1,13 +1,8 @@ +#include "prx/libSceNpPartner001/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include -extern "C" { -int APS5_VABI sceNpEAAccessInitialize(void); -int APS5_VABI sceNpEAAccessTerminate(void); -int APS5_VABI sceNpHasEAAccessSubscription(int, bool*); -} - namespace { void Require(bool value) { if (!value) std::abort(); } diff --git a/core/libs/tests/GuestNpParty.cpp b/core/libs/tests/GuestNpParty.cpp index e60834546c..fbda80be4a 100644 --- a/core/libs/tests/GuestNpParty.cpp +++ b/core/libs/tests/GuestNpParty.cpp @@ -1,24 +1,10 @@ +#include "prx/libSceNpParty/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include #include #include -extern "C" { -int APS5_VABI sceNpPartyGetState(std::uint16_t* state); -int APS5_VABI sceNpPartyInitialize(const void* param); -int APS5_VABI sceNpPartyTerminate(void); -int APS5_VABI sceNpPartyCheckCallback(void); -int APS5_VABI sceNpPartyRegisterHandlerA(const void* handlers, void* userdata); -int APS5_VABI sceNpPartyGetStateAsUserA(std::int32_t asUserId, std::uint16_t* state); -int APS5_VABI sceNpPartyGetId(void* id); -int APS5_VABI sceNpPartyGetMembersA(void* memberList); -int APS5_VABI sceNpPartyGetMemberInfoA(std::uint16_t memberId, void* memberInfo); -int APS5_VABI sceNpPartyGetMemberSessionInfo(std::uint16_t memberId, void* memberGameSessionInfo); -int APS5_VABI sceNpPartyGetMemberVoiceInfo(std::uint16_t asMemberId, std::uint16_t memberId, std::uint8_t* memberVoiceState); -int APS5_VABI sceNpPartySendBinaryMessage(const void* sendParams); -} - namespace { constexpr int kAlreadyInitialized = static_cast(0x80552502u); diff --git a/core/libs/tests/GuestNpProfileDialog.cpp b/core/libs/tests/GuestNpProfileDialog.cpp index a9d2986bfe..cb7fa68f8d 100644 --- a/core/libs/tests/GuestNpProfileDialog.cpp +++ b/core/libs/tests/GuestNpProfileDialog.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNpProfileDialog/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -6,17 +7,6 @@ #include #include -extern "C" { -int APS5_VABI sceNpProfileDialogInitialize(void); -int APS5_VABI sceNpProfileDialogTerminate(void); -int APS5_VABI sceNpProfileDialogUpdateStatus(void); -int APS5_VABI sceNpProfileDialogGetStatus(void); -int APS5_VABI sceNpProfileDialogOpen(const void* param); -int APS5_VABI sceNpProfileDialogOpenA(const void* param); -int APS5_VABI sceNpProfileDialogClose(void); -int APS5_VABI sceNpProfileDialogGetResult(void* result); -} - namespace { void Require(bool value) { if (!value) std::abort(); } @@ -91,12 +81,12 @@ int main() { Require(sceNpProfileDialogTerminate() == kErrNotInitialized); Require(sceNpProfileDialogClose() == kErrNotInitialized); - Require(sceNpProfileDialogGetResult(result) == kErrNotInitialized); + Require(sceNpProfileDialogGetResult(reinterpret_cast(result)) == kErrNotInitialized); Require(sceNpProfileDialogGetResult(nullptr) == kErrNotInitialized); Require(sceNpProfileDialogGetStatus() == kStatusNone); Require(sceNpProfileDialogUpdateStatus() == kStatusNone); - RequireThrows([&] { sceNpProfileDialogOpen(param); }); - RequireThrows([&] { sceNpProfileDialogOpenA(paramA); }); + RequireThrows([&] { sceNpProfileDialogOpen(reinterpret_cast(param)); }); + RequireThrows([&] { sceNpProfileDialogOpenA(reinterpret_cast(paramA)); }); Require(sceNpProfileDialogGetStatus() == kStatusNone); Require(result[0] == kSentinel); @@ -105,7 +95,7 @@ int main() { Require(sceNpProfileDialogGetStatus() == kStatusInitialized); Require(sceNpProfileDialogUpdateStatus() == kStatusInitialized); - Require(sceNpProfileDialogGetResult(result) == kErrNotFinished); + Require(sceNpProfileDialogGetResult(reinterpret_cast(result)) == kErrNotFinished); Require(result[0] == kSentinel); RequireThrows([] { sceNpProfileDialogGetResult(nullptr); }); RequireThrows([] { sceNpProfileDialogClose(); }); @@ -117,24 +107,24 @@ int main() { alignas(8) std::uint8_t wrong[kParamSize + 16]; MakeParam(wrong, sizeof(wrong), kParamASize, 1, kParamUserData, &first); - RequireThrows([&] { sceNpProfileDialogOpen(wrong); }); + RequireThrows([&] { sceNpProfileDialogOpen(reinterpret_cast(wrong)); }); MakeParam(wrong, sizeof(wrong), kParamSize, 1, kParamAUserData, &second); - RequireThrows([&] { sceNpProfileDialogOpenA(wrong); }); + RequireThrows([&] { sceNpProfileDialogOpenA(reinterpret_cast(wrong)); }); MakeParam(wrong, sizeof(wrong), kParamSize, 0, kParamUserData, &first); - RequireThrows([&] { sceNpProfileDialogOpen(wrong); }); + RequireThrows([&] { sceNpProfileDialogOpen(reinterpret_cast(wrong)); }); MakeParam(wrong, sizeof(wrong), kParamASize, 5, kParamAUserData, &second); - RequireThrows([&] { sceNpProfileDialogOpenA(wrong); }); + RequireThrows([&] { sceNpProfileDialogOpenA(reinterpret_cast(wrong)); }); Require(sceNpProfileDialogGetStatus() == kStatusInitialized); - Require(sceNpProfileDialogGetResult(result) == kErrNotFinished); + Require(sceNpProfileDialogGetResult(reinterpret_cast(result)) == kErrNotFinished); std::uint8_t paramCopy[sizeof(param)]; std::memcpy(paramCopy, param, sizeof(param)); - Require(sceNpProfileDialogOpen(param) == 0); + Require(sceNpProfileDialogOpen(reinterpret_cast(param)) == 0); Require(std::memcmp(param, paramCopy, sizeof(param)) == 0); Require(sceNpProfileDialogGetStatus() == kStatusFinished); Require(sceNpProfileDialogUpdateStatus() == kStatusFinished); Require(sceNpProfileDialogGetResult(nullptr) == kErrArgNull); - Require(sceNpProfileDialogGetResult(result) == 0); + Require(sceNpProfileDialogGetResult(reinterpret_cast(result)) == 0); RequireCanceled(result, &first); RequireThrows([] { sceNpProfileDialogClose(); }); Require(sceNpProfileDialogGetStatus() == kStatusFinished); @@ -144,25 +134,25 @@ int main() { std::uint8_t paramACopy[sizeof(paramA)]; std::memcpy(paramACopy, paramA, sizeof(paramA)); std::memset(result, kSentinel, sizeof(result)); - Require(sceNpProfileDialogOpenA(paramA) == 0); + Require(sceNpProfileDialogOpenA(reinterpret_cast(paramA)) == 0); Require(std::memcmp(paramA, paramACopy, sizeof(paramA)) == 0); Require(sceNpProfileDialogUpdateStatus() == kStatusFinished); - Require(sceNpProfileDialogGetResult(result) == 0); + Require(sceNpProfileDialogGetResult(reinterpret_cast(result)) == 0); RequireCanceled(result, &second); } Require(sceNpProfileDialogTerminate() == 0); Require(sceNpProfileDialogTerminate() == kErrNotInitialized); Require(sceNpProfileDialogGetStatus() == kStatusNone); - Require(sceNpProfileDialogGetResult(result) == kErrNotInitialized); + Require(sceNpProfileDialogGetResult(reinterpret_cast(result)) == kErrNotInitialized); Require(sceNpProfileDialogInitialize() == 0); std::memset(result, kSentinel, sizeof(result)); - Require(sceNpProfileDialogGetResult(result) == kErrNotFinished); + Require(sceNpProfileDialogGetResult(reinterpret_cast(result)) == kErrNotFinished); Require(result[0] == kSentinel); Store(param, 56, 4); - Require(sceNpProfileDialogOpen(param) == 0); - Require(sceNpProfileDialogGetResult(result) == 0); + Require(sceNpProfileDialogOpen(reinterpret_cast(param)) == 0); + Require(sceNpProfileDialogGetResult(reinterpret_cast(result)) == 0); RequireCanceled(result, &first); Require(sceNpProfileDialogTerminate() == 0); return 0; diff --git a/core/libs/tests/GuestNpPs4Imports.cpp b/core/libs/tests/GuestNpPs4Imports.cpp index dd30ac0629..4ffc79c2fe 100644 --- a/core/libs/tests/GuestNpPs4Imports.cpp +++ b/core/libs/tests/GuestNpPs4Imports.cpp @@ -1,3 +1,6 @@ +#include "prx/libSceNpTrophy/include/Api.hpp" +#include "prx/libSceNpSignaling/include/Api.hpp" +#include "prx/libSceNpMatching2/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "SceTypes.hpp" #include @@ -11,19 +14,6 @@ #include #include -extern "C" { -int APS5_VABI sceNpTrophyCreateContext(int* context, int userId, std::uint32_t serviceLabel, std::uint64_t options); -int APS5_VABI sceNpTrophyCreateHandle(int* handle); -int APS5_VABI sceNpTrophyRegisterContext(int context, int handle, std::uint64_t options); -int APS5_VABI sceNpTrophyUnlockTrophy(int context, int handle, int trophyId, int* platinumId); -int APS5_VABI sceNpTrophyGetGameInfo(int context, int handle, void* details, void* data); -int APS5_VABI sceNpTrophyGetGroupInfo(int context, int handle, int groupId, void* details, void* data); -int APS5_VABI sceNpTrophyGetTrophyInfo(int context, int handle, int trophyId, void* details, void* data); -int APS5_VABI sceNpMatching2Initialize(const void* param); -int APS5_VABI sceNpMatching2Terminate(void); -int APS5_VABI sceNpSignalingDeactivateConnection(void); -} - namespace { constexpr int Matching2AlreadyInitialized = static_cast(0x80550C02u); @@ -34,50 +24,6 @@ constexpr int TrophyInvalidTrophyId = static_cast(0x8055160au); constexpr int TrophyInvalidGroupId = static_cast(0x8055160bu); constexpr int TrophyNotRegistered = static_cast(0x8055160fu); -struct TrophyGameDetails { - std::uint64_t size; - std::uint32_t numGroups, numTrophies, numPlatinum, numGold, numSilver, numBronze; - char title[128]; - char description[1024]; -}; - -struct TrophyGameData { - std::uint64_t size; - std::uint32_t unlockedTrophies, unlockedPlatinum, unlockedGold, unlockedSilver, unlockedBronze, progressPercentage; -}; - -struct TrophyGroupDetails { - std::uint64_t size; - std::int32_t groupId; - std::uint32_t numTrophies, numPlatinum, numGold, numSilver, numBronze; - char title[128]; - char description[1024]; -}; - -struct TrophyGroupData { - std::uint64_t size; - std::int32_t groupId; - std::uint32_t unlockedTrophies, unlockedPlatinum, unlockedGold, unlockedSilver, unlockedBronze, progressPercentage; - std::uint8_t reserved[4]; -}; - -struct TrophyDetails { - std::uint64_t size; - std::int32_t trophyId, trophyGrade, groupId; - bool hidden; - std::uint8_t reserved[3]; - char name[128]; - char description[1024]; -}; - -struct TrophyData { - std::uint64_t size; - std::int32_t trophyId; - bool unlocked; - std::uint8_t reserved[3]; - std::uint64_t timestamp; -}; - void Require(bool condition, const char* message) { if (!condition) { std::fprintf(stderr, "NpPs4Imports: %s\n", message); @@ -85,17 +31,6 @@ void Require(bool condition, const char* message) { } } -template -void RequireNotImplemented(TCall call, const std::string& name) { - try { - call(); - } catch (const std::runtime_error& error) { - Require(std::string(error.what()) == name + " not implemented", "a declared function threw another error"); - return; - } - Require(false, "a declared function returned"); -} - void WriteBigEndian(std::vector& bytes, std::size_t at, std::uint64_t value, std::size_t width) { for (std::size_t index = 0; index < width; ++index) bytes[at + index] = static_cast(value >> (8u * (width - 1u - index))); } @@ -128,8 +63,8 @@ void CheckTrophyInfo() { int context = -1; int handle = -1; Require(sceNpTrophyCreateContext(&context, user, label, 0u) == 0 && sceNpTrophyCreateHandle(&handle) == 0, "trophy context or handle not created"); - TrophyGameDetails game{}; - TrophyGameData gameData{}; + GameDetails game{}; + GameData gameData{}; game.size = sizeof(game); gameData.size = sizeof(gameData); Require(sceNpTrophyGetGameInfo(context, handle, &game, &gameData) == TrophyNotRegistered, "game info answered before registration"); @@ -153,8 +88,8 @@ void CheckTrophyInfo() { Require(trophy.trophyId == 1 && trophy.trophyGrade == 0 && trophy.groupId == -1 && !trophy.hidden && trophy.name[0] == '\0' && trophyData.trophyId == 1 && trophyData.unlocked, "trophy 1 info is wrong"); Require(sceNpTrophyGetTrophyInfo(context, handle, 0, nullptr, &trophyData) == 0 && trophyData.trophyId == 0 && !trophyData.unlocked, "trophy 0 reported unlocked"); Require(sceNpTrophyGetTrophyInfo(context, handle, 3, &trophy, &trophyData) == TrophyInvalidTrophyId, "a trophy past the package accepted"); - TrophyGroupDetails group{}; - TrophyGroupData groupData{}; + GroupDetails group{}; + GroupData groupData{}; group.size = sizeof(group); groupData.size = sizeof(groupData); Require(sceNpTrophyGetGroupInfo(context, handle, -1, &group, &groupData) == 0, "base game group refused"); @@ -173,25 +108,20 @@ void CheckMatching2() { Require(sceNpMatching2Terminate() == Matching2NotInitialized, "NpMatching2 terminated before initialization"); Require(sceNpMatching2Initialize(nullptr) == Matching2InvalidArgument, "a null NpMatching2 parameter was accepted"); setSize(0x20u); - Require(sceNpMatching2Initialize(param) == Matching2InvalidArgument, "an NpMatching2 parameter of size 0x20 was accepted"); + Require(sceNpMatching2Initialize(reinterpret_cast(param)) == Matching2InvalidArgument, "an NpMatching2 parameter of size 0x20 was accepted"); setSize(0x28u); - Require(sceNpMatching2Initialize(param) == 0, "an NpMatching2 parameter of size 0x28 was refused"); - Require(sceNpMatching2Initialize(param) == Matching2AlreadyInitialized, "NpMatching2 initialized twice"); + Require(sceNpMatching2Initialize(reinterpret_cast(param)) == 0, "an NpMatching2 parameter of size 0x28 was refused"); + Require(sceNpMatching2Initialize(reinterpret_cast(param)) == Matching2AlreadyInitialized, "NpMatching2 initialized twice"); Require(sceNpMatching2Terminate() == 0, "NpMatching2 did not terminate"); setSize(0x30u); - Require(sceNpMatching2Initialize(param) == 0, "an NpMatching2 parameter with an SSL pool was refused"); + Require(sceNpMatching2Initialize(reinterpret_cast(param)) == 0, "an NpMatching2 parameter with an SSL pool was refused"); Require(sceNpMatching2Terminate() == 0, "NpMatching2 did not terminate after the SSL form"); } -void CheckSignaling() { - RequireNotImplemented([] { sceNpSignalingDeactivateConnection(); }, "sceNpSignalingDeactivateConnection"); -} - } int main() { CheckTrophyInfo(); CheckMatching2(); - CheckSignaling(); return 0; } diff --git a/core/libs/tests/GuestNpReachability.cpp b/core/libs/tests/GuestNpReachability.cpp index e6995ac80d..1c16e32fe7 100644 --- a/core/libs/tests/GuestNpReachability.cpp +++ b/core/libs/tests/GuestNpReachability.cpp @@ -1,14 +1,7 @@ +#include "prx/libSceNpManager/include/Api.hpp" #include "SceTypes.hpp" #include -extern "C" { -int APS5_VABI sceNpRegisterNpReachabilityStateCallback(void*, void*); -int APS5_VABI sceNpUnregisterNpReachabilityStateCallback(); -int APS5_VABI sceNpGetNpReachabilityState(int, uint32_t*); -int APS5_VABI sceNpCheckCallback(); -int APS5_VABI sceNpCheckNpAvailability(int, const NpOnlineId*, std::uint8_t*); -} - static constexpr int ErrorArgument = static_cast(0x80550003); static constexpr int ErrorAlreadyRegistered = static_cast(0x80550008); static constexpr int ErrorNotRegistered = static_cast(0x80550009); diff --git a/core/libs/tests/GuestNpScoreOffline.cpp b/core/libs/tests/GuestNpScoreOffline.cpp index cb6adb87eb..15cc132c95 100644 --- a/core/libs/tests/GuestNpScoreOffline.cpp +++ b/core/libs/tests/GuestNpScoreOffline.cpp @@ -1,26 +1,9 @@ +#include "prx/libSceNpScoreRanking/include/Api.hpp" #include "SceTypes.hpp" #include #include #include -extern "C" { -int APS5_VABI sceNpScoreCreateNpTitleCtx(std::uint32_t serviceLabel, const void* selfNpId); -int APS5_VABI sceNpScoreDeleteNpTitleCtx(int titleCtxId); -int APS5_VABI sceNpScoreCreateRequest(int titleCtxId); -int APS5_VABI sceNpScoreDeleteRequest(int reqId); -int APS5_VABI sceNpScoreAbortRequest(int reqId); -int APS5_VABI sceNpScorePollAsync(int reqId, int* result); -int APS5_VABI sceNpScoreRecordScore(int reqId, std::uint32_t boardId, std::int64_t score, const void* scoreComment, const void* gameInfo, std::uint32_t* tmpRank, const void* compareDate, void* option); -int APS5_VABI sceNpScoreRecordScoreAsync(int reqId, std::uint32_t boardId, std::int64_t score, const void* scoreComment, const void* gameInfo, std::uint32_t* tmpRank, const void* compareDate, void* option); -int APS5_VABI sceNpScoreGetRankingByRange(int reqId, std::uint32_t boardId, std::uint32_t startSerialRank, void* rankArray, std::uint64_t rankArraySize, void* commentArray, std::uint64_t commentArraySize, void* infoArray, std::uint64_t infoArraySize, std::uint64_t arrayNum, void* lastSortDate, void* totalRecord, void* option); -int APS5_VABI sceNpScoreGetRankingByRangeAsync(int reqId, std::uint32_t boardId, std::uint32_t startSerialRank, void* rankArray, std::uint64_t rankArraySize, void* commentArray, std::uint64_t commentArraySize, void* infoArray, std::uint64_t infoArraySize, std::uint64_t arrayNum, void* lastSortDate, void* totalRecord, void* option); -int APS5_VABI sceNpScoreGetRankingByNpId(int reqId, std::uint32_t boardId, const void* npIdArray, std::uint64_t npIdArraySize, void* rankArray, std::uint64_t rankArraySize, void* commentArray, std::uint64_t commentArraySize, void* infoArray, std::uint64_t infoArraySize, std::uint64_t arrayNum, void* lastSortDate, void* totalRecord, void* option); -int APS5_VABI sceNpScoreGetRankingByNpIdAsync(int reqId, std::uint32_t boardId, const void* npIdArray, std::uint64_t npIdArraySize, void* rankArray, std::uint64_t rankArraySize, void* commentArray, std::uint64_t commentArraySize, void* infoArray, std::uint64_t infoArraySize, std::uint64_t arrayNum, void* lastSortDate, void* totalRecord, void* option); -int APS5_VABI sceNpScoreGetFriendsRanking(int reqId, std::uint32_t boardId, int includeSelf, void* rankArray, std::uint64_t rankArraySize, void* commentArray, std::uint64_t commentArraySize, void* infoArray, std::uint64_t infoArraySize, std::uint64_t arrayNum, void* lastSortDate, void* totalRecord, const void* option); -int APS5_VABI sceNpScoreGetFriendsRankingAsync(int reqId, std::uint32_t boardId, int includeSelf, void* rankArray, std::uint64_t rankArraySize, void* commentArray, std::uint64_t commentArraySize, void* infoArray, std::uint64_t infoArraySize, std::uint64_t arrayNum, void* lastSortDate, void* totalRecord, const void* option); -int APS5_VABI sceNpScoreGetBoardInfo(int reqId, std::uint32_t boardId, void* boardInfo, void* option); -} - namespace { constexpr int SignedOut = static_cast(0x80550006u); @@ -34,18 +17,6 @@ constexpr int TooManyNpId = static_cast(0x80550719u); constexpr int PollFinished = 0; constexpr int PollRunning = 1; -struct GameInfo { - std::uint64_t infoSize; - std::uint8_t data[189]; - std::uint8_t pad[3]; -}; - -struct FriendOption { - std::uint64_t size; - const std::uint32_t* startSerialRank; - const std::uint32_t* hits; -}; - int failures = 0; int context = 0; unsigned char selfNpId[36]; @@ -122,10 +93,11 @@ void CheckRequests() { Require(sceNpScorePollAsync(req, &result) == PollFinished && result == SignedOut, "sceNpScoreAbortRequest", "aborting a finished request changed its result"); Require(sceNpScoreRecordScore(req, 1, 5, nullptr, nullptr, nullptr, nullptr, nullptr) == SignedOut, "sceNpScoreRecordScore", "a finished request was not reused"); sceNpScoreDeleteRequest(req); + } void CheckRecord() { - GameInfo info{}; + NpScoreGameInfo info{}; std::uint32_t tmpRank = 77; const int req = NewRequest(); info.infoSize = 190; @@ -138,6 +110,7 @@ void CheckRecord() { CheckOffline("sceNpScoreRecordScoreAsync", sceNpScoreRecordScoreAsync(req, 1, 5, nullptr, &info, &tmpRank, nullptr, nullptr), req); Require(tmpRank == 77, "sceNpScoreRecordScoreAsync", "a rank was written"); sceNpScoreDeleteRequest(req); + } void CheckRange() { @@ -156,6 +129,7 @@ void CheckRange() { Require(sceNpScoreGetRankingByRangeAsync(req, 1, 0, ranks, 0x100, nullptr, 0, nullptr, 0, 2, nullptr, nullptr, nullptr) == InvalidArgument, "sceNpScoreGetRankingByRangeAsync", "rank 0 was taken"); Require(sceNpScoreGetRankingByRangeAsync(req, 1, 1, manyRanks, 100 * 0x80, nullptr, 0, nullptr, 0, 100, nullptr, nullptr, nullptr) == SignedOut, "sceNpScoreGetRankingByRangeAsync", "100 ranks did not return SIGNED_OUT"); sceNpScoreDeleteRequest(req); + } void CheckNpId() { @@ -171,15 +145,16 @@ void CheckNpId() { Require(sceNpScoreGetRankingByNpIdAsync(req, 1, npIds, 0, ranks, 0, nullptr, 0, nullptr, 0, 0, nullptr, nullptr, nullptr) == SignedOut, "sceNpScoreGetRankingByNpIdAsync", "zero NpIds did not return SIGNED_OUT"); Require(sceNpScoreGetRankingByNpIdAsync(req, 1, manyNpIds, sizeof(manyNpIds), manyRanks, sizeof(manyRanks), nullptr, 0, nullptr, 0, 101, nullptr, nullptr, nullptr) == SignedOut, "sceNpScoreGetRankingByNpIdAsync", "101 NpIds did not return SIGNED_OUT"); sceNpScoreDeleteRequest(req); + } void CheckFriends() { const int req = NewRequest(); const std::uint32_t zero = 0; const std::uint32_t five = 5; - const FriendOption shortOption{16, nullptr, nullptr}; - const FriendOption rankZero{24, &zero, nullptr}; - const FriendOption rankFive{24, &five, nullptr}; + const NpScoreFriendRankingOption shortOption{16, nullptr, nullptr}; + const NpScoreFriendRankingOption rankZero{24, &zero, nullptr}; + const NpScoreFriendRankingOption rankFive{24, &five, nullptr}; Require(sceNpScoreGetFriendsRanking(req, 1, 0, nullptr, 0x80, nullptr, 0, nullptr, 0, 0, nullptr, nullptr, &shortOption) == InvalidArgument, "sceNpScoreGetFriendsRanking", "a null rank array was taken"); Require(sceNpScoreGetFriendsRanking(req, 1, 0, ranks, 0x88, nullptr, 0, nullptr, 0, 1, nullptr, nullptr, &shortOption) == InvalidAlignment, "sceNpScoreGetFriendsRanking", "the rank array size was not checked before the option"); Require(sceNpScoreGetFriendsRanking(req, 1, 0, ranks, 0x80, nullptr, 0, nullptr, 0, 1, nullptr, nullptr, &rankFive) == InvalidArgument, "sceNpScoreGetFriendsRanking", "an option without includeSelf was taken"); @@ -192,6 +167,7 @@ void CheckFriends() { Require(sceNpScoreGetFriendsRankingAsync(req, 1, 0, ranks, 0x100, nullptr, 0, nullptr, 0, 2, nullptr, nullptr, nullptr) == SignedOut, "sceNpScoreGetFriendsRankingAsync", "valid arguments did not return SIGNED_OUT"); Require(sceNpScoreGetFriendsRankingAsync(req, 1, 0, manyRanks, 100 * 0x80, nullptr, 0, nullptr, 0, 100, nullptr, nullptr, nullptr) == SignedOut, "sceNpScoreGetFriendsRankingAsync", "100 friends did not return SIGNED_OUT"); sceNpScoreDeleteRequest(req); + } void CheckBoard() { @@ -200,6 +176,7 @@ void CheckBoard() { Require(sceNpScoreGetBoardInfo(req + 100, 1, board, nullptr) == InvalidId, "sceNpScoreGetBoardInfo", "an unknown request was taken"); CheckOffline("sceNpScoreGetBoardInfo", sceNpScoreGetBoardInfo(req, 1, board, nullptr), req); sceNpScoreDeleteRequest(req); + } } diff --git a/core/libs/tests/GuestNpSessionSignaling.cpp b/core/libs/tests/GuestNpSessionSignaling.cpp index 74240e67b1..1818d3df1b 100644 --- a/core/libs/tests/GuestNpSessionSignaling.cpp +++ b/core/libs/tests/GuestNpSessionSignaling.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNpSessionSignaling/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -5,24 +6,6 @@ #include #include -extern "C" { -int APS5_VABI sceNpSessionSignalingInitialize(void* param); -int APS5_VABI sceNpSessionSignalingCreateContext(const void* param, std::uint32_t* contextId); -int APS5_VABI sceNpSessionSignalingCreateContext2(const void* param, std::uint32_t* contextId); -int APS5_VABI sceNpSessionSignalingDestroyContext(std::uint32_t contextId); -int APS5_VABI sceNpSessionSignalingDeactivate(std::uint32_t contextId, std::uint32_t connectionId); -std::int32_t APS5_VABI sceNpSessionSignalingGetLocalNetInfo(std::int32_t contextId, void* info); -int APS5_VABI sceNpSessionSignalingRequestPrepare(std::uint32_t contextId, std::uint32_t* requestId); -std::int32_t APS5_VABI sceNpSessionSignalingGetConnectionStatus(std::int32_t contextId, std::int32_t connectionId, std::int32_t* status, void* peerAddress, std::uint16_t* peerPort); -std::int32_t APS5_VABI sceNpSessionSignalingGetGroupInfo(std::int32_t contextId, std::int32_t groupId, void* info); -std::int32_t APS5_VABI sceNpSessionSignalingGetGroupFromSessionId(std::int32_t contextId, const void* sessionId, std::int32_t* groupId); -std::int32_t APS5_VABI sceNpSessionSignalingGetConnectionFromNetAddress(std::int32_t contextId, std::uint32_t address, std::uint16_t port, std::int32_t* connectionId); -std::int32_t APS5_VABI sceNpSessionSignalingGetConnectionFromNetAddress2(std::int32_t contextId, std::int32_t groupId, std::uint32_t address, std::uint16_t port, std::int32_t* connectionId); -std::int32_t APS5_VABI sceNpSessionSignalingGetConnectionFromPeerAddress(std::int32_t contextId, const void* peerAddress, std::int32_t* connectionId); -std::int32_t APS5_VABI sceNpSessionSignalingGetConnectionFromPeerAddress2(std::int32_t contextId, std::int32_t groupId, const void* peerAddress, std::int32_t* connectionId); -int APS5_VABI sceNpSessionSignalingTerminate(void); -} - namespace { constexpr int InvalidArgument = static_cast(0x80553303u); @@ -49,10 +32,10 @@ int main() { Require(sceNpSessionSignalingCreateContext2(nullptr, nullptr) == NotInitialized, "initialization check precedes context arguments"); Require(sceNpSessionSignalingGetConnectionStatus(0, 0, nullptr, nullptr, nullptr) == NotInitialized, "status before initialize"); Require(sceNpSessionSignalingInitialize(nullptr) == InvalidArgument, "null initialize parameter"); - Require(sceNpSessionSignalingInitialize(initializeParam) == InvalidArgument, "zero pool size"); + Require(sceNpSessionSignalingInitialize(reinterpret_cast(initializeParam)) == InvalidArgument, "zero pool size"); const std::uint64_t poolSize = 4 * 1024 * 1024; std::memcpy(initializeParam + 8, &poolSize, sizeof(poolSize)); - Require(sceNpSessionSignalingInitialize(initializeParam) == 0, "initialize failed"); + Require(sceNpSessionSignalingInitialize(reinterpret_cast(initializeParam)) == 0, "initialize failed"); Require(sceNpSessionSignalingInitialize(nullptr) == AlreadyInitialized, "initialization check precedes initialize arguments"); alignas(8) unsigned char contextParam[56] = {}; std::uint32_t contextId = 0; @@ -60,24 +43,24 @@ int main() { Require(contextId == 0, "invalid context parameter wrote an id"); Require(sceNpSessionSignalingCreateContext2(nullptr, &contextId) == InvalidArgument, "null context2 parameter"); Require(contextId == 0, "invalid context2 parameter wrote an id"); - Require(sceNpSessionSignalingCreateContext(contextParam, nullptr) == InvalidArgument, "null context id"); - Require(sceNpSessionSignalingCreateContext2(contextParam, nullptr) == InvalidArgument, "null context2 id"); - Require(sceNpSessionSignalingCreateContext2(contextParam, &contextId) == 0, "context creation failed"); + Require(sceNpSessionSignalingCreateContext(reinterpret_cast(contextParam), nullptr) == InvalidArgument, "null context id"); + Require(sceNpSessionSignalingCreateContext2(reinterpret_cast(contextParam), nullptr) == InvalidArgument, "null context2 id"); + Require(sceNpSessionSignalingCreateContext2(reinterpret_cast(contextParam), &contextId) == 0, "context creation failed"); const auto firstId = contextId; - Require(sceNpSessionSignalingCreateContext2(contextParam, &contextId) == ContextLimit, "duplicate user context"); + Require(sceNpSessionSignalingCreateContext2(reinterpret_cast(contextParam), &contextId) == ContextLimit, "duplicate user context"); Require(contextId == firstId, "duplicate context modified output"); std::array otherContexts{}; for (std::int32_t userId = 1; userId <= 9; ++userId) { std::memcpy(contextParam, &userId, sizeof(userId)); - Require(sceNpSessionSignalingCreateContext2(contextParam, &otherContexts[userId - 1]) == 0, "create remaining contexts"); + Require(sceNpSessionSignalingCreateContext2(reinterpret_cast(contextParam), &otherContexts[userId - 1]) == 0, "create remaining contexts"); } const std::int32_t overflowUser = 10; std::memcpy(contextParam, &overflowUser, sizeof(overflowUser)); - Require(sceNpSessionSignalingCreateContext2(contextParam, &contextId) == ContextLimit, "context limit"); + Require(sceNpSessionSignalingCreateContext2(reinterpret_cast(contextParam), &contextId) == ContextLimit, "context limit"); Require(contextId == firstId, "context limit modified output"); Require(sceNpSessionSignalingDestroyContext(firstId) == 0, "destroy first context"); Require(sceNpSessionSignalingDestroyContext(firstId) == ContextNotFound, "destroy stale context"); - Require(sceNpSessionSignalingCreateContext2(contextParam, &contextId) == 0, "reuse context slot"); + Require(sceNpSessionSignalingCreateContext2(reinterpret_cast(contextParam), &contextId) == 0, "reuse context slot"); Require(contextId != firstId, "reused context kept stale id"); std::uint32_t requestId = 0xa5a5a5a5u; @@ -93,7 +76,7 @@ int main() { unsigned char untouched[sizeof(info)]; std::memcpy(untouched, info, sizeof(info)); Require(sceNpSessionSignalingGetLocalNetInfo(netContextId, nullptr) == InvalidArgument, "null info"); - Require(sceNpSessionSignalingGetLocalNetInfo(netContextId, info) == Unavailable, "local net info without network"); + Require(sceNpSessionSignalingGetLocalNetInfo(netContextId, reinterpret_cast(info)) == Unavailable, "local net info without network"); Require(std::memcmp(info, untouched, sizeof(info)) == 0, "failed query modified the info"); std::int32_t status = 0x5a5a5a5a; @@ -108,30 +91,30 @@ int main() { Require(sceNpSessionSignalingDeactivate(contextId, 1) == GroupNotFound, "deactivate nonexistent group"); Require(sceNpSessionSignalingGetGroupInfo(netContextId, 1, nullptr) == InvalidArgument, "null group info"); - Require(sceNpSessionSignalingGetGroupInfo(netContextId, 1, info) == GroupNotFound, "group info without a session"); + Require(sceNpSessionSignalingGetGroupInfo(netContextId, 1, reinterpret_cast(info)) == GroupNotFound, "group info without a session"); Require(std::memcmp(info, untouched, sizeof(info)) == 0, "failed group query modified the info"); const unsigned char sessionId[48] = {}; const unsigned char peer[40] = {}; std::int32_t found = 0x5a5a5a5a; - Require(sceNpSessionSignalingGetGroupFromSessionId(netContextId, nullptr, &found) == InvalidArgument, "null session id"); - Require(sceNpSessionSignalingGetGroupFromSessionId(netContextId, sessionId, nullptr) == InvalidArgument, "null group id"); - Require(sceNpSessionSignalingGetGroupFromSessionId(netContextId, sessionId, &found) == GroupNotFound, "group from session id without a session"); + Require(sceNpSessionSignalingGetGroupFromSessionId(netContextId, nullptr, reinterpret_cast(&found)) == InvalidArgument, "null session id"); + Require(sceNpSessionSignalingGetGroupFromSessionId(netContextId, reinterpret_cast(sessionId), nullptr) == InvalidArgument, "null group id"); + Require(sceNpSessionSignalingGetGroupFromSessionId(netContextId, reinterpret_cast(sessionId), reinterpret_cast(&found)) == GroupNotFound, "group from session id without a session"); Require(sceNpSessionSignalingGetConnectionFromNetAddress(netContextId, 0x0100007fu, 3658, nullptr) == InvalidArgument, "null connection id from net address"); - Require(sceNpSessionSignalingGetConnectionFromNetAddress(netContextId, 0x0100007fu, 3658, &found) == ConnectionNotFound, "connection from net address without a session"); + Require(sceNpSessionSignalingGetConnectionFromNetAddress(netContextId, 0x0100007fu, 3658, reinterpret_cast(&found)) == ConnectionNotFound, "connection from net address without a session"); Require(sceNpSessionSignalingGetConnectionFromNetAddress2(netContextId, 1, 0x0100007fu, 3658, nullptr) == InvalidArgument, "null connection id from group net address"); - Require(sceNpSessionSignalingGetConnectionFromNetAddress2(netContextId, 1, 0x0100007fu, 3658, &found) == GroupNotFound, "connection from group net address without a session"); - Require(sceNpSessionSignalingGetConnectionFromPeerAddress(netContextId, nullptr, &found) == InvalidArgument, "null peer address"); - Require(sceNpSessionSignalingGetConnectionFromPeerAddress(netContextId, peer, nullptr) == InvalidArgument, "null connection id from peer address"); - Require(sceNpSessionSignalingGetConnectionFromPeerAddress(netContextId, peer, &found) == ConnectionNotFound, "connection from peer address without a session"); - Require(sceNpSessionSignalingGetConnectionFromPeerAddress2(netContextId, 1, nullptr, &found) == InvalidArgument, "null group peer address"); - Require(sceNpSessionSignalingGetConnectionFromPeerAddress2(netContextId, 1, peer, nullptr) == InvalidArgument, "null connection id from group peer address"); - Require(sceNpSessionSignalingGetConnectionFromPeerAddress2(netContextId, 1, peer, &found) == GroupNotFound, "connection from group peer address without a session"); - Require(sceNpSessionSignalingGetGroupInfo(firstId, 1, info) == ContextNotFound, "group info stale context"); - Require(sceNpSessionSignalingGetGroupFromSessionId(firstId, sessionId, &found) == ContextNotFound, "group from session id stale context"); - Require(sceNpSessionSignalingGetConnectionFromNetAddress(firstId, 0x0100007fu, 3658, &found) == ContextNotFound, "connection from net address stale context"); - Require(sceNpSessionSignalingGetConnectionFromNetAddress2(firstId, 1, 0x0100007fu, 3658, &found) == ContextNotFound, "connection from group net address stale context"); - Require(sceNpSessionSignalingGetConnectionFromPeerAddress(firstId, peer, &found) == ContextNotFound, "connection from peer address stale context"); + Require(sceNpSessionSignalingGetConnectionFromNetAddress2(netContextId, 1, 0x0100007fu, 3658, reinterpret_cast(&found)) == GroupNotFound, "connection from group net address without a session"); + Require(sceNpSessionSignalingGetConnectionFromPeerAddress(netContextId, nullptr, reinterpret_cast(&found)) == InvalidArgument, "null peer address"); + Require(sceNpSessionSignalingGetConnectionFromPeerAddress(netContextId, reinterpret_cast(peer), nullptr) == InvalidArgument, "null connection id from peer address"); + Require(sceNpSessionSignalingGetConnectionFromPeerAddress(netContextId, reinterpret_cast(peer), reinterpret_cast(&found)) == ConnectionNotFound, "connection from peer address without a session"); + Require(sceNpSessionSignalingGetConnectionFromPeerAddress2(netContextId, 1, nullptr, reinterpret_cast(&found)) == InvalidArgument, "null group peer address"); + Require(sceNpSessionSignalingGetConnectionFromPeerAddress2(netContextId, 1, reinterpret_cast(peer), nullptr) == InvalidArgument, "null connection id from group peer address"); + Require(sceNpSessionSignalingGetConnectionFromPeerAddress2(netContextId, 1, reinterpret_cast(peer), reinterpret_cast(&found)) == GroupNotFound, "connection from group peer address without a session"); + Require(sceNpSessionSignalingGetGroupInfo(firstId, 1, reinterpret_cast(info)) == ContextNotFound, "group info stale context"); + Require(sceNpSessionSignalingGetGroupFromSessionId(firstId, reinterpret_cast(sessionId), reinterpret_cast(&found)) == ContextNotFound, "group from session id stale context"); + Require(sceNpSessionSignalingGetConnectionFromNetAddress(firstId, 0x0100007fu, 3658, reinterpret_cast(&found)) == ContextNotFound, "connection from net address stale context"); + Require(sceNpSessionSignalingGetConnectionFromNetAddress2(firstId, 1, 0x0100007fu, 3658, reinterpret_cast(&found)) == ContextNotFound, "connection from group net address stale context"); + Require(sceNpSessionSignalingGetConnectionFromPeerAddress(firstId, reinterpret_cast(peer), reinterpret_cast(&found)) == ContextNotFound, "connection from peer address stale context"); Require(found == 0x5a5a5a5a, "a failed lookup wrote an id"); Require(sceNpSessionSignalingTerminate() == 0, "terminate failed"); @@ -142,7 +125,7 @@ int main() { Require(sceNpSessionSignalingGetConnectionFromNetAddress2(netContextId, 1, 0, 0, nullptr) == NotInitialized, "connection from group net address after terminate"); Require(sceNpSessionSignalingGetConnectionFromPeerAddress(netContextId, nullptr, nullptr) == NotInitialized, "connection from peer address after terminate"); Require(sceNpSessionSignalingTerminate() == NotInitialized, "repeated terminate"); - Require(sceNpSessionSignalingInitialize(initializeParam) == 0, "reinitialize"); + Require(sceNpSessionSignalingInitialize(reinterpret_cast(initializeParam)) == 0, "reinitialize"); Require(sceNpSessionSignalingRequestPrepare(contextId, &requestId) == ContextNotFound, "reinitialize retained a context"); Require(sceNpSessionSignalingTerminate() == 0, "final terminate"); } diff --git a/core/libs/tests/GuestNpSignalingOffline.cpp b/core/libs/tests/GuestNpSignalingOffline.cpp index dd246473a7..f457b0aeae 100644 --- a/core/libs/tests/GuestNpSignalingOffline.cpp +++ b/core/libs/tests/GuestNpSignalingOffline.cpp @@ -1,19 +1,9 @@ +#include "prx/libSceNpSignaling/include/Api.hpp" #include "SceTypes.hpp" #include #include #include -extern "C" { -int APS5_VABI sceNpSignalingInitialize(std::int64_t memorySize, int threadPriority, int cpuAffinityMask, std::int64_t threadStackSize); -int APS5_VABI sceNpSignalingTerminate(); -int APS5_VABI sceNpSignalingCreateContext(const void* npId, void* callback, void* callbackArg, int* outContextId); -int APS5_VABI sceNpSignalingDeleteContext(int ctxId); -int APS5_VABI sceNpSignalingSetContextOption(int ctxId, int optionId, int optionValue); -int APS5_VABI sceNpSignalingActivateConnection(int ctxId, const void* peerNpId, int* outConnId); -int APS5_VABI sceNpSignalingTerminateConnection(int ctxId, int connId); -int APS5_VABI sceNpSignalingGetConnectionInfo(int ctxId, int connId, int infoCode, void* outInfo); -} - namespace { constexpr int SignedOut = static_cast(0x80550006u); @@ -71,6 +61,7 @@ int main() { Require(sceNpSignalingSetContextOption(1, 1, 1) == NotInitialized, "sceNpSignalingSetContextOption", "a call before initialization did not return NOT_INITIALIZED"); Require(sceNpSignalingActivateConnection(1, nullptr, nullptr) == NotInitialized, "sceNpSignalingActivateConnection", "a call before initialization did not return NOT_INITIALIZED first"); Require(sceNpSignalingTerminateConnection(1, 1) == NotInitialized, "sceNpSignalingTerminateConnection", "a call before initialization did not return NOT_INITIALIZED"); + Require(sceNpSignalingDeactivateConnection(1, 1) == NotInitialized, "sceNpSignalingDeactivateConnection", "a call before initialization did not return NOT_INITIALIZED"); Require(sceNpSignalingGetConnectionInfo(1, 1, 1, nullptr) == NotInitialized, "sceNpSignalingGetConnectionInfo", "a call before initialization did not return NOT_INITIALIZED first"); Require(sceNpSignalingTerminate() == NotInitialized, "sceNpSignalingTerminate", "terminating before initialization did not return NOT_INITIALIZED"); @@ -114,6 +105,8 @@ int main() { Require(sceNpSignalingTerminateConnection(99, 1) == CtxNotFound, "sceNpSignalingTerminateConnection", "an unknown context was taken"); Require(sceNpSignalingTerminateConnection(context, 1) == ConnNotFound, "sceNpSignalingTerminateConnection", "a connection that was never created was found"); + Require(sceNpSignalingDeactivateConnection(99, 1) == CtxNotFound, "sceNpSignalingDeactivateConnection", "an unknown context was taken"); + Require(sceNpSignalingDeactivateConnection(context, 1) == ConnNotFound, "sceNpSignalingDeactivateConnection", "a connection that was never created was found"); Require(sceNpSignalingGetConnectionInfo(99, 1, 1, nullptr) == InvalidArgument, "sceNpSignalingGetConnectionInfo", "a null output was not refused before the context"); Require(sceNpSignalingGetConnectionInfo(99, 1, 1, info) == CtxNotFound, "sceNpSignalingGetConnectionInfo", "an unknown context was taken"); Require(sceNpSignalingGetConnectionInfo(context, 1, 1, info) == ConnNotFound, "sceNpSignalingGetConnectionInfo", "a connection that was never created was found"); diff --git a/core/libs/tests/GuestNpSnsFacebookDialog.cpp b/core/libs/tests/GuestNpSnsFacebookDialog.cpp index 2b78b0007c..347a2dcfe3 100644 --- a/core/libs/tests/GuestNpSnsFacebookDialog.cpp +++ b/core/libs/tests/GuestNpSnsFacebookDialog.cpp @@ -1,17 +1,8 @@ +#include "prx/libSceNpSnsFacebookDialog/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include -extern "C" { -int APS5_VABI sceNpSnsFacebookDialogInitialize(void); -int APS5_VABI sceNpSnsFacebookDialogOpen(const void* param); -int APS5_VABI sceNpSnsFacebookDialogUpdateStatus(void); -int APS5_VABI sceNpSnsFacebookDialogGetStatus(void); -int APS5_VABI sceNpSnsFacebookDialogGetResult(void* result); -int APS5_VABI sceNpSnsFacebookDialogClose(void); -int APS5_VABI sceNpSnsFacebookDialogTerminate(void); -} - namespace { void Require(bool value) { if (!value) std::abort(); } diff --git a/core/libs/tests/GuestNpTrophy.cpp b/core/libs/tests/GuestNpTrophy.cpp index e8a9b8749f..51da08e5d2 100644 --- a/core/libs/tests/GuestNpTrophy.cpp +++ b/core/libs/tests/GuestNpTrophy.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNpTrophy/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -9,18 +10,6 @@ #include #include -extern "C" { -int APS5_VABI sceNpTrophyCreateContext(int* context, int userId, std::uint32_t serviceLabel, std::uint64_t options); -int APS5_VABI sceNpTrophyDestroyContext(int context); -int APS5_VABI sceNpTrophyCreateHandle(int* handle); -int APS5_VABI sceNpTrophyDestroyHandle(int handle); -int APS5_VABI sceNpTrophyRegisterContext(int context, int handle, std::uint64_t options); -int APS5_VABI sceNpTrophyGetTrophyUnlockState(int context, int handle, std::uint32_t* flags, std::uint32_t* count); -int APS5_VABI sceNpTrophyUnlockTrophy(int context, int handle, int trophyId, int* platinumId); -int APS5_VABI sceNpTrophyGetGameIcon(int context, int handle, void* buffer, std::uint64_t* size); -int APS5_VABI sceNpTrophyGetTrophyIcon(int context, int handle, int trophyId, void* buffer, std::uint64_t* size); -} - namespace { constexpr int InvalidArgument = static_cast(0x80551604u); @@ -78,10 +67,10 @@ int main() { Require(sceNpTrophyCreateHandle(&handle) == 0, "create the handle"); std::uint32_t flags[4] = {}, count = 0; - Require(sceNpTrophyGetTrophyUnlockState(context, handle, flags, &count) == NotRegistered, "state before registration"); + Require(sceNpTrophyGetTrophyUnlockState(context, handle, reinterpret_cast(flags), &count) == NotRegistered, "state before registration"); Require(sceNpTrophyRegisterContext(context, handle, 0) == 0, "register the context"); Require(sceNpTrophyRegisterContext(context, handle, 0) == AlreadyRegistered, "register twice"); - Require(sceNpTrophyGetTrophyUnlockState(context, handle, flags, &count) == 0 && count == 2 && flags[0] == 0, "two trophies, none unlocked"); + Require(sceNpTrophyGetTrophyUnlockState(context, handle, reinterpret_cast(flags), &count) == 0 && count == 2 && flags[0] == 0, "two trophies, none unlocked"); std::uint64_t size = 0; Require(sceNpTrophyGetGameIcon(context, handle, nullptr, &size) == 0 && size == 9, "game icon size"); @@ -96,7 +85,7 @@ int main() { Require(sceNpTrophyUnlockTrophy(context, handle, 2, &platinum) == InvalidTrophyId, "unlock a trophy past the count"); Require(sceNpTrophyUnlockTrophy(context, handle, 1, &platinum) == 0 && platinum == -1, "unlock trophy 1"); Require(sceNpTrophyUnlockTrophy(context, handle, 1, &platinum) == AlreadyUnlocked, "unlock trophy 1 twice"); - Require(sceNpTrophyGetTrophyUnlockState(context, handle, flags, &count) == 0 && flags[0] == 2u, "trophy 1 unlocked"); + Require(sceNpTrophyGetTrophyUnlockState(context, handle, reinterpret_cast(flags), &count) == 0 && flags[0] == 2u, "trophy 1 unlocked"); size = sizeof(icon); Require(sceNpTrophyGetTrophyIcon(context, handle, 1, icon, &size) == 0 && size == 6 && std::memcmp(icon, "second", 6) == 0, "icon of the unlocked trophy"); int saved = -1; diff --git a/core/libs/tests/GuestNpTrophy2.cpp b/core/libs/tests/GuestNpTrophy2.cpp index 27e80b54a4..2dcaa5f409 100644 --- a/core/libs/tests/GuestNpTrophy2.cpp +++ b/core/libs/tests/GuestNpTrophy2.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNpTrophy2/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libSceNpTrophy2/include/NpTrophy2Constants.hpp" #include "prx/libSceNpTrophy2/include/NpTrophy2Types.hpp" @@ -5,16 +6,6 @@ #include #include -extern "C" { -int APS5_VABI sceNpTrophy2RegisterUnlockCallback(void*, void*); -int APS5_VABI sceNpTrophy2UnregisterUnlockCallback(); -int APS5_VABI sceNpTrophy2GetGameInfo(int, int, NpTrophy2GameDetails*, NpTrophy2GameData*); -int APS5_VABI sceNpTrophy2GetGroupInfo(int, int, int, NpTrophy2GroupDetails*, NpTrophy2GroupData*); -int APS5_VABI sceNpTrophy2GetTrophyInfo(int, int, int, NpTrophy2Details*, NpTrophy2Data*); -int APS5_VABI sceNpTrophy2ShowTrophyList(int); -int APS5_VABI sceNpTrophy2GetRewardIcon(int, int, int, void*, std::size_t*); -} - static void Require(bool value) { if (!value) std::abort(); } static void APS5_VABI OnUnlock(int, int, void*) {} diff --git a/core/libs/tests/GuestNpTrophyData.cpp b/core/libs/tests/GuestNpTrophyData.cpp index 8bf4e7ad00..6810f8a3da 100644 --- a/core/libs/tests/GuestNpTrophyData.cpp +++ b/core/libs/tests/GuestNpTrophyData.cpp @@ -1,3 +1,5 @@ +#include "prx/libSceNpUniversalDataSystem/include/Api.hpp" +#include "prx/libSceNpTrophy2/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libSceNpTrophy2/include/NpTrophy2Types.hpp" #include "prx/libSceNpTrophy2/include/TrophyStore.hpp" @@ -18,24 +20,6 @@ struct NpUniversalDataSystemEvent; struct NpUniversalDataSystemEventPropertyObject; -extern "C" { -int APS5_VABI sceNpUniversalDataSystemCreateContext(int*, int, uint32_t, uint64_t); -int APS5_VABI sceNpUniversalDataSystemRegisterContext(int, int, uint64_t); -int APS5_VABI sceNpUniversalDataSystemCreateHandle(int*); -int APS5_VABI sceNpUniversalDataSystemCreateEvent(const char*, const NpUniversalDataSystemEventPropertyObject*, NpUniversalDataSystemEvent**, NpUniversalDataSystemEventPropertyObject**); -int APS5_VABI sceNpUniversalDataSystemDestroyEvent(NpUniversalDataSystemEvent*); -int APS5_VABI sceNpUniversalDataSystemPostEvent(int, int, const void*, uint64_t); -int APS5_VABI sceNpUniversalDataSystemCreateEventPropertyObject(NpUniversalDataSystemEventPropertyObject**); -int APS5_VABI sceNpUniversalDataSystemDestroyEventPropertyObject(NpUniversalDataSystemEventPropertyObject*); -int APS5_VABI sceNpUniversalDataSystemEventPropertyObjectSetInt32(NpUniversalDataSystemEventPropertyObject*, const char*, int32_t); -int APS5_VABI sceNpTrophy2CreateContext(int*, int, uint32_t, uint64_t); -int APS5_VABI sceNpTrophy2GetGameInfo(int, int, NpTrophy2GameDetails*, NpTrophy2GameData*); -int APS5_VABI sceNpTrophy2GetGroupInfo(int, int, int, NpTrophy2GroupDetails*, NpTrophy2GroupData*); -int APS5_VABI sceNpTrophy2GetGroupInfoArray(int, int, uint32_t, uint32_t, NpTrophy2GroupDetails*, NpTrophy2GroupData*, uint32_t*); -int APS5_VABI sceNpTrophy2GetTrophyInfo(int, int, int, NpTrophy2Details*, NpTrophy2Data*); -int APS5_VABI sceNpTrophy2GetTrophyInfoArray(int, int, uint32_t, uint32_t, NpTrophy2Details*, NpTrophy2Data*, uint32_t*); -} - static constexpr int InitialUser = 0x10000000; static constexpr int InvalidTrophyId = static_cast(0x8055390Au); diff --git a/core/libs/tests/GuestNpTrophyStats.cpp b/core/libs/tests/GuestNpTrophyStats.cpp index a8e94f7516..0128a97160 100644 --- a/core/libs/tests/GuestNpTrophyStats.cpp +++ b/core/libs/tests/GuestNpTrophyStats.cpp @@ -1,3 +1,5 @@ +#include "prx/libSceNpUniversalDataSystem/include/Api.hpp" +#include "prx/libSceNpTrophy2/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libSceNpTrophy2/include/NpTrophy2Types.hpp" #include "prx/libSceNpTrophy2/include/TrophyStore.hpp" @@ -21,26 +23,6 @@ struct NpUniversalDataSystemEvent; struct NpUniversalDataSystemEventPropertyObject; -extern "C" { -int APS5_VABI sceNpUniversalDataSystemCreateContext(int*, int, uint32_t, uint64_t); -int APS5_VABI sceNpUniversalDataSystemRegisterContext(int, int, uint64_t); -int APS5_VABI sceNpUniversalDataSystemCreateHandle(int*); -int APS5_VABI sceNpUniversalDataSystemCreateEvent(const char*, const NpUniversalDataSystemEventPropertyObject*, NpUniversalDataSystemEvent**, NpUniversalDataSystemEventPropertyObject**); -int APS5_VABI sceNpUniversalDataSystemDestroyEvent(NpUniversalDataSystemEvent*); -int APS5_VABI sceNpUniversalDataSystemPostEvent(int, int, const void*, uint64_t); -int APS5_VABI sceNpUniversalDataSystemCreateEventPropertyObject(NpUniversalDataSystemEventPropertyObject**); -int APS5_VABI sceNpUniversalDataSystemDestroyEventPropertyObject(NpUniversalDataSystemEventPropertyObject*); -int APS5_VABI sceNpUniversalDataSystemEventPropertyObjectSetInt32(NpUniversalDataSystemEventPropertyObject*, const char*, int32_t); -int APS5_VABI sceNpUniversalDataSystemEventPropertyObjectSetUInt32(NpUniversalDataSystemEventPropertyObject*, const char*, uint32_t); -int APS5_VABI sceNpUniversalDataSystemEventPropertyObjectSetInt64(NpUniversalDataSystemEventPropertyObject*, const char*, int64_t); -int APS5_VABI sceNpUniversalDataSystemEventPropertyObjectSetUInt64(NpUniversalDataSystemEventPropertyObject*, const char*, uint64_t); -int APS5_VABI sceNpUniversalDataSystemEventPropertyObjectSetFloat32(NpUniversalDataSystemEventPropertyObject*, const char*, float); -int APS5_VABI sceNpUniversalDataSystemEventPropertyObjectSetObject(NpUniversalDataSystemEventPropertyObject*, const char*, const NpUniversalDataSystemEventPropertyObject*, NpUniversalDataSystemEventPropertyObject**); -int APS5_VABI sceNpTrophy2CreateContext(int*, int, uint32_t, uint64_t); -int APS5_VABI sceNpTrophy2GetGameInfo(int, int, NpTrophy2GameDetails*, NpTrophy2GameData*); -int APS5_VABI sceNpTrophy2GetTrophyInfo(int, int, int, NpTrophy2Details*, NpTrophy2Data*); -} - static constexpr int InitialUser = 0x10000000; static const char TropConf[] = R"({"defaultLanguage":"en-US","trophies":[ @@ -165,13 +147,13 @@ private: int saved = -1; }; -struct Uds { +struct UdsSession { int context = 0; int handle = 0; }; -static Uds OpenUds(std::uint32_t serviceLabel) { - Uds uds; +static UdsSession OpenUds(std::uint32_t serviceLabel) { + UdsSession uds; Require(sceNpUniversalDataSystemCreateContext(&uds.context, InitialUser, serviceLabel, 0) == 0, "UDS context was not created"); Require(sceNpUniversalDataSystemCreateHandle(&uds.handle) == 0, "UDS handle was not created"); Require(sceNpUniversalDataSystemRegisterContext(uds.context, uds.handle, 0) == 0, "UDS context was not registered"); @@ -179,7 +161,7 @@ static Uds OpenUds(std::uint32_t serviceLabel) { } template -static void Post(const Uds& uds, const char* name, TSet set) { +static void Post(const UdsSession& uds, const char* name, TSet set) { NpUniversalDataSystemEventPropertyObject* properties = nullptr; Require(sceNpUniversalDataSystemCreateEventPropertyObject(&properties) == 0, "property object was not created"); set(properties); diff --git a/core/libs/tests/GuestNpTrophyUnlocks.cpp b/core/libs/tests/GuestNpTrophyUnlocks.cpp index be3d6e2859..ba632255da 100644 --- a/core/libs/tests/GuestNpTrophyUnlocks.cpp +++ b/core/libs/tests/GuestNpTrophyUnlocks.cpp @@ -1,3 +1,5 @@ +#include "prx/libSceNpUniversalDataSystem/include/Api.hpp" +#include "prx/libSceNpTrophy2/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libSceNpTrophy2/include/NpTrophy2Types.hpp" @@ -12,21 +14,6 @@ struct NpUniversalDataSystemEvent; struct NpUniversalDataSystemEventPropertyObject; -extern "C" { -int APS5_VABI sceNpUniversalDataSystemCreateContext(int*, int, uint32_t, uint64_t); -int APS5_VABI sceNpUniversalDataSystemRegisterContext(int, int, uint64_t); -int APS5_VABI sceNpUniversalDataSystemCreateHandle(int*); -int APS5_VABI sceNpUniversalDataSystemCreateEvent(const char*, const NpUniversalDataSystemEventPropertyObject*, NpUniversalDataSystemEvent**, NpUniversalDataSystemEventPropertyObject**); -int APS5_VABI sceNpUniversalDataSystemDestroyEvent(NpUniversalDataSystemEvent*); -int APS5_VABI sceNpUniversalDataSystemPostEvent(int, int, const void*, uint64_t); -int APS5_VABI sceNpUniversalDataSystemCreateEventPropertyObject(NpUniversalDataSystemEventPropertyObject**); -int APS5_VABI sceNpUniversalDataSystemDestroyEventPropertyObject(NpUniversalDataSystemEventPropertyObject*); -int APS5_VABI sceNpUniversalDataSystemEventPropertyObjectSetInt32(NpUniversalDataSystemEventPropertyObject*, const char*, int32_t); -int APS5_VABI sceNpTrophy2CreateContext(int*, int, uint32_t, uint64_t); -int APS5_VABI sceNpTrophy2GetGameInfo(int, int, NpTrophy2GameDetails*, NpTrophy2GameData*); -int APS5_VABI sceNpTrophy2GetTrophyInfo(int, int, int, NpTrophy2Details*, NpTrophy2Data*); -} - static constexpr int InitialUser = 0x10000000; static void Require(bool value, const char* message) { diff --git a/core/libs/tests/GuestNpTus.cpp b/core/libs/tests/GuestNpTus.cpp index d252efcfaa..b80d87fa8b 100644 --- a/core/libs/tests/GuestNpTus.cpp +++ b/core/libs/tests/GuestNpTus.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNpTus/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "SceTypes.hpp" #include @@ -5,39 +6,6 @@ #include #include -extern "C" { -int APS5_VABI sceNpTusCreateNpTitleCtxA(std::uint32_t serviceLabel, int userId); -int APS5_VABI sceNpTusDeleteNpTitleCtx(int titleCtxId); -int APS5_VABI sceNpTssCreateNpTitleCtx(std::uint32_t serviceLabel, const NpId* npId); -int APS5_VABI sceNpTssCreateNpTitleCtxA(std::uint32_t serviceLabel, int userId); -int APS5_VABI sceNpTusCreateRequest(int titleCtxId); -int APS5_VABI sceNpTusDeleteRequest(int reqId); -int APS5_VABI sceNpTusAbortRequest(int reqId); -int APS5_VABI sceNpTusPollAsync(int reqId, int* result); -int APS5_VABI sceNpTusGetMultiSlotVariableAAsync(int reqId, std::uint64_t targetAccountId, const std::int32_t* slotIds, void* variableArray, std::uint64_t variableArraySize, int arrayLen, void* option); -int APS5_VABI sceNpTusSetMultiSlotVariableAAsync(int reqId, std::uint64_t targetAccountId, const std::int32_t* slotIds, const std::int64_t* variableArray, int arrayLen, void* option); -int APS5_VABI sceNpTusDeleteMultiSlotVariableAAsync(int reqId, std::uint64_t targetAccountId, const std::int32_t* slotIds, int arrayLen, void* option); -int APS5_VABI sceNpTusAddAndGetVariableAAsync(int reqId, std::uint64_t targetAccountId, std::int32_t slotId, std::int64_t inVariable, const std::uint64_t* isLastChangedAuthor, const void* isLastChangedDate, void* outVariable, std::uint64_t outVariableSize, void* option); -int APS5_VABI sceNpTusWaitAsync(int reqId, int* result); -int APS5_VABI sceNpTusGetMultiSlotVariableA(int reqId, std::uint64_t targetAccountId, const std::int32_t* slotIds, void* variableArray, std::uint64_t variableArraySize, int arrayLen, void* option); -int APS5_VABI sceNpTusGetMultiSlotVariableAsync(int reqId, const void* targetNpId, const std::int32_t* slotIds, void* variableArray, std::uint64_t variableArraySize, int arrayLen, void* option); -int APS5_VABI sceNpTusGetMultiSlotVariableVUserAsync(int reqId, const NpOnlineId* targetVirtualUserId, const std::int32_t* slotIds, void* variableArray, std::uint64_t variableArraySize, int arrayLen, void* option); -int APS5_VABI sceNpTusGetMultiSlotVariableAVUserAsync(int reqId, const NpOnlineId* targetVirtualUserId, const std::int32_t* slotIds, void* variableArray, std::uint64_t variableArraySize, int arrayLen, void* option); -int APS5_VABI sceNpTusGetMultiSlotVariableAVUser(int reqId, const NpOnlineId* targetVirtualUserId, const std::int32_t* slotIds, void* variableArray, std::uint64_t variableArraySize, int arrayLen, void* option); -int APS5_VABI sceNpTusGetMultiSlotVariableForCrossSaveAsync(int reqId, std::uint64_t targetAccountId, const std::int32_t* slotIds, void* variableArray, std::uint64_t variableArraySize, int arrayLen, void* option); -int APS5_VABI sceNpTusGetMultiSlotVariableForCrossSave(int reqId, std::uint64_t targetAccountId, const std::int32_t* slotIds, void* variableArray, std::uint64_t variableArraySize, int arrayLen, void* option); -int APS5_VABI sceNpTusGetMultiSlotVariableForCrossSaveVUserAsync(int reqId, const NpOnlineId* targetVirtualUserId, const std::int32_t* slotIds, void* variableArray, std::uint64_t variableArraySize, int arrayLen, void* option); -int APS5_VABI sceNpTusGetMultiSlotVariableForCrossSaveVUser(int reqId, const NpOnlineId* targetVirtualUserId, const std::int32_t* slotIds, void* variableArray, std::uint64_t variableArraySize, int arrayLen, void* option); -int APS5_VABI sceNpTusSetMultiSlotVariableA(int reqId, std::uint64_t targetAccountId, const std::int32_t* slotIds, const std::int64_t* variableArray, int arrayLen, void* option); -int APS5_VABI sceNpTusSetMultiSlotVariableAsync(int reqId, const void* targetNpId, const std::int32_t* slotIds, const std::int64_t* variableArray, int arrayLen, void* option); -int APS5_VABI sceNpTusSetMultiSlotVariableVUserAsync(int reqId, const NpOnlineId* targetVirtualUserId, const std::int32_t* slotIds, const std::int64_t* variableArray, int arrayLen, void* option); -int APS5_VABI sceNpTusDeleteMultiSlotVariableA(int reqId, std::uint64_t targetAccountId, const std::int32_t* slotIds, int arrayLen, void* option); -int APS5_VABI sceNpTusDeleteMultiSlotVariableAsync(int reqId, const void* targetNpId, const std::int32_t* slotIds, int arrayLen, void* option); -int APS5_VABI sceNpTusDeleteMultiSlotVariable(int reqId, const void* targetNpId, const std::int32_t* slotIds, int arrayLen, void* option); -int APS5_VABI sceNpTusDeleteMultiSlotVariableVUserAsync(int reqId, const NpOnlineId* targetVirtualUserId, const std::int32_t* slotIds, int arrayLen, void* option); -int APS5_VABI sceNpTusDeleteMultiSlotVariableVUser(int reqId, const NpOnlineId* targetVirtualUserId, const std::int32_t* slotIds, int arrayLen, void* option); -} - static constexpr int SIGNED_OUT = static_cast(0x80550006); static constexpr int INVALID_ARGUMENT = static_cast(0x80550704); static constexpr int TOO_MANY_OBJECTS = static_cast(0x80550706); diff --git a/core/libs/tests/GuestNpTusOffline.cpp b/core/libs/tests/GuestNpTusOffline.cpp index af24d244c8..565dcceaa4 100644 --- a/core/libs/tests/GuestNpTusOffline.cpp +++ b/core/libs/tests/GuestNpTusOffline.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNpTus/include/Api.hpp" #include "SceTypes.hpp" #include #include @@ -5,95 +6,6 @@ #include #include -extern "C" { -int APS5_VABI sceNpTusCreateNpTitleCtxA(std::uint32_t, int); -int APS5_VABI sceNpTusCreateRequest(int); -int APS5_VABI sceNpTusDeleteRequest(int); -int APS5_VABI sceNpTusWaitAsync(int, int*); -int APS5_VABI sceNpTssGetSmallStorage(int reqId, void* data, std::uint64_t maxSize, std::uint64_t* contentLength, void* option); -int APS5_VABI sceNpTssGetSmallStorageAsync(int reqId, void* data, std::uint64_t maxSize, std::uint64_t* contentLength, void* option); -int APS5_VABI sceNpTusAddAndGetVariable(int reqId, const void* targetNpId, std::int32_t slotId, std::int64_t inVariable, const void* isLastChangedAuthor, const void* isLastChangedDate, void* outVariable, std::uint64_t outVariableSize, void* option); -int APS5_VABI sceNpTusAddAndGetVariableA(int reqId, std::uint64_t targetAccountId, std::int32_t slotId, std::int64_t inVariable, const std::uint64_t* isLastChangedAuthor, const void* isLastChangedDate, void* outVariable, std::uint64_t outVariableSize, void* option); -int APS5_VABI sceNpTusAddAndGetVariableAVUser(int reqId, const NpOnlineId* targetVirtualUserId, std::int32_t slotId, std::int64_t inVariable, const std::uint64_t* isLastChangedAuthor, const void* isLastChangedDate, void* outVariable, std::uint64_t outVariableSize, void* option); -int APS5_VABI sceNpTusAddAndGetVariableAVUserAsync(int reqId, const NpOnlineId* targetVirtualUserId, std::int32_t slotId, std::int64_t inVariable, const std::uint64_t* isLastChangedAuthor, const void* isLastChangedDate, void* outVariable, std::uint64_t outVariableSize, void* option); -int APS5_VABI sceNpTusAddAndGetVariableAsync(int reqId, const void* targetNpId, std::int32_t slotId, std::int64_t inVariable, const void* isLastChangedAuthor, const void* isLastChangedDate, void* outVariable, std::uint64_t outVariableSize, void* option); -int APS5_VABI sceNpTusAddAndGetVariableForCrossSave(int reqId, std::uint64_t targetAccountId, std::int32_t slotId, std::int64_t inVariable, const std::uint64_t* isLastChangedAuthor, const void* isLastChangedDate, void* outVariable, std::uint64_t outVariableSize, void* option); -int APS5_VABI sceNpTusAddAndGetVariableForCrossSaveAsync(int reqId, std::uint64_t targetAccountId, std::int32_t slotId, std::int64_t inVariable, const std::uint64_t* isLastChangedAuthor, const void* isLastChangedDate, void* outVariable, std::uint64_t outVariableSize, void* option); -int APS5_VABI sceNpTusAddAndGetVariableForCrossSaveVUser(int reqId, const NpOnlineId* targetVirtualUserId, std::int32_t slotId, std::int64_t inVariable, const std::uint64_t* isLastChangedAuthor, const void* isLastChangedDate, void* outVariable, std::uint64_t outVariableSize, void* option); -int APS5_VABI sceNpTusAddAndGetVariableForCrossSaveVUserAsync(int reqId, const NpOnlineId* targetVirtualUserId, std::int32_t slotId, std::int64_t inVariable, const std::uint64_t* isLastChangedAuthor, const void* isLastChangedDate, void* outVariable, std::uint64_t outVariableSize, void* option); -int APS5_VABI sceNpTusAddAndGetVariableVUser(int reqId, const NpOnlineId* targetVirtualUserId, std::int32_t slotId, std::int64_t inVariable, const void* isLastChangedAuthor, const void* isLastChangedDate, void* outVariable, std::uint64_t outVariableSize, void* option); -int APS5_VABI sceNpTusAddAndGetVariableVUserAsync(int reqId, const NpOnlineId* targetVirtualUserId, std::int32_t slotId, std::int64_t inVariable, const void* isLastChangedAuthor, const void* isLastChangedDate, void* outVariable, std::uint64_t outVariableSize, void* option); -int APS5_VABI sceNpTusDeleteMultiSlotData(int reqId, const void* targetNpId, const std::int32_t* slotIds, int arrayLen, void* option); -int APS5_VABI sceNpTusDeleteMultiSlotDataA(int reqId, std::uint64_t targetAccountId, const std::int32_t* slotIds, int arrayLen, void* option); -int APS5_VABI sceNpTusDeleteMultiSlotDataAAsync(int reqId, std::uint64_t targetAccountId, const std::int32_t* slotIds, int arrayLen, void* option); -int APS5_VABI sceNpTusDeleteMultiSlotDataAsync(int reqId, const void* targetNpId, const std::int32_t* slotIds, int arrayLen, void* option); -int APS5_VABI sceNpTusGetDataA(int reqId, std::uint64_t targetAccountId, std::int32_t slotId, void* dataStatus, std::uint64_t dataStatusSize, void* data, std::uint64_t recvSize, void* option); -int APS5_VABI sceNpTusGetDataAAsync(int reqId, std::uint64_t targetAccountId, std::int32_t slotId, void* dataStatus, std::uint64_t dataStatusSize, void* data, std::uint64_t recvSize, void* option); -int APS5_VABI sceNpTusGetDataAVUser(int reqId, const NpOnlineId* targetVirtualUserId, std::int32_t slotId, void* dataStatus, std::uint64_t dataStatusSize, void* data, std::uint64_t recvSize, void* option); -int APS5_VABI sceNpTusGetDataAVUserAsync(int reqId, const NpOnlineId* targetVirtualUserId, std::int32_t slotId, void* dataStatus, std::uint64_t dataStatusSize, void* data, std::uint64_t recvSize, void* option); -int APS5_VABI sceNpTusGetDataAsync(int reqId, const void* targetNpId, std::int32_t slotId, void* dataStatus, std::uint64_t dataStatusSize, void* data, std::uint64_t recvSize, void* option); -int APS5_VABI sceNpTusGetDataForCrossSave(int reqId, std::uint64_t targetAccountId, std::int32_t slotId, void* dataStatus, std::uint64_t dataStatusSize, void* data, std::uint64_t recvSize, void* option); -int APS5_VABI sceNpTusGetDataForCrossSaveAsync(int reqId, std::uint64_t targetAccountId, std::int32_t slotId, void* dataStatus, std::uint64_t dataStatusSize, void* data, std::uint64_t recvSize, void* option); -int APS5_VABI sceNpTusGetDataVUserAsync(int reqId, const NpOnlineId* targetVirtualUserId, std::int32_t slotId, void* dataStatus, std::uint64_t dataStatusSize, void* data, std::uint64_t recvSize, void* option); -int APS5_VABI sceNpTusGetFriendsDataStatus(int reqId, std::int32_t slotId, std::int32_t includeSelf, std::int32_t sortType, void* statusArray, std::uint64_t statusArraySize, int arrayLen, void* option); -int APS5_VABI sceNpTusGetFriendsDataStatusAsync(int reqId, std::int32_t slotId, std::int32_t includeSelf, std::int32_t sortType, void* statusArray, std::uint64_t statusArraySize, int arrayLen, void* option); -int APS5_VABI sceNpTusGetFriendsVariable(int reqId, std::int32_t slotId, std::int32_t includeSelf, std::int32_t sortType, void* variableArray, std::uint64_t variableArraySize, int arrayLen, void* option); -int APS5_VABI sceNpTusGetFriendsVariableAsync(int reqId, std::int32_t slotId, std::int32_t includeSelf, std::int32_t sortType, void* variableArray, std::uint64_t variableArraySize, int arrayLen, void* option); -int APS5_VABI sceNpTusGetMultiSlotDataStatus(int reqId, const void* targetNpId, const std::int32_t* slotIds, void* statusArray, std::uint64_t statusArraySize, int arrayLen, void* option); -int APS5_VABI sceNpTusGetMultiSlotDataStatusA(int reqId, std::uint64_t targetAccountId, const std::int32_t* slotIds, void* statusArray, std::uint64_t statusArraySize, int arrayLen, void* option); -int APS5_VABI sceNpTusGetMultiSlotDataStatusAAsync(int reqId, std::uint64_t targetAccountId, const std::int32_t* slotIds, void* statusArray, std::uint64_t statusArraySize, int arrayLen, void* option); -int APS5_VABI sceNpTusGetMultiSlotDataStatusAVUser(int reqId, const NpOnlineId* targetVirtualUserId, const std::int32_t* slotIds, void* statusArray, std::uint64_t statusArraySize, int arrayLen, void* option); -int APS5_VABI sceNpTusGetMultiSlotDataStatusAVUserAsync(int reqId, const NpOnlineId* targetVirtualUserId, const std::int32_t* slotIds, void* statusArray, std::uint64_t statusArraySize, int arrayLen, void* option); -int APS5_VABI sceNpTusGetMultiSlotDataStatusAsync(int reqId, const void* targetNpId, const std::int32_t* slotIds, void* statusArray, std::uint64_t statusArraySize, int arrayLen, void* option); -int APS5_VABI sceNpTusGetMultiSlotDataStatusForCrossSave(int reqId, std::uint64_t targetAccountId, const std::int32_t* slotIds, void* statusArray, std::uint64_t statusArraySize, int arrayLen, void* option); -int APS5_VABI sceNpTusGetMultiSlotDataStatusForCrossSaveAsync(int reqId, std::uint64_t targetAccountId, const std::int32_t* slotIds, void* statusArray, std::uint64_t statusArraySize, int arrayLen, void* option); -int APS5_VABI sceNpTusGetMultiSlotDataStatusForCrossSaveVUser(int reqId, const NpOnlineId* targetVirtualUserId, const std::int32_t* slotIds, void* statusArray, std::uint64_t statusArraySize, int arrayLen, void* option); -int APS5_VABI sceNpTusGetMultiSlotDataStatusForCrossSaveVUserAsync(int reqId, const NpOnlineId* targetVirtualUserId, const std::int32_t* slotIds, void* statusArray, std::uint64_t statusArraySize, int arrayLen, void* option); -int APS5_VABI sceNpTusGetMultiSlotDataStatusVUser(int reqId, const NpOnlineId* targetVirtualUserId, const std::int32_t* slotIds, void* statusArray, std::uint64_t statusArraySize, int arrayLen, void* option); -int APS5_VABI sceNpTusGetMultiSlotDataStatusVUserAsync(int reqId, const NpOnlineId* targetVirtualUserId, const std::int32_t* slotIds, void* statusArray, std::uint64_t statusArraySize, int arrayLen, void* option); -int APS5_VABI sceNpTusGetMultiUserDataStatus(int reqId, const void* targetNpIdArray, std::int32_t slotId, void* statusArray, std::uint64_t statusArraySize, int arrayLen, void* option); -int APS5_VABI sceNpTusGetMultiUserDataStatusA(int reqId, const std::uint64_t* targetAccountIdArray, std::int32_t slotId, void* statusArray, std::uint64_t statusArraySize, int arrayLen, void* option); -int APS5_VABI sceNpTusGetMultiUserDataStatusAAsync(int reqId, const std::uint64_t* targetAccountIdArray, std::int32_t slotId, void* statusArray, std::uint64_t statusArraySize, int arrayLen, void* option); -int APS5_VABI sceNpTusGetMultiUserDataStatusAVUser(int reqId, const NpOnlineId* targetVirtualUserIdArray, std::int32_t slotId, void* statusArray, std::uint64_t statusArraySize, int arrayLen, void* option); -int APS5_VABI sceNpTusGetMultiUserDataStatusAVUserAsync(int reqId, const NpOnlineId* targetVirtualUserIdArray, std::int32_t slotId, void* statusArray, std::uint64_t statusArraySize, int arrayLen, void* option); -int APS5_VABI sceNpTusGetMultiUserDataStatusAsync(int reqId, const void* targetNpIdArray, std::int32_t slotId, void* statusArray, std::uint64_t statusArraySize, int arrayLen, void* option); -int APS5_VABI sceNpTusGetMultiUserDataStatusForCrossSave(int reqId, const std::uint64_t* targetAccountIdArray, std::int32_t slotId, void* statusArray, std::uint64_t statusArraySize, int arrayLen, void* option); -int APS5_VABI sceNpTusGetMultiUserDataStatusForCrossSaveAsync(int reqId, const std::uint64_t* targetAccountIdArray, std::int32_t slotId, void* statusArray, std::uint64_t statusArraySize, int arrayLen, void* option); -int APS5_VABI sceNpTusGetMultiUserDataStatusForCrossSaveVUser(int reqId, const NpOnlineId* targetVirtualUserIdArray, std::int32_t slotId, void* statusArray, std::uint64_t statusArraySize, int arrayLen, void* option); -int APS5_VABI sceNpTusGetMultiUserDataStatusForCrossSaveVUserAsync(int reqId, const NpOnlineId* targetVirtualUserIdArray, std::int32_t slotId, void* statusArray, std::uint64_t statusArraySize, int arrayLen, void* option); -int APS5_VABI sceNpTusGetMultiUserDataStatusVUser(int reqId, const NpOnlineId* targetVirtualUserIdArray, std::int32_t slotId, void* statusArray, std::uint64_t statusArraySize, int arrayLen, void* option); -int APS5_VABI sceNpTusGetMultiUserDataStatusVUserAsync(int reqId, const NpOnlineId* targetVirtualUserIdArray, std::int32_t slotId, void* statusArray, std::uint64_t statusArraySize, int arrayLen, void* option); -int APS5_VABI sceNpTusGetMultiUserVariable(int reqId, const void* targetNpIdArray, std::int32_t slotId, void* variableArray, std::uint64_t variableArraySize, int arrayLen, void* option); -int APS5_VABI sceNpTusGetMultiUserVariableA(int reqId, const std::uint64_t* targetAccountIdArray, std::int32_t slotId, void* variableArray, std::uint64_t variableArraySize, int arrayLen, void* option); -int APS5_VABI sceNpTusGetMultiUserVariableAAsync(int reqId, const std::uint64_t* targetAccountIdArray, std::int32_t slotId, void* variableArray, std::uint64_t variableArraySize, int arrayLen, void* option); -int APS5_VABI sceNpTusGetMultiUserVariableAVUser(int reqId, const NpOnlineId* targetVirtualUserIdArray, std::int32_t slotId, void* variableArray, std::uint64_t variableArraySize, int arrayLen, void* option); -int APS5_VABI sceNpTusGetMultiUserVariableAVUserAsync(int reqId, const NpOnlineId* targetVirtualUserIdArray, std::int32_t slotId, void* variableArray, std::uint64_t variableArraySize, int arrayLen, void* option); -int APS5_VABI sceNpTusGetMultiUserVariableAsync(int reqId, const void* targetNpIdArray, std::int32_t slotId, void* variableArray, std::uint64_t variableArraySize, int arrayLen, void* option); -int APS5_VABI sceNpTusGetMultiUserVariableForCrossSaveAsync(int reqId, const std::uint64_t* targetAccountIdArray, std::int32_t slotId, void* variableArray, std::uint64_t variableArraySize, int arrayLen, void* option); -int APS5_VABI sceNpTusGetMultiUserVariableForCrossSaveVUser(int reqId, const NpOnlineId* targetVirtualUserIdArray, std::int32_t slotId, void* variableArray, std::uint64_t variableArraySize, int arrayLen, void* option); -int APS5_VABI sceNpTusGetMultiUserVariableForCrossSaveVUserAsync(int reqId, const NpOnlineId* targetVirtualUserIdArray, std::int32_t slotId, void* variableArray, std::uint64_t variableArraySize, int arrayLen, void* option); -int APS5_VABI sceNpTusGetMultiUserVariableVUser(int reqId, const NpOnlineId* targetVirtualUserIdArray, std::int32_t slotId, void* variableArray, std::uint64_t variableArraySize, int arrayLen, void* option); -int APS5_VABI sceNpTusGetMultiUserVariableVUserAsync(int reqId, const NpOnlineId* targetVirtualUserIdArray, std::int32_t slotId, void* variableArray, std::uint64_t variableArraySize, int arrayLen, void* option); -int APS5_VABI sceNpTusSetDataA(int reqId, std::uint64_t targetAccountId, std::int32_t slotId, std::uint64_t totalSize, std::uint64_t sendSize, const void* data, const void* info, std::uint64_t infoStructSize, const std::uint64_t* isLastChangedAuthor, const void* isLastChangedDate, void* option); -int APS5_VABI sceNpTusSetDataAAsync(int reqId, std::uint64_t targetAccountId, std::int32_t slotId, std::uint64_t totalSize, std::uint64_t sendSize, const void* data, const void* info, std::uint64_t infoStructSize, const std::uint64_t* isLastChangedAuthor, const void* isLastChangedDate, void* option); -int APS5_VABI sceNpTusSetDataAVUser(int reqId, const NpOnlineId* targetVirtualUserId, std::int32_t slotId, std::uint64_t totalSize, std::uint64_t sendSize, const void* data, const void* info, std::uint64_t infoStructSize, const std::uint64_t* isLastChangedAuthor, const void* isLastChangedDate, void* option); -int APS5_VABI sceNpTusSetDataAVUserAsync(int reqId, const NpOnlineId* targetVirtualUserId, std::int32_t slotId, std::uint64_t totalSize, std::uint64_t sendSize, const void* data, const void* info, std::uint64_t infoStructSize, const std::uint64_t* isLastChangedAuthor, const void* isLastChangedDate, void* option); -int APS5_VABI sceNpTusSetDataAsync(int reqId, const void* targetNpId, std::int32_t slotId, std::uint64_t totalSize, std::uint64_t sendSize, const void* data, const void* info, std::uint64_t infoStructSize, const void* isLastChangedAuthor, const void* isLastChangedDate, void* option); -int APS5_VABI sceNpTusSetDataVUserAsync(int reqId, const NpOnlineId* targetVirtualUserId, std::int32_t slotId, std::uint64_t totalSize, std::uint64_t sendSize, const void* data, const void* info, std::uint64_t infoStructSize, const void* isLastChangedAuthor, const void* isLastChangedDate, void* option); -int APS5_VABI sceNpTusTryAndSetVariable(int reqId, const void* targetNpId, std::int32_t slotId, std::int32_t opeType, std::int64_t variable, const std::int64_t* compareValue, const void* isLastChangedAuthor, const void* isLastChangedDate, void* resultVariable, std::uint64_t resultVariableSize, void* option); -int APS5_VABI sceNpTusTryAndSetVariableA(int reqId, std::uint64_t targetAccountId, std::int32_t slotId, std::int32_t opeType, std::int64_t variable, const std::int64_t* compareValue, const std::uint64_t* isLastChangedAuthor, const void* isLastChangedDate, void* resultVariable, std::uint64_t resultVariableSize, void* option); -int APS5_VABI sceNpTusTryAndSetVariableAAsync(int reqId, std::uint64_t targetAccountId, std::int32_t slotId, std::int32_t opeType, std::int64_t variable, const std::int64_t* compareValue, const std::uint64_t* isLastChangedAuthor, const void* isLastChangedDate, void* resultVariable, std::uint64_t resultVariableSize, void* option); -int APS5_VABI sceNpTusTryAndSetVariableAVUser(int reqId, const NpOnlineId* targetVirtualUserId, std::int32_t slotId, std::int32_t opeType, std::int64_t variable, const std::int64_t* compareValue, const std::uint64_t* isLastChangedAuthor, const void* isLastChangedDate, void* resultVariable, std::uint64_t resultVariableSize, void* option); -int APS5_VABI sceNpTusTryAndSetVariableAVUserAsync(int reqId, const NpOnlineId* targetVirtualUserId, std::int32_t slotId, std::int32_t opeType, std::int64_t variable, const std::int64_t* compareValue, const std::uint64_t* isLastChangedAuthor, const void* isLastChangedDate, void* resultVariable, std::uint64_t resultVariableSize, void* option); -int APS5_VABI sceNpTusTryAndSetVariableAsync(int reqId, const void* targetNpId, std::int32_t slotId, std::int32_t opeType, std::int64_t variable, const std::int64_t* compareValue, const void* isLastChangedAuthor, const void* isLastChangedDate, void* resultVariable, std::uint64_t resultVariableSize, void* option); -int APS5_VABI sceNpTusTryAndSetVariableForCrossSave(int reqId, std::uint64_t targetAccountId, std::int32_t slotId, std::int32_t opeType, std::int64_t variable, const std::int64_t* compareValue, const std::uint64_t* isLastChangedAuthor, const void* isLastChangedDate, void* resultVariable, std::uint64_t resultVariableSize, void* option); -int APS5_VABI sceNpTusTryAndSetVariableForCrossSaveAsync(int reqId, std::uint64_t targetAccountId, std::int32_t slotId, std::int32_t opeType, std::int64_t variable, const std::int64_t* compareValue, const std::uint64_t* isLastChangedAuthor, const void* isLastChangedDate, void* resultVariable, std::uint64_t resultVariableSize, void* option); -int APS5_VABI sceNpTusTryAndSetVariableForCrossSaveVUser(int reqId, const NpOnlineId* targetVirtualUserId, std::int32_t slotId, std::int32_t opeType, std::int64_t variable, const std::int64_t* compareValue, const std::uint64_t* isLastChangedAuthor, const void* isLastChangedDate, void* resultVariable, std::uint64_t resultVariableSize, void* option); -int APS5_VABI sceNpTusTryAndSetVariableForCrossSaveVUserAsync(int reqId, const NpOnlineId* targetVirtualUserId, std::int32_t slotId, std::int32_t opeType, std::int64_t variable, const std::int64_t* compareValue, const std::uint64_t* isLastChangedAuthor, const void* isLastChangedDate, void* resultVariable, std::uint64_t resultVariableSize, void* option); -int APS5_VABI sceNpTusTryAndSetVariableVUser(int reqId, const NpOnlineId* targetVirtualUserId, std::int32_t slotId, std::int32_t opeType, std::int64_t variable, const std::int64_t* compareValue, const void* isLastChangedAuthor, const void* isLastChangedDate, void* resultVariable, std::uint64_t resultVariableSize, void* option); -int APS5_VABI sceNpTusTryAndSetVariableVUserAsync(int reqId, const NpOnlineId* targetVirtualUserId, std::int32_t slotId, std::int32_t opeType, std::int64_t variable, const std::int64_t* compareValue, const void* isLastChangedAuthor, const void* isLastChangedDate, void* resultVariable, std::uint64_t resultVariableSize, void* option); -} - namespace { constexpr int SignedOut = static_cast(0x80550006u); @@ -137,11 +49,13 @@ void CheckAsync(const char* name, const std::function& valid, const st int result = 0; Require(sceNpTusWaitAsync(req, &result) == 0 && result == SignedOut, name, "the request did not finish signed out"); sceNpTusDeleteRequest(req); + Require(unknownRequest() == InvalidId, name, "an unknown request was not refused with INVALID_ID"); if (withOption) { req = NewRequest(); Require(withOption(req) == InvalidArgument, name, "a non-null option was not refused with INVALID_ARGUMENT"); sceNpTusDeleteRequest(req); + } } @@ -149,6 +63,7 @@ void CheckSync(const char* name, const std::function& call) { const int req = NewRequest(); Require(call(req) == SignedOut, name, "the synchronous call did not return SIGNED_OUT"); sceNpTusDeleteRequest(req); + } } @@ -261,6 +176,7 @@ int main() { Require(sceNpTusGetFriendsVariableAsync(req, 1, 0, 5, buffer, sizeof(buffer), 2, nullptr) == InvalidArgument, "sceNpTusGetFriendsVariableAsync", "sort type 5 was taken"); Require(sceNpTusGetFriendsVariableAsync(req, 1, 0, 1, buffer, sizeof(buffer), 101, nullptr) == TooManyNpId, "sceNpTusGetFriendsVariableAsync", "101 friends were taken"); sceNpTusDeleteRequest(req); + } if (failures != 0) return 1; std::puts("NpTus offline request tests passed"); diff --git a/core/libs/tests/GuestNpUtilityOffline.cpp b/core/libs/tests/GuestNpUtilityOffline.cpp index 08cd2b84e2..42c76ec96c 100644 --- a/core/libs/tests/GuestNpUtilityOffline.cpp +++ b/core/libs/tests/GuestNpUtilityOffline.cpp @@ -1,25 +1,9 @@ +#include "prx/libSceNpUtility/include/Api.hpp" #include "SceTypes.hpp" #include #include #include -extern "C" { -int APS5_VABI sceNpLookupCreateTitleCtx(const void* selfNpId); -int APS5_VABI sceNpLookupDeleteTitleCtx(int titleCtxId); -int APS5_VABI sceNpLookupCreateRequest(int titleCtxId); -int APS5_VABI sceNpLookupDeleteRequest(int reqId); -int APS5_VABI sceNpLookupNpId(int reqId, const NpOnlineId* onlineId, void* npId, void* option); -int APS5_VABI sceNpWordFilterCreateTitleCtx(const void* selfNpId); -int APS5_VABI sceNpWordFilterDeleteTitleCtx(int titleCtxId); -int APS5_VABI sceNpWordFilterCreateRequest(int titleCtxId); -int APS5_VABI sceNpWordFilterCreateAsyncRequest(int titleCtxId, const std::uint64_t* param); -int APS5_VABI sceNpWordFilterDeleteRequest(int reqId); -int APS5_VABI sceNpWordFilterAbortRequest(int reqId); -int APS5_VABI sceNpWordFilterPollAsync(int reqId, int* result); -int APS5_VABI sceNpWordFilterCensorComment(int reqId, const char* comment, void* option); -int APS5_VABI sceNpWordFilterSanitizeComment(int reqId, const char* comment, char* sanitizedComment, void* option); -} - namespace { constexpr int SignedOut = static_cast(0x80550006u); diff --git a/core/libs/tests/GuestNpWebApi.cpp b/core/libs/tests/GuestNpWebApi.cpp index 9281e58632..55fc787258 100644 --- a/core/libs/tests/GuestNpWebApi.cpp +++ b/core/libs/tests/GuestNpWebApi.cpp @@ -1,19 +1,9 @@ +#include "prx/libSceNpWebApi/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include #include -extern "C" { -int APS5_VABI sceNpWebApiInitialize(int libHttpCtxId, std::size_t poolSize); -int APS5_VABI sceNpWebApiTerminate(int libCtxId); -int APS5_VABI sceNpWebApiCreateHandle(int libCtxId); -int APS5_VABI sceNpWebApiDeleteHandle(int libCtxId, int handleId); -int APS5_VABI sceNpWebApiCreatePushEventFilter(int libCtxId, const void* filterParam, std::size_t filterParamNum); -int APS5_VABI sceNpWebApiDeletePushEventFilter(int libCtxId, int filterId); -int APS5_VABI sceNpWebApiCreateServicePushEventFilter(int libCtxId, int handleId, const char* npServiceName, unsigned npServiceLabel, const void* filterParam, std::size_t filterParamNum); -int APS5_VABI sceNpWebApiDeleteServicePushEventFilter(int libCtxId, int filterId); -} - namespace { constexpr int InvalidArgument = static_cast(0x80552902u); diff --git a/core/libs/tests/GuestNpWebApi2.cpp b/core/libs/tests/GuestNpWebApi2.cpp index 1adccd989d..6144dccf18 100644 --- a/core/libs/tests/GuestNpWebApi2.cpp +++ b/core/libs/tests/GuestNpWebApi2.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceNpWebApi2/include/Api.hpp" #include "SceTypes.hpp" #include #include @@ -5,31 +6,6 @@ #include #include -struct NpWebApi2MemoryPoolStats { - std::size_t pool_size; - std::size_t max_inuse_size; - std::size_t current_inuse_size; - std::int32_t reserved; -}; - -extern "C" { -int APS5_VABI sceNpWebApi2Initialize(int, std::size_t); -int APS5_VABI sceNpWebApi2InitializeForPresence(int, std::uint64_t); -int APS5_VABI sceNpWebApi2IntInitialize(const NpWebApi2IntInitializeArgs*); -int APS5_VABI sceNpWebApi2IntInitialize2(const NpWebApi2IntInitialize2Args*); -int APS5_VABI sceNpWebApi2Terminate(int); -int APS5_VABI sceNpWebApi2GetMemoryPoolStats(int, NpWebApi2MemoryPoolStats*); -int APS5_VABI sceNpWebApi2PushEventCreateHandle(int); -int APS5_VABI sceNpWebApi2PushEventAbortHandle(int, int); -int APS5_VABI sceNpWebApi2PushEventDeleteHandle(int, int); -int APS5_VABI sceNpWebApi2PushEventSetHandleTimeout(int, int, std::uint32_t); -int APS5_VABI sceNpWebApi2CreateUserContext(int, int); -int APS5_VABI sceNpWebApi2CreateRequest(int, const char*, const char*, const char*, const void*, std::int64_t*); -int APS5_VABI sceNpWebApi2SetRequestTimeout(std::int64_t, std::uint32_t); -int APS5_VABI sceNpWebApi2AddWebTraceTag(std::int64_t, const char*); -int APS5_VABI sceNpWebApi2DeleteRequest(std::int64_t); -} - static void Require(bool value) { if (!value) std::abort(); } int main() { diff --git a/core/libs/tests/GuestOfflineImports.cpp b/core/libs/tests/GuestOfflineImports.cpp index 351c78faa7..3dd2c7a0b7 100644 --- a/core/libs/tests/GuestOfflineImports.cpp +++ b/core/libs/tests/GuestOfflineImports.cpp @@ -1,3 +1,7 @@ +#include "prx/libSceVideoRecordingP/include/Api.hpp" +#include "prx/libSceRudp/include/Api.hpp" +#include "prx/libSceNpEntitlementAccess/include/Api.hpp" +#include "prx/libSceHttp/include/Http.hpp" #include "SceTypes.hpp" #include @@ -7,30 +11,6 @@ #include #include -extern "C" { -int APS5_VABI sceVideoRecordingGetInfo(std::int32_t info, void* data, std::size_t size); -int APS5_VABI sceVideoRecordingSetInfo(std::int32_t info, const void* data, std::size_t size); -int APS5_VABI sceNpEntitlementAccessAbortRequest(std::int64_t); -int APS5_VABI sceNpEntitlementAccessDeleteRequest(std::int64_t); -int APS5_VABI sceHttpSendRequest(int, const void*, std::size_t); -int APS5_VABI sceNpEntitlementAccessGetEntitlementKey( - std::uint32_t, const NpUnifiedEntitlementLabel*, NpEntitlementAccessEntitlementKey*); -int APS5_VABI sceNpEntitlementAccessGetGameTrialsFlag(std::uint32_t*); -int APS5_VABI sceNpEntitlementAccessGetPftFlag(std::uint32_t*); -int APS5_VABI sceNpEntitlementAccessRequestUnifiedEntitlementInfoList(std::int32_t userId, std::uint32_t serviceLabel, const NpUnifiedEntitlementLabel* entitlementLabels, std::uint32_t labelCount, const NpEntitlementAccessListParameter* parameter, std::int64_t* requestId); -int APS5_VABI sceNpEntitlementAccessPollUnifiedEntitlementInfoList(std::int64_t requestId, std::int32_t* result, NpEntitlementAccessUnifiedInfo* infos, std::uint32_t capacity, std::int32_t* firstResult, std::int32_t* secondResult, std::int32_t* thirdResult); -int APS5_VABI sceNpEntitlementAccessRequestServiceEntitlementInfoList(std::int32_t userId, std::uint32_t serviceLabel, const NpServiceEntitlementLabel* entitlementLabels, std::uint32_t labelCount, const NpEntitlementAccessListParameter* parameter, std::int64_t* requestId); -int APS5_VABI sceNpEntitlementAccessPollServiceEntitlementInfoList(std::int64_t requestId, std::int32_t* result, NpEntitlementAccessServiceInfo* infos, std::uint32_t capacity, std::int32_t* firstResult, std::int32_t* secondResult, std::int32_t* thirdResult); -int APS5_VABI sceNpEntitlementAccessRequestUnifiedEntitlementInfo(std::int32_t userId, std::uint32_t serviceLabel, const NpUnifiedEntitlementLabel* entitlementLabel, std::int64_t* requestId); -int APS5_VABI sceNpEntitlementAccessPollUnifiedEntitlementInfo(std::int64_t requestId, std::int32_t* result, NpEntitlementAccessUnifiedInfo* info); -int APS5_VABI sceNpEntitlementAccessRequestServiceEntitlementInfo(std::int32_t userId, std::uint32_t serviceLabel, const NpServiceEntitlementLabel* entitlementLabel, std::int64_t* requestId); -int APS5_VABI sceNpEntitlementAccessPollServiceEntitlementInfo(std::int64_t requestId, std::int32_t* result, NpEntitlementAccessServiceInfo* info); -int APS5_VABI sceRudpInit_nid_postfix(void*, int); -int APS5_VABI sceRudpActivate(std::int32_t, const void*, std::uint32_t); -int APS5_VABI sceRudpGetStatus(void*, std::size_t); -int APS5_VABI sceRudpEnd(); -} - static void Require(bool value) { if (!value) std::abort(); } int main() { @@ -63,11 +43,13 @@ int main() { bool deleteFailed = false; try { sceNpEntitlementAccessAbortRequest(requestId); + } catch (const std::logic_error&) { abortFailed = true; } try { sceNpEntitlementAccessDeleteRequest(requestId); + } catch (const std::logic_error&) { deleteFailed = true; } diff --git a/core/libs/tests/GuestOnce.cpp b/core/libs/tests/GuestOnce.cpp index 3e60f58ec3..be0de52b29 100644 --- a/core/libs/tests/GuestOnce.cpp +++ b/core/libs/tests/GuestOnce.cpp @@ -1,3 +1,6 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libkernel/Pthread/include/ThreadLifecycle.hpp" +#include "prx/libkernel/Pthread/include/Cancel.hpp" #include "SceTypes.hpp" #include #include @@ -6,20 +9,9 @@ #include #include -struct GuestOnce { std::int32_t state; void* mutex; }; static_assert(sizeof(GuestOnce) == 16 && offsetof(GuestOnce, mutex) == 8); using Initializer = void (APS5_VABI *)(); -extern "C" { -int APS5_VABI pthread_once_nid_postfix(GuestOnce*, Initializer); -int APS5_VABI scePthreadOnce(std::int32_t* once, Initializer init); -int APS5_VABI scePthreadCreate(Pthread* thread, const PthreadAttr* attr, PthreadEntry entry, void* arg, const char* name); -int APS5_VABI scePthreadJoin(Pthread thread, void** retval); -void APS5_VABI scePthreadExit(void* retval); -int APS5_VABI scePthreadCancel(Pthread thread); -void APS5_VABI scePthreadTestcancel(); -Pthread APS5_VABI scePthreadSelf(); -void APS5_VABI __pthread_cleanup_push_imp_nid_postfix(void (APS5_VABI* routine)(void*), void* argument, void* info); -} + static void Require(bool value) { if (!value) std::abort(); } static GuestOnce control{}, nested{}, retry{}; static std::atomic calls{0}, arrived{0}; @@ -41,12 +33,14 @@ static void APS5_VABI ExitInsideInitializer() { scePthreadExit(nullptr); } static void APS5_VABI CancelInsideInitializer() { Require(scePthreadCancel(scePthreadSelf()) == 0); scePthreadTestcancel(); + } static void APS5_VABI CountRetry() { ++retried; } static void APS5_VABI AbortCleanup(void*) { std::abort(); } static void APS5_VABI PushAndThrow() { std::uintptr_t info[8]; __pthread_cleanup_push_imp_nid_postfix(AbortCleanup, nullptr, info); + throw 7; } static GuestOnce pushed{}; diff --git a/core/libs/tests/GuestOperationMode.cpp b/core/libs/tests/GuestOperationMode.cpp index b3fe29f518..e0f08ff13c 100644 --- a/core/libs/tests/GuestOperationMode.cpp +++ b/core/libs/tests/GuestOperationMode.cpp @@ -1,10 +1,8 @@ +#include "prx/libkernel/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include -extern "C" { -void APS5_VABI sceKernelGetOperationMode(int* mode, int* submode); -int APS5_VABI sceKernelIsTrinityMode(void); -} + static void Require(bool value) { if (!value) std::abort(); } static bool Throws(int* mode, int* submode) { try { sceKernelGetOperationMode(mode, submode); } catch (const std::invalid_argument&) { return true; } @@ -13,6 +11,7 @@ static bool Throws(int* mode, int* submode) { int main() { int out[4] = {-1, -1, -1, -1}; sceKernelGetOperationMode(&out[0], &out[2]); + Require(out[0] == 2 && out[1] == -1); Require(out[2] == 0 && out[3] == -1); int value = -1; diff --git a/core/libs/tests/GuestOpusCeltDec.cpp b/core/libs/tests/GuestOpusCeltDec.cpp index b0dc8ae383..653acfe878 100644 --- a/core/libs/tests/GuestOpusCeltDec.cpp +++ b/core/libs/tests/GuestOpusCeltDec.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceOpusCeltDec/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -7,15 +8,6 @@ #include #include -extern "C" { -int APS5_VABI sceOpusCeltDecInitialize(std::uint32_t*); -int APS5_VABI sceOpusCeltDecTerminate(const std::uint32_t*); -int APS5_VABI sceOpusCeltDecGetSize(int); -int APS5_VABI sceOpusCeltDecCreateEx(const std::uint32_t*, void*, int, int); -int APS5_VABI sceOpusCeltDecDecode(void*, const std::uint8_t*, int, std::int16_t*, int); -int APS5_VABI sceOpusCeltDecDestroy(void*); -} - namespace { void Require(bool value) { if (!value) std::abort(); } diff --git a/core/libs/tests/GuestOpusDec.cpp b/core/libs/tests/GuestOpusDec.cpp index 6446a6e8e3..24eddac922 100644 --- a/core/libs/tests/GuestOpusDec.cpp +++ b/core/libs/tests/GuestOpusDec.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceOpusDec/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -9,15 +10,6 @@ #include #include -extern "C" { -int APS5_VABI sceOpusDecInitialize(std::uint32_t*); -int APS5_VABI sceOpusDecTerminate(const std::uint32_t*); -int APS5_VABI sceOpusDecGetSize(int); -int APS5_VABI sceOpusDecCreateEx(const std::uint32_t*, void*, int, int); -int APS5_VABI sceOpusDecDecode(void*, const std::uint8_t*, int, std::int16_t*, int); -int APS5_VABI sceOpusDecDestroy(void*); -} - namespace { void Require(bool value) { if (!value) std::abort(); } diff --git a/core/libs/tests/GuestOverflowError.cpp b/core/libs/tests/GuestOverflowError.cpp index 9bfb21a082..7b7e633934 100644 --- a/core/libs/tests/GuestOverflowError.cpp +++ b/core/libs/tests/GuestOverflowError.cpp @@ -1,10 +1,11 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include #include struct TypeRecord { const void* const* vtable; const char* name; const TypeRecord* base; }; -struct Object { const void* vtable; const char* message; }; + struct Vtable { std::ptrdiff_t offset; const TypeRecord* type; const void* destroy; const void* deleteObject; const void* what; }; extern "C" { @@ -12,8 +13,7 @@ extern const TypeRecord _ZTISt13runtime_error_nid_postfix; extern const TypeRecord _ZTISt14overflow_error_nid_postfix; extern const Vtable _ZTVSt13runtime_error_nid_postfix; extern const Vtable _ZTVSt14overflow_error_nid_postfix; -void APS5_VABI _ZNSt13runtime_errorC1EPKc_nid_postfix(Object*, const char*); -void APS5_VABI _ZNSt14overflow_errorD1Ev_nid_postfix(Object*); + } static void Require(bool value) { if (!value) std::abort(); } @@ -27,12 +27,15 @@ int main() { const auto& runtimeTable = _ZTVSt13runtime_error_nid_postfix; Require(table.offset == 0 && table.type == &type); Require(table.destroy == runtimeTable.destroy && table.deleteObject == runtimeTable.deleteObject && table.what == runtimeTable.what); - Object object{}; + LibcException::ExceptionObject object{}; _ZNSt13runtime_errorC1EPKc_nid_postfix(&object, "value too large"); + Require(object.message != nullptr && std::strcmp(object.message, "value too large") == 0); _ZNSt14overflow_errorD1Ev_nid_postfix(&object); + Require(object.message == nullptr); _ZNSt14overflow_errorD1Ev_nid_postfix(&object); + Require(object.message == nullptr); return 0; } diff --git a/core/libs/tests/GuestPad.cpp b/core/libs/tests/GuestPad.cpp index 36e3e9e0ab..beab5d7f6a 100644 --- a/core/libs/tests/GuestPad.cpp +++ b/core/libs/tests/GuestPad.cpp @@ -14,38 +14,6 @@ #include #include -extern "C" { -int APS5_VABI scePadOpen_nid_postfix(int, int, int, const void*); -int APS5_VABI scePadOpenExt(int, int, int, const void*); -int APS5_VABI scePadClose_nid_postfix(int); -int APS5_VABI scePadGetHandle(int, int, int); -int APS5_VABI scePadSetVibrationTriggerEffectWeakWhileEmbeddedMicInUse(bool); -int APS5_VABI scePadSetVibrationMode(int, int); -int APS5_VABI scePadInit_nid_postfix(void); -int APS5_VABI scePadUnknown_n3kSX62fgNo(); -int APS5_VABI scePadRead_nid_postfix(int, PadData*, int); -int APS5_VABI scePadReadState(int, PadData*); -int APS5_VABI scePadSetTiltCorrectionState(int, bool); -int APS5_VABI scePadResetOrientation(int); -int APS5_VABI scePadSetAngularVelocityDeadbandState(int, bool); -int APS5_VABI scePadSetAngularVelocityBiasCorrectionState(int, bool); -int APS5_VABI scePadIsRemoteController(int, bool*); -int APS5_VABI scePadGetAccessibilityControllerState(int, std::uint32_t*); -bool APS5_VABI scePadIsDS4Connected(std::int32_t); -bool APS5_VABI scePadIsBlasterConnected(std::int32_t); -bool APS5_VABI scePadIsMoveConnected(std::int32_t); -int APS5_VABI scePadGetControllerInformation(int, PadControllerInformation*); -int APS5_VABI scePadDeviceClassParseData(int, const PadData*, PadDeviceClassData*); -int APS5_VABI scePadDeviceClassGetExtendedInformation(int, PadDeviceClassExtendedInformation*); -int APS5_VABI scePadSetVibration(int, const PadVibrationParam*); -int APS5_VABI scePadGetExtControllerInformation(int, void*); -int APS5_VABI scePadResetLightBar(int); -int APS5_VABI scePadSetLightBar(int, const PadLightBarParam*); -int APS5_VABI scePadSetMotionSensorState(int, bool); -int APS5_VABI scePadGetControllerType(int, std::int32_t*); -int APS5_VABI scePadGetInfo_nid_postfix(PadInfo*); -} - static void Require(bool value) { if (!value) std::abort(); } static void CheckInputCommands() { @@ -354,6 +322,9 @@ static void CheckSpecialPort(int user, int handle) { Require(extended.deviceClass == -1 && extended.reserved[0] == 0); Require(scePadDeviceClassGetExtendedInformation(handle, &extended) == PAD_OK); Require(extended.deviceClass == 0); + std::int32_t specialType = -1; + Require(scePadGetControllerType(special, &specialType) == PAD_OK); + Require(specialType == PAD_CONTROLLER_TYPE_UNKNOWN); const PadVibrationParam vibration{0, 0}; const PadLightBarParam lightBar{0, 0, 255}; Require(scePadSetVibration(special, nullptr) == PAD_ERROR_INVALID_ARG); @@ -621,7 +592,11 @@ int main() { Require(scePadGetHandle(user, 0, 0) == noHandle); Require(scePadOpen_nid_postfix(user, 1, 0, nullptr) == PAD_ERROR_INVALID_ARG); - Require(scePadOpen_nid_postfix(user, 0, 1, nullptr) == PAD_ERROR_INVALID_ARG); + Require(scePadOpen_nid_postfix(user, 0, 1, nullptr) == static_cast(0x809b0003)); + for (const int type : {0, 2, 3, 4}) Require(scePadOpen_nid_postfix(-1, type, 0, nullptr) == static_cast(0x809b0001)); + Require(scePadOpen_nid_postfix(-1, 0, 1, nullptr) == static_cast(0x809b0001)); + Require(scePadOpen_nid_postfix(-1, 1, 0, nullptr) == PAD_ERROR_INVALID_ARG); + for (const int type : {5, 6, 16, 0xff, -1}) Require(scePadOpen_nid_postfix(user, type, 0, nullptr) == PAD_ERROR_INVALID_ARG); Require(scePadGetHandle(user, 0, 0) == noHandle); const unsigned char wheel[16]{0xb7, 0x0e, 0x04, 0x0e, 0x08, 0x6e, 0x01}; Require(scePadOpenExt(user, PAD_PORT_TYPE_SPECIAL, 0, wheel) == static_cast(0x80920007)); @@ -716,6 +691,9 @@ int main() { std::uint32_t p2AccessState = 7; Require(scePadGetAccessibilityControllerState(handle2, &p2AccessState) == PAD_OK); Require(p2AccessState == 0); + std::int32_t p2Type = -1; + Require(scePadGetControllerType(handle2, &p2Type) == PAD_OK); + Require(p2Type == PAD_CONTROLLER_TYPE_DUAL_SENSE); PadSetPortConnected_nid_postfix(1, true); Require(scePadGetInfo_nid_postfix(&info) == PAD_OK); diff --git a/core/libs/tests/GuestPadVibrationMode.cpp b/core/libs/tests/GuestPadVibrationMode.cpp index 1d826fedb1..3b82071a1f 100644 --- a/core/libs/tests/GuestPadVibrationMode.cpp +++ b/core/libs/tests/GuestPadVibrationMode.cpp @@ -3,13 +3,6 @@ #include #include -extern "C" { -int APS5_VABI scePadInit_nid_postfix(void); -int APS5_VABI scePadOpen_nid_postfix(int userId, int type, int index, const void* param); -int APS5_VABI scePadClose_nid_postfix(int handle); -int APS5_VABI scePadSetVibrationMode(int handle, int mode); -} - static void Require(bool value) { if (!value) std::abort(); } int main() { diff --git a/core/libs/tests/GuestPageTableStats.cpp b/core/libs/tests/GuestPageTableStats.cpp index 2ef3d599be..18b33b9f39 100644 --- a/core/libs/tests/GuestPageTableStats.cpp +++ b/core/libs/tests/GuestPageTableStats.cpp @@ -1,3 +1,4 @@ +#include "prx/libkernel/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libkernel/KernelErrors.hpp" @@ -7,18 +8,6 @@ #include #include -extern "C" { -int APS5_VABI sceKernelGetPageTableStats(int*, int*, int*, int*); -int APS5_VABI sceKernelGetTraceMemoryStats(std::uint64_t*, std::uint64_t*); -int APS5_VABI sceKernelMapFlexibleMemory(void**, std::size_t, int, int); -int APS5_VABI sceKernelMapDirectMemory(void**, std::size_t, int, int, std::int64_t, std::size_t); -int APS5_VABI sceKernelAllocateDirectMemory(std::int64_t, std::int64_t, std::size_t, std::size_t, int, std::int64_t*); -int APS5_VABI sceKernelReleaseDirectMemory(std::int64_t, std::size_t); -int APS5_VABI sceKernelReserveVirtualRange(void**, std::size_t, int, std::size_t); -int APS5_VABI sceKernelMprotect(const void*, std::size_t, int); -int APS5_VABI sceKernelMunmap(void*, std::size_t); -} - static void Require(bool condition, std::source_location location = std::source_location::current()) { if (!condition) { std::fprintf(stderr, "Page table stats check failed at %s:%u\n", location.file_name(), static_cast(location.line())); @@ -77,7 +66,7 @@ static void CheckCpuGranules() { RequireTaken(before, 1, 0); Map(base + PageTableGranule, 0x4000, 0); RequireTaken(before, 2, 0); - Require(sceKernelMunmap(base, GpuDirectorySpan * 2) == 0); + Require(sceKernelMunmap(reinterpret_cast(base), GpuDirectorySpan * 2) == 0); RequireTaken(before, 0, 0); } @@ -90,7 +79,7 @@ static void CheckGpuEntries() { RequireTaken(before, 3, 4); Map(base + GpuDirectorySpan, 0x4000, 0x33); RequireTaken(before, 4, 6); - Require(sceKernelMunmap(base, GpuDirectorySpan * 2) == 0); + Require(sceKernelMunmap(reinterpret_cast(base), GpuDirectorySpan * 2) == 0); RequireTaken(before, 0, 0); } @@ -107,7 +96,7 @@ static void CheckGpuDirectMapping() { Require(sceKernelMapDirectMemory(&small, 0x10000, 0x33, 0x10, phys + static_cast(2 * PageTableGranule), 0x10000) == 0); Require(small == base + 2 * PageTableGranule + 0x10000); RequireTaken(before, 3, 2); - Require(sceKernelMunmap(base, GpuDirectorySpan * 2) == 0); + Require(sceKernelMunmap(reinterpret_cast(base), GpuDirectorySpan * 2) == 0); Require(sceKernelReleaseDirectMemory(phys, 3 * PageTableGranule) == 0); RequireTaken(before, 0, 0); } diff --git a/core/libs/tests/GuestParentProcess.cpp b/core/libs/tests/GuestParentProcess.cpp index 3465efc6aa..6098a0766a 100644 --- a/core/libs/tests/GuestParentProcess.cpp +++ b/core/libs/tests/GuestParentProcess.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #ifdef _WIN32 @@ -6,14 +8,6 @@ #include #endif -extern "C" { -int APS5_VABI getpid_nid_postfix(void); -int APS5_VABI getppid_nid_postfix(void); -int APS5_VABI getsid_nid_postfix(int); -int APS5_VABI setpgid_nid_postfix(int, int); -int APS5_VABI setpgrp_nid_postfix(int, int); -int* APS5_VABI __error_nid_postfix(); -} static void Require(bool value) { if (!value) std::abort(); } int main() { const int self = getpid_nid_postfix(); diff --git a/core/libs/tests/GuestPathCase.cpp b/core/libs/tests/GuestPathCase.cpp index 18b87e9c6e..675bd28809 100644 --- a/core/libs/tests/GuestPathCase.cpp +++ b/core/libs/tests/GuestPathCase.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/File/include/File.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/General.hpp" #include "prx/libc/include/FileStream.hpp" #include "prx/libkernel/File/include/FileFlags.hpp" @@ -8,21 +10,6 @@ #include #include -extern "C" { -int APS5_VABI sceKernelOpen(const char*, int, std::uint16_t); -int APS5_VABI sceKernelClose(int); -std::int64_t APS5_VABI sceKernelRead(int, void*, std::size_t); -std::int64_t APS5_VABI sceKernelWrite(int, const void*, std::size_t); -int APS5_VABI sceKernelStat(const char*, FileStat*); -int APS5_VABI chdir_nid_postfix(const char*); -int APS5_VABI access_nid_postfix(const char*, int); -int APS5_VABI rename_nid_postfix(const char*, const char*); -int APS5_VABI remove_nid_postfix(const char*); -FileStream* APS5_VABI fopen_nid_postfix(const char*, const char*); -std::size_t APS5_VABI fread_nid_postfix(void*, std::size_t, std::size_t, FileStream*); -int APS5_VABI fclose_nid_postfix(FileStream*); -} - static void Require(bool value) { if (!value) std::abort(); } static void CheckRead(const std::string& path, char expected) { diff --git a/core/libs/tests/GuestPathErrors.cpp b/core/libs/tests/GuestPathErrors.cpp index 3da76d9739..9eb21a8c7a 100644 --- a/core/libs/tests/GuestPathErrors.cpp +++ b/core/libs/tests/GuestPathErrors.cpp @@ -1,3 +1,6 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libkernel/File/include/File.hpp" +#include "prx/libc/include/Api.hpp" #include "SceTypes.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libkernel/File/include/FileFlags.hpp" @@ -12,26 +15,6 @@ #include #include -extern "C" { -int APS5_VABI sceKernelOpen(const char* path, int flags, std::uint16_t mode); -int APS5_VABI sceKernelUnlink(const char* path); -int APS5_VABI sceKernelClose(int d); -int APS5_VABI open_nid_postfix(const char* path, int flags, int mode); -int APS5_VABI unlink_nid_postfix(const char* path); -int APS5_VABI sceKernelStat(const char* path, FileStat* sb); -int APS5_VABI stat_nid_postfix(const char* path, FileStat* sb); -int APS5_VABI lstat_nid_postfix(const char* path, FileStat* sb); -int APS5_VABI sceKernelMkdir(const char* path, std::uint16_t mode); -int APS5_VABI sceKernelRmdir(const char* path); -int APS5_VABI mkdir_nid_postfix(const char* path, std::uint16_t mode); -int APS5_VABI rmdir_nid_postfix(const char* path); -int APS5_VABI sceKernelRename(const char* from, const char* to); -int APS5_VABI rename_nid_postfix(const char* from, const char* to); -int APS5_VABI sceKernelTruncate_nid_postfix(const char* path, std::int64_t length); -int APS5_VABI truncate_nid_postfix(const char* path, std::int64_t length); -int* APS5_VABI __error_nid_postfix(); -} - namespace { void Require(bool value, int line) { diff --git a/core/libs/tests/GuestPathLifetime.cpp b/core/libs/tests/GuestPathLifetime.cpp index 44e8f59072..041de1ffb8 100644 --- a/core/libs/tests/GuestPathLifetime.cpp +++ b/core/libs/tests/GuestPathLifetime.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/General.hpp" #include "prx/libc/include/Shutdown.hpp" #include @@ -9,8 +10,6 @@ #include #include -extern "C" char* APS5_VABI getcwd_nid_postfix(char*, std::size_t); - namespace { int events[2]; diff --git a/core/libs/tests/GuestPathNameLength.cpp b/core/libs/tests/GuestPathNameLength.cpp index 793fd3e651..c6197d2e8f 100644 --- a/core/libs/tests/GuestPathNameLength.cpp +++ b/core/libs/tests/GuestPathNameLength.cpp @@ -1,22 +1,11 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include #include #include -extern "C" { -int APS5_VABI open_nid_postfix(const char*, int, int); -int APS5_VABI close_nid_postfix(int); -int APS5_VABI mkdir_nid_postfix(const char*, int); -int APS5_VABI rmdir_nid_postfix(const char*); -int APS5_VABI unlink_nid_postfix(const char*); -int APS5_VABI rename_nid_postfix(const char*, const char*); -int APS5_VABI stat_nid_postfix(const char*, void*); -int APS5_VABI access_nid_postfix(const char*, int); -int APS5_VABI chflags_nid_postfix(const char*, std::uint64_t); -int* APS5_VABI __error_nid_postfix(); -} - namespace { constexpr int ErrorNoEntry = 2; @@ -32,7 +21,7 @@ bool Fails(long result, int error) { return result == -1 && *__error_nid_postfix bool TooLong(const std::string& path) { unsigned char status[256]; - return Fails(stat_nid_postfix(path.c_str(), status), ErrorNameTooLong); + return Fails(stat_nid_postfix(path.c_str(), reinterpret_cast(status)), ErrorNameTooLong); } } @@ -42,11 +31,12 @@ int main() { const std::string longName(256, 'n'); const std::string longPath(1100, 'p'); const std::string maxName(255, 'm'); - Require(Fails(stat_nid_postfix(longName.c_str(), status), ErrorNameTooLong), "stat of a name above NAME_MAX (255) must fail with ENAMETOOLONG (63)"); + Require(Fails(stat_nid_postfix(longName.c_str(), reinterpret_cast(status)), ErrorNameTooLong), "stat of a name above NAME_MAX (255) must fail with ENAMETOOLONG (63)"); rmdir_nid_postfix("anyps5_name_length"); + Require(mkdir_nid_postfix("anyps5_name_length", 0755) == 0, "mkdir of the test directory failed"); - Require(Fails(stat_nid_postfix(("anyps5_name_length/" + longName).c_str(), status), ErrorNameTooLong), "stat of a long final component below an existing directory must fail with ENAMETOOLONG (63)"); - Require(Fails(stat_nid_postfix(("anyps5_name_length/missing/" + longName).c_str(), status), ErrorNoEntry), "stat of a long component below a missing directory must fail with ENOENT (2), the lookup stops there first"); + Require(Fails(stat_nid_postfix(("anyps5_name_length/" + longName).c_str(), reinterpret_cast(status)), ErrorNameTooLong), "stat of a long final component below an existing directory must fail with ENAMETOOLONG (63)"); + Require(Fails(stat_nid_postfix(("anyps5_name_length/missing/" + longName).c_str(), reinterpret_cast(status)), ErrorNoEntry), "stat of a long component below a missing directory must fail with ENOENT (2), the lookup stops there first"); const std::string below = "anyps5_name_length/"; const std::string name255(255, 'n'); Require(!TooLong(below + name255), "a final component of exactly 255 bytes must not be too long"); @@ -60,8 +50,8 @@ int main() { #endif Require(TooLong(block + block + block + block), "a path of exactly 1024 bytes must fail with ENAMETOOLONG (63)"); Require(rmdir_nid_postfix("anyps5_name_length") == 0, "rmdir of the test directory failed"); - Require(Fails(stat_nid_postfix((longName + "/x").c_str(), status), ErrorNameTooLong), "stat of a long first component must fail with ENAMETOOLONG (63)"); - Require(Fails(stat_nid_postfix(longPath.c_str(), status), ErrorNameTooLong), "stat of a path of 1100 bytes must fail with ENAMETOOLONG (63)"); + Require(Fails(stat_nid_postfix((longName + "/x").c_str(), reinterpret_cast(status)), ErrorNameTooLong), "stat of a long first component must fail with ENAMETOOLONG (63)"); + Require(Fails(stat_nid_postfix(longPath.c_str(), reinterpret_cast(status)), ErrorNameTooLong), "stat of a path of 1100 bytes must fail with ENAMETOOLONG (63)"); Require(Fails(access_nid_postfix(longName.c_str(), 0), ErrorNameTooLong), "access of a long name must fail with ENAMETOOLONG (63)"); Require(Fails(chflags_nid_postfix(longName.c_str(), 0), ErrorNameTooLong), "chflags of a long name must fail with ENAMETOOLONG (63)"); Require(Fails(unlink_nid_postfix(longName.c_str()), ErrorNameTooLong), "unlink of a long name must fail with ENAMETOOLONG (63)"); @@ -71,6 +61,6 @@ int main() { Require(Fails(rename_nid_postfix(longName.c_str(), "anyps5_name_length_target"), ErrorNameTooLong), "rename from a long name must fail with ENAMETOOLONG (63)"); Require(Fails(rename_nid_postfix("anyps5_name_length_source", longName.c_str()), ErrorNameTooLong), "rename to a long name must fail with ENAMETOOLONG (63)"); - Require(Fails(stat_nid_postfix(maxName.c_str(), status), ErrorNoEntry), "a name of exactly 255 bytes is not too long"); + Require(Fails(stat_nid_postfix(maxName.c_str(), reinterpret_cast(status)), ErrorNoEntry), "a name of exactly 255 bytes is not too long"); return 0; } diff --git a/core/libs/tests/GuestPlayGo.cpp b/core/libs/tests/GuestPlayGo.cpp index c03f4761ca..cf8538a5b3 100644 --- a/core/libs/tests/GuestPlayGo.cpp +++ b/core/libs/tests/GuestPlayGo.cpp @@ -1,3 +1,4 @@ +#include "prx/libScePlayGo/include/Api.hpp" #include "SceTypes.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -14,20 +15,6 @@ #include #include -extern "C" { -int APS5_VABI scePlayGoInitialize(const PlayGoInitParams*); -int APS5_VABI scePlayGoOpen(int*, const void*); -int APS5_VABI scePlayGoClose(int); -int APS5_VABI scePlayGoGetLanguageMask(int, std::uint64_t*); -int APS5_VABI scePlayGoSetLanguageMask(int, std::uint64_t); -int APS5_VABI scePlayGoGetSupportedOptionalChunk(int, std::uint32_t, PlayGoOptionalChunk*); -int APS5_VABI scePlayGoGetOptionalChunk(int, std::uint32_t, PlayGoOptionalChunk*); -int APS5_VABI scePlayGoSetToDoList(int, const PlayGoToDo*, std::uint32_t); -int APS5_VABI scePlayGoGetToDoList(int, PlayGoToDo*, std::uint32_t, std::uint32_t*); -int APS5_VABI scePlayGoGetLocus(int, const std::uint16_t*, std::uint32_t, std::int8_t*); -int APS5_VABI scePlayGoGetChunkId(int, std::uint16_t*, std::uint32_t, std::uint32_t*); -} - static void Require(bool value, const std::source_location location = std::source_location::current()) { if (value) return; std::fprintf(stderr, "requirement failed at line %u\n", location.line()); @@ -175,6 +162,7 @@ static int CheckRejectedLayout(const char* root, const char* fileName) { bool threw = false; try { scePlayGoGetLocus(handle, &chunk, 1, &locus); + } catch (const std::runtime_error& error) { threw = std::string_view(error.what()).find(fileName) != std::string_view::npos; } @@ -221,6 +209,7 @@ static int CheckUnknownUnlistedChunkAnswer(const char* root) { bool threw = false; try { scePlayGoGetLocus(handle, &unlisted, 1, &locus); + } catch (const std::runtime_error& error) { threw = std::string_view(error.what()).find("APS5_PLAYGO_UNLISTED_CHUNKS must be installed or absent") != std::string_view::npos; } diff --git a/core/libs/tests/GuestPlayGoDialog.cpp b/core/libs/tests/GuestPlayGoDialog.cpp index 0a8291f96c..e8a89d8e49 100644 --- a/core/libs/tests/GuestPlayGoDialog.cpp +++ b/core/libs/tests/GuestPlayGoDialog.cpp @@ -1,19 +1,10 @@ +#include "prx/libScePlayGoDialog/include/Api.hpp" #include "SceTypes.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include #include -extern "C" { -int APS5_VABI scePlayGoDialogInitialize(void); -int APS5_VABI scePlayGoDialogTerminate(void); -int APS5_VABI scePlayGoDialogOpen(const void* param); -int APS5_VABI scePlayGoDialogClose(void); -int APS5_VABI scePlayGoDialogUpdateStatus(void); -int APS5_VABI scePlayGoDialogGetStatus(void); -int APS5_VABI scePlayGoDialogGetResult(PlayGoDialogResult* result); -} - static void Require(bool value) { if (!value) std::abort(); } int main() { diff --git a/core/libs/tests/GuestPlayerReviewDialog.cpp b/core/libs/tests/GuestPlayerReviewDialog.cpp index 45621694d4..c14e478429 100644 --- a/core/libs/tests/GuestPlayerReviewDialog.cpp +++ b/core/libs/tests/GuestPlayerReviewDialog.cpp @@ -1,21 +1,10 @@ +#include "prx/libSceCdlgPlayerReview/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include "prx/libSceUserService/UserService.hpp" #include "prx/libSceCommonDialog/CommonDialog.hpp" #include -extern "C" { -int APS5_VABI sceUserServiceInitialize(const UserServiceInitParam* param); -int APS5_VABI sceUserServiceTerminate(); -int APS5_VABI scePlayerReviewDialogInitialize(void); -int APS5_VABI scePlayerReviewDialogTerminate(void); -int APS5_VABI scePlayerReviewDialogOpen(const void* param); -int APS5_VABI scePlayerReviewDialogClose(void); -int APS5_VABI scePlayerReviewDialogGetStatus(void); -int APS5_VABI scePlayerReviewDialogUpdateStatus(void); -int APS5_VABI scePlayerReviewDialogGetResult(void* result); -} - namespace { constexpr int COMMON_DIALOG_STATUS_NONE = 0; @@ -44,13 +33,13 @@ int main() { Require(scePlayerReviewDialogGetStatus() == COMMON_DIALOG_STATUS_NONE); Require(scePlayerReviewDialogOpen(¶m) == COMMON_DIALOG_ERROR_NOT_INITIALIZED); Require(scePlayerReviewDialogClose() == COMMON_DIALOG_ERROR_NOT_INITIALIZED); - Require(scePlayerReviewDialogGetResult(result) == COMMON_DIALOG_ERROR_NOT_INITIALIZED); + Require(scePlayerReviewDialogGetResult(reinterpret_cast(result)) == COMMON_DIALOG_ERROR_NOT_INITIALIZED); Require(scePlayerReviewDialogInitialize() == 0); Require(scePlayerReviewDialogInitialize() == COMMON_DIALOG_ERROR_ALREADY_INITIALIZED); Require(scePlayerReviewDialogGetStatus() == COMMON_DIALOG_STATUS_INITIALIZED); Require(scePlayerReviewDialogUpdateStatus() == COMMON_DIALOG_STATUS_INITIALIZED); - Require(scePlayerReviewDialogGetResult(result) == COMMON_DIALOG_ERROR_NOT_FINISHED); + Require(scePlayerReviewDialogGetResult(reinterpret_cast(result)) == COMMON_DIALOG_ERROR_NOT_FINISHED); Require(scePlayerReviewDialogTerminate() == 0); Require(scePlayerReviewDialogTerminate() == COMMON_DIALOG_ERROR_NOT_INITIALIZED); Require(scePlayerReviewDialogGetStatus() == COMMON_DIALOG_STATUS_NONE); @@ -86,7 +75,7 @@ int main() { Require(scePlayerReviewDialogGetStatus() == COMMON_DIALOG_STATUS_FINISHED); Require(scePlayerReviewDialogUpdateStatus() == COMMON_DIALOG_STATUS_FINISHED); Require(scePlayerReviewDialogGetResult(nullptr) == COMMON_DIALOG_ERROR_ARG_NULL); - Require(scePlayerReviewDialogGetResult(result) == COMMON_DIALOG_RESULT_USER_CANCELED); + Require(scePlayerReviewDialogGetResult(reinterpret_cast(result)) == COMMON_DIALOG_RESULT_USER_CANCELED); Require(result[0] == -1 && result[1] == -1 && result[3] == -1); Require(result[2] == COMMON_DIALOG_RESULT_USER_CANCELED); Require(scePlayerReviewDialogClose() == static_cast(0x80B8000Bu)); @@ -100,7 +89,7 @@ int main() { Require(scePlayerReviewDialogGetStatus() == COMMON_DIALOG_STATUS_INITIALIZED); Require(scePlayerReviewDialogUpdateStatus() == COMMON_DIALOG_STATUS_INITIALIZED); result[2] = -1; - Require(scePlayerReviewDialogGetResult(result) == COMMON_DIALOG_ERROR_NOT_FINISHED); + Require(scePlayerReviewDialogGetResult(reinterpret_cast(result)) == COMMON_DIALOG_ERROR_NOT_FINISHED); Require(result[0] == -1 && result[1] == -1 && result[3] == -1); Require(result[2] == -1); Require(scePlayerReviewDialogTerminate() == 0); diff --git a/core/libs/tests/GuestPlayerSelectionDialog.cpp b/core/libs/tests/GuestPlayerSelectionDialog.cpp index 4d3e163d12..4b1c516bd1 100644 --- a/core/libs/tests/GuestPlayerSelectionDialog.cpp +++ b/core/libs/tests/GuestPlayerSelectionDialog.cpp @@ -1,3 +1,4 @@ +#include "prx/libScePlayerSelectionDialog/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -5,19 +6,6 @@ #include "prx/libSceCommonDialog/CommonDialog.hpp" #include "prx/libSceUserService/UserService.hpp" -extern "C" { -int APS5_VABI sceUserServiceInitialize(const UserServiceInitParam* param); -int APS5_VABI sceUserServiceTerminate(); -int APS5_VABI scePlayerSelectionDialogInitialize(void); -int APS5_VABI scePlayerSelectionDialogOpen(const PlayerSelectionDialogParam* param); -int APS5_VABI scePlayerSelectionDialogUpdateStatus(void); -int APS5_VABI scePlayerSelectionDialogGetStatus(void); -int APS5_VABI scePlayerSelectionDialogGetResult(PlayerSelectionDialogResult* result); -int APS5_VABI scePlayerSelectionDialogParamInitialize(void* param); -int APS5_VABI scePlayerSelectionDialogClose(void); -int APS5_VABI scePlayerSelectionDialogTerminate(void); -} - namespace { void Require(bool value) { if (!value) std::abort(); } @@ -47,6 +35,7 @@ int main() { bool threw = false; try { scePlayerSelectionDialogParamInitialize(¶m); + } catch (const std::runtime_error&) { threw = true; } diff --git a/core/libs/tests/GuestPngDec.cpp b/core/libs/tests/GuestPngDec.cpp index 4ee4031ad2..f7dab4a743 100644 --- a/core/libs/tests/GuestPngDec.cpp +++ b/core/libs/tests/GuestPngDec.cpp @@ -1,3 +1,4 @@ +#include "prx/libScePngDec/include/Api.hpp" #include "SceTypes.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "Decoder/Png.hpp" @@ -8,14 +9,6 @@ #include #include -extern "C" { -std::int32_t APS5_VABI scePngDecQueryMemorySize(const PngDecCreateParam*); -std::int32_t APS5_VABI scePngDecCreate(const PngDecCreateParam*, void*, std::uint32_t, void**); -std::int32_t APS5_VABI scePngDecDelete(void*); -std::int32_t APS5_VABI scePngDecParseHeader(const PngDecParseParam*, PngDecImageInfo*); -std::int32_t APS5_VABI scePngDecDecode(void*, const PngDecDecodeParam*, PngDecImageInfo*); -} - static void Require(bool value) { if (!value) std::abort(); } template diff --git a/core/libs/tests/GuestPngEnc.cpp b/core/libs/tests/GuestPngEnc.cpp index d8227b3bab..53cbcd808f 100644 --- a/core/libs/tests/GuestPngEnc.cpp +++ b/core/libs/tests/GuestPngEnc.cpp @@ -1,3 +1,4 @@ +#include "prx/libScePngEnc/include/Api.hpp" #include "SceTypes.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "Decoder/Png.hpp" @@ -7,13 +8,6 @@ #include #include -extern "C" { -int APS5_VABI scePngEncQueryMemorySize(const PngEncCreateParam*); -int APS5_VABI scePngEncCreate(const PngEncCreateParam*, void*, std::uint32_t, void**); -int APS5_VABI scePngEncDelete(void*); -int APS5_VABI scePngEncEncode(void*, const PngEncEncodeParam*, PngEncOutputInfo*); -} - static void Require(bool value) { if (!value) std::abort(); } int main() { diff --git a/core/libs/tests/GuestPoll.cpp b/core/libs/tests/GuestPoll.cpp index 328a7e722e..8d9c7ee484 100644 --- a/core/libs/tests/GuestPoll.cpp +++ b/core/libs/tests/GuestPoll.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN #include @@ -17,35 +19,7 @@ #include #include #include -struct PollDescriptor { - int descriptor; - short events; - short revents; -}; -extern "C" { -int APS5_VABI socket_nid_postfix(int, int, int); -int APS5_VABI bind_nid_postfix(int, const void*, std::uint32_t); -int APS5_VABI listen_nid_postfix(int, int); -int APS5_VABI accept_nid_postfix(int, void*, std::uint32_t*); -int APS5_VABI connect_nid_postfix(int, const void*, std::uint32_t); -int APS5_VABI getsockname_nid_postfix(int, void*, std::uint32_t*); -std::int64_t APS5_VABI send_nid_postfix(int, const void*, std::uint64_t, int); -std::int64_t APS5_VABI recv_nid_postfix(int, void*, std::uint64_t, int); -int APS5_VABI close_nid_postfix(int); -int APS5_VABI shutdown_nid_postfix(int, int); -int APS5_VABI open_nid_postfix(const char*, int, int); -int APS5_VABI mkdir_nid_postfix(const char*, unsigned short); -int APS5_VABI rmdir_nid_postfix(const char*); -int APS5_VABI unlink_nid_postfix(const char*); -int APS5_VABI poll_nid_postfix(PollDescriptor*, std::uint32_t, int); -int APS5_VABI pipe_nid_postfix(int*); -int APS5_VABI kqueue_nid_postfix(); -int APS5_VABI kevent_nid_postfix(int, const KernelEvent*, int, KernelEvent*, int, const KernelTimespec*); -std::int64_t APS5_VABI read_nid_postfix(int, void*, std::uint64_t); -std::int64_t APS5_VABI write_nid_postfix(int, const char*, std::int64_t); -int APS5_VABI fcntl_nid_postfix(int, int, ...); -int* APS5_VABI __error_nid_postfix(); -} + #ifdef _WIN32 using NativeSocket = SOCKET; constexpr NativeSocket NativeInvalid = INVALID_SOCKET; @@ -79,7 +53,7 @@ static KernelEvent UserEvent(std::uint16_t flags, std::uint32_t fflags) { static void PollsKqueues(int socket) { const int queue = kqueue_nid_postfix(); Require(queue >= 0); - PollDescriptor kq{queue, static_cast(In | ReadNormal | Out | Priority | ReadBand | WriteBand), -1}; + GuestPollDescriptor kq{queue, static_cast(In | ReadNormal | Out | Priority | ReadBand | WriteBand), -1}; Require(poll_nid_postfix(&kq, 1, 0) == 0 && kq.revents == 0); const auto added = UserEvent(EvAdd | EvClear, 0); Require(kevent_nid_postfix(queue, &added, 1, nullptr, 0, nullptr) == 0); @@ -92,7 +66,7 @@ static void PollsKqueues(int socket) { const auto triggered = UserEvent(0, NoteTrigger); Require(kevent_nid_postfix(queue, &triggered, 1, nullptr, 0, nullptr) == 0); }); - PollDescriptor mixed[2]{{socket, In, -1}, {queue, static_cast(In | Out), -1}}; + GuestPollDescriptor mixed[2]{{socket, In, -1}, {queue, static_cast(In | Out), -1}}; Require(poll_nid_postfix(mixed, 2, -1) == 1); trigger.join(); Require(mixed[0].revents == 0 && mixed[1].revents == In); @@ -114,16 +88,16 @@ static void PollsFilesAndDirectories(int socket) { Require(mkdir_nid_postfix(directoryPath.c_str(), 0755) == 0); const int directory = open_nid_postfix(directoryPath.c_str(), DirectoryFlag, 0); Require(directory >= 0); - PollDescriptor vnode{file, static_cast(In | Out | ReadNormal | Priority | ReadBand | WriteBand), -1}; + GuestPollDescriptor vnode{file, static_cast(In | Out | ReadNormal | Priority | ReadBand | WriteBand), -1}; Require(poll_nid_postfix(&vnode, 1, 0) == 1 && vnode.revents == (In | Out | ReadNormal)); vnode.events = static_cast(Priority | ReadBand | WriteBand); Require(poll_nid_postfix(&vnode, 1, 0) == 0 && vnode.revents == 0); const auto start = std::chrono::steady_clock::now(); Require(poll_nid_postfix(&vnode, 1, 30) == 0); Require(std::chrono::steady_clock::now() - start >= std::chrono::milliseconds(25)); - PollDescriptor folder{directory, static_cast(In | Out), -1}; + GuestPollDescriptor folder{directory, static_cast(In | Out), -1}; Require(poll_nid_postfix(&folder, 1, -1) == 1 && folder.revents == (In | Out)); - PollDescriptor mixed[3]{{socket, In, -1}, {file, Out, -1}, {directory, ReadNormal, -1}}; + GuestPollDescriptor mixed[3]{{socket, In, -1}, {file, Out, -1}, {directory, ReadNormal, -1}}; Require(poll_nid_postfix(mixed, 3, -1) == 2); Require(mixed[0].revents == 0 && mixed[1].revents == Out && mixed[2].revents == ReadNormal); Require(close_nid_postfix(directory) == 0 && close_nid_postfix(file) == 0); @@ -133,9 +107,9 @@ static void PollsFilesAndDirectories(int socket) { static void TestPipes(int socket) { int ends[2]; Require(pipe_nid_postfix(ends) == 0); - PollDescriptor empty[2]{{ends[0], In, -1}, {ends[1], Out, -1}}; + GuestPollDescriptor empty[2]{{ends[0], In, -1}, {ends[1], Out, -1}}; Require(poll_nid_postfix(empty, 2, 0) == 1 && empty[0].revents == 0 && empty[1].revents == Out); - PollDescriptor reader{ends[0], In | ReadNormal, -1}; + GuestPollDescriptor reader{ends[0], In | ReadNormal, -1}; const auto start = std::chrono::steady_clock::now(); Require(poll_nid_postfix(&reader, 1, 50) == 0 && reader.revents == 0); Require(std::chrono::steady_clock::now() - start >= std::chrono::milliseconds(40)); @@ -145,13 +119,13 @@ static void TestPipes(int socket) { Require(shortWait >= std::chrono::milliseconds(40) && shortWait < std::chrono::milliseconds(200)); Require(write_nid_postfix(ends[1], "wake", 4) == 4); Require(poll_nid_postfix(&reader, 1, 1000) == 1 && reader.revents == (In | ReadNormal)); - PollDescriptor writer{ends[1], In, -1}; + GuestPollDescriptor writer{ends[1], In, -1}; Require(poll_nid_postfix(&writer, 1, 0) == 0 && writer.revents == 0); - PollDescriptor readerOut{ends[0], Out, -1}; + GuestPollDescriptor readerOut{ends[0], Out, -1}; bool threw = false; try { poll_nid_postfix(&readerOut, 1, 0); } catch (const std::runtime_error&) { threw = true; } Require(threw); - PollDescriptor mixed[2]{{socket, In, -1}, {ends[0], In, -1}}; + GuestPollDescriptor mixed[2]{{socket, In, -1}, {ends[0], In, -1}}; Require(poll_nid_postfix(mixed, 2, 1000) == 1 && mixed[0].revents == 0 && mixed[1].revents == In); char buffer[8]{}; Require(read_nid_postfix(ends[0], buffer, sizeof(buffer)) == 4); @@ -178,14 +152,14 @@ static void TestPipes(int socket) { Require(read_nid_postfix(ends[0], buffer, sizeof(buffer)) == 1); Require(poll_nid_postfix(&reader, 1, 0) == 1 && reader.revents == (In | ReadNormal | Hup)); Require(read_nid_postfix(ends[0], buffer, sizeof(buffer)) == 0); - PollDescriptor closedPipe{ends[1], In, -1}; + GuestPollDescriptor closedPipe{ends[1], In, -1}; Require(poll_nid_postfix(&closedPipe, 1, 0) == 1 && closedPipe.revents == Invalid); Require(close_nid_postfix(ends[0]) == 0); int full[2]; Require(pipe_nid_postfix(full) == 0); static char block[4096]; std::int64_t queued = 0; - PollDescriptor fill{full[1], Out, -1}; + GuestPollDescriptor fill{full[1], Out, -1}; while (poll_nid_postfix(&fill, 1, 0) == 1) { Require(fill.revents == Out && queued < (1 << 20)); Require(write_nid_postfix(full[1], block, 256) == 256); @@ -203,7 +177,7 @@ static void TestPipes(int socket) { int other[2]; Require(pipe_nid_postfix(other) == 0); Require(close_nid_postfix(other[0]) == 0); - PollDescriptor orphan{other[1], Out, -1}; + GuestPollDescriptor orphan{other[1], Out, -1}; Require(poll_nid_postfix(&orphan, 1, 0) == 1 && orphan.revents == Hup); orphan.events = In | Out; Require(poll_nid_postfix(&orphan, 1, 0) == 1 && orphan.revents == (In | Hup)); @@ -221,11 +195,11 @@ static void PollsUrgentData() { Require(client >= 0 && fcntl_nid_postfix(client, 4, 4) == 0); if (connect_nid_postfix(client, address.data(), address.size()) != 0) Require(*__error_nid_postfix() == 36); - PollDescriptor connecting{client, Priority | Out, -1}; + GuestPollDescriptor connecting{client, Priority | Out, -1}; Require(poll_nid_postfix(&connecting, 1, 1000) == 1 && connecting.revents == Out); const int server = accept_nid_postfix(listener, nullptr, nullptr); Require(server >= 0); - PollDescriptor pair[2]{{server, Priority | Out, -1}, {client, In | Priority | Out | ReadBand, -1}}; + GuestPollDescriptor pair[2]{{server, Priority | Out, -1}, {client, In | Priority | Out | ReadBand, -1}}; Require(poll_nid_postfix(pair, 2, 0) == 2 && pair[0].revents == Out && pair[1].revents == Out); char byte = 'u'; Require(send_nid_postfix(client, &byte, 1, 1) == -1 && *__error_nid_postfix() == 45); @@ -239,14 +213,14 @@ static void PollsUrgentData() { Require(::connect(peer, reinterpret_cast(&native), sizeof(native)) == 0); const int urgent = accept_nid_postfix(listener, nullptr, nullptr); Require(urgent >= 0); - PollDescriptor waiting{urgent, Priority, -1}; + GuestPollDescriptor waiting{urgent, Priority, -1}; Require(poll_nid_postfix(&waiting, 1, 0) == 0 && waiting.revents == 0); Require(::send(peer, "u", 1, MSG_OOB) == 1); Require(poll_nid_postfix(&waiting, 1, 1000) == 1 && waiting.revents == Priority); - PollDescriptor bands{urgent, In | Priority | Out, -1}; + GuestPollDescriptor bands{urgent, In | Priority | Out, -1}; Require(poll_nid_postfix(&bands, 1, 0) == 1 && bands.revents == (Priority | Out)); #ifdef _WIN32 - PollDescriptor band{urgent, ReadBand, -1}; + GuestPollDescriptor band{urgent, ReadBand, -1}; Require(poll_nid_postfix(&band, 1, 0) == 1 && band.revents == ReadBand); #endif CloseNative(peer); @@ -268,7 +242,7 @@ static void PollsAStreamWhosePeerClosed() { Require(server >= 0); Require(shutdown_nid_postfix(client, 1) == 0); - PollDescriptor wait{server, In, 0}; + GuestPollDescriptor wait{server, In, 0}; Require(poll_nid_postfix(&wait, 1, 1000) == 1 && wait.revents == In); wait = {server, static_cast(In | Out), 0}; Require(poll_nid_postfix(&wait, 1, 1000) == 1 && wait.revents == (In | Out)); @@ -297,7 +271,7 @@ int main() { std::uint32_t size = address.size(); Require(getsockname_nid_postfix(listener, address.data(), &size) == 0); Require(listen_nid_postfix(listener, 4) == 0); - PollDescriptor single{listener, In, -1}; + GuestPollDescriptor single{listener, In, -1}; Require(poll_nid_postfix(&single, 1, 0) == 0 && single.revents == 0); const auto start = std::chrono::steady_clock::now(); Require(poll_nid_postfix(&single, 1, 50) == 0); @@ -307,7 +281,7 @@ int main() { Require(poll_nid_postfix(&single, 1, 1000) == 1 && single.revents == In); const int server = accept_nid_postfix(listener, nullptr, nullptr); Require(server >= 0); - PollDescriptor pair[3]{{server, In, 0}, {-1, In, 7}, {client, Out, 0}}; + GuestPollDescriptor pair[3]{{server, In, 0}, {-1, In, 7}, {client, Out, 0}}; Require(poll_nid_postfix(pair, 3, 1000) == 1); Require(pair[0].revents == 0 && pair[1].revents == 0 && pair[2].revents == Out); const char message[] = "poll"; @@ -319,7 +293,7 @@ int main() { Require(close_nid_postfix(client) == 0); Require(poll_nid_postfix(pair, 1, 1000) == 1 && (pair[0].revents & (In | Hup)) != 0); Require(recv_nid_postfix(server, buffer, sizeof(buffer), 0) == 0); - PollDescriptor closed[2]{{client, In, 0}, {listener, In, 0}}; + GuestPollDescriptor closed[2]{{client, In, 0}, {listener, In, 0}}; Require(poll_nid_postfix(closed, 2, -1) == 1 && closed[0].revents == Invalid && closed[1].revents == 0); Require(poll_nid_postfix(nullptr, 0, 10) == 0); const auto shortWaitStart = std::chrono::steady_clock::now(); @@ -334,20 +308,20 @@ int main() { for (const char* path : {"/dev/urandom", "/dev/random"}) { const int random = open_nid_postfix(path, 0, 0); Require(random >= 0); - PollDescriptor device{random, static_cast(In | Out | Priority), -1}; + GuestPollDescriptor device{random, static_cast(In | Out | Priority), -1}; Require(poll_nid_postfix(&device, 1, 0) == 1 && device.revents == In); device.events = static_cast(ReadNormal | Out); Require(poll_nid_postfix(&device, 1, 0) == 1 && device.revents == ReadNormal); device.events = static_cast(Out | Priority | ReadBand | WriteBand); Require(poll_nid_postfix(&device, 1, -1) == 1 && device.revents == (Out | Priority | ReadBand | WriteBand)); - PollDescriptor mixed[2]{{listener, In, 0}, {random, Out, 0}}; + GuestPollDescriptor mixed[2]{{listener, In, 0}, {random, Out, 0}}; Require(poll_nid_postfix(mixed, 2, -1) == 1 && mixed[0].revents == 0 && mixed[1].revents == Out); Require(close_nid_postfix(random) == 0); } - PollDescriptor console[3]{{0, static_cast(In | ReadNormal | Out), -1}, {1, static_cast(In | Out | WriteBand), -1}, {2, Out, -1}}; + GuestPollDescriptor console[3]{{0, static_cast(In | ReadNormal | Out), -1}, {1, static_cast(In | Out | WriteBand), -1}, {2, Out, -1}}; Require(poll_nid_postfix(console, 3, 0) == 2); Require(console[0].revents == 0 && console[1].revents == Out && console[2].revents == Out); - PollDescriptor input{0, In, -1}; + GuestPollDescriptor input{0, In, -1}; const auto inputStart = std::chrono::steady_clock::now(); Require(poll_nid_postfix(&input, 1, 30) == 0 && input.revents == 0); Require(std::chrono::steady_clock::now() - inputStart >= std::chrono::milliseconds(25)); diff --git a/core/libs/tests/GuestPositionedClose.cpp b/core/libs/tests/GuestPositionedClose.cpp index 3d44da1f08..1d89c27276 100644 --- a/core/libs/tests/GuestPositionedClose.cpp +++ b/core/libs/tests/GuestPositionedClose.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libkernel/File/include/File.hpp" #include "prx/libc/include/PreciseWait.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libkernel/File/include/FileFlags.hpp" @@ -13,12 +15,6 @@ #include #include -extern "C" { -int APS5_VABI sceKernelOpen(const char*, int, std::uint16_t); -int APS5_VABI sceKernelClose(int); -std::int64_t APS5_VABI sceKernelPread(int, void*, std::size_t, std::int64_t); -} - static void Check(bool value, int line) { if (!value) { std::fprintf(stderr, "Positioned close check failed at line %d\n", line); diff --git a/core/libs/tests/GuestPositionedRace.cpp b/core/libs/tests/GuestPositionedRace.cpp index 6c936c56b4..90c3257cf6 100644 --- a/core/libs/tests/GuestPositionedRace.cpp +++ b/core/libs/tests/GuestPositionedRace.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libkernel/File/include/File.hpp" #include "SceTypes.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libkernel/File/include/FileFlags.hpp" @@ -12,13 +14,7 @@ #include #include #include -extern "C" { -int APS5_VABI sceKernelOpen(const char* path, int flags, std::uint16_t mode); -int APS5_VABI sceKernelClose(int d); -std::int64_t APS5_VABI sceKernelRead(int d, void* buf, std::size_t nbytes); -std::int64_t APS5_VABI sceKernelPread(int d, void* buf, std::size_t nbytes, std::int64_t offset); -std::int64_t APS5_VABI sceKernelLseek(int d, std::int64_t offset, int whence); -} + static void Check(bool value, int line) { if (!value) { std::fprintf(stderr, "Positioned race check failed at line %d\n", line); diff --git a/core/libs/tests/GuestPosixFilesystem.cpp b/core/libs/tests/GuestPosixFilesystem.cpp index fbe8e7566e..c18d690982 100644 --- a/core/libs/tests/GuestPosixFilesystem.cpp +++ b/core/libs/tests/GuestPosixFilesystem.cpp @@ -1,3 +1,7 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libkernel/Time/include/Time.hpp" +#include "prx/libc/include/Api.hpp" +#include "prx/libScePosixForWebKit/include/Api.hpp" #include "prx/libc/include/General.hpp" #include "SceTypes.hpp" #include @@ -18,32 +22,6 @@ #include #endif -extern "C" { -int APS5_VABI mkstemp_nid_postfix(char*); -int APS5_VABI isatty_nid_postfix(int); -int* APS5_VABI __error_nid_postfix(); -int APS5_VABI close_nid_postfix(int); -int APS5_VABI pipe_nid_postfix(int*); -int APS5_VABI socket_nid_postfix(int, int, int); -std::int64_t APS5_VABI read_nid_postfix(int, void*, std::size_t); -std::int64_t APS5_VABI write_nid_postfix(int, const void*, std::size_t); -std::int64_t APS5_VABI lseek_nid_postfix(int, std::int64_t, int); -int APS5_VABI access_nid_postfix(const char*, int); -int APS5_VABI __wrap_access(const char*, int); -int APS5_VABI clock_gettime_nid_postfix(int, KernelTimespec*); -int APS5_VABI __wrap_clock_gettime(int, KernelTimespec*); -char* APS5_VABI getcwd_nid_postfix(char*, std::size_t); -char* APS5_VABI __wrap_getcwd(char*, std::size_t); -char* APS5_VABI getenv_nid_postfix(const char*); -char* APS5_VABI __wrap_getenv(const char*); -int APS5_VABI setenv_nid_postfix(const char*, const char*, int); -int APS5_VABI lstat_nid_postfix(const char*, FileStat*); -int APS5_VABI __wrap_lstat(const char*, FileStat*); -void* APS5_VABI mmap_nid_postfix(void*, std::size_t, int, int, int, std::int64_t) noexcept; -void* APS5_VABI __wrap_mmap(void*, std::size_t, int, int, int, std::int64_t); -int APS5_VABI munmap_nid_postfix(void*, std::size_t) noexcept; -} - static void Require(bool condition, std::source_location location = std::source_location::current()) { if (!condition) { std::fprintf(stderr, "POSIX filesystem check failed at line %u (guest errno %d)\n", location.line(), *__error_nid_postfix()); diff --git a/core/libs/tests/GuestPosixNamedSem.cpp b/core/libs/tests/GuestPosixNamedSem.cpp index 0a7de1f321..99ab8cb8a5 100644 --- a/core/libs/tests/GuestPosixNamedSem.cpp +++ b/core/libs/tests/GuestPosixNamedSem.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "SceTypes.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -7,19 +9,6 @@ #include #include -extern "C" { -void* APS5_VABI sem_open_nid_postfix(const char* name, int flags, ...); -int APS5_VABI sem_close_nid_postfix(void* sem); -int APS5_VABI sem_unlink_nid_postfix(const char* name); -int APS5_VABI sem_init_nid_postfix(void* sem, int pshared, unsigned int value); -int APS5_VABI sem_destroy_nid_postfix(void* sem); -int APS5_VABI sem_wait_nid_postfix(void* sem); -int APS5_VABI sem_trywait_nid_postfix(void* sem); -int APS5_VABI sem_post_nid_postfix(void* sem); -int APS5_VABI sem_getvalue_nid_postfix(void* sem, int* value); -int* APS5_VABI __error_nid_postfix(); -} - static constexpr int GUEST_ENOENT = 2; static constexpr int GUEST_EEXIST = 17; static constexpr int GUEST_EINVAL = 22; diff --git a/core/libs/tests/GuestPosixRandom.cpp b/core/libs/tests/GuestPosixRandom.cpp index 396fcc3aa1..e4f7307064 100644 --- a/core/libs/tests/GuestPosixRandom.cpp +++ b/core/libs/tests/GuestPosixRandom.cpp @@ -1,3 +1,4 @@ +#include "prx/libScePosixForWebKit/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -7,9 +8,6 @@ #include #include -extern "C" void APS5_VABI arc4random_buf_nid_postfix(void*, std::size_t); -extern "C" std::uint32_t APS5_VABI arc4random_nid_postfix(); - void Require(bool condition, std::source_location location = std::source_location::current()) { if (!condition) { std::fprintf(stderr, "Posix random check failed at line %u\n", location.line()); @@ -22,15 +20,18 @@ int main() { std::array second{}; first.fill(0xa5); arc4random_buf_nid_postfix(first.data(), 0); + Require(std::all_of(first.begin(), first.end(), [](unsigned char value) { return value == 0xa5; })); for (const std::size_t size : {1u, 3u, 5u, 4098u}) { first.fill(0xa5); arc4random_buf_nid_postfix(first.data(), size); + Require(std::all_of(first.begin() + static_cast(size), first.end(), [](unsigned char value) { return value == 0xa5; })); } arc4random_buf_nid_postfix(first.data(), first.size()); arc4random_buf_nid_postfix(second.data(), second.size()); + Require(first != second); std::array counts{}; for (const auto value : first) ++counts[value]; diff --git a/core/libs/tests/GuestPosixScalarIo.cpp b/core/libs/tests/GuestPosixScalarIo.cpp index ec96da483a..ea79971ed5 100644 --- a/core/libs/tests/GuestPosixScalarIo.cpp +++ b/core/libs/tests/GuestPosixScalarIo.cpp @@ -1,3 +1,6 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libkernel/File/include/File.hpp" +#include "prx/libc/include/Api.hpp" #include "SceTypes.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libkernel/File/include/FileFlags.hpp" @@ -20,30 +23,6 @@ #include #endif -extern "C" { -int APS5_VABI open_nid_postfix(const char*, int, int); -int APS5_VABI close_nid_postfix(int); -int APS5_VABI pipe_nid_postfix(int*); -int* APS5_VABI __error_nid_postfix(); -std::int64_t APS5_VABI read_nid_postfix(int, void*, std::uint64_t); -std::int64_t APS5_VABI write_nid_postfix(int, const char*, std::int64_t); -std::int64_t APS5_VABI _read_nid_postfix(int, void*, std::size_t); -std::int64_t APS5_VABI _write_nid_postfix(int, const void*, std::size_t); -std::int64_t APS5_VABI lseek_nid_postfix(int, std::int64_t, int); -std::int64_t APS5_VABI pread_nid_postfix(int, void*, std::size_t, std::int64_t); -std::int64_t APS5_VABI pwrite_nid_disambig1_nid_postfix(int, const void*, std::size_t, std::int64_t); -std::int64_t APS5_VABI sceKernelRead(int, void*, std::size_t); -std::int64_t APS5_VABI sceKernelWrite(int, const void*, std::size_t); -std::int64_t APS5_VABI sceKernelLseek(int, std::int64_t, int); -int APS5_VABI sceKernelStat(const char*, FileStat*); -int APS5_VABI sceKernelUnlink(const char*); -int APS5_VABI sceKernelTruncate_nid_postfix(const char*, std::int64_t); -int APS5_VABI sceKernelUtimes_nid_postfix(const char*, const void*); -int APS5_VABI sceKernelMkdir(const char*, std::uint16_t); -int APS5_VABI sceKernelRmdir(const char*); -int APS5_VABI sceKernelRename(const char*, const char*); -} - static void Check(bool value, int line) { if (!value) { std::fprintf(stderr, "POSIX scalar I/O check failed at line %d (guest errno %d)\n", line, *__error_nid_postfix()); @@ -145,6 +124,7 @@ int main() { bool limitDiagnosticPreserved = false; try { write_nid_postfix(descriptor, payload, static_cast(std::numeric_limits::max()) + 1); + } catch (const std::runtime_error& error) { limitDiagnosticPreserved = std::string(error.what()).find("nbytes exceeds platform limit") != std::string::npos; } diff --git a/core/libs/tests/GuestPosixSem.cpp b/core/libs/tests/GuestPosixSem.cpp index f6a2963120..89e0a0b511 100644 --- a/core/libs/tests/GuestPosixSem.cpp +++ b/core/libs/tests/GuestPosixSem.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "SceTypes.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -9,16 +11,6 @@ #include #include -extern "C" { -int APS5_VABI sem_init_nid_postfix(void*, int, unsigned int); -int APS5_VABI sem_destroy_nid_postfix(void*); -int APS5_VABI sem_post_nid_postfix(void*); -int APS5_VABI sem_trywait_nid_postfix(void*); -int APS5_VABI sem_timedwait_nid_postfix(void*, const KernelTimespec*); -int APS5_VABI sem_getvalue_nid_postfix(void*, int*); -int* APS5_VABI __error_nid_postfix(); -} - static void Require(bool condition, const char* message) { if (!condition) { std::fprintf(stderr, "%s\n", message); diff --git a/core/libs/tests/GuestPosixSpawn.cpp b/core/libs/tests/GuestPosixSpawn.cpp index 5b714f2fb0..ecfb146655 100644 --- a/core/libs/tests/GuestPosixSpawn.cpp +++ b/core/libs/tests/GuestPosixSpawn.cpp @@ -1,3 +1,5 @@ +#include "prx/libc/include/Api.hpp" +#include "prx/libSceLibcInternal/include/Api.hpp" #include "prx/libSceLibcInternal/include/Spawn.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -10,33 +12,6 @@ #include #include -extern "C" { -int APS5_VABI posix_spawnattr_init_nid_postfix(PosixSpawnAttributes**); -int APS5_VABI posix_spawnattr_destroy_nid_postfix(PosixSpawnAttributes**); -int APS5_VABI posix_spawnattr_setflags_nid_postfix(PosixSpawnAttributes**, std::int16_t); -int APS5_VABI posix_spawnattr_setsigdefault_nid_postfix(PosixSpawnAttributes**, const GuestSignalSet*); -int APS5_VABI posix_spawnattr_getflags_nid_postfix(PosixSpawnAttributes* const*, std::int16_t*); -int APS5_VABI posix_spawnattr_getpgroup_nid_postfix(PosixSpawnAttributes* const*, std::int32_t*); -int APS5_VABI posix_spawnattr_getschedparam_nid_postfix(PosixSpawnAttributes* const*, std::int32_t*); -int APS5_VABI posix_spawnattr_getschedpolicy_nid_postfix(PosixSpawnAttributes* const*, std::int32_t*); -int APS5_VABI posix_spawnattr_getsigdefault_nid_postfix(PosixSpawnAttributes* const*, GuestSignalSet*); -int APS5_VABI posix_spawnattr_getsigmask_nid_postfix(PosixSpawnAttributes* const*, GuestSignalSet*); -int APS5_VABI posix_spawnattr_setpgroup_nid_postfix(PosixSpawnAttributes**, std::int32_t); -int APS5_VABI posix_spawnattr_setschedparam_nid_postfix(PosixSpawnAttributes**, const std::int32_t*); -int APS5_VABI posix_spawnattr_setschedpolicy_nid_postfix(PosixSpawnAttributes**, std::int32_t); -int APS5_VABI posix_spawnattr_setsigmask_nid_postfix(PosixSpawnAttributes**, const GuestSignalSet*); -int APS5_VABI posix_spawn_file_actions_init_nid_postfix(PosixSpawnFileActions**); -int APS5_VABI posix_spawn_file_actions_destroy_nid_postfix(PosixSpawnFileActions**); -int APS5_VABI posix_spawn_file_actions_addopen_nid_postfix(PosixSpawnFileActions**, int, const char*, int, std::uint16_t); -int APS5_VABI posix_spawn_file_actions_adddup2_nid_postfix(PosixSpawnFileActions**, int, int); -int APS5_VABI posix_spawn_file_actions_addclose_nid_postfix(PosixSpawnFileActions**, int); -int APS5_VABI posix_spawn_nid_postfix(std::int32_t*, const char*, PosixSpawnFileActions* const*, PosixSpawnAttributes* const*, char* const*, char* const*); -int APS5_VABI posix_spawnp_nid_postfix(std::int32_t*, const char*, PosixSpawnFileActions* const*, PosixSpawnAttributes* const*, char* const*, char* const*); -int APS5_VABI setenv_nid_postfix(const char*, const char*, int); -int APS5_VABI unsetenv_nid_postfix(const char*); -int APS5_VABI chdir_nid_postfix(const char*); -} - static void Require(bool condition, int line) { if (!condition) { std::fprintf(stderr, "Posix spawn check failed at line %d\n", line); diff --git a/core/libs/tests/GuestPosixThreadName.cpp b/core/libs/tests/GuestPosixThreadName.cpp new file mode 100644 index 0000000000..05f284f0db --- /dev/null +++ b/core/libs/tests/GuestPosixThreadName.cpp @@ -0,0 +1,46 @@ +#include "SceTypes.hpp" +#include "prx/libScePosixForWebKit/include/Api.hpp" +#include "prx/libkernel/include/Api.hpp" +#include +#include +#include +#include + +static constexpr int GUEST_EINVAL = 22; +static constexpr int GUEST_ENAMETOOLONG = 63; + +static void Require(bool value) { if (!value) std::abort(); } + +static std::string ReadName(Pthread thread) { + std::array buffer{}; + buffer.fill(0x55); + Require(pthread_getname_np_nid_postfix(thread, buffer.data()) == 0); + return std::string(buffer.data()); +} + +static void RequireStored(Pthread thread, const std::string& name) { + Require(ReadName(thread) == name); +} + +int main() { + const Pthread self = pthread_self_nid_postfix(); + RequireStored(self, ""); + + Require(pthread_setname_np_nid_postfix(self, "webkit") == 0); + RequireStored(self, "webkit"); + + Require(pthread_setname_np_nid_postfix(self, "") == 0); + RequireStored(self, ""); + + Require(pthread_setname_np_nid_postfix(self, nullptr) == GUEST_EINVAL); + Require(pthread_setname_np_nid_postfix(nullptr, "name") == GUEST_EINVAL); + + const std::string longest(31, 'b'); + Require(pthread_setname_np_nid_postfix(self, longest.c_str()) == 0); + RequireStored(self, longest); + + const std::string tooLong(32, 'c'); + Require(pthread_setname_np_nid_postfix(self, tooLong.c_str()) == GUEST_ENAMETOOLONG); + RequireStored(self, longest); + return 0; +} diff --git a/core/libs/tests/GuestProcessArguments.cpp b/core/libs/tests/GuestProcessArguments.cpp index fa0f5584b8..d32233f67b 100644 --- a/core/libs/tests/GuestProcessArguments.cpp +++ b/core/libs/tests/GuestProcessArguments.cpp @@ -1,11 +1,9 @@ +#include "prx/libkernel/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include #include -extern "C" int APS5_VABI getargc_nid_postfix(void); -extern "C" const char** APS5_VABI getargv_nid_postfix(void); - static void Require(bool condition, const char* message) { if (!condition) { std::fprintf(stderr, "%s\n", message); diff --git a/core/libs/tests/GuestProgramName.cpp b/core/libs/tests/GuestProgramName.cpp index 7f14669adb..7436649aa5 100644 --- a/core/libs/tests/GuestProgramName.cpp +++ b/core/libs/tests/GuestProgramName.cpp @@ -1,12 +1,13 @@ +#include "prx/libc/include/Api.hpp" +#include "prx/libSceLibcInternal/include/Api.hpp" #include "SceTypes.hpp" #include #include extern "C" { -const char* APS5_VABI getprogname_nid_postfix(); -const char* APS5_VABI _getprogname_nid_postfix(); + extern const char* __progname_nid_postfix; -int* APS5_VABI __error_nid_postfix(); + } static void Require(bool value) { if (!value) std::abort(); } diff --git a/core/libs/tests/GuestProprietaryVoiceChatHelper.cpp b/core/libs/tests/GuestProprietaryVoiceChatHelper.cpp index 27f0e6dff8..f3f512f138 100644 --- a/core/libs/tests/GuestProprietaryVoiceChatHelper.cpp +++ b/core/libs/tests/GuestProprietaryVoiceChatHelper.cpp @@ -1,17 +1,10 @@ +#include "prx/libSceProprietaryVoiceChatHelperPrx/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include #include -extern "C" { -int APS5_VABI sceProprietaryVoiceChatHelperInitialize(); -int APS5_VABI sceProprietaryVoiceChatHelperTerminate(); -int APS5_VABI sceProprietaryVoiceChatHelperSetVoiceChatState(); -int APS5_VABI sceProprietaryVoiceChatHelperGetVoiceChatUsageState(); -int APS5_VABI sceProprietaryVoiceChatHelperGetVoiceChat(); -} - static void Require(bool value, const char* what) { if (value) return; std::printf("ProprietaryVoiceChatHelper: %s\n", what); diff --git a/core/libs/tests/GuestProtectionReport.cpp b/core/libs/tests/GuestProtectionReport.cpp index 87a3d29b52..00bf0c9ab7 100644 --- a/core/libs/tests/GuestProtectionReport.cpp +++ b/core/libs/tests/GuestProtectionReport.cpp @@ -1,3 +1,4 @@ +#include "prx/libkernel/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "SceTypes.hpp" #include @@ -5,17 +6,6 @@ #include #include -extern "C" { -int APS5_VABI mprotect_nid_postfix(void*, std::size_t, int) noexcept; -int APS5_VABI sceKernelMapFlexibleMemory(void**, std::size_t, int, int); -int APS5_VABI sceKernelAllocateDirectMemory(std::int64_t, std::int64_t, std::size_t, std::size_t, int, std::int64_t*); -int APS5_VABI sceKernelMapDirectMemory(void**, std::size_t, int, int, std::int64_t, std::size_t); -int APS5_VABI sceKernelMprotect(const void*, std::size_t, int); -int APS5_VABI sceKernelMunmap(std::uint64_t, std::size_t); -int APS5_VABI sceKernelVirtualQuery(const void*, int, VirtualQueryInfo*, std::uint64_t); -int APS5_VABI sceKernelQueryMemoryProtection(void*, void**, void**, int*); -} - namespace { constexpr std::size_t Page = 0x4000; diff --git a/core/libs/tests/GuestPsml.cpp b/core/libs/tests/GuestPsml.cpp index 882a4b5d04..d2cc7925b7 100644 --- a/core/libs/tests/GuestPsml.cpp +++ b/core/libs/tests/GuestPsml.cpp @@ -1,3 +1,4 @@ +#include "prx/libScePsml_debug/libScePsml_debug.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -7,28 +8,6 @@ #include #include -extern "C" { -std::int32_t APS5_VABI scePsmlMfsrGetContextBufferRequirement1100(void* requirement, const void* param); -std::int32_t APS5_VABI scePsmlMfsrCreateContext1100(void** context, const void* param); -std::int32_t APS5_VABI scePsmlMfsrGetDispatchMfsrPacket1100(void* context, void* commandBuffer, const void* param); -std::int32_t APS5_VABI scePsmlMfsrGetContextBufferRequirement800M3_2(void* requirement, const void* param); -std::int32_t APS5_VABI scePsmlMfsrCreateContext800M3_2(void** context, const void* param); -std::int32_t APS5_VABI scePsmlMfsrCreateContext1300(void** context, const void* param); -std::int32_t APS5_VABI scePsmlMfsrGetDispatchMfsrPacket900(void* context, void* commandBuffer, const void* param); -std::int32_t APS5_VABI scePsmlMfsrGetDispatchMfsrPacket1000(void* context, void* commandBuffer, const void* param); -std::int32_t APS5_VABI scePsmlMfsrGetDispatchMfsrPacket1300(void* context, void* commandBuffer, const void* param); -std::int32_t APS5_VABI scePsmlMfsrInit(); -std::int32_t APS5_VABI scePsmlMfsrGetSharedResourcesInitRequirement(void* requirement, const void* param); -std::int32_t APS5_VABI scePsmlMfsrCreateSharedResources(void** sharedResources, const void* param); -std::int32_t APS5_VABI scePsmlMfsrReleaseSharedResources(void* sharedResources); -std::int32_t APS5_VABI scePsmlMfsrReleaseContext(void* context); -std::int32_t APS5_VABI scePsmlMfsrGetDispatchMfsrPacketSizeInDwords(void* context, std::uint32_t* packetSizeInDwords); -std::int32_t APS5_VABI scePsmlMfsrSelectConfig(void* config); -std::int32_t APS5_VABI scePsmlMfsrGetMipmapBias(void* context, float* bias, std::uint32_t dimension); -std::int32_t APS5_VABI scePsmlMfsrRequestCapture(void* context); -std::int32_t APS5_VABI scePsmlMfsrIsCaptureInProgress(void* context); -} - namespace { void Require(bool value) { if (!value) std::abort(); } @@ -37,20 +16,15 @@ constexpr std::int32_t kErrNotInitialized = static_cast(0x8A810001 constexpr std::int32_t kErrInvalidArgument = static_cast(0x8A810005); constexpr std::int32_t kErrNullOutput = static_cast(0x8A810009); -struct CommandBuffer { - std::uint32_t* cursor; - std::uint32_t sizeInDwords; -}; - -using CreateContext = std::int32_t (APS5_VABI*)(void**, const void*); using GetDispatchPacket = std::int32_t (APS5_VABI*)(void*, void*, const void*); -void CreateContextUntouched(CreateContext create) { +template +void CreateContextUntouched(std::int32_t (APS5_VABI* create)(void**, const TParam*)) { std::array param{}; std::uint64_t contextStorage = 0; void* const sentinel = &contextStorage; void* context = sentinel; - Require(create(&context, param.data()) == kErrNotInitialized); + Require(create(&context, reinterpret_cast(param.data())) == kErrNotInitialized); Require(context == sentinel); Require(create(nullptr, nullptr) == kErrNotInitialized); } @@ -61,7 +35,7 @@ void DispatchPacketUntouched(GetDispatchPacket dispatch) { std::array dwords; dwords.fill(0xa5a5a5a5u); const auto untouchedDwords = dwords; - CommandBuffer commandBuffer{dwords.data(), static_cast(dwords.size())}; + MfsrCommandBuffer commandBuffer{dwords.data(), static_cast(dwords.size())}; Require(dispatch(&contextStorage, &commandBuffer, param.data()) == kErrNotInitialized); Require(dispatch(nullptr, &commandBuffer, nullptr) == kErrNotInitialized); Require(commandBuffer.cursor == dwords.data()); @@ -79,29 +53,10 @@ bool Throws(TCall call, const char* text) { return false; } -struct Requirement { - std::uint64_t blockBytes; - std::uint64_t alignment; - std::uint64_t blockCount; -}; - -struct Block { - std::uint64_t address; - std::uint64_t bytes; -}; - -struct SharedParam { - std::uint32_t type; - std::uint32_t reserved; - const Block* blocks; - std::uint64_t blockCount; - std::uint64_t reserved2; -}; - struct ContextParam { std::array bytes{}; - void Set(const Block* blocks, std::uint64_t count, void* shared) { + void Set(const MfsrBlock* blocks, std::uint64_t count, void* shared) { std::memcpy(bytes.data() + 0x08, &blocks, sizeof(blocks)); std::memcpy(bytes.data() + 0x10, &count, sizeof(count)); std::memcpy(bytes.data() + 0x38, &shared, sizeof(shared)); @@ -117,8 +72,8 @@ struct ContextParam { } }; -std::vector Blocks(const Requirement& requirement, std::uint64_t first) { - std::vector blocks(requirement.blockCount); +std::vector Blocks(const MfsrRequirement& requirement, std::uint64_t first) { + std::vector blocks(requirement.blockCount); for (std::size_t i = 0; i < blocks.size(); ++i) blocks[i] = {first + i * requirement.blockBytes, requirement.blockBytes}; return blocks; } @@ -127,8 +82,8 @@ void SetupBeforeInit() { std::uint64_t storage = 0; void* const sentinel = &storage; void* handle = sentinel; - Requirement requirement{1, 2, 3}; - SharedParam sharedParam{}; + MfsrRequirement requirement{1, 2, 3}; + MfsrSharedResourcesParam sharedParam{}; Require(scePsmlMfsrGetSharedResourcesInitRequirement(&requirement, &sharedParam) == kErrNotInitialized); Require(requirement.blockBytes == 1 && requirement.alignment == 2 && requirement.blockCount == 3); Require(scePsmlMfsrCreateSharedResources(&handle, &sharedParam) == kErrNotInitialized); @@ -151,8 +106,8 @@ void SetupAfterInit() { Require(scePsmlMfsrInit() == 0); Require(scePsmlMfsrInit() == 0); - SharedParam sharedParam{}; - Requirement shared{}; + MfsrSharedResourcesParam sharedParam{}; + MfsrRequirement shared{}; Require(scePsmlMfsrGetSharedResourcesInitRequirement(&shared, &sharedParam) == 0); Require(shared.blockBytes == 0x200000 && shared.alignment == 0x200000 && shared.blockCount == 52); @@ -165,14 +120,14 @@ void SetupAfterInit() { ContextParam contextParam; contextParam.Set(nullptr, 0, sharedResources); - Requirement context{}; - Require(scePsmlMfsrGetContextBufferRequirement800M3_2(&context, contextParam.bytes.data()) == 0); + MfsrRequirement context{}; + Require(scePsmlMfsrGetContextBufferRequirement800M3_2(&context, reinterpret_cast(contextParam.bytes.data())) == 0); Require(context.blockBytes == 0x200000 && context.alignment == 0x200000 && context.blockCount == 4); const auto contextBlocks = Blocks(context, 0x20000000); contextParam.Set(contextBlocks.data(), contextBlocks.size(), sharedResources); void* mfsrContext = nullptr; - Require(scePsmlMfsrCreateContext800M3_2(&mfsrContext, contextParam.bytes.data()) == 0); + Require(scePsmlMfsrCreateContext800M3_2(&mfsrContext, reinterpret_cast(contextParam.bytes.data())) == 0); Require(mfsrContext != nullptr && mfsrContext != sharedResources); std::uint32_t packetDwords = 0; @@ -202,7 +157,7 @@ void SetupAfterInit() { dimensionsParam.Set(contextBlocks.data(), contextBlocks.size(), sharedResources); dimensionsParam.SetInputDimensions(1920, 1080); void* dimensionContext = nullptr; - Require(scePsmlMfsrCreateContext800M3_2(&dimensionContext, dimensionsParam.bytes.data()) == 0); + Require(scePsmlMfsrCreateContext800M3_2(&dimensionContext, reinterpret_cast(dimensionsParam.bytes.data())) == 0); Require(scePsmlMfsrGetMipmapBias(dimensionContext, &bias, 3840) == 0); Require(bias == 0.0f); Require(scePsmlMfsrGetMipmapBias(dimensionContext, &bias, 1920) == 0); @@ -218,7 +173,7 @@ void SetupAfterInit() { descriptorParam.Set(contextBlocks.data(), contextBlocks.size(), sharedResources); descriptorParam.SetDescriptor0(descriptor.data()); void* descriptorContext = nullptr; - Require(scePsmlMfsrCreateContext800M3_2(&descriptorContext, descriptorParam.bytes.data()) == 0); + Require(scePsmlMfsrCreateContext800M3_2(&descriptorContext, reinterpret_cast(descriptorParam.bytes.data())) == 0); Require(scePsmlMfsrGetMipmapBias(descriptorContext, &bias, 2560) == 0); Require(bias == 0.0f); Require(scePsmlMfsrReleaseContext(descriptorContext) == 0); @@ -230,9 +185,47 @@ void SetupAfterInit() { Require(scePsmlMfsrReleaseSharedResources(sharedResources) == 0); } +void Mfsr2OnBaseConsole() { + constexpr std::int32_t notInitialized = static_cast(0x8A8A0001); + constexpr std::int32_t unsupportedConsole = static_cast(0x8A8A0012); + Require(scePsmlMfsr2Init() == unsupportedConsole); + Require(scePsmlMfsr2Init() == unsupportedConsole); + + std::array param{}; + std::array requirement; + requirement.fill(0xa5); + const auto untouchedRequirement = requirement; + Require(scePsmlMfsr2GetSharedResourcesInitRequirement(reinterpret_cast(requirement.data()), reinterpret_cast(param.data())) == notInitialized); + Require(scePsmlMfsr2GetContextInitRequirement(reinterpret_cast(requirement.data()), reinterpret_cast(param.data())) == notInitialized); + Require(requirement == untouchedRequirement); + + std::uint64_t storage = 0; + void* const sentinel = &storage; + void* handle = sentinel; + Require(scePsmlMfsr2CreateSharedResources(&handle, reinterpret_cast(param.data())) == notInitialized); + Require(scePsmlMfsr2CreateContext(&handle, reinterpret_cast(param.data())) == notInitialized); + Require(handle == sentinel); + Require(scePsmlMfsr2ReleaseContext(sentinel) == notInitialized); + Require(scePsmlMfsr2ReleaseSharedResources(sentinel) == notInitialized); + + std::uint32_t packetDwords = 0xa5a5a5a5; + Require(scePsmlMfsr2GetDispatchPacketsSizeInDwords(sentinel, &packetDwords) == notInitialized); + Require(packetDwords == 0xa5a5a5a5); + + std::array dispatchParam{}; + std::array dwords; + dwords.fill(0xa5a5a5a5u); + const auto untouchedDwords = dwords; + MfsrCommandBuffer commandBuffer{dwords.data(), static_cast(dwords.size())}; + Require(scePsmlMfsr2GetDispatchPackets(sentinel, &commandBuffer, reinterpret_cast(dispatchParam.data())) == notInitialized); + Require(commandBuffer.cursor == dwords.data()); + Require(commandBuffer.sizeInDwords == dwords.size()); + Require(dwords == untouchedDwords); +} + void RefusedAfterInit() { - SharedParam sharedParam{}; - Requirement requirement{}; + MfsrSharedResourcesParam sharedParam{}; + MfsrRequirement requirement{}; sharedParam.type = 1; Require(Throws([&] { scePsmlMfsrGetSharedResourcesInitRequirement(&requirement, &sharedParam); }, "type 1 is not supported")); @@ -254,12 +247,12 @@ void RefusedAfterInit() { ContextParam contextParam; contextParam.Set(blocks.data(), blocks.size(), &foreign); void* context = nullptr; - Require(Throws([&] { scePsmlMfsrCreateContext800M3_2(&context, contextParam.bytes.data()); }, "shared resources handle was not created")); + Require(Throws([&] { scePsmlMfsrCreateContext800M3_2(&context, reinterpret_cast(contextParam.bytes.data())); }, "shared resources handle was not created")); Require(context == nullptr); std::array param{}; std::array dwords{}; - CommandBuffer commandBuffer{dwords.data(), static_cast(dwords.size())}; + MfsrCommandBuffer commandBuffer{dwords.data(), static_cast(dwords.size())}; Require(Throws([&] { scePsmlMfsrGetContextBufferRequirement1100(&requirement, param.data()); }, "not implemented")); Require(Throws([&] { scePsmlMfsrCreateContext1300(&context, param.data()); }, "not implemented")); Require(Throws([&] { scePsmlMfsrGetDispatchMfsrPacket900(&foreign, &commandBuffer, param.data()); }, "not implemented")); @@ -289,7 +282,7 @@ int main() { std::array dwords; dwords.fill(0xa5a5a5a5u); const auto untouchedDwords = dwords; - CommandBuffer commandBuffer{dwords.data(), static_cast(dwords.size())}; + MfsrCommandBuffer commandBuffer{dwords.data(), static_cast(dwords.size())}; Require(scePsmlMfsrGetDispatchMfsrPacket1100(&contextStorage, &commandBuffer, param.data()) == kErrNotInitialized); Require(commandBuffer.cursor == dwords.data()); Require(commandBuffer.sizeInDwords == dwords.size()); @@ -301,7 +294,7 @@ int main() { std::array olderRequirement; olderRequirement.fill(0xa5); const auto untouchedOlderRequirement = olderRequirement; - Require(scePsmlMfsrGetContextBufferRequirement800M3_2(olderRequirement.data(), param.data()) == kErrNotInitialized); + Require(scePsmlMfsrGetContextBufferRequirement800M3_2(reinterpret_cast(olderRequirement.data()), reinterpret_cast(param.data())) == kErrNotInitialized); Require(olderRequirement == untouchedOlderRequirement); Require(scePsmlMfsrGetContextBufferRequirement800M3_2(nullptr, nullptr) == kErrNotInitialized); @@ -311,6 +304,7 @@ int main() { DispatchPacketUntouched(scePsmlMfsrGetDispatchMfsrPacket1000); DispatchPacketUntouched(scePsmlMfsrGetDispatchMfsrPacket1300); SetupBeforeInit(); + Mfsr2OnBaseConsole(); SetupAfterInit(); RefusedAfterInit(); } diff --git a/core/libs/tests/GuestPthreadAttr.cpp b/core/libs/tests/GuestPthreadAttr.cpp index 5afa252aa8..5e905c13e9 100644 --- a/core/libs/tests/GuestPthreadAttr.cpp +++ b/core/libs/tests/GuestPthreadAttr.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/KernelErrors.hpp" +#include "prx/libkernel/include/Api.hpp" #include "SceTypes.hpp" #include #include @@ -5,42 +7,7 @@ #include #include -extern "C" { -int APS5_VABI scePthreadCreate(Pthread* thread, const PthreadAttr* attr, PthreadEntry entry, void* arg, const char* name); -int APS5_VABI scePthreadJoin(Pthread thread, void** retval); -int APS5_VABI scePthreadSetprio(Pthread thread, int prio); -int APS5_VABI scePthreadSetaffinity(Pthread thread, KernelCpumask mask); -int APS5_VABI scePthreadAttrInit(PthreadAttr* attr); -int APS5_VABI scePthreadAttrDestroy(PthreadAttr* attr); -int APS5_VABI scePthreadAttrGet(Pthread thread, PthreadAttr* attr); -int APS5_VABI scePthreadAttrSetinheritsched(PthreadAttr* attr, int inheritSched); -int APS5_VABI scePthreadAttrSetschedparam(PthreadAttr* attr, const KernelSchedParam* param); -int APS5_VABI scePthreadAttrSetaffinity(PthreadAttr* attr, KernelCpumask mask); -int APS5_VABI scePthreadAttrSetstacksize(PthreadAttr* attr, std::size_t stackSize); -int APS5_VABI scePthreadAttrGetschedparam(const PthreadAttr* attr, KernelSchedParam* param); -int APS5_VABI scePthreadAttrGetaffinity(const PthreadAttr* attr, KernelCpumask* mask); -int APS5_VABI scePthreadAttrGetstacksize(const PthreadAttr* attr, std::size_t* stackSize); -int APS5_VABI scePthreadAttrGetdetachstate(const PthreadAttr* attr, int* state); -int APS5_VABI scePthreadAttrGetsolosched(const PthreadAttr* attr, int* solosched); -int APS5_VABI pthread_attr_setstacksize_nid_postfix(PthreadAttr* attr, std::size_t stackSize); -int APS5_VABI pthread_attr_setsolosched_np_nid_postfix(PthreadAttr* attr, int solosched); -int APS5_VABI pthread_attr_getinheritsched_nid_postfix(const PthreadAttr* attr, int* inherit_sched); -int APS5_VABI pthread_attr_setinheritsched_nid_postfix(PthreadAttr* attr, int inherit_sched); -int APS5_VABI pthread_attr_getscope_nid_postfix(const PthreadAttr* attr, int* scope); -int APS5_VABI pthread_attr_setscope_nid_postfix(PthreadAttr* attr, int scope); -int APS5_VABI pthread_attr_get_np_nid_postfix(Pthread thread, PthreadAttr* attr); -int APS5_VABI pthread_attr_setschedparam_nid_postfix(PthreadAttr* attr, const KernelSchedParam* param); -int APS5_VABI pthread_attr_setschedpolicy_nid_postfix(PthreadAttr* attr, int policy); -int APS5_VABI pthread_attr_getschedpolicy_nid_postfix(const PthreadAttr* attr, int* policy); -int APS5_VABI scePthreadAttrSetdetachstate(PthreadAttr* attr, int state); -int APS5_VABI scePthreadKeyCreate(PthreadKey* key, pthread_key_destructor_func_t destructor); -int APS5_VABI scePthreadKeyDelete(PthreadKey key); -int APS5_VABI scePthreadSetspecific(PthreadKey key, void* value); -Pthread APS5_VABI scePthreadSelf(); -} - static constexpr int SCE_OK = 0; -static constexpr int SCE_KERNEL_ERROR_EINVAL = static_cast(0x80020016); static constexpr int EXPLICIT_SCHED = 0; static constexpr int INHERIT_SCHED = 4; static constexpr int SCOPE_PROCESS = 0; @@ -54,7 +21,6 @@ static constexpr std::size_t STACK_SIZE = 2u << 20; static constexpr std::size_t MIN_STACK_SIZE = 16384; static constexpr int GUEST_EINVAL = 22; static constexpr int GUEST_ENOTSUP = 45; -static constexpr int SCE_KERNEL_ERROR_ESRCH = static_cast(0x80020003); static constexpr int DETACH_DETACHED = 1; static constexpr int DETACHED_THREADS = 32; @@ -67,12 +33,6 @@ struct ReportedAttributes { int detachState = -1; }; -extern "C" { -int APS5_VABI pthread_attr_setstack_nid_postfix(PthreadAttr* attr, void* addr, std::size_t size); -int APS5_VABI pthread_attr_getstack_nid_postfix(const PthreadAttr* attr, void** addr, std::size_t* size); -int APS5_VABI pthread_attr_getstackaddr_nid_postfix(const PthreadAttr* attr, void** addr); -} - static ReportedAttributes Query(Pthread thread) { PthreadAttr attr = nullptr; Require(scePthreadAttrInit(&attr) == SCE_OK); @@ -101,8 +61,6 @@ static void CheckStackSizeLimit() { Require(scePthreadAttrDestroy(&attr) == SCE_OK); } -extern "C" int APS5_VABI scePthreadAttrSetsolosched(PthreadAttr* attr, int solosched); - static void CheckSoloSched() { PthreadAttr attr = nullptr; Require(pthread_attr_setsolosched_np_nid_postfix(nullptr, 1) == GUEST_EINVAL); @@ -207,6 +165,7 @@ static void CheckSchedulingAttributes() { bool threw = false; try { pthread_attr_getinheritsched_nid_postfix(&attr, nullptr); + } catch (const std::exception&) { threw = true; } diff --git a/core/libs/tests/GuestPthreadAttrErrors.cpp b/core/libs/tests/GuestPthreadAttrErrors.cpp index 06c2e15832..97636eb722 100644 --- a/core/libs/tests/GuestPthreadAttrErrors.cpp +++ b/core/libs/tests/GuestPthreadAttrErrors.cpp @@ -1,29 +1,12 @@ +#include "prx/libkernel/KernelErrors.hpp" +#include "prx/libkernel/include/Api.hpp" #include "SceTypes.hpp" #include #include #include #include -extern "C" { -int APS5_VABI scePthreadAttrInit(PthreadAttr* attr); -int APS5_VABI scePthreadAttrDestroy(PthreadAttr* attr); -int APS5_VABI scePthreadAttrSetstacksize(PthreadAttr* attr, std::size_t stackSize); -int APS5_VABI scePthreadAttrGetstacksize(const PthreadAttr* attr, std::size_t* stackSize); -int APS5_VABI scePthreadAttrSetdetachstate(PthreadAttr* attr, int state); -int APS5_VABI scePthreadAttrGetdetachstate(const PthreadAttr* attr, int* state); -int APS5_VABI scePthreadAttrSetschedpolicy(PthreadAttr* attr, int policy); -int APS5_VABI scePthreadAttrGetschedpolicy(const PthreadAttr* attr, int* policy); -int APS5_VABI scePthreadAttrSetinheritsched(PthreadAttr* attr, int inheritSched); -int APS5_VABI scePthreadAttrGetinheritsched(const PthreadAttr* attr, int* inheritSched); -int APS5_VABI scePthreadAttrSetschedparam(PthreadAttr* attr, const KernelSchedParam* param); -int APS5_VABI scePthreadAttrGetschedparam(const PthreadAttr* attr, KernelSchedParam* param); -int APS5_VABI scePthreadAttrSetaffinity(PthreadAttr* attr, KernelCpumask mask); -int APS5_VABI scePthreadAttrGetaffinity(const PthreadAttr* attr, KernelCpumask* mask); -} - static constexpr int SCE_OK = 0; -static constexpr int SCE_KERNEL_ERROR_EINVAL = static_cast(0x80020016u); -static constexpr int SCE_KERNEL_ERROR_EOPNOTSUPP = static_cast(0x8002002Du); static void Require(bool value) { if (!value) std::abort(); } diff --git a/core/libs/tests/GuestPthreadAttrStack.cpp b/core/libs/tests/GuestPthreadAttrStack.cpp index faf907527a..4193f08fe6 100644 --- a/core/libs/tests/GuestPthreadAttrStack.cpp +++ b/core/libs/tests/GuestPthreadAttrStack.cpp @@ -1,19 +1,9 @@ +#include "prx/libkernel/include/Api.hpp" #include "SceTypes.hpp" #include #include #include -extern "C" { -int APS5_VABI scePthreadAttrInit(PthreadAttr* attr); -int APS5_VABI scePthreadAttrDestroy(PthreadAttr* attr); -int APS5_VABI scePthreadAttrGetstack(const PthreadAttr* attr, void** stackAddress, std::size_t* stackSize); -int APS5_VABI scePthreadAttrGetstackaddr(const PthreadAttr* attr, void** stackAddress); -int APS5_VABI scePthreadAttrGetguardsize(const PthreadAttr* attr, std::size_t* guardSize); -int APS5_VABI scePthreadAttrSetguardsize(PthreadAttr* attr, std::size_t guardSize); -int APS5_VABI scePthreadAttrSetstack(PthreadAttr* attr, void* stackAddress, std::size_t stackSize); -int APS5_VABI scePthreadAttrSetstackaddr(PthreadAttr* attr, void* stackAddress); -} - static constexpr int SCE_OK = 0; static constexpr int SceEinval = static_cast(0x80020016u); static constexpr std::size_t DefaultStackSize = 1u << 20; diff --git a/core/libs/tests/GuestPthreadBarrier.cpp b/core/libs/tests/GuestPthreadBarrier.cpp index 163c97b14c..3b314e9430 100644 --- a/core/libs/tests/GuestPthreadBarrier.cpp +++ b/core/libs/tests/GuestPthreadBarrier.cpp @@ -1,24 +1,10 @@ +#include "prx/libkernel/include/Api.hpp" #include "SceTypes.hpp" #include #include #include #include -struct GuestBarrier; -struct GuestBarrierattr; - -extern "C" { -int APS5_VABI scePthreadCreate(Pthread* thread, const PthreadAttr* attr, PthreadEntry entry, void* arg, const char* name); -int APS5_VABI scePthreadJoin(Pthread thread, void** retval); -int APS5_VABI pthread_barrierattr_init_nid_postfix(GuestBarrierattr** attr); -int APS5_VABI pthread_barrierattr_destroy_nid_postfix(GuestBarrierattr** attr); -int APS5_VABI pthread_barrierattr_getpshared_nid_postfix(GuestBarrierattr* const* attr, int* pshared); -int APS5_VABI pthread_barrierattr_setpshared_nid_postfix(GuestBarrierattr** attr, int pshared); -int APS5_VABI pthread_barrier_init_nid_postfix(GuestBarrier** barrier, GuestBarrierattr* const* attr, unsigned count); -int APS5_VABI pthread_barrier_wait_nid_postfix(GuestBarrier** barrier); -int APS5_VABI pthread_barrier_destroy_nid_postfix(GuestBarrier** barrier); -} - static constexpr int GUEST_EINVAL = 22; static constexpr int PROCESS_PRIVATE = 0; static constexpr int PROCESS_SHARED = 1; @@ -28,7 +14,7 @@ static constexpr unsigned WAITERS = 4; static void Require(bool value) { if (!value) std::abort(); } struct Context { - GuestBarrier* barrier = nullptr; + PthreadBarrierPrivate* barrier = nullptr; std::atomic serial{0}; std::atomic released{0}; }; @@ -57,7 +43,7 @@ static void RunWaiters(Context& context) { } int main() { - GuestBarrierattr* missing = nullptr; + PthreadBarrierattrPrivate* missing = nullptr; int pshared = -1; Require(pthread_barrierattr_init_nid_postfix(nullptr) == GUEST_EINVAL); Require(pthread_barrierattr_destroy_nid_postfix(nullptr) == GUEST_EINVAL); @@ -68,7 +54,7 @@ int main() { Require(pthread_barrierattr_setpshared_nid_postfix(&missing, PROCESS_PRIVATE) == GUEST_EINVAL); Require(pshared == -1); - GuestBarrierattr* attr = nullptr; + PthreadBarrierattrPrivate* attr = nullptr; Require(pthread_barrierattr_init_nid_postfix(&attr) == 0 && attr != nullptr); Require(pthread_barrierattr_getpshared_nid_postfix(&attr, &pshared) == 0 && pshared == PROCESS_PRIVATE); Require(pthread_barrierattr_setpshared_nid_postfix(&attr, 2) == GUEST_EINVAL); @@ -88,7 +74,7 @@ int main() { catch (const std::invalid_argument&) { rejected = true; } Require(rejected); - GuestBarrier* invalid = nullptr; + PthreadBarrierPrivate* invalid = nullptr; Require(pthread_barrier_init_nid_postfix(nullptr, &attr, 1) == GUEST_EINVAL); Require(pthread_barrier_init_nid_postfix(&invalid, &attr, 0) == GUEST_EINVAL && invalid == nullptr); Require(pthread_barrier_init_nid_postfix(&invalid, &attr, 0x80000000u) == GUEST_EINVAL && invalid == nullptr); @@ -120,7 +106,7 @@ int main() { Require(destroyed.serial == 1); } - GuestBarrier* single = nullptr; + PthreadBarrierPrivate* single = nullptr; Require(pthread_barrierattr_init_nid_postfix(&attr) == 0); Require(pthread_barrier_init_nid_postfix(&single, &attr, 1) == 0); Require(pthread_barrier_wait_nid_postfix(&single) == BARRIER_SERIAL_THREAD); diff --git a/core/libs/tests/GuestPthreadCancel.cpp b/core/libs/tests/GuestPthreadCancel.cpp index 81cc47ebde..9309d74dae 100644 --- a/core/libs/tests/GuestPthreadCancel.cpp +++ b/core/libs/tests/GuestPthreadCancel.cpp @@ -1,3 +1,10 @@ +#include "prx/libkernel/KernelErrors.hpp" +#include "prx/libkernel/include/Api.hpp" +#include "prx/libkernel/Time/include/Time.hpp" +#include "prx/libkernel/Pthread/include/ThreadLifecycle.hpp" +#include "prx/libkernel/Pthread/include/Mutex.hpp" +#include "prx/libkernel/Pthread/include/Cond.hpp" +#include "prx/libkernel/Pthread/include/Cancel.hpp" #include "SceTypes.hpp" #include #include @@ -5,42 +12,7 @@ #include #include -extern "C" { -int APS5_VABI scePthreadCreate(Pthread* thread, const PthreadAttr* attr, PthreadEntry entry, void* arg, const char* name); -int APS5_VABI scePthreadJoin(Pthread thread, void** retval); -Pthread APS5_VABI scePthreadSelf(); -void APS5_VABI scePthreadExit(void* retval); -int APS5_VABI scePthreadCancel(Pthread thread); -int APS5_VABI scePthreadSetcancelstate(int state, int* old_state); -int APS5_VABI scePthreadSetcanceltype(int type, int* old_type); -void APS5_VABI scePthreadTestcancel(); -int APS5_VABI scePthreadMutexInit(PthreadMutex* mutex, const PthreadMutexattr* attr, const char* name); -int APS5_VABI scePthreadMutexDestroy(PthreadMutex* mutex); -int APS5_VABI scePthreadMutexLock(PthreadMutex* mutex); -int APS5_VABI scePthreadMutexUnlock(PthreadMutex* mutex); -int APS5_VABI scePthreadCondInit(PthreadCond* cond, const PthreadCondattr* attr, const char* name); -int APS5_VABI scePthreadCondDestroy(PthreadCond* cond); -int APS5_VABI scePthreadCondWait(PthreadCond* cond, PthreadMutex* mutex); -int APS5_VABI scePthreadSemInit(PthreadSem* sem, int flag, unsigned int value, const char* name); -int APS5_VABI scePthreadSemDestroy(PthreadSem* sem); -int APS5_VABI scePthreadSemWait(PthreadSem* sem); -int APS5_VABI sceKernelUsleep_nid_postfix(KernelUseconds microseconds); -int APS5_VABI pthread_cancel_nid_postfix(Pthread thread); -int APS5_VABI pthread_setcanceltype_nid_postfix(int type, int* old_type); -int APS5_VABI sem_init_nid_postfix(void* sem, int pshared, unsigned int value); -int APS5_VABI sem_destroy_nid_postfix(void* sem); -int APS5_VABI sem_wait_nid_postfix(void* sem); -int APS5_VABI sem_timedwait_nid_postfix(void* sem, const KernelTimespec* abstime); -int APS5_VABI sem_getvalue_nid_postfix(void* sem, int* value); -void APS5_VABI __pthread_cleanup_push_imp_nid_postfix(void (APS5_VABI* routine)(void*), void* argument, void* info); -void APS5_VABI __pthread_cleanup_pop_imp_nid_postfix(int execute); -void APS5_VABI pthread_cleanup_push_nid_postfix(void (APS5_VABI* routine)(void*), void* argument); -void APS5_VABI pthread_cleanup_pop_nid_postfix(int execute); -} - static constexpr int SCE_OK = 0; -static constexpr int SCE_KERNEL_ERROR_ESRCH = static_cast(0x80020003); -static constexpr int SCE_KERNEL_ERROR_EINVAL = static_cast(0x80020016); static constexpr int GUEST_ESRCH = 3; static constexpr int GUEST_EINVAL = 22; static constexpr int CANCEL_ENABLE = 0; @@ -80,6 +52,7 @@ static void* APS5_VABI CondWaiter(void*) { std::uintptr_t info[8]; Require(scePthreadMutexLock(&shared.mutex) == SCE_OK); __pthread_cleanup_push_imp_nid_postfix(UnlockMutex, nullptr, info); + shared.ready.store(true); for (;;) Require(scePthreadCondWait(&shared.cond, &shared.mutex) == SCE_OK); } @@ -87,6 +60,7 @@ static void* APS5_VABI CondWaiter(void*) { static void* APS5_VABI SemWaiter(void*) { shared.ready.store(true); scePthreadSemWait(&shared.sem); + shared.returned.store(true); return nullptr; } @@ -94,6 +68,7 @@ static void* APS5_VABI SemWaiter(void*) { static void* APS5_VABI PosixSemWaiter(void*) { shared.ready.store(true); sem_wait_nid_postfix(&shared.posixSem); + shared.returned.store(true); return nullptr; } @@ -144,6 +119,7 @@ static void* APS5_VABI Idler(void*) { static void* APS5_VABI Joiner(void*) { shared.ready.store(true); scePthreadJoin(shared.target, nullptr); + shared.returned.store(true); return nullptr; } @@ -160,10 +136,12 @@ static void* APS5_VABI Disabled(void*) { while (!shared.release.load()) { sceKernelUsleep_nid_postfix(1000); scePthreadTestcancel(); + } shared.survived.store(true); Require(scePthreadSetcancelstate(CANCEL_ENABLE, &old) == SCE_OK && old == CANCEL_DISABLE); scePthreadTestcancel(); + shared.returned.store(true); return nullptr; } @@ -175,6 +153,7 @@ static void* APS5_VABI Asynchronous(void*) { shared.ready.store(true); while (!shared.release.load()) std::this_thread::sleep_for(std::chrono::milliseconds(1)); scePthreadSetcancelstate(CANCEL_ENABLE, nullptr); + shared.returned.store(true); return nullptr; } @@ -185,8 +164,10 @@ static void* APS5_VABI Handlers(void*) { __pthread_cleanup_push_imp_nid_postfix(RecordOrder, reinterpret_cast(std::intptr_t{1}), first); __pthread_cleanup_push_imp_nid_postfix(RecordOrder, reinterpret_cast(std::intptr_t{2}), second); __pthread_cleanup_pop_imp_nid_postfix(0); + __pthread_cleanup_push_imp_nid_postfix(RecordOrder, reinterpret_cast(std::intptr_t{3}), second); __pthread_cleanup_pop_imp_nid_postfix(1); + scePthreadExit(reinterpret_cast(std::intptr_t{7})); return nullptr; } @@ -196,8 +177,10 @@ static void* APS5_VABI HeapHandlers(void*) { __pthread_cleanup_push_imp_nid_postfix(RecordOrder, reinterpret_cast(std::intptr_t{1}), first); pthread_cleanup_push_nid_postfix(RecordOrder, reinterpret_cast(std::intptr_t{2})); pthread_cleanup_pop_nid_postfix(0); + pthread_cleanup_push_nid_postfix(RecordOrder, reinterpret_cast(std::intptr_t{3})); __pthread_cleanup_pop_imp_nid_postfix(1); + pthread_cleanup_push_nid_postfix(RecordOrder, reinterpret_cast(std::intptr_t{4})); scePthreadExit(reinterpret_cast(std::intptr_t{8})); return nullptr; diff --git a/core/libs/tests/GuestPthreadCancelRecovery.cpp b/core/libs/tests/GuestPthreadCancelRecovery.cpp index 297f761a92..e7f647ad7c 100644 --- a/core/libs/tests/GuestPthreadCancelRecovery.cpp +++ b/core/libs/tests/GuestPthreadCancelRecovery.cpp @@ -1,3 +1,8 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libkernel/Time/include/Time.hpp" +#include "prx/libkernel/Pthread/include/Mutex.hpp" +#include "prx/libkernel/Pthread/include/Cond.hpp" +#include "prx/libkernel/Pthread/include/Cancel.hpp" #include "SceTypes.hpp" #include "prx/libkernel/Pthread/include/Pthread.hpp" #include @@ -17,46 +22,6 @@ #include #endif -extern "C" { -int APS5_VABI scePthreadCreate(Pthread* thread, const PthreadAttr* attr, PthreadEntry entry, void* arg, const char* name); -int APS5_VABI scePthreadJoin(Pthread thread, void** retval); -int APS5_VABI scePthreadCancel(Pthread thread); -int APS5_VABI scePthreadSetcancelstate(int state, int* oldState); -int APS5_VABI scePthreadSetcanceltype(int type, int* oldType); -void APS5_VABI scePthreadTestcancel(); -int APS5_VABI scePthreadKeyCreate(PthreadKey* key, pthread_key_destructor_func_t destructor); -int APS5_VABI scePthreadKeyDelete(PthreadKey key); -int APS5_VABI scePthreadSetspecific(PthreadKey key, void* value); -int APS5_VABI scePthreadMutexInit(PthreadMutex* mutex, const PthreadMutexattr* attr, const char* name); -int APS5_VABI scePthreadMutexattrInit(PthreadMutexattr* attr); -int APS5_VABI scePthreadMutexattrDestroy(PthreadMutexattr* attr); -int APS5_VABI scePthreadMutexattrSettype(PthreadMutexattr* attr, int type); -int APS5_VABI scePthreadMutexDestroy(PthreadMutex* mutex); -int APS5_VABI scePthreadMutexLock(PthreadMutex* mutex); -int APS5_VABI scePthreadMutexUnlock(PthreadMutex* mutex); -int APS5_VABI scePthreadCondInit(PthreadCond* cond, const PthreadCondattr* attr, const char* name); -int APS5_VABI scePthreadCondDestroy(PthreadCond* cond); -int APS5_VABI scePthreadCondSignal(PthreadCond* cond); -int APS5_VABI scePthreadCondTimedwait(PthreadCond* cond, PthreadMutex* mutex, KernelUseconds usec); -int APS5_VABI scePthreadCondWait(PthreadCond* cond, PthreadMutex* mutex); -int APS5_VABI pthread_cond_wait_nid_postfix(PthreadCond* cond, PthreadMutex* mutex); -int APS5_VABI pthread_cond_timedwait_nid_postfix(PthreadCond* cond, PthreadMutex* mutex, const KernelTimespec* abstime); -int APS5_VABI clock_gettime_nid_postfix(int clockId, KernelTimespec* time); -int APS5_VABI scePthreadSemInit(PthreadSem* sem, int flag, unsigned int value, const char* name); -int APS5_VABI scePthreadSemDestroy(PthreadSem* sem); -int APS5_VABI scePthreadSemWait(PthreadSem* sem); -int APS5_VABI scePthreadSemTimedwait(PthreadSem* sem, KernelUseconds usec); -int APS5_VABI scePthreadSemGetvalue(PthreadSem* sem, int* value); -int APS5_VABI sem_init_nid_postfix(void* sem, int pshared, unsigned int value); -int APS5_VABI sem_destroy_nid_postfix(void* sem); -int APS5_VABI sem_wait_nid_postfix(void* sem); -int APS5_VABI sem_reltimedwait_np_nid_postfix(void* sem, std::uint32_t usec); -int APS5_VABI sem_getvalue_nid_postfix(void* sem, int* value); -int APS5_VABI sceKernelUsleep_nid_postfix(KernelUseconds microseconds); -void APS5_VABI __pthread_cleanup_push_imp_nid_postfix(void (APS5_VABI* routine)(void*), void* argument, void* info); -void APS5_VABI __pthread_cleanup_pop_imp_nid_postfix(int execute); -} - static constexpr int CANCEL_ENABLE = 0; static constexpr int CANCEL_DISABLE = 1; static constexpr int CANCEL_DEFERRED = 0; @@ -121,6 +86,7 @@ static void APS5_VABI Record(void* value) { static void APS5_VABI CleanupWithPoints(void*) { Record(reinterpret_cast(std::uintptr_t{2})); scePthreadTestcancel(); + Require(sceKernelUsleep_nid_postfix(1) == 0); Record(reinterpret_cast(std::uintptr_t{3})); } @@ -150,6 +116,7 @@ static void* APS5_VABI PendingToken(void*) { Require(scePthreadSetspecific(key, &normalResult) == 0); __pthread_cleanup_push_imp_nid_postfix(Record, reinterpret_cast(std::uintptr_t{1}), first); __pthread_cleanup_push_imp_nid_postfix(CleanupWithPoints, nullptr, second); + Gate(); WaitForToken(); returned = true; @@ -161,6 +128,7 @@ static void CheckDefaults() { Require(scePthreadSetcancelstate(CANCEL_ENABLE, &old) == 0 && old == CANCEL_ENABLE); Require(scePthreadSetcanceltype(CANCEL_DEFERRED, &old) == 0 && old == CANCEL_DEFERRED); scePthreadTestcancel(); + } static void* APS5_VABI ConsumeToken(void*) { @@ -198,17 +166,21 @@ static void* APS5_VABI ConditionWaiter(void*) { Require(scePthreadMutexLock(&mutex) == 0); std::uintptr_t info[8]; __pthread_cleanup_push_imp_nid_postfix(Unlock, nullptr, info); + Signal(ready); while (!conditionReleased) Require(scePthreadCondTimedwait(&cond, &mutex, WAIT_MICROSECONDS) == 0); Require(scePthreadMutexUnlock(&mutex) == 0); __pthread_cleanup_pop_imp_nid_postfix(0); + if (disabled) { stage = 1; scePthreadTestcancel(); + int old = -1; Require(scePthreadSetcancelstate(CANCEL_ENABLE, &old) == 0 && old == CANCEL_DISABLE); stage = 2; scePthreadTestcancel(); + } returned = true; return &normalResult; @@ -279,6 +251,7 @@ static void* APS5_VABI SignaledConditionWaiter(void* value) { for (int level = 0; level < context.lockCount; ++level) Require(scePthreadMutexLock(&context.mutex) == 0); std::uintptr_t cleanup[8]; __pthread_cleanup_push_imp_nid_postfix(UnlockSignaledCondition, &worker, cleanup); + context.ready.fetch_add(1); int result = 0; do { @@ -303,6 +276,7 @@ static void* APS5_VABI SignaledConditionWaiter(void* value) { } while (result == 0 && !context.released); context.results[worker.index] = result; __pthread_cleanup_pop_imp_nid_postfix(1); + return nullptr; } diff --git a/core/libs/tests/GuestPthreadCondattr.cpp b/core/libs/tests/GuestPthreadCondattr.cpp index a05d017c80..fb96e05b2d 100644 --- a/core/libs/tests/GuestPthreadCondattr.cpp +++ b/core/libs/tests/GuestPthreadCondattr.cpp @@ -1,19 +1,10 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libkernel/Pthread/include/Cond.hpp" #include "SceTypes.hpp" #include #include #include -extern "C" { -int APS5_VABI scePthreadCondattrInit(PthreadCondattr* attr); -int APS5_VABI scePthreadCondattrDestroy(PthreadCondattr* attr); -int APS5_VABI scePthreadCondattrSetclock(PthreadCondattr* attr, KernelClockid clockId); -int APS5_VABI pthread_condattr_setclock_nid_postfix(PthreadCondattr* attr, KernelClockid clockId); -int APS5_VABI pthread_condattr_setpshared_nid_postfix(PthreadCondattr* attr, int pshared); -int APS5_VABI pthread_condattr_getpshared_nid_postfix(const PthreadCondattr* attr, int* pshared); -int APS5_VABI scePthreadCondattrSetpshared(PthreadCondattr* attr, int pshared); -int APS5_VABI scePthreadCondattrGetpshared(const PthreadCondattr* attr, int* pshared); -} - static constexpr int SCE_OK = 0; static constexpr int SceEinval = static_cast(0x80020016u); static constexpr int GuestEinval = 22; @@ -57,6 +48,7 @@ int main() { bool threw = false; try { pthread_condattr_getpshared_nid_postfix(&attr, nullptr); + } catch (const std::runtime_error&) { threw = true; } diff --git a/core/libs/tests/GuestPthreadDestroyedObjects.cpp b/core/libs/tests/GuestPthreadDestroyedObjects.cpp index ca35d7b099..3232f4c87e 100644 --- a/core/libs/tests/GuestPthreadDestroyedObjects.cpp +++ b/core/libs/tests/GuestPthreadDestroyedObjects.cpp @@ -1,26 +1,12 @@ +#include "prx/libkernel/KernelErrors.hpp" +#include "prx/libkernel/include/Api.hpp" +#include "prx/libkernel/Pthread/include/Mutex.hpp" +#include "prx/libkernel/Pthread/include/Cond.hpp" #include "SceTypes.hpp" #include #include -extern "C" { -int APS5_VABI scePthreadMutexInit(PthreadMutex* mutex, const PthreadMutexattr* attr, const char* name); -int APS5_VABI scePthreadMutexDestroy(PthreadMutex* mutex); -int APS5_VABI scePthreadMutexLock(PthreadMutex* mutex); -int APS5_VABI scePthreadMutexTrylock(PthreadMutex* mutex); -int APS5_VABI scePthreadMutexUnlock(PthreadMutex* mutex); -int APS5_VABI scePthreadCondInit(PthreadCond* cond, const PthreadCondattr* attr, const char* name); -int APS5_VABI scePthreadCondDestroy(PthreadCond* cond); -int APS5_VABI scePthreadCondSignal(PthreadCond* cond); -int APS5_VABI scePthreadCondBroadcast(PthreadCond* cond); -int APS5_VABI scePthreadCondWait(PthreadCond* cond, PthreadMutex* mutex); -int APS5_VABI pthread_mutex_lock_nid_postfix(PthreadMutex* mutex); -int APS5_VABI pthread_cond_signal_nid_postfix(PthreadCond* cond); -int APS5_VABI pthread_cond_destroy_nid_postfix(PthreadCond* cond); -} - static constexpr int SCE_OK = 0; -static constexpr int SCE_KERNEL_ERROR_EPERM = static_cast(0x80020001u); -static constexpr int SCE_KERNEL_ERROR_EINVAL = static_cast(0x80020016u); static constexpr int POSIX_EINVAL = 22; static void Require(bool value) { if (!value) std::abort(); } diff --git a/core/libs/tests/GuestPthreadDestructorLifetime.cpp b/core/libs/tests/GuestPthreadDestructorLifetime.cpp index 4bddcb951c..2001d54acb 100644 --- a/core/libs/tests/GuestPthreadDestructorLifetime.cpp +++ b/core/libs/tests/GuestPthreadDestructorLifetime.cpp @@ -1,23 +1,11 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libkernel/Time/include/Time.hpp" +#include "prx/libkernel/Pthread/include/ThreadLifecycle.hpp" #include "SceTypes.hpp" #include #include #include -extern "C" { -int APS5_VABI scePthreadCreate(Pthread* thread, const PthreadAttr* attr, PthreadEntry entry, void* arg, const char* name); -int APS5_VABI scePthreadJoin(Pthread thread, void** retval); -int APS5_VABI scePthreadCancel(Pthread thread); -void APS5_VABI scePthreadExit(void* retval); -Pthread APS5_VABI scePthreadSelf(); -int APS5_VABI scePthreadGetthreadid(); -int APS5_VABI scePthreadGetname(Pthread thread, char* name); -int APS5_VABI scePthreadKeyCreate(PthreadKey* key, pthread_key_destructor_func_t destructor); -int APS5_VABI scePthreadKeyDelete(PthreadKey key); -void* APS5_VABI scePthreadGetspecific(PthreadKey key); -int APS5_VABI scePthreadSetspecific(PthreadKey key, void* value); -int APS5_VABI sceKernelUsleep_nid_postfix(KernelUseconds microseconds); -} - struct Context { PthreadKey key = -1; Pthread expected = nullptr; diff --git a/core/libs/tests/GuestPthreadFrameChain.cpp b/core/libs/tests/GuestPthreadFrameChain.cpp index d9c491090f..b0d3fc5822 100644 --- a/core/libs/tests/GuestPthreadFrameChain.cpp +++ b/core/libs/tests/GuestPthreadFrameChain.cpp @@ -1,13 +1,9 @@ +#include "prx/libkernel/include/Api.hpp" #include "SceTypes.hpp" #include #include #include -extern "C" { -int APS5_VABI scePthreadCreate(Pthread* thread, const PthreadAttr* attr, PthreadEntry entry, void* arg, const char* name); -int APS5_VABI scePthreadJoin(Pthread thread, void** retval); -} - static constexpr int SCE_OK = 0; static constexpr std::uintptr_t ChainReach = std::uintptr_t{64} << 10; diff --git a/core/libs/tests/GuestPthreadGetname.cpp b/core/libs/tests/GuestPthreadGetname.cpp index f8545f6078..fe3554d545 100644 --- a/core/libs/tests/GuestPthreadGetname.cpp +++ b/core/libs/tests/GuestPthreadGetname.cpp @@ -1,18 +1,10 @@ +#include "prx/libkernel/include/Api.hpp" #include "SceTypes.hpp" #include #include #include #include -extern "C" { -Pthread APS5_VABI pthread_self_nid_postfix(void); -int APS5_VABI pthread_rename_np_nid_postfix(Pthread thread, const char* name); -int APS5_VABI pthread_getname_np_nid_postfix(Pthread thread, char* name); -int APS5_VABI scePthreadCreate(Pthread* thread, const PthreadAttr* attr, PthreadEntry entry, void* arg, const char* name); -int APS5_VABI scePthreadJoin(Pthread thread, void** retval); -int APS5_VABI scePthreadGetname(Pthread thread, char* name); -} - static constexpr int GUEST_ESRCH = 3; static constexpr int GUEST_EFAULT = 14; diff --git a/core/libs/tests/GuestPthreadJoinDetach.cpp b/core/libs/tests/GuestPthreadJoinDetach.cpp index 48a982989e..20c8014765 100644 --- a/core/libs/tests/GuestPthreadJoinDetach.cpp +++ b/core/libs/tests/GuestPthreadJoinDetach.cpp @@ -1,3 +1,4 @@ +#include "prx/libkernel/include/Api.hpp" #include "prx/libkernel/Pthread/include/Pthread.hpp" #include "prx/libkernel/KernelErrors.hpp" #include @@ -7,10 +8,6 @@ #include #include -extern "C" int APS5_VABI scePthreadCreate(Pthread* thread, const PthreadAttr* attr, PthreadEntry entry, void* arg, const char* name); -extern "C" int APS5_VABI scePthreadJoin(Pthread thread, void** retval); -extern "C" int APS5_VABI scePthreadDetach(Pthread thread); - static constexpr int SCE_OK = 0; static void Require(bool condition, const char* message) { diff --git a/core/libs/tests/GuestPthreadJoinSelf.cpp b/core/libs/tests/GuestPthreadJoinSelf.cpp index 2fec26bef7..6277b58467 100644 --- a/core/libs/tests/GuestPthreadJoinSelf.cpp +++ b/core/libs/tests/GuestPthreadJoinSelf.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/KernelErrors.hpp" +#include "prx/libkernel/include/Api.hpp" #include "SceTypes.hpp" #include #include @@ -5,16 +7,7 @@ #include #include -extern "C" { -int APS5_VABI scePthreadCreate(Pthread* thread, const PthreadAttr* attr, PthreadEntry entry, void* arg, const char* name); -int APS5_VABI scePthreadJoin(Pthread thread, void** retval); -Pthread APS5_VABI scePthreadSelf(void); -int APS5_VABI pthread_join_nid_postfix(Pthread thread, void** retval); -int APS5_VABI scePthreadDetach(Pthread thread); -} - static constexpr int SCE_OK = 0; -static constexpr int SCE_KERNEL_ERROR_EDEADLK = static_cast(0x8002000Bu); static constexpr int GUEST_EDEADLK = 11; static void Require(bool value) { if (!value) std::abort(); } diff --git a/core/libs/tests/GuestPthreadKey.cpp b/core/libs/tests/GuestPthreadKey.cpp index ae87651a61..bbe608bc54 100644 --- a/core/libs/tests/GuestPthreadKey.cpp +++ b/core/libs/tests/GuestPthreadKey.cpp @@ -1,21 +1,11 @@ +#include "prx/libkernel/KernelErrors.hpp" +#include "prx/libkernel/include/Api.hpp" #include "SceTypes.hpp" #include #include #include -extern "C" { -int APS5_VABI scePthreadCreate(Pthread* thread, const PthreadAttr* attr, PthreadEntry entry, void* arg, const char* name); -int APS5_VABI scePthreadJoin(Pthread thread, void** retval); -int APS5_VABI scePthreadKeyCreate(PthreadKey* key, pthread_key_destructor_func_t destructor); -int APS5_VABI scePthreadKeyDelete(PthreadKey key); -void* APS5_VABI scePthreadGetspecific(PthreadKey key); -int APS5_VABI scePthreadSetspecific(PthreadKey key, void* value); -int APS5_VABI pthread_key_create_nid_postfix(PthreadKey* key, pthread_key_destructor_func_t destructor); -int APS5_VABI pthread_key_delete_nid_postfix(PthreadKey key); -} - static constexpr int SCE_OK = 0; -static constexpr int SCE_KERNEL_ERROR_EINVAL = static_cast(0x80020016); static void Require(bool value) { if (!value) std::abort(); } diff --git a/core/libs/tests/GuestPthreadMutexErrors.cpp b/core/libs/tests/GuestPthreadMutexErrors.cpp index da1083b121..7d7947f824 100644 --- a/core/libs/tests/GuestPthreadMutexErrors.cpp +++ b/core/libs/tests/GuestPthreadMutexErrors.cpp @@ -1,38 +1,13 @@ +#include "prx/libkernel/KernelErrors.hpp" +#include "prx/libkernel/include/Api.hpp" +#include "prx/libkernel/Pthread/include/Mutex.hpp" #include "SceTypes.hpp" #include #include #include #include -extern "C" { -int APS5_VABI scePthreadMutexattrInit(PthreadMutexattr* attr); -int APS5_VABI scePthreadMutexattrDestroy(PthreadMutexattr* attr); -int APS5_VABI scePthreadMutexattrSettype(PthreadMutexattr* attr, int type); -int APS5_VABI scePthreadMutexattrSetprotocol(PthreadMutexattr* attr, int protocol); -int APS5_VABI scePthreadMutexInit(PthreadMutex* mutex, const PthreadMutexattr* attr, const char* name); -int APS5_VABI scePthreadMutexDestroy(PthreadMutex* mutex); -int APS5_VABI scePthreadMutexLock(PthreadMutex* mutex); -int APS5_VABI scePthreadMutexUnlock(PthreadMutex* mutex); -int APS5_VABI scePthreadMutexGetspinloops(PthreadMutex* mutex, int* count); -int APS5_VABI scePthreadMutexSetspinloops(PthreadMutex* mutex, int count); -int APS5_VABI scePthreadMutexGetyieldloops(PthreadMutex* mutex, int* count); -int APS5_VABI scePthreadMutexSetyieldloops(PthreadMutex* mutex, int count); -int APS5_VABI scePthreadCreate(Pthread* thread, const PthreadAttr* attr, PthreadEntry entry, void* arg, const char* name); -int APS5_VABI scePthreadJoin(Pthread thread, void** retval); -int APS5_VABI pthread_mutex_lock_nid_postfix(PthreadMutex* mutex); -int APS5_VABI pthread_mutex_unlock_nid_postfix(PthreadMutex* mutex); -int APS5_VABI pthread_mutex_destroy_nid_postfix(PthreadMutex* mutex); -int APS5_VABI pthread_mutex_reltimedlock_np_nid_postfix(PthreadMutex* mutex, KernelUseconds usec); -int APS5_VABI pthread_mutex_isowned_np_nid_postfix(PthreadMutex* mutex); -int APS5_VABI pthread_mutex_getspinloops_np_nid_postfix(PthreadMutex* mutex, int* count); -int APS5_VABI pthread_mutex_setspinloops_np_nid_postfix(PthreadMutex* mutex, int count); -int APS5_VABI pthread_mutex_getyieldloops_np_nid_postfix(PthreadMutex* mutex, int* count); -int APS5_VABI pthread_mutex_setyieldloops_np_nid_postfix(PthreadMutex* mutex, int count); -} - static constexpr int SCE_OK = 0; -static constexpr int SCE_KERNEL_ERROR_EINVAL = static_cast(0x80020016u); -static constexpr int SCE_KERNEL_ERROR_EBUSY = static_cast(0x80020010u); static constexpr int POSIX_EDEADLK = 11; static constexpr int POSIX_EINVAL = 22; @@ -72,7 +47,7 @@ static void CheckOwnershipAndRelativeLock() { Require(pthread_mutex_isowned_np_nid_postfix(&adaptive) == 0 && adaptive == AdaptiveInitializer); Require(pthread_mutex_reltimedlock_np_nid_postfix(&mutex, 1000) == 0 && mutex != nullptr); Require(pthread_mutex_isowned_np_nid_postfix(&mutex) == 1); - Require(pthread_mutex_reltimedlock_np_nid_postfix(&mutex, 1000) == POSIX_EDEADLK); + Require(pthread_mutex_reltimedlock_np_nid_postfix(&mutex, 1000) == POSIX_ETIMEDOUT); OtherThread other{&mutex}; Pthread thread = nullptr; Require(scePthreadCreate(&thread, nullptr, CheckFromOtherThread, &other, nullptr) == SCE_OK); diff --git a/core/libs/tests/GuestPthreadMutexattr.cpp b/core/libs/tests/GuestPthreadMutexattr.cpp index 859dc770e1..58774211dd 100644 --- a/core/libs/tests/GuestPthreadMutexattr.cpp +++ b/core/libs/tests/GuestPthreadMutexattr.cpp @@ -1,50 +1,19 @@ +#include "prx/libkernel/Pthread/include/Mutex.hpp" +#include "prx/libc/include/Api.hpp" +#include "prx/libkernel/include/Api.hpp" #include "SceTypes.hpp" #include #include #include #include -extern "C" { -int APS5_VABI pthread_mutexattr_init_nid_postfix(PthreadMutexattr* attr); -int APS5_VABI pthread_mutexattr_destroy_nid_postfix(PthreadMutexattr* attr); -int APS5_VABI pthread_mutexattr_getpshared_nid_postfix(const PthreadMutexattr* attr, int* pshared); -int APS5_VABI pthread_mutexattr_setpshared_nid_postfix(PthreadMutexattr* attr, int pshared); -int APS5_VABI pthread_mutexattr_setprotocol_nid_postfix(PthreadMutexattr* attr, int protocol); -int APS5_VABI pthread_mutexattr_getprotocol_nid_postfix(const PthreadMutexattr* attr, int* protocol); -int APS5_VABI pthread_mutexattr_setprioceiling_nid_postfix(PthreadMutexattr* attr, int prioceiling); -int APS5_VABI pthread_mutexattr_getprioceiling_nid_postfix(const PthreadMutexattr* attr, int* prioceiling); -int APS5_VABI pthread_mutexattr_settype_nid_postfix(PthreadMutexattr* attr, int type); -int APS5_VABI pthread_mutexattr_gettype_nid_postfix(const PthreadMutexattr* attr, int* type); -int APS5_VABI pthread_mutexattr_setkind_np_nid_postfix(PthreadMutexattr* attr, int kind); -int APS5_VABI pthread_mutexattr_getkind_np_nid_postfix(PthreadMutexattr attr); -int APS5_VABI scePthreadMutexattrInit(PthreadMutexattr* attr); -int APS5_VABI scePthreadMutexattrDestroy(PthreadMutexattr* attr); -int APS5_VABI scePthreadMutexattrSettype(PthreadMutexattr* attr, int type); -int APS5_VABI scePthreadMutexattrGettype(const PthreadMutexattr* attr, int* type); -int APS5_VABI scePthreadMutexattrSetprotocol(PthreadMutexattr* attr, int protocol); -int APS5_VABI scePthreadMutexattrGetprotocol(const PthreadMutexattr* attr, int* protocol); -int APS5_VABI scePthreadMutexattrSetprioceiling(PthreadMutexattr* attr, int prioceiling); -int APS5_VABI scePthreadMutexattrGetprioceiling(const PthreadMutexattr* attr, int* prioceiling); -int APS5_VABI scePthreadMutexattrSetpshared(PthreadMutexattr* attr, int pshared); -int APS5_VABI scePthreadMutexattrGetpshared(const PthreadMutexattr* attr, int* pshared); -int* APS5_VABI __error_nid_postfix(); -int APS5_VABI pthread_mutex_init_nid_postfix(PthreadMutex* mutex, const PthreadMutexattr* attr); -int APS5_VABI pthread_mutex_lock_nid_postfix(PthreadMutex* mutex); -int APS5_VABI pthread_mutex_unlock_nid_postfix(PthreadMutex* mutex); -int APS5_VABI pthread_mutex_destroy_nid_postfix(PthreadMutex* mutex); -int APS5_VABI pthread_mutex_timedlock_nid_postfix(PthreadMutex* mutex, const KernelTimespec* abstime); -int APS5_VABI scePthreadCreate(Pthread* thread, const PthreadAttr* attr, PthreadEntry entry, void* arg, const char* name); -int APS5_VABI scePthreadJoin(Pthread thread, void** retval); -int APS5_VABI sched_get_priority_max_nid_postfix(int policy); -} - static constexpr int GUEST_EINVAL = 22; static constexpr int SCE_OK = 0; static constexpr int SCE_KERNEL_ERROR_EINVAL = static_cast(0x80020016u); static constexpr int PRIO_NONE = 0; static constexpr int PRIO_INHERIT = 1; static constexpr int PRIO_PROTECT = 2; -static constexpr int SCHED_RR = 3; +static constexpr int GuestSched_Rr = 3; static void Require(bool value) { if (!value) std::abort(); } @@ -154,7 +123,7 @@ static void CheckSceAccessors() { Require(scePthreadMutexattrSetprioceiling(&attr, 300) == SCE_KERNEL_ERROR_EINVAL); Require(scePthreadMutexattrGetprioceiling(&attr, &value) == SCE_KERNEL_ERROR_EINVAL); Require(scePthreadMutexattrSetprotocol(&attr, PRIO_PROTECT) == SCE_OK); - Require(scePthreadMutexattrGetprioceiling(&attr, &value) == SCE_OK && value == sched_get_priority_max_nid_postfix(SCHED_RR)); + Require(scePthreadMutexattrGetprioceiling(&attr, &value) == SCE_OK && value == sched_get_priority_max_nid_postfix(GuestSched_Rr)); Require(scePthreadMutexattrSetprioceiling(&attr, 300) == SCE_OK); Require(scePthreadMutexattrGetprioceiling(&attr, &value) == SCE_OK && value == 300); int protocol = -1; @@ -232,7 +201,7 @@ int main() { Require(pthread_mutexattr_setprioceiling_nid_postfix(&attr, 300) == GUEST_EINVAL); Require(pthread_mutexattr_setprotocol_nid_postfix(&attr, PRIO_PROTECT) == 0); Require(pthread_mutexattr_getprotocol_nid_postfix(&attr, &protocol) == 0 && protocol == PRIO_PROTECT); - Require(pthread_mutexattr_getprioceiling_nid_postfix(&attr, &ceiling) == 0 && ceiling == sched_get_priority_max_nid_postfix(SCHED_RR)); + Require(pthread_mutexattr_getprioceiling_nid_postfix(&attr, &ceiling) == 0 && ceiling == sched_get_priority_max_nid_postfix(GuestSched_Rr)); Require(pthread_mutexattr_setprioceiling_nid_postfix(&attr, 300) == 0); Require(pthread_mutexattr_getprioceiling_nid_postfix(&attr, &ceiling) == 0 && ceiling == 300); PthreadMutex mutex = nullptr; @@ -242,7 +211,7 @@ int main() { Require(pthread_mutex_destroy_nid_postfix(&mutex) == 0); Require(pthread_mutexattr_setprotocol_nid_postfix(&attr, PRIO_PROTECT) == 0); Require(pthread_mutexattr_getprotocol_nid_postfix(&attr, &protocol) == 0 && protocol == PRIO_PROTECT); - Require(pthread_mutexattr_getprioceiling_nid_postfix(&attr, &ceiling) == 0 && ceiling == sched_get_priority_max_nid_postfix(SCHED_RR)); + Require(pthread_mutexattr_getprioceiling_nid_postfix(&attr, &ceiling) == 0 && ceiling == sched_get_priority_max_nid_postfix(GuestSched_Rr)); Require(pthread_mutexattr_setprotocol_nid_postfix(&attr, PRIO_NONE) == 0); Require(pthread_mutexattr_getprotocol_nid_postfix(&attr, &protocol) == 0 && protocol == PRIO_NONE); Require(pthread_mutexattr_getprioceiling_nid_postfix(&attr, &ceiling) == GUEST_EINVAL); diff --git a/core/libs/tests/GuestPthreadRename.cpp b/core/libs/tests/GuestPthreadRename.cpp index e3fdbd18b1..ccfa5ced39 100644 --- a/core/libs/tests/GuestPthreadRename.cpp +++ b/core/libs/tests/GuestPthreadRename.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "SceTypes.hpp" #include #include @@ -5,15 +7,6 @@ #include #include -extern "C" { -int APS5_VABI scePthreadCreate(Pthread* thread, const PthreadAttr* attr, PthreadEntry entry, void* arg, const char* name); -int APS5_VABI scePthreadJoin(Pthread thread, void** retval); -Pthread APS5_VABI scePthreadSelf(); -int APS5_VABI scePthreadGetname(Pthread thread, char* name); -int APS5_VABI pthread_rename_np_nid_postfix(Pthread thread, const char* name); -int* APS5_VABI __error_nid_postfix(); -} - static void Require(bool value) { if (!value) std::abort(); } static void CheckStoredName(Pthread thread, const std::string& expected) { diff --git a/core/libs/tests/GuestPthreadRwlock.cpp b/core/libs/tests/GuestPthreadRwlock.cpp index 9c8c6d557c..1f6783b2d5 100644 --- a/core/libs/tests/GuestPthreadRwlock.cpp +++ b/core/libs/tests/GuestPthreadRwlock.cpp @@ -1,3 +1,7 @@ +#include "prx/libkernel/KernelErrors.hpp" +#include "prx/libkernel/include/Api.hpp" +#include "prx/libkernel/Time/include/Time.hpp" +#include "prx/libkernel/Pthread/include/Rwlock.hpp" #include "SceTypes.hpp" #include #include @@ -6,43 +10,9 @@ #include #include -extern "C" { -int APS5_VABI scePthreadCreate(Pthread* thread, const PthreadAttr* attr, PthreadEntry entry, void* arg, const char* name); -int APS5_VABI scePthreadJoin(Pthread thread, void** retval); -int APS5_VABI clock_gettime_nid_postfix(int clockId, KernelTimespec* tp); -int APS5_VABI pthread_rwlock_destroy_nid_postfix(PthreadRwlock* rwlock); -int APS5_VABI pthread_rwlock_init_nid_postfix(PthreadRwlock* rwlock, const PthreadRwlockattr* attr); -int APS5_VABI pthread_rwlockattr_init_nid_postfix(PthreadRwlockattr* attr); -int APS5_VABI pthread_rwlockattr_destroy_nid_postfix(PthreadRwlockattr* attr); -int APS5_VABI pthread_rwlockattr_getpshared_nid_postfix(const PthreadRwlockattr* attr, int* pshared); -int APS5_VABI pthread_rwlockattr_setpshared_nid_postfix(PthreadRwlockattr* attr, int pshared); -int APS5_VABI pthread_rwlockattr_gettype_np_nid_postfix(const PthreadRwlockattr* attr, int* type); -int APS5_VABI scePthreadRwlockattrSettype(PthreadRwlockattr* attr, int type); -int APS5_VABI scePthreadRwlockattrGettype(const PthreadRwlockattr* attr, int* type); -int APS5_VABI scePthreadRwlockattrSetpshared(PthreadRwlockattr* attr, int pshared); -int APS5_VABI scePthreadRwlockattrGetpshared(const PthreadRwlockattr* attr, int* pshared); -int APS5_VABI pthread_rwlock_rdlock_nid_postfix(PthreadRwlock* rwlock); -int APS5_VABI pthread_rwlock_wrlock_nid_postfix(PthreadRwlock* rwlock); -int APS5_VABI pthread_rwlock_unlock_nid_postfix(PthreadRwlock* rwlock); -int APS5_VABI pthread_rwlock_tryrdlock_nid_postfix(PthreadRwlock* rwlock); -int APS5_VABI pthread_rwlock_trywrlock_nid_postfix(PthreadRwlock* rwlock); -int APS5_VABI pthread_rwlock_timedrdlock_nid_postfix(PthreadRwlock* rwlock, const KernelTimespec* abstime); -int APS5_VABI pthread_rwlock_timedwrlock_nid_postfix(PthreadRwlock* rwlock, const KernelTimespec* abstime); -int APS5_VABI pthread_rwlock_reltimedrdlock_np_nid_postfix(PthreadRwlock* rwlock, KernelUseconds usec); -int APS5_VABI pthread_rwlock_reltimedwrlock_np_nid_postfix(PthreadRwlock* rwlock, KernelUseconds usec); -int APS5_VABI scePthreadRwlockInit(PthreadRwlock* rwlock, const PthreadRwlockattr* attr, const char* name); -int APS5_VABI scePthreadRwlockDestroy(PthreadRwlock* rwlock); -int APS5_VABI scePthreadRwlockRdlock(PthreadRwlock* rwlock); -int APS5_VABI scePthreadRwlockWrlock(PthreadRwlock* rwlock); -int APS5_VABI scePthreadRwlockTryrdlock(PthreadRwlock* rwlock); -int APS5_VABI scePthreadRwlockUnlock(PthreadRwlock* rwlock); -int APS5_VABI scePthreadRwlockattrSettype(PthreadRwlockattr* attr, int type); -} - using TimedLock = int (APS5_VABI *)(PthreadRwlock*, const KernelTimespec*); static constexpr int SCE_OK = 0; -static constexpr int SCE_KERNEL_ERROR_EINVAL = 0x80020016; static constexpr int GUEST_EPERM = 1; static constexpr int GUEST_EDEADLK = 11; static constexpr int GUEST_EBUSY = 16; @@ -212,7 +182,7 @@ static void CheckFailedLockAttempts() { PthreadRwlock rwlock = nullptr; Require(pthread_rwlock_wrlock_nid_postfix(&rwlock) == 0); const KernelTimespec timeout = After(10); - Require(pthread_rwlock_timedrdlock_nid_postfix(&rwlock, &timeout) == GUEST_EDEADLK); + Require(pthread_rwlock_timedrdlock_nid_postfix(&rwlock, &timeout) == GUEST_ETIMEDOUT); Require(pthread_rwlock_tryrdlock_nid_postfix(&rwlock) == GUEST_EBUSY); Require(pthread_rwlock_unlock_nid_postfix(&rwlock) == 0); Require(pthread_rwlock_destroy_nid_postfix(&rwlock) == 0); @@ -477,9 +447,10 @@ int main() { Require(pthread_rwlock_trywrlock_nid_postfix(&rwlock) == 0); Require(pthread_rwlock_tryrdlock_nid_postfix(&rwlock) == GUEST_EBUSY); Require(pthread_rwlock_trywrlock_nid_postfix(&rwlock) == GUEST_EBUSY); - KernelTimespec deadline = After(5000); - Require(pthread_rwlock_timedrdlock_nid_postfix(&rwlock, &deadline) == GUEST_EDEADLK); - Require(pthread_rwlock_timedwrlock_nid_postfix(&rwlock, &deadline) == GUEST_EDEADLK); + KernelTimespec deadline = After(20); + Require(pthread_rwlock_timedrdlock_nid_postfix(&rwlock, &deadline) == GUEST_ETIMEDOUT); + deadline = After(20); + Require(pthread_rwlock_timedwrlock_nid_postfix(&rwlock, &deadline) == GUEST_ETIMEDOUT); Require(pthread_rwlock_unlock_nid_postfix(&rwlock) == 0); Require(pthread_rwlock_unlock_nid_postfix(&rwlock) == GUEST_EPERM); Require(pthread_rwlock_tryrdlock_nid_postfix(&rwlock) == 0); diff --git a/core/libs/tests/GuestPthreadSchedparam.cpp b/core/libs/tests/GuestPthreadSchedparam.cpp index 171d3fc5be..71d9ab1a58 100644 --- a/core/libs/tests/GuestPthreadSchedparam.cpp +++ b/core/libs/tests/GuestPthreadSchedparam.cpp @@ -1,33 +1,13 @@ +#include "prx/libkernel/KernelErrors.hpp" +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "SceTypes.hpp" #include #include #include #include -extern "C" { -int APS5_VABI scePthreadCreate(Pthread* thread, const PthreadAttr* attr, PthreadEntry entry, void* arg, const char* name); -int APS5_VABI scePthreadJoin(Pthread thread, void** retval); -Pthread APS5_VABI scePthreadSelf(void); -int APS5_VABI scePthreadGetschedparam(Pthread thread, int* policy, KernelSchedParam* param); -int APS5_VABI scePthreadSetschedparam(Pthread thread, int policy, const KernelSchedParam* param); -int APS5_VABI pthread_getschedparam_nid_postfix(Pthread thread, int* policy, KernelSchedParam* param); -int APS5_VABI pthread_getprio_nid_postfix(Pthread thread); -int* APS5_VABI __error_nid_postfix(); -int APS5_VABI pthread_setschedparam_nid_postfix(Pthread thread, int policy, const KernelSchedParam* param); -int APS5_VABI scePthreadAttrInit(PthreadAttr* attr); -int APS5_VABI scePthreadAttrDestroy(PthreadAttr* attr); -int APS5_VABI scePthreadAttrGet(Pthread thread, PthreadAttr* attr); -int APS5_VABI pthread_attr_get_np_nid_postfix(Pthread thread, PthreadAttr* attr); -int APS5_VABI scePthreadAttrGetschedpolicy(const PthreadAttr* attr, int* policy); -int APS5_VABI scePthreadAttrGetschedparam(const PthreadAttr* attr, KernelSchedParam* param); -int APS5_VABI scePthreadAttrSetinheritsched(PthreadAttr* attr, int inheritSched); -int APS5_VABI scePthreadAttrSetschedpolicy(PthreadAttr* attr, int policy); -int APS5_VABI scePthreadAttrSetschedparam(PthreadAttr* attr, const KernelSchedParam* param); -} - static constexpr int SCE_OK = 0; -static constexpr int SCE_KERNEL_ERROR_EINVAL = static_cast(0x80020016); -static constexpr int SCE_KERNEL_ERROR_ESRCH = static_cast(0x80020003); static constexpr int GUEST_EINVAL = 22; static constexpr int GUEST_ESRCH = 3; static constexpr int GUEST_SCHED_FIFO = 1; diff --git a/core/libs/tests/GuestPthreadSecondJoin.cpp b/core/libs/tests/GuestPthreadSecondJoin.cpp index 0173a7bd2c..3bca2b8745 100644 --- a/core/libs/tests/GuestPthreadSecondJoin.cpp +++ b/core/libs/tests/GuestPthreadSecondJoin.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/KernelErrors.hpp" +#include "prx/libkernel/include/Api.hpp" #include "SceTypes.hpp" #include #include @@ -6,18 +8,7 @@ #include #include -extern "C" { -int APS5_VABI scePthreadCreate(Pthread* thread, const PthreadAttr* attr, PthreadEntry entry, void* arg, const char* name); -int APS5_VABI scePthreadJoin(Pthread thread, void** retval); -int APS5_VABI scePthreadDetach(Pthread thread); -int APS5_VABI scePthreadGetname(Pthread thread, char* name); -int APS5_VABI pthread_join_nid_postfix(Pthread thread, void** retval); -} - static constexpr int SCE_OK = 0; -static constexpr int SCE_KERNEL_ERROR_ESRCH = static_cast(0x80020003u); -static constexpr int SCE_KERNEL_ERROR_EINVAL = static_cast(0x80020016u); -static constexpr int SCE_KERNEL_ERROR_ENAMETOOLONG = static_cast(0x8002003fu); static constexpr int GUEST_ESRCH = 3; static constexpr std::size_t REUSED_SLOT_ROUNDS = 64; diff --git a/core/libs/tests/GuestPthreadSem.cpp b/core/libs/tests/GuestPthreadSem.cpp index 574228ddf4..c2f4373538 100644 --- a/core/libs/tests/GuestPthreadSem.cpp +++ b/core/libs/tests/GuestPthreadSem.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/KernelErrors.hpp" +#include "prx/libkernel/include/Api.hpp" #include "SceTypes.hpp" #include #include @@ -7,23 +9,7 @@ #include #include -extern "C" { -int APS5_VABI scePthreadCreate(Pthread* thread, const PthreadAttr* attr, PthreadEntry entry, void* arg, const char* name); -int APS5_VABI scePthreadJoin(Pthread thread, void** retval); -int APS5_VABI scePthreadSemInit(PthreadSem* sem, int flag, unsigned int value, const char* name); -int APS5_VABI scePthreadSemDestroy(PthreadSem* sem); -int APS5_VABI scePthreadSemPost(PthreadSem* sem); -int APS5_VABI scePthreadSemWait(PthreadSem* sem); -int APS5_VABI scePthreadSemTrywait(PthreadSem* sem); -int APS5_VABI scePthreadSemTimedwait(PthreadSem* sem, unsigned int usec); -int APS5_VABI scePthreadSemGetvalue(PthreadSem* sem, int* value); -} - static constexpr int SCE_OK = 0; -static constexpr int SCE_KERNEL_ERROR_EBUSY = static_cast(0x80020010); -static constexpr int SCE_KERNEL_ERROR_EINVAL = static_cast(0x80020016u); -static constexpr int SCE_KERNEL_ERROR_EOVERFLOW = static_cast(0x80020054u); -static constexpr int SCE_KERNEL_ERROR_ETIMEDOUT = static_cast(0x8002003C); static void Require(bool value) { if (!value) std::abort(); } diff --git a/core/libs/tests/GuestPthreadSpin.cpp b/core/libs/tests/GuestPthreadSpin.cpp index ca7e2b6926..2308710c88 100644 --- a/core/libs/tests/GuestPthreadSpin.cpp +++ b/core/libs/tests/GuestPthreadSpin.cpp @@ -1,25 +1,15 @@ +#include "prx/libkernel/include/Api.hpp" #include "SceTypes.hpp" #include #include -struct PthreadSpinlockPrivate; using PthreadSpinlock = PthreadSpinlockPrivate*; -extern "C" { -int APS5_VABI scePthreadCreate(Pthread* thread, const PthreadAttr* attr, PthreadEntry entry, void* arg, const char* name); -int APS5_VABI scePthreadJoin(Pthread thread, void** retval); -int APS5_VABI pthread_spin_init_nid_postfix(PthreadSpinlock* lock, int pshared); -int APS5_VABI pthread_spin_destroy_nid_postfix(PthreadSpinlock* lock); -int APS5_VABI pthread_spin_lock_nid_postfix(PthreadSpinlock* lock); -int APS5_VABI pthread_spin_trylock_nid_postfix(PthreadSpinlock* lock); -int APS5_VABI pthread_spin_unlock_nid_postfix(PthreadSpinlock* lock); -} - static constexpr int GUEST_EPERM = 1; static constexpr int GUEST_EBUSY = 16; static constexpr int GUEST_EINVAL = 22; -static constexpr int PTHREAD_PROCESS_PRIVATE = 0; -static constexpr int PTHREAD_PROCESS_SHARED = 1; +static constexpr int GuestPthread_Process_Private = 0; +static constexpr int GuestPthread_Process_Shared = 1; static constexpr int Increments = 200000; static void Require(bool value) { if (!value) std::abort(); } @@ -49,9 +39,9 @@ static void* APS5_VABI Incrementer(void* arg) { } static void ArgumentErrors() { - Require(pthread_spin_init_nid_postfix(nullptr, PTHREAD_PROCESS_PRIVATE) == GUEST_EINVAL); + Require(pthread_spin_init_nid_postfix(nullptr, GuestPthread_Process_Private) == GUEST_EINVAL); PthreadSpinlock lock = nullptr; - Require(pthread_spin_init_nid_postfix(&lock, PTHREAD_PROCESS_SHARED) == GUEST_EINVAL); + Require(pthread_spin_init_nid_postfix(&lock, GuestPthread_Process_Shared) == GUEST_EINVAL); Require(pthread_spin_init_nid_postfix(&lock, 2) == GUEST_EINVAL); Require(pthread_spin_init_nid_postfix(&lock, -1) == GUEST_EINVAL); Require(lock == nullptr); @@ -75,6 +65,7 @@ static void SingleThread(int pshared) { bool threw = false; try { pthread_spin_lock_nid_postfix(&lock); + } catch (const std::runtime_error&) { threw = true; } @@ -90,7 +81,7 @@ static void SingleThread(int pshared) { static void HeldByAnotherThread() { Shared shared; - Require(pthread_spin_init_nid_postfix(&shared.lock, PTHREAD_PROCESS_PRIVATE) == 0); + Require(pthread_spin_init_nid_postfix(&shared.lock, GuestPthread_Process_Private) == 0); Require(pthread_spin_lock_nid_postfix(&shared.lock) == 0); Pthread thread = nullptr; Require(scePthreadCreate(&thread, nullptr, Contender, &shared, nullptr) == 0); @@ -103,7 +94,7 @@ static void HeldByAnotherThread() { static void MutualExclusion() { Shared shared; - Require(pthread_spin_init_nid_postfix(&shared.lock, PTHREAD_PROCESS_PRIVATE) == 0); + Require(pthread_spin_init_nid_postfix(&shared.lock, GuestPthread_Process_Private) == 0); Pthread first = nullptr; Pthread second = nullptr; Require(scePthreadCreate(&first, nullptr, Incrementer, &shared, nullptr) == 0); @@ -116,7 +107,7 @@ static void MutualExclusion() { int main() { ArgumentErrors(); - SingleThread(PTHREAD_PROCESS_PRIVATE); + SingleThread(GuestPthread_Process_Private); HeldByAnotherThread(); MutualExclusion(); } diff --git a/core/libs/tests/GuestPthreadStack.cpp b/core/libs/tests/GuestPthreadStack.cpp index a00fdd183e..d0e2472a70 100644 --- a/core/libs/tests/GuestPthreadStack.cpp +++ b/core/libs/tests/GuestPthreadStack.cpp @@ -1,3 +1,4 @@ +#include "prx/libkernel/include/Api.hpp" #include "SceTypes.hpp" #ifdef __linux__ #include "prx/libc/include/GuestAllocations.hpp" @@ -17,16 +18,9 @@ #include extern "C" { -int APS5_VABI scePthreadCreate(Pthread* thread, const PthreadAttr* attr, PthreadEntry entry, void* arg, const char* name); -int APS5_VABI scePthreadJoin(Pthread thread, void** retval); -int APS5_VABI scePthreadAttrInit(PthreadAttr* attr); -int APS5_VABI scePthreadAttrDestroy(PthreadAttr* attr); -int APS5_VABI scePthreadAttrGet(Pthread thread, PthreadAttr* attr); -int APS5_VABI scePthreadAttrSetstacksize(PthreadAttr* attr, std::size_t stackSize); -int APS5_VABI scePthreadAttrGetstack(const PthreadAttr* attr, void** stackAddress, std::size_t* stackSize); -Pthread APS5_VABI scePthreadSelf(); + #ifdef __linux__ -int APS5_VABI scePthreadDetach(Pthread thread); + #endif } diff --git a/core/libs/tests/GuestPthreadTimedLocks.cpp b/core/libs/tests/GuestPthreadTimedLocks.cpp index ae2a8187fa..601619c9cd 100644 --- a/core/libs/tests/GuestPthreadTimedLocks.cpp +++ b/core/libs/tests/GuestPthreadTimedLocks.cpp @@ -1,24 +1,10 @@ +#include "prx/libkernel/include/Api.hpp" #include "SceTypes.hpp" #include #include #include #include -extern "C" { -int APS5_VABI scePthreadCreate(Pthread* thread, const PthreadAttr* attr, PthreadEntry entry, void* arg, const char* name); -int APS5_VABI scePthreadJoin(Pthread thread, void** retval); -int APS5_VABI pthread_rwlock_wrlock_nid_postfix(PthreadRwlock* rwlock); -int APS5_VABI pthread_rwlock_unlock_nid_postfix(PthreadRwlock* rwlock); -int APS5_VABI pthread_rwlock_destroy_nid_postfix(PthreadRwlock* rwlock); -int APS5_VABI pthread_rwlock_timedrdlock_nid_postfix(PthreadRwlock* rwlock, const KernelTimespec* abstime); -int APS5_VABI pthread_rwlock_timedwrlock_nid_postfix(PthreadRwlock* rwlock, const KernelTimespec* abstime); -int APS5_VABI pthread_mutex_init_nid_postfix(PthreadMutex* mutex, const PthreadMutexattr* attr); -int APS5_VABI pthread_mutex_lock_nid_postfix(PthreadMutex* mutex); -int APS5_VABI pthread_mutex_unlock_nid_postfix(PthreadMutex* mutex); -int APS5_VABI pthread_mutex_destroy_nid_postfix(PthreadMutex* mutex); -int APS5_VABI pthread_mutex_timedlock_nid_postfix(PthreadMutex* mutex, const KernelTimespec* abstime); -} - static constexpr int SCE_OK = 0; static constexpr int GUEST_EDEADLK = 11; static constexpr auto HoldTime = std::chrono::milliseconds(50); diff --git a/core/libs/tests/GuestQsort.cpp b/core/libs/tests/GuestQsort.cpp index f27a089c63..00e7f72ef2 100644 --- a/core/libs/tests/GuestQsort.cpp +++ b/core/libs/tests/GuestQsort.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/ApplicationHeap.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -8,14 +9,6 @@ #include #include -extern "C" { -int APS5_VABI mergesort_nid_postfix(void*, std::size_t, std::size_t, int (APS5_VABI*)(const void*, const void*)); -int* APS5_VABI __error_nid_postfix(); -void APS5_VABI qsort_nid_postfix(void*, std::size_t, std::size_t, int (APS5_VABI*)(const void*, const void*)); -int APS5_VABI qsort_s_nid_postfix(void*, std::size_t, std::size_t, int (APS5_VABI*)(const void*, const void*, void*), void*); -void* APS5_VABI set_constraint_handler_s_nid_postfix(void*); -} - namespace { bool failAllocation = false; @@ -156,6 +149,7 @@ bool ExpectOrder(const char* name, const std::vector& keys, const std::vect std::vector elements; for (std::size_t index = 0; index < keys.size(); ++index) elements.push_back({keys[index], static_cast(index)}); qsort_nid_postfix(elements.data(), elements.size(), sizeof(Element), CompareKeys); + for (std::size_t index = 0; index < tags.size(); ++index) { if (elements[index].tag != tags[index]) { std::fprintf(stderr, "%s: element %zu has tag %d, expected %d\n", name, index, elements[index].tag, tags[index]); @@ -175,6 +169,7 @@ bool ExpectSorted(std::size_t size, std::size_t count) { std::vector counts(256); for (std::size_t index = 0; index < count; ++index) ++counts[bytes[index * size]]; qsort_nid_postfix(bytes.data(), count, size, CompareFirstByte); + for (std::size_t index = 0; index < count; ++index) { if (index > 0 && bytes[(index - 1) * size] > bytes[index * size]) { std::fprintf(stderr, "qsort of %zu %zu-byte elements is not sorted at %zu\n", count, size, index); @@ -191,7 +186,6 @@ bool ExpectSorted(std::size_t size, std::size_t count) { return true; } - bool CheckMergesort() { InitializeHeap(); bool correct = true; diff --git a/core/libs/tests/GuestRaiseException.cpp b/core/libs/tests/GuestRaiseException.cpp index 6c2fabea02..205e6e4c81 100644 --- a/core/libs/tests/GuestRaiseException.cpp +++ b/core/libs/tests/GuestRaiseException.cpp @@ -1,3 +1,8 @@ +#include "prx/libkernel/KernelErrors.hpp" +#include "prx/libkernel/include/Api.hpp" +#include "prx/libkernel/Semaphore/include/Semaphore.hpp" +#include "prx/libkernel/Pthread/include/Rwlock.hpp" +#include "prx/libkernel/Pthread/include/Mutex.hpp" #include "SceTypes.hpp" #include #include @@ -13,33 +18,6 @@ #include #endif -extern "C" { -int APS5_VABI sceKernelInstallExceptionHandler(int signum, void* handler); -int APS5_VABI sceKernelRemoveExceptionHandler(int signum); -int APS5_VABI sceKernelRaiseException(Pthread thread, int signum); -int APS5_VABI scePthreadCreate(Pthread* thread, const PthreadAttr* attr, PthreadEntry entry, void* arg, const char* name); -int APS5_VABI scePthreadJoin(Pthread thread, void** retval); -Pthread APS5_VABI scePthreadSelf(); -int APS5_VABI sceKernelCreateSema(KernelSema* sem, const char* name, uint32_t attr, int init, int max, void* opt); -int APS5_VABI sceKernelDeleteSema(KernelSema sem); -int APS5_VABI sceKernelSignalSema(KernelSema sem, int count); -int APS5_VABI sceKernelWaitSema(KernelSema sem, int need, KernelUseconds* time); -int APS5_VABI scePthreadMutexInit(PthreadMutex* mutex, const PthreadMutexattr* attr, const char* name); -int APS5_VABI scePthreadMutexDestroy(PthreadMutex* mutex); -int APS5_VABI scePthreadMutexLock(PthreadMutex* mutex); -int APS5_VABI scePthreadMutexTimedlock(PthreadMutex* mutex, KernelUseconds usec); -int APS5_VABI scePthreadMutexUnlock(PthreadMutex* mutex); -int APS5_VABI scePthreadRwlockInit(PthreadRwlock* rwlock, const PthreadRwlockattr* attr, const char* name); -int APS5_VABI scePthreadRwlockDestroy(PthreadRwlock* rwlock); -int APS5_VABI scePthreadRwlockWrlock(PthreadRwlock* rwlock); -int APS5_VABI scePthreadRwlockUnlock(PthreadRwlock* rwlock); -int APS5_VABI sceKernelSyncOnAddressWait(std::uint32_t* address, std::uint32_t expected, const KernelUseconds* timeout, const char* name); -int APS5_VABI sceKernelSyncOnAddressWake(void* address, std::int32_t count); -} - -static constexpr int SCE_KERNEL_ERROR_EINVAL = static_cast(0x80020016); -static constexpr int SCE_KERNEL_ERROR_ESRCH = static_cast(0x80020003); -static constexpr int SCE_KERNEL_ERROR_ETIMEDOUT = static_cast(0x8002003c); static constexpr int SIGUSR1 = 30; static constexpr int Repeats = 50; static constexpr std::size_t R12Offset = 0xa0; @@ -579,6 +557,7 @@ int main() { bool rejected = false; try { sceKernelRaiseException(scePthreadSelf(), SIGUSR1); + } catch (const std::runtime_error&) { rejected = true; } @@ -687,6 +666,7 @@ int main() { bool refused = false; try { sceKernelRaiseException(loopingThread, SIGUSR1); + } catch (const std::runtime_error&) { refused = true; } diff --git a/core/libs/tests/GuestRaiseInHostCode.cpp b/core/libs/tests/GuestRaiseInHostCode.cpp index 0a41f83ca8..e89332fc4c 100644 --- a/core/libs/tests/GuestRaiseInHostCode.cpp +++ b/core/libs/tests/GuestRaiseInHostCode.cpp @@ -1,3 +1,4 @@ +#include "prx/libkernel/include/Api.hpp" #include "SceTypes.hpp" #include #include @@ -8,14 +9,6 @@ #include #include -extern "C" { -int APS5_VABI scePthreadCreate(Pthread*, const PthreadAttr*, PthreadEntry, void*, const char*); -int APS5_VABI scePthreadJoin(Pthread, void**); -int APS5_VABI sceKernelInstallExceptionHandler(int, void*); -int APS5_VABI sceKernelRemoveExceptionHandler(int); -int APS5_VABI sceKernelRaiseException(Pthread, int); -} - static constexpr int SigUsr1 = 30; static constexpr int Raises = 100; static void Require(bool value) { if (!value) std::abort(); } diff --git a/core/libs/tests/GuestRaiseInSystemCall.cpp b/core/libs/tests/GuestRaiseInSystemCall.cpp index 834594d260..f1b75ad913 100644 --- a/core/libs/tests/GuestRaiseInSystemCall.cpp +++ b/core/libs/tests/GuestRaiseInSystemCall.cpp @@ -1,3 +1,4 @@ +#include "prx/libkernel/include/Api.hpp" #include "SceTypes.hpp" #include #include @@ -10,14 +11,6 @@ #include #include -extern "C" { -int APS5_VABI scePthreadCreate(Pthread*, const PthreadAttr*, PthreadEntry, void*, const char*); -int APS5_VABI scePthreadJoin(Pthread, void**); -int APS5_VABI sceKernelInstallExceptionHandler(int, void*); -int APS5_VABI sceKernelRemoveExceptionHandler(int); -int APS5_VABI sceKernelRaiseException(Pthread, int); -} - static constexpr int SigUsr1 = 30; static constexpr int Raises = 10; static constexpr DWORD PipeBytes = 4096; diff --git a/core/libs/tests/GuestRaiseNestedSleep.cpp b/core/libs/tests/GuestRaiseNestedSleep.cpp index 839f831ecf..b5e27b4f5a 100644 --- a/core/libs/tests/GuestRaiseNestedSleep.cpp +++ b/core/libs/tests/GuestRaiseNestedSleep.cpp @@ -1,18 +1,11 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libkernel/Time/include/Time.hpp" #include "SceTypes.hpp" #include #include #include #include -extern "C" { -int APS5_VABI sceKernelInstallExceptionHandler(int signum, void* handler); -int APS5_VABI sceKernelRemoveExceptionHandler(int signum); -int APS5_VABI sceKernelRaiseException(Pthread thread, int signum); -int APS5_VABI scePthreadCreate(Pthread* thread, const PthreadAttr* attr, PthreadEntry entry, void* arg, const char* name); -int APS5_VABI scePthreadJoin(Pthread thread, void** retval); -int APS5_VABI sceKernelUsleep_nid_postfix(KernelUseconds microseconds); -} - static constexpr int SIGUSR1 = 30; static constexpr int SCE_OK = 0; static constexpr KernelUseconds OuterSleep = 1000000; diff --git a/core/libs/tests/GuestRandom.cpp b/core/libs/tests/GuestRandom.cpp index df1d5f83c9..9ac352658a 100644 --- a/core/libs/tests/GuestRandom.cpp +++ b/core/libs/tests/GuestRandom.cpp @@ -1,11 +1,9 @@ +#include "prx/libSceRandom/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include #include -extern "C" { -int APS5_VABI sceRandomGetRandomNumber(void*, std::size_t); -} static void Require(bool value) { if (!value) std::abort(); } int main() { constexpr int invalid = static_cast(0x817C0016); diff --git a/core/libs/tests/GuestRandomDeviceSeed.cpp b/core/libs/tests/GuestRandomDeviceSeed.cpp index 0aaee61657..0f2ffde1ad 100644 --- a/core/libs/tests/GuestRandomDeviceSeed.cpp +++ b/core/libs/tests/GuestRandomDeviceSeed.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/HostEntropy.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -9,13 +10,6 @@ #include #include -extern "C" { -std::int64_t APS5_VABI random_nid_postfix(); -void APS5_VABI srandomdev_nid_postfix(); -char* APS5_VABI initstate_nid_postfix(std::uint64_t, char*, std::int64_t); -char* APS5_VABI setstate_nid_postfix(char*); -} - static void* entropyBuffer; static std::size_t entropySize; static bool failEntropy; diff --git a/core/libs/tests/GuestRandomState.cpp b/core/libs/tests/GuestRandomState.cpp index dc4259eb5e..a660db24f8 100644 --- a/core/libs/tests/GuestRandomState.cpp +++ b/core/libs/tests/GuestRandomState.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -10,24 +11,6 @@ #include #include -extern "C" { -std::int64_t APS5_VABI random_nid_postfix(); -void APS5_VABI srandom_nid_postfix(std::uint64_t); -void APS5_VABI srandomdev_nid_postfix(); -char* APS5_VABI initstate_nid_postfix(std::uint64_t, char*, std::int64_t); -char* APS5_VABI setstate_nid_postfix(char*); -int* APS5_VABI __error_nid_postfix(); -double APS5_VABI erand48_nid_postfix(std::uint16_t*); -std::int64_t APS5_VABI nrand48_nid_postfix(std::uint16_t*); -std::int64_t APS5_VABI jrand48_nid_postfix(std::uint16_t*); -double APS5_VABI drand48_nid_postfix(); -std::int64_t APS5_VABI lrand48_nid_postfix(); -std::int64_t APS5_VABI mrand48_nid_postfix(); -void APS5_VABI srand48_nid_postfix(std::int64_t); -std::uint16_t* APS5_VABI seed48_nid_postfix(const std::uint16_t*); -void APS5_VABI lcong48_nid_postfix(const std::uint16_t*); -} - static int failures = 0; static void Require(bool condition, const char* message) { @@ -79,6 +62,7 @@ static void CheckRand48() { const std::uint16_t parameters[7] = {1, 0, 0, 3, 0, 0, 5}; lcong48_nid_postfix(parameters); + Require(lrand48_nid_postfix() == 0 && mrand48_nid_postfix() == 0, "lcong48 sets seed, multiplier and addend"); std::uint16_t high[3] = {0, 0, 1}; Require(jrand48_nid_postfix(high) == 196608 && SeedIs(high, 5, 0, 3), "lcong48 multiplier scales the seed"); @@ -91,6 +75,7 @@ static void CheckRand48() { Require(drand48_nid_postfix() == erand48_nid_postfix(again), "seed48 restores the default multiplier and addend"); lcong48_nid_postfix(parameters); srand48_nid_postfix(0x1234abcd); + std::uint16_t reset[3] = {0x330e, 0xabcd, 0x1234}; Require(lrand48_nid_postfix() == nrand48_nid_postfix(reset), "srand48 restores the default multiplier and addend"); @@ -102,6 +87,7 @@ static void CheckRand48() { Require(jrand48_nid_postfix(ones) == 4294582547, "jrand48 matches the console for an all-ones seed"); constexpr std::array consoleMrand48 {178800969, 1952030186, 3585512650, 1443049011, 2428758494, 7588830}; srand48_nid_postfix(1); + for (const std::int64_t expected : consoleMrand48) Require(mrand48_nid_postfix() == expected, "mrand48 matches the console after srand48(1)"); #ifndef _WIN32 @@ -114,6 +100,7 @@ static void CheckRand48() { } ::srand48(1234567); srand48_nid_postfix(1234567); + for (int round = 0; round < 32; ++round) { Require(drand48_nid_postfix() == ::drand48(), "drand48 matches the host"); Require(lrand48_nid_postfix() == ::lrand48(), "lrand48 matches the host"); @@ -137,10 +124,13 @@ int main() { Require(Draw() == seedOne, "unseeded random must match srandom(1)"); srandom_nid_postfix(1); + Require(Draw() == seedOne, "srandom(1) sequence"); srandom_nid_postfix(0x100000001ull); + Require(Draw() == seedOne, "srandom must use the low 32 bits of the seed"); srandom_nid_postfix(12345); + Require(Draw() == seed12345, "srandom(12345) sequence"); struct SizeCase { @@ -174,8 +164,10 @@ int main() { alignas(4) std::array small{}; alignas(4) std::array large{}; initstate_nid_postfix(7, small.data(), static_cast(small.size())); + for (std::size_t i = 0; i < 3; ++i) Require(random_nid_postfix() == seed7Type1[i], "initstate(7) on 32 bytes"); initstate_nid_postfix(7, large.data(), static_cast(large.size())); + Require(setstate_nid_postfix(small.data()) == large.data(), "setstate must return the 64-byte state"); Require(setstate_nid_postfix(large.data()) == small.data(), "setstate must return the 32-byte state"); Require(Word(small.data(), 0) == 5 * 3 + 1, "setstate must save the rear position of the old state"); @@ -204,6 +196,7 @@ int main() { bool threw = false; try { initstate_nid_postfix(1, nullptr, 128); + } catch (const std::invalid_argument&) { threw = true; } @@ -211,6 +204,7 @@ int main() { threw = false; try { setstate_nid_postfix(nullptr); + } catch (const std::invalid_argument&) { threw = true; } @@ -219,9 +213,11 @@ int main() { constexpr std::size_t threadCount = 4; constexpr std::size_t callsPerThread = 2000; srandom_nid_postfix(99); + std::vector serial(threadCount * callsPerThread); for (auto& value : serial) value = random_nid_postfix(); srandom_nid_postfix(99); + std::vector concurrent(threadCount * callsPerThread); std::vector threads; for (std::size_t t = 0; t < threadCount; ++t) diff --git a/core/libs/tests/GuestRazorCpu.cpp b/core/libs/tests/GuestRazorCpu.cpp index 69f35dbfa0..f938b7a80b 100644 --- a/core/libs/tests/GuestRazorCpu.cpp +++ b/core/libs/tests/GuestRazorCpu.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceRazorCpu/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -5,31 +6,6 @@ #include #include -extern "C" { -std::uint32_t APS5_VABI sceRazorCpuIsCapturing(void); -int APS5_VABI sceRazorCpuJobManagerDispatch(const char* label, std::uint16_t firstId, std::uint16_t secondId, std::uint16_t firstCount, std::uint16_t secondCount, std::uint64_t firstValue, std::uint64_t secondValue); -int APS5_VABI sceRazorCpuJobManagerJob(std::uint16_t firstId, std::uint16_t secondId, std::uint16_t thirdId, std::uint16_t event); -int APS5_VABI sceRazorCpuJobManagerSequence(const char* label, std::uint16_t firstId, std::uint16_t secondId, std::uint16_t event); -int APS5_VABI sceRazorCpuPushMarker(const char* label, std::uint32_t color, std::uint32_t flags); -int APS5_VABI sceRazorCpuNamedSync(const char* label); -int APS5_VABI sceRazorCpuPushMarkerStatic(const char* name, std::uint32_t color, std::uint32_t flags); -int APS5_VABI sceRazorCpuPopMarker(void); -bool APS5_VABI sceRazorCpuFlushOccurred(std::uint64_t* timeSpentInFlush); -int APS5_VABI sceRazorCpuPlotValue(const char* series, float value); -int APS5_VABI sceRazorCpuWriteBookmark(const char* label, const char* description); -int APS5_VABI sceRazorCpuSync(void); -void APS5_VABI sceRazorCpuDisableFiberUserMarkers(void); -int APS5_VABI sceRazorCpuInitDataTags(void* buffer, std::size_t size); -int APS5_VABI sceRazorCpuShutdownDataTags(void); -std::size_t APS5_VABI sceRazorCpuGetDataTagStorageSize(std::uint32_t tagCount); -int APS5_VABI sceRazorCpuTagArray(const char* label, std::uint32_t category, void* array, std::size_t bufferSize, std::size_t elementSize); -int APS5_VABI sceRazorCpuTagBuffer(const char* label, std::uint32_t category, void* buffer, std::size_t bufferSize); -int APS5_VABI sceRazorCpuResizeTaggedBuffer(std::uint32_t category, void* buffer, std::size_t newBufferSize); -int APS5_VABI sceRazorCpuUnTagBuffer(std::uint32_t category, void* buffer); -int APS5_VABI sceRazorCpuBeginLogicalFileAccess(const char* filename, std::uint64_t tag, std::uint64_t size, std::uint8_t operation); -int APS5_VABI sceRazorCpuEndLogicalFileAccess(void); -} - namespace { void Require(bool value) { if (!value) std::abort(); } @@ -91,6 +67,7 @@ int main() { bool threw = false; try { sceRazorCpuGetDataTagStorageSize(16); + } catch (const std::runtime_error&) { threw = true; } diff --git a/core/libs/tests/GuestReallocalign.cpp b/core/libs/tests/GuestReallocalign.cpp index f94576018d..ff924916d5 100644 --- a/core/libs/tests/GuestReallocalign.cpp +++ b/core/libs/tests/GuestReallocalign.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/ApplicationHeap.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -5,13 +6,6 @@ #include #include -extern "C" { -void* APS5_VABI reallocalign_nid_postfix(void*, std::size_t, std::size_t); -std::size_t APS5_VABI malloc_usable_size_nid_postfix(void*); -void APS5_VABI free_nid_postfix(void*); -int* APS5_VABI __error_nid_postfix(); -} - namespace { void Require(bool value) { @@ -50,8 +44,10 @@ int main() { for (int index = 0; index < 16; ++index) Require(shrunk[index] == 0x5a); Require(reallocalign_nid_postfix(shrunk, 0, 16) == shrunk && malloc_usable_size_nid_postfix(shrunk) == 0); free_nid_postfix(shrunk); + void* empty = reallocalign_nid_postfix(nullptr, 0, 0); Require(empty != nullptr); free_nid_postfix(empty); + return 0; } diff --git a/core/libs/tests/GuestRealpath.cpp b/core/libs/tests/GuestRealpath.cpp index faae73050f..52240b0a7f 100644 --- a/core/libs/tests/GuestRealpath.cpp +++ b/core/libs/tests/GuestRealpath.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/ApplicationHeap.hpp" #include "prx/libc/include/General.hpp" #include "prx/libc/include/general/VabiMacros.hpp" @@ -11,13 +12,6 @@ #include #include -extern "C" { -char* APS5_VABI realpath_nid_postfix(const char*, char*); -int APS5_VABI chdir_nid_postfix(const char*); -void APS5_VABI free_nid_postfix(void*); -int* APS5_VABI __error_nid_postfix(); -} - static void Require(bool value) { if (!value) std::abort(); } static bool Resolves(const std::string& path, const std::string& expected) { diff --git a/core/libs/tests/GuestRecordLockOwners.cpp b/core/libs/tests/GuestRecordLockOwners.cpp index cbffd82062..416bb02141 100644 --- a/core/libs/tests/GuestRecordLockOwners.cpp +++ b/core/libs/tests/GuestRecordLockOwners.cpp @@ -1,3 +1,6 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libkernel/File/include/File.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libkernel/File/include/FileFlags.hpp" @@ -12,13 +15,6 @@ #include #include -extern "C" { -int APS5_VABI sceKernelOpen(const char* path, int flags, std::uint16_t mode); -int APS5_VABI sceKernelClose(int d); -int APS5_VABI fcntl_nid_postfix(int descriptor, int command, ...); -int* APS5_VABI __error_nid_postfix(); -} - namespace { void Require(bool value, int line) { diff --git a/core/libs/tests/GuestRefusedConnect.cpp b/core/libs/tests/GuestRefusedConnect.cpp index 409f8ad97c..b78fccbe41 100644 --- a/core/libs/tests/GuestRefusedConnect.cpp +++ b/core/libs/tests/GuestRefusedConnect.cpp @@ -1,3 +1,6 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" +#include "prx/libSceNet/include/Net.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -5,22 +8,6 @@ #include #include -extern "C" { -int APS5_VABI socket_nid_postfix(int, int, int); -int APS5_VABI bind_nid_postfix(int, const void*, std::uint32_t); -int APS5_VABI connect_nid_postfix(int, const void*, std::uint32_t); -int APS5_VABI listen_nid_postfix(int, int); -int APS5_VABI accept_nid_postfix(int, void*, std::uint32_t*); -int APS5_VABI getsockname_nid_postfix(int, void*, std::uint32_t*); -int APS5_VABI close_nid_postfix(int); -int* APS5_VABI __error_nid_postfix(); -int APS5_VABI sceNetInit_nid_postfix(); -int APS5_VABI sceNetSocket(const char*, int, int, int); -int APS5_VABI sceNetConnect(int, const void*, std::uint32_t); -int APS5_VABI sceNetSocketClose(int); -int* APS5_VABI sceNetErrnoLoc(); -} - namespace { constexpr int GuestInet = 2; diff --git a/core/libs/tests/GuestRegMgr.cpp b/core/libs/tests/GuestRegMgr.cpp index dfdf074535..f9e8901ef4 100644 --- a/core/libs/tests/GuestRegMgr.cpp +++ b/core/libs/tests/GuestRegMgr.cpp @@ -1,13 +1,10 @@ +#include "prx/libSceRegMgr/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include #include #include -extern "C" { -std::int32_t APS5_VABI sceRegMgrNonSysGetInt(std::int64_t key, std::int32_t unk, std::int32_t* data); -} - static void Require(bool value) { if (!value) std::abort(); } template diff --git a/core/libs/tests/GuestRenameDot.cpp b/core/libs/tests/GuestRenameDot.cpp index ed44b81e35..83260cf108 100644 --- a/core/libs/tests/GuestRenameDot.cpp +++ b/core/libs/tests/GuestRenameDot.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -7,15 +9,6 @@ #include #endif -extern "C" { -int APS5_VABI mkdir_nid_postfix(const char*, int); -int APS5_VABI rmdir_nid_postfix(const char*); -int APS5_VABI rename_nid_postfix(const char*, const char*); -int APS5_VABI sceKernelRename(const char*, const char*); -int APS5_VABI stat_nid_postfix(const char*, void*); -int* APS5_VABI __error_nid_postfix(); -} - namespace { constexpr int ErrorNoEntry = 2; @@ -32,6 +25,7 @@ void Cleanup() { rmdir_nid_postfix(Source); rmdir_nid_postfix(Target); rmdir_nid_postfix(Moved); + std::remove(PlainFile); std::remove(Loop); } @@ -47,7 +41,7 @@ bool Fails(long result, int error) { return result == -1 && *__error_nid_postfix bool Exists(const char* path) { unsigned char status[256]; - return stat_nid_postfix(path, status) == 0; + return stat_nid_postfix(path, reinterpret_cast(status)) == 0; } } diff --git a/core/libs/tests/GuestRenderingWait.cpp b/core/libs/tests/GuestRenderingWait.cpp index a17c039713..352b8b1d1d 100644 --- a/core/libs/tests/GuestRenderingWait.cpp +++ b/core/libs/tests/GuestRenderingWait.cpp @@ -8,14 +8,7 @@ #include #include #include -extern "C" std::uint32_t APS5_VABI sceAgcDriverGetWaitRenderingPacketSizeInDwords(); -extern "C" std::uint32_t APS5_VABI sceAgcDriverGetSetFlipPacketSizeInDwords(); -extern "C" std::uint32_t APS5_VABI sceAgcDriverGetSetWorkloadsActivePacketSize(); -extern "C" std::uint32_t APS5_VABI sceAgcDriverGetSetWorkloadCompletePacketSize(); -extern "C" std::uint32_t APS5_VABI sceAgcDriverGetSetWorkloadStreamInactivePacketSize(); -extern "C" std::uint32_t APS5_VABI sceAgcDriverNopDataGetPacketSize(std::uint32_t); -extern "C" std::uint32_t APS5_VABI sceAgcDriverUserDataGetPacketSize(std::uint32_t); -extern "C" std::uint32_t APS5_VABI sceAgcDriverWaitUntilSafeForRendering(std::uint32_t**, std::uint32_t, std::uint32_t, std::uint32_t, int); + static void Require(bool value) { if (!value) std::abort(); } class Output final : public AgcDriver::IVideoOutput, public AgcDriver::IRenderingWait, public AgcDriver::IFlipRequest, public std::enable_shared_from_this { diff --git a/core/libs/tests/GuestResolver.cpp b/core/libs/tests/GuestResolver.cpp index 20f02e1d16..3773c62df8 100644 --- a/core/libs/tests/GuestResolver.cpp +++ b/core/libs/tests/GuestResolver.cpp @@ -1,3 +1,5 @@ +#include "prx/libScePosixForWebKit/include/Api.hpp" +#include "prx/libSceNet/include/Net.hpp" #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN #include @@ -16,14 +18,6 @@ #include #include -extern "C" { -GuestResolver::HostEntry* APS5_VABI gethostbyname_nid_postfix(const char*); -int* APS5_VABI sceNetErrnoLoc(); -int APS5_VABI getaddrinfo_nid_postfix(const char*, const char*, const GuestResolver::AddressInfo*, GuestResolver::AddressInfo**); -void APS5_VABI freeaddrinfo_nid_postfix(GuestResolver::AddressInfo*); -int APS5_VABI getnameinfo_nid_postfix(const void*, std::uint32_t, char*, std::uint32_t, char*, std::uint32_t, int); -const char* APS5_VABI gai_strerror_nid_postfix(int); -} void Require(bool condition, std::source_location location = std::source_location::current()) { if (!condition) { std::fprintf(stderr, "Resolver check failed at line %u\n", location.line()); @@ -135,6 +129,7 @@ int main() { Require(std::strcmp(host, numeric) == 0 && std::strcmp(service, "27910") == 0); } freeaddrinfo_nid_postfix(result); + } GuestResolver::AddressInfo* result = reinterpret_cast(1); hints.family = 1234; @@ -145,4 +140,5 @@ int main() { hints.flags = 12; Require(getaddrinfo_nid_postfix("invalid-numeric-address", "1", &hints, &result) == 8 && !result); freeaddrinfo_nid_postfix(nullptr); + } diff --git a/core/libs/tests/GuestRtc.cpp b/core/libs/tests/GuestRtc.cpp index 09d0659f5f..8d9b302b49 100644 --- a/core/libs/tests/GuestRtc.cpp +++ b/core/libs/tests/GuestRtc.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceRtc/include/Rtc.hpp" #include "SceTypes.hpp" #include "ProcessParametersFixture.hpp" #include "prx/libc/include/general/VabiMacros.hpp" @@ -7,7 +8,6 @@ #include #include #include -#include #include #include #include @@ -15,69 +15,7 @@ #include #include #include - -extern "C" { -int APS5_VABI sceRtcCheckValid(const RtcDateTime*); -int APS5_VABI sceRtcIsLeapYear(int); -int APS5_VABI sceRtcGetDaysInMonth(int, int); -int APS5_VABI sceRtcGetDayOfWeek(int, int, int); -int APS5_VABI sceRtcGetTickResolution(void); -int APS5_VABI sceRtcGetTick(const RtcDateTime*, RtcTick*); -int APS5_VABI sceRtcSetTick(RtcDateTime*, const RtcTick*); -int APS5_VABI sceRtcGetCurrentTick(RtcTick*); -int APS5_VABI sceRtcGetCurrentNetworkTick(RtcTick*); -int APS5_VABI sceRtcGetCurrentClock(RtcDateTime*, int); -int APS5_VABI sceRtcGetCurrentClockLocalTime(RtcDateTime*); -int APS5_VABI sceRtcConvertUtcToLocalTime(const RtcTick*, RtcTick*); -int APS5_VABI sceRtcConvertLocalTimeToUtc(const RtcTick*, RtcTick*); -int APS5_VABI sceRtcGetTime_t(const RtcDateTime*, std::int64_t*); -int APS5_VABI sceRtcSetTime_t(RtcDateTime*, std::int64_t); -int APS5_VABI sceRtcGetWin32FileTime(const RtcDateTime*, std::uint64_t*); -int APS5_VABI sceRtcSetWin32FileTime(RtcDateTime*, std::uint64_t); -int APS5_VABI sceRtcGetDosTime(const RtcDateTime*, std::uint32_t*); -int APS5_VABI sceRtcSetDosTime(RtcDateTime*, std::uint32_t); -int APS5_VABI sceRtcGetYear(const RtcDateTime*); -int APS5_VABI sceRtcSetYear(RtcDateTime*, int); -int APS5_VABI sceRtcGetMonth(const RtcDateTime*); -int APS5_VABI sceRtcSetMonth(RtcDateTime*, int); -int APS5_VABI sceRtcGetDay(const RtcDateTime*); -int APS5_VABI sceRtcSetDay(RtcDateTime*, int); -int APS5_VABI sceRtcGetHour(const RtcDateTime*); -int APS5_VABI sceRtcSetHour(RtcDateTime*, int); -int APS5_VABI sceRtcGetMinute(const RtcDateTime*); -int APS5_VABI sceRtcSetMinute(RtcDateTime*, int); -int APS5_VABI sceRtcGetSecond(const RtcDateTime*); -int APS5_VABI sceRtcSetSecond(RtcDateTime*, int); -int APS5_VABI sceRtcGetMicrosecond(const RtcDateTime*); -int APS5_VABI sceRtcSetMicrosecond(RtcDateTime*, int); -int APS5_VABI sceRtcFormatRFC3339(char*, const RtcTick*, int); -int APS5_VABI sceRtcParseRFC3339(RtcTick*, const char*); -int APS5_VABI sceRtcParseDateTime(RtcTick*, const char*); -int APS5_VABI sceRtcTickAddTicks(RtcTick*, const RtcTick*, std::int64_t); -int APS5_VABI sceRtcTickAddMicroseconds(RtcTick*, const RtcTick*, std::int64_t); -int APS5_VABI sceRtcTickAddSeconds(RtcTick*, const RtcTick*, std::int64_t); -int APS5_VABI sceRtcTickAddMinutes(RtcTick*, const RtcTick*, std::int64_t); -int APS5_VABI sceRtcTickAddHours(RtcTick*, const RtcTick*, std::int32_t); -int APS5_VABI sceRtcTickAddDays(RtcTick*, const RtcTick*, std::int32_t); -int APS5_VABI sceRtcTickAddWeeks(RtcTick*, const RtcTick*, std::int32_t); -int APS5_VABI sceRtcTickAddMonths(RtcTick*, const RtcTick*, std::int32_t); -int APS5_VABI sceRtcTickAddYears(RtcTick*, const RtcTick*, std::int16_t); -int APS5_VABI sceRtcFormatRFC3339LocalTime(char*, const RtcTick*); -int APS5_VABI sceRtcFormatRFC2822(char*, const RtcTick*, int); -int APS5_VABI sceRtcFormatRFC2822LocalTime(char*, const RtcTick*); -int APS5_VABI sceRtcFormatRFC3339Precise(char*, const RtcTick*, int, int); -int APS5_VABI sceRtcFormatRFC3339PreciseLocalTime(char*, const RtcTick*, int); -int APS5_VABI sceRtcCompareTick(const RtcTick*, const RtcTick*); -int APS5_VABI sceRtcGetCurrentAdNetworkTick(RtcTick*); -int APS5_VABI sceRtcGetCurrentRawNetworkTick(RtcTick*); -int APS5_VABI sceRtcGetCurrentDebugNetworkTick(RtcTick*); -int APS5_VABI sceRtcSetCurrentTick(const RtcTick*); -int APS5_VABI sceRtcSetCurrentNetworkTick(const RtcTick*); -int APS5_VABI sceRtcSetCurrentAdNetworkTick(const RtcTick*); -int APS5_VABI sceRtcSetCurrentDebugNetworkTick(const RtcTick*); -int APS5_VABI sceRtcInit(void); -int APS5_VABI sceRtcEnd(void); -} +#include static void Require(bool value) { if (!value) std::abort(); } @@ -126,7 +64,7 @@ static void SetCompiledSdkVersion(std::byte* process, std::uint32_t version) { } static void EnterTitleDirectory(const char* titleId) { - const auto directory = std::filesystem::temp_directory_path() / ("rtc-test-" + std::to_string(std::chrono::steady_clock::now().time_since_epoch().count())); + const auto directory = std::filesystem::temp_directory_path() / ("rtc-test-" + std::to_string(std::random_device{}())); std::filesystem::create_directories(directory / "app0" / "sce_sys"); std::filesystem::current_path(directory); if (titleId == nullptr) return; @@ -824,10 +762,11 @@ int main(int argc, char** argv) { RtcTick now{}; Require(sceRtcGetCurrentTick(&now) == 0 && now.tick > leapDayTick); + const RtcTick fixed{leapDayTick}; RtcTick local{}; RtcTick back{}; - Require(sceRtcConvertUtcToLocalTime(&now, &local) == 0); - Require(sceRtcConvertLocalTimeToUtc(&local, &back) == 0 && back.tick == now.tick); + Require(sceRtcConvertUtcToLocalTime(&fixed, &local) == 0); + Require(sceRtcConvertLocalTimeToUtc(&local, &back) == 0 && back.tick == fixed.tick); char rfc2822[32]; tick.tick = leapDayTick; diff --git a/core/libs/tests/GuestRtprioThread.cpp b/core/libs/tests/GuestRtprioThread.cpp index 4d7aa6cc78..0d44857120 100644 --- a/core/libs/tests/GuestRtprioThread.cpp +++ b/core/libs/tests/GuestRtprioThread.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "SceTypes.hpp" #include #include @@ -6,25 +8,6 @@ #include #include -extern "C" { -int APS5_VABI scePthreadCreate(Pthread* thread, const PthreadAttr* attr, PthreadEntry entry, void* arg, const char* name); -int APS5_VABI scePthreadJoin(Pthread thread, void** retval); -Pthread APS5_VABI scePthreadSelf(void); -int APS5_VABI scePthreadGetthreadid(void); -int APS5_VABI scePthreadGetschedparam(Pthread thread, int* policy, KernelSchedParam* param); -int APS5_VABI scePthreadAttrInit(PthreadAttr* attr); -int APS5_VABI scePthreadAttrDestroy(PthreadAttr* attr); -int APS5_VABI scePthreadAttrSetinheritsched(PthreadAttr* attr, int inheritSched); -int APS5_VABI scePthreadAttrSetschedpolicy(PthreadAttr* attr, int policy); -int APS5_VABI scePthreadAttrSetschedparam(PthreadAttr* attr, const KernelSchedParam* param); -struct GuestRtPrio { - std::uint16_t type; - std::uint16_t prio; -}; -int APS5_VABI rtprio_thread_nid_postfix(int function, int lwpid, GuestRtPrio* priority); -int* APS5_VABI __error_nid_postfix(); -} - static constexpr int SCE_OK = 0; static constexpr int GUEST_SCHED_FIFO = 1; static constexpr int GUEST_SCHED_RR = 3; diff --git a/core/libs/tests/GuestRudpContextLifecycle.cpp b/core/libs/tests/GuestRudpContextLifecycle.cpp index 51a119e0d8..766e84b8dd 100644 --- a/core/libs/tests/GuestRudpContextLifecycle.cpp +++ b/core/libs/tests/GuestRudpContextLifecycle.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceRudp/include/Api.hpp" #include "SceTypes.hpp" #include @@ -10,21 +11,7 @@ #include extern "C" { -using GuestRudpEventHandler = void(APS5_VABI*)(int, int, int, void*); -int APS5_VABI sceRudpInit_nid_postfix(void*, int); -int APS5_VABI sceRudpEnd(); -int APS5_VABI sceRudpActivate(std::int32_t, const void*, std::uint32_t); -int APS5_VABI sceRudpEnableInternalIOThread(std::uint32_t, std::uint32_t); -int APS5_VABI sceRudpSetEventHandler(GuestRudpEventHandler, void*); -int APS5_VABI sceRudpCreateContext(GuestRudpEventHandler, void*, int*); -int APS5_VABI sceRudpBind(int, std::uint16_t, int, std::uint16_t); -int APS5_VABI sceRudpSetOption(int, int, const void*, std::uint32_t); -int APS5_VABI sceRudpGetOption(int, int, void*, std::uint32_t); -int APS5_VABI sceRudpInitiate(int, const void*, std::uint32_t, std::uint16_t); -int APS5_VABI sceRudpGetContextStatus(int, void*, std::uint32_t); -int APS5_VABI sceRudpWrite(int, const void*, std::uint32_t, int); -int APS5_VABI sceRudpRead(int, void*, std::uint32_t, int, void*); -int APS5_VABI sceRudpTerminate(int); + } static void Require(bool value) { if (!value) std::abort(); } @@ -78,6 +65,7 @@ static void CheckOptions(int context) { bool threw = false; try { sceRudpGetOption(context, option, &value, sizeof(value)); + } catch (const std::runtime_error&) { threw = true; } @@ -91,6 +79,7 @@ static void CheckOptions(int context) { threw = false; try { sceRudpGetOption(current, option, &value, sizeof(value)); + } catch (const std::runtime_error&) { threw = true; } @@ -176,6 +165,7 @@ int main() { bool activationUnsupported = false; try { sceRudpActivate(ctx, address, sizeof(address)); + } catch (const std::runtime_error&) { activationUnsupported = true; } diff --git a/core/libs/tests/GuestRudpContextQueries.cpp b/core/libs/tests/GuestRudpContextQueries.cpp index 76374d4b86..a45bc97d8e 100644 --- a/core/libs/tests/GuestRudpContextQueries.cpp +++ b/core/libs/tests/GuestRudpContextQueries.cpp @@ -1,17 +1,11 @@ +#include "prx/libSceRudp/include/Api.hpp" #include "SceTypes.hpp" #include #include extern "C" { -using GuestRudpEventHandler = void(APS5_VABI*)(int, int, int, void*); -int APS5_VABI sceRudpInit_nid_postfix(void*, int); -int APS5_VABI sceRudpCreateContext(GuestRudpEventHandler, void*, int*); -int APS5_VABI sceRudpTerminate(int); -int APS5_VABI sceRudpEnd(); -int APS5_VABI sceRudpGetNumberOfPacketsToRead(int); -int APS5_VABI sceRudpGetSizeWritable(int); -int APS5_VABI sceRudpGetSizeReadable(int); + } static void Require(bool value) { diff --git a/core/libs/tests/GuestRudpPoll.cpp b/core/libs/tests/GuestRudpPoll.cpp index a76e793be5..21274887b3 100644 --- a/core/libs/tests/GuestRudpPoll.cpp +++ b/core/libs/tests/GuestRudpPoll.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceRudp/include/Api.hpp" #include "SceTypes.hpp" #include @@ -11,20 +12,7 @@ #include extern "C" { -using GuestRudpEventHandler = void(APS5_VABI*)(int, int, int, void*); -struct GuestRudpPollEvent { - int ctxId; - std::uint16_t reqEvents; - std::uint16_t rtnEvents; -}; -int APS5_VABI sceRudpInit_nid_postfix(void*, int); -int APS5_VABI sceRudpCreateContext(GuestRudpEventHandler, void*, int*); -int APS5_VABI sceRudpTerminate(int); -int APS5_VABI sceRudpEnd(); -int APS5_VABI sceRudpPollCreate(std::size_t); -int APS5_VABI sceRudpPollControl(int, int, int, std::uint16_t); -int APS5_VABI sceRudpPollWait(int, GuestRudpPollEvent*, std::size_t, std::uint64_t); -int APS5_VABI sceRudpPollDestroy(int); + } static void Require(bool value) { @@ -46,7 +34,7 @@ int main() { constexpr std::uint16_t write = 0x0002; constexpr std::uint64_t forever = std::numeric_limits::max(); alignas(16) static std::array pool{}; - std::array events{}; + std::array events{}; const auto eventCount = static_cast(events.size()); Require(sceRudpPollCreate(1) == notInitialized); diff --git a/core/libs/tests/GuestRudpPump.cpp b/core/libs/tests/GuestRudpPump.cpp index 2cc7f5586f..26482bfeea 100644 --- a/core/libs/tests/GuestRudpPump.cpp +++ b/core/libs/tests/GuestRudpPump.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceRudp/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -6,16 +7,6 @@ #include #include -extern "C" { -int APS5_VABI sceRudpInit_nid_postfix(void*, int); -int APS5_VABI sceRudpEnd(); -int APS5_VABI sceRudpProcessEvents(std::uint64_t timeout); -int APS5_VABI sceRudpNetFlush(); -int APS5_VABI sceRudpGetMaxSegmentSize(std::uint16_t*); -int APS5_VABI sceRudpNetReceived(int socketId, const void* data, std::size_t dataSize, const void* sourceAddress, std::uint32_t sourceAddressSize); -int APS5_VABI sceRudpEnableInternalIOThread2(std::uint32_t, std::uint32_t, std::uint64_t); -} - static void Require(bool value, int line) { if (!value) { std::fprintf(stderr, "rudp check failed at line %d\n", line); diff --git a/core/libs/tests/GuestRudpStatus.cpp b/core/libs/tests/GuestRudpStatus.cpp index ab845fffac..8aed90988d 100644 --- a/core/libs/tests/GuestRudpStatus.cpp +++ b/core/libs/tests/GuestRudpStatus.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceRudp/include/Api.hpp" #include "SceTypes.hpp" #include @@ -7,12 +8,7 @@ #include extern "C" { -using GuestRudpEventHandler = void(APS5_VABI*)(int, int, int, void*); -int APS5_VABI sceRudpInit_nid_postfix(void*, int); -int APS5_VABI sceRudpGetStatus(void*, std::size_t); -int APS5_VABI sceRudpCreateContext(GuestRudpEventHandler, void*, int*); -int APS5_VABI sceRudpTerminate(int); -int APS5_VABI sceRudpEnd(); + } static void Require(bool value) { if (!value) std::abort(); } diff --git a/core/libs/tests/GuestRuneLocale.cpp b/core/libs/tests/GuestRuneLocale.cpp index ff51720da5..31a506c9f8 100644 --- a/core/libs/tests/GuestRuneLocale.cpp +++ b/core/libs/tests/GuestRuneLocale.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -11,43 +12,6 @@ extern "C" { extern const unsigned char _DefaultRuneLocale_nid_postfix[4224]; extern const unsigned char* _CurrentRuneLocale_nid_postfix; extern int __mb_sb_limit_nid_postfix; -int APS5_VABI isalpha_nid_postfix(int); -int APS5_VABI iscntrl_nid_postfix(int); -int APS5_VABI isdigit_nid_postfix(int); -int APS5_VABI isgraph_nid_postfix(int); -int APS5_VABI islower_nid_postfix(int); -int APS5_VABI isprint_nid_postfix(int); -int APS5_VABI ispunct_nid_postfix(int); -int APS5_VABI isspace_nid_postfix(int); -int APS5_VABI isupper_nid_postfix(int); -int APS5_VABI isxdigit_nid_postfix(int); -int APS5_VABI isblank_nid_postfix(int); -int APS5_VABI tolower_nid_postfix(int); -int APS5_VABI toupper_nid_postfix(int); -int APS5_VABI iswalnum_nid_postfix(std::uint32_t); -int APS5_VABI iswalpha_nid_postfix(std::uint32_t); -int APS5_VABI iswblank_nid_postfix(std::uint32_t); -int APS5_VABI iswcntrl_nid_postfix(std::uint32_t); -int APS5_VABI iswdigit_nid_postfix(std::uint32_t); -int APS5_VABI iswgraph_nid_postfix(std::uint32_t); -int APS5_VABI iswlower_nid_postfix(std::uint32_t); -int APS5_VABI iswprint_nid_postfix(std::uint32_t); -int APS5_VABI iswpunct_nid_postfix(std::uint32_t); -int APS5_VABI iswspace_nid_postfix(std::uint32_t); -int APS5_VABI iswupper_nid_postfix(std::uint32_t); -int APS5_VABI iswxdigit_nid_postfix(std::uint32_t); -int APS5_VABI iswctype_nid_postfix(std::uint32_t, std::uint64_t); -std::uint64_t APS5_VABI wctype_nid_postfix(const char*); -std::uint32_t APS5_VABI towlower_nid_postfix(std::uint32_t); -std::uint32_t APS5_VABI towupper_nid_postfix(std::uint32_t); -std::uint64_t APS5_VABI wctrans_nid_postfix(const char*); -std::uint32_t APS5_VABI towctrans_nid_postfix(std::uint32_t, std::uint64_t); -std::uint32_t APS5_VABI _Towlower_nid_postfix(std::uint32_t, const void*); -std::uint32_t APS5_VABI _Towupper_nid_postfix(std::uint32_t, const void*); -int APS5_VABI _Tolower_nid_postfix(int, const void*); -int APS5_VABI _Toupper_nid_postfix(int, const void*); -std::uint32_t APS5_VABI btowc_nid_postfix(int); -int APS5_VABI wctob_nid_postfix(std::uint32_t); } void Require(bool condition, std::source_location location = std::source_location::current()) { @@ -120,6 +84,10 @@ int main() { } Require(entry.wide(0xffffffff) == 0 && iswctype_nid_postfix(0xffffffff, entry.mask) == 0); } + for (std::uint32_t c = 0; c < 300; ++c) { + Require((iswascii_nid_postfix(c) != 0) == (c <= 0x7f)); + } + Require(iswascii_nid_postfix(0xffffffff) == 0); Require(wctype_nid_postfix("ideogram") == 0x80000 && wctype_nid_postfix("special") == 0x100000); Require(wctype_nid_postfix("phonogram") == 0x200000 && wctype_nid_postfix("number") == 0x400000); Require(wctype_nid_postfix("rune") == 0xffffff00 && wctype_nid_postfix("") == 0 && wctype_nid_postfix("Alpha") == 0); diff --git a/core/libs/tests/GuestRuntimeLifecycle.cpp b/core/libs/tests/GuestRuntimeLifecycle.cpp index e424940b2a..2a4dd8a22d 100644 --- a/core/libs/tests/GuestRuntimeLifecycle.cpp +++ b/core/libs/tests/GuestRuntimeLifecycle.cpp @@ -1,3 +1,4 @@ +#include "prx/libkernel/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -12,12 +13,6 @@ #include #include -extern "C" { -char* APS5_VABI dlerror_nid_postfix(); -std::int32_t APS5_VABI sceKernelLoadStartModule(const char*, std::size_t, const void*, std::uint32_t, const void*, int*); -int APS5_VABI sceKernelStopUnloadModule(std::int32_t, std::size_t, const void*, std::uint32_t, const void*, int*); -} - namespace { struct Event { std::size_t args; const void* argp; }; std::array events{}; diff --git a/core/libs/tests/GuestSafeErrors.cpp b/core/libs/tests/GuestSafeErrors.cpp index 436ce48e09..b253f14d6c 100644 --- a/core/libs/tests/GuestSafeErrors.cpp +++ b/core/libs/tests/GuestSafeErrors.cpp @@ -1,3 +1,5 @@ +#include "prx/libc/include/WindowsFormatting.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -8,15 +10,6 @@ #include #include -extern "C" { -int APS5_VABI strerror_s_nid_postfix(char*, std::size_t, int); -std::size_t APS5_VABI strerrorlen_s_nid_postfix(int); -int APS5_VABI strerror_r_nid_postfix(int, char*, std::size_t); -int* APS5_VABI __error_nid_postfix(); -void* APS5_VABI set_constraint_handler_s_nid_postfix(void*); -void APS5_VABI ignore_handler_s_nid_postfix(const char*, void*, int); -} - namespace { void Require(bool condition, const char* message) { @@ -96,8 +89,10 @@ void CheckConstraints() { Require(violations == before + 1 && violationBuffer == nullptr, "one callback for null destination"); } set_constraint_handler_s_nid_postfix(reinterpret_cast(ignore_handler_s_nid_postfix)); + Require(strerror_s_nid_postfix(nullptr, 1, 2) == 22, "installed ignore handler returns to caller"); set_constraint_handler_s_nid_postfix(reinterpret_cast(Constraint)); + } void CheckThreads() { @@ -122,5 +117,6 @@ int main() { CheckConstraints(); CheckThreads(); set_constraint_handler_s_nid_postfix(previous); + std::puts("safe error message checks passed"); } diff --git a/core/libs/tests/GuestSandboxCertificates.cpp b/core/libs/tests/GuestSandboxCertificates.cpp index 2c76c900ba..5fb1e400b3 100644 --- a/core/libs/tests/GuestSandboxCertificates.cpp +++ b/core/libs/tests/GuestSandboxCertificates.cpp @@ -1,3 +1,6 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libkernel/File/include/File.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/General.hpp" #include "prx/libkernel/KernelErrors.hpp" #include "SceTypes.hpp" @@ -7,16 +10,7 @@ #include #include #include -extern "C" { -const char* APS5_VABI sceKernelGetFsSandboxRandomWord(); -int APS5_VABI sceKernelOpen(const char*, int, unsigned short); -int APS5_VABI sceKernelClose(int); -std::int64_t APS5_VABI sceKernelRead(int, void*, std::size_t); -int APS5_VABI sceKernelStat(const char*, FileStat*); -void* APS5_VABI fopen_nid_postfix(const char*, const char*); -std::size_t APS5_VABI fread_nid_postfix(void*, std::size_t, std::size_t, void*); -int APS5_VABI fclose_nid_postfix(void*); -} + static void Check(bool value, int line) { if (!value) { std::fprintf(stderr, "Sandbox certificates check failed at line %d\n", line); @@ -37,7 +31,7 @@ static std::string ReadKernel(const std::string& path) { return text; } static std::string ReadStream(const std::string& path) { - void* stream = fopen_nid_postfix(path.c_str(), "rb"); + FileStream* stream = fopen_nid_postfix(path.c_str(), "rb"); Require(stream != nullptr); std::string text; char buffer[4096]; diff --git a/core/libs/tests/GuestSandboxRandomWord.cpp b/core/libs/tests/GuestSandboxRandomWord.cpp index 15eb6eb241..b9ec713584 100644 --- a/core/libs/tests/GuestSandboxRandomWord.cpp +++ b/core/libs/tests/GuestSandboxRandomWord.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -5,12 +7,6 @@ #include #include -extern "C" { -const char* APS5_VABI sceKernelGetFsSandboxRandomWord(); -int APS5_VABI open_nid_postfix(const char*, int, int); -int* APS5_VABI __error_nid_postfix(); -} - static void Require(bool value) { if (!value) std::abort(); } int main() { diff --git a/core/libs/tests/GuestSaveDataCancel.cpp b/core/libs/tests/GuestSaveDataCancel.cpp index ce9c2e8c20..5f9612d5ce 100644 --- a/core/libs/tests/GuestSaveDataCancel.cpp +++ b/core/libs/tests/GuestSaveDataCancel.cpp @@ -1,14 +1,14 @@ +#include "prx/libSceSaveData.native/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include #include #include -extern "C" int APS5_VABI sceSaveDataCancel(std::uint32_t cancelArgument); - int main() { try { sceSaveDataCancel(0); + } catch (const std::runtime_error& error) { if (std::string(error.what()) == "sceSaveDataCancel not implemented") return 0; std::fprintf(stderr, "sceSaveDataCancel threw: %s\n", error.what()); diff --git a/core/libs/tests/GuestSaveDataConvert.cpp b/core/libs/tests/GuestSaveDataConvert.cpp index df8f6743ce..85fd30503b 100644 --- a/core/libs/tests/GuestSaveDataConvert.cpp +++ b/core/libs/tests/GuestSaveDataConvert.cpp @@ -1,3 +1,5 @@ +#include "prx/libSceSaveData/include/Api.hpp" +#include "prx/libSceSaveData.native/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "SceTypes.hpp" #include @@ -10,14 +12,6 @@ #include #include -extern "C" { -int APS5_VABI sceSaveDataConvert(const SaveDataConvert*); -int APS5_VABI sceSaveDataGetConvertProgress(float*); -int APS5_VABI sceSaveDataInitialize3(const void*); -int APS5_VABI sceSaveDataTerminate(); -int APS5_VABI sceSaveDataGetEventResult(const void*, SaveDataEvent*); -} - namespace { constexpr int SaveDataErrorParameter = -2137063424; diff --git a/core/libs/tests/GuestSaveDataDelete.cpp b/core/libs/tests/GuestSaveDataDelete.cpp index 0ebbce1462..b84152d310 100644 --- a/core/libs/tests/GuestSaveDataDelete.cpp +++ b/core/libs/tests/GuestSaveDataDelete.cpp @@ -1,3 +1,6 @@ +#include "prx/libc/include/Api.hpp" +#include "prx/libSceSaveData/include/Api.hpp" +#include "prx/libSceSaveData.native/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libc/include/FileStream.hpp" #include "SceTypes.hpp" @@ -13,17 +16,6 @@ #include #include -extern "C" { -int APS5_VABI sceSaveDataDelete(const SaveDataDelete*); -int APS5_VABI sceSaveDataInitialize3(const void*); -int APS5_VABI sceSaveDataMount3(const SaveDataMount3*, SaveDataMountResult*); -int APS5_VABI sceSaveDataUmount2(std::uint32_t, const SaveDataMountPoint*); -FileStream* APS5_VABI fopen_nid_postfix(const char*, const char*); -std::size_t APS5_VABI fread_nid_postfix(void*, std::size_t, std::size_t, FileStream*); -std::size_t APS5_VABI fwrite_nid_postfix(const void*, std::size_t, std::size_t, FileStream*); -int APS5_VABI fclose_nid_postfix(FileStream*); -} - namespace { constexpr int SaveDataErrorParameter = -2137063424; diff --git a/core/libs/tests/GuestSaveDataDialog.cpp b/core/libs/tests/GuestSaveDataDialog.cpp index c520246469..e3f2ef95bf 100644 --- a/core/libs/tests/GuestSaveDataDialog.cpp +++ b/core/libs/tests/GuestSaveDataDialog.cpp @@ -1,3 +1,5 @@ +#include "prx/libSceSaveDataDialog/include/Api.hpp" +#include "prx/libSceSaveDataDialog.native/include/Api.hpp" #include "prx/libSceSaveDataDialog.native/SaveDataDialog.hpp" #include "prx/libc/include/general/VabiMacros.hpp" @@ -5,19 +7,6 @@ #include #include -extern "C" { -int APS5_VABI sceSaveDataDialogInitialize(); -int APS5_VABI sceSaveDataDialogOpen(const void* param); -int APS5_VABI sceSaveDataDialogGetStatus(); -int APS5_VABI sceSaveDataDialogUpdateStatus(); -int APS5_VABI sceSaveDataDialogIsReadyToDisplay(); -int APS5_VABI sceSaveDataDialogProgressBarInc(int target, std::uint32_t delta); -int APS5_VABI sceSaveDataDialogProgressBarSetValue(int target, std::uint32_t rate); -int APS5_VABI sceSaveDataDialogClose(const void* param); -int APS5_VABI sceSaveDataDialogGetResult(void* result); -int APS5_VABI sceSaveDataDialogTerminate(); -} - static void Require(bool value, const char* message) { if (!value) { std::fprintf(stderr, "%s\n", message); diff --git a/core/libs/tests/GuestSaveDataMountStatus.cpp b/core/libs/tests/GuestSaveDataMountStatus.cpp index 33fd69861e..182d79a5bd 100644 --- a/core/libs/tests/GuestSaveDataMountStatus.cpp +++ b/core/libs/tests/GuestSaveDataMountStatus.cpp @@ -1,3 +1,5 @@ +#include "prx/libSceSaveData/include/Api.hpp" +#include "prx/libSceSaveData.native/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "SceTypes.hpp" #include @@ -7,20 +9,9 @@ #include #include #include - -extern "C" { -int APS5_VABI sceSaveDataInitialize3(const void*); -int APS5_VABI sceSaveDataBackup(const SaveDataBackup*); -int APS5_VABI sceSaveDataGetEventResult(const void*, SaveDataEvent*); -int APS5_VABI sceSaveDataMount3(const SaveDataMount3*, SaveDataMountResult*); -int APS5_VABI sceSaveDataUmount2(std::uint32_t, const SaveDataMountPoint*); -int APS5_VABI sceSaveDataGetMountInfo(const SaveDataMountPoint*, SaveDataMountInfo*); -int APS5_VABI sceSaveDataGetParam(const SaveDataMountPoint*, std::uint32_t, void*, std::size_t, std::size_t*); -int APS5_VABI sceSaveDataSetParam(const SaveDataMountPoint*, std::uint32_t, const void*, std::size_t); -int APS5_VABI sceSaveDataLoadIcon(const SaveDataMountPoint*, SaveDataIcon*); -int APS5_VABI sceSaveDataSaveIcon(const SaveDataMountPoint*, const SaveDataIcon*); -int APS5_VABI sceSaveDataSaveIconByPath(const SaveDataMountPoint*, const char*); -} +#ifdef _WIN32 +#include +#endif namespace { @@ -163,7 +154,15 @@ void CheckEquivalentMounts() { const auto casePath = std::filesystem::path("_sd") / "IDENTITY"; const bool caseAlias = std::filesystem::exists(casePath) && std::filesystem::equivalent(originalPath, casePath, error); Check(!error || error == std::errc::no_such_file_or_directory, "case-alias identity check succeeds"); +#ifdef _WIN32 + error.clear(); + if (!CreateSymbolicLinkW((std::filesystem::path("_sd") / "linked").c_str(), L"identity", + SYMBOLIC_LINK_FLAG_DIRECTORY | SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE)) { + error = std::error_code(GetLastError(), std::system_category()); + } +#else std::filesystem::create_directory_symlink("identity", std::filesystem::path("_sd") / "linked", error); +#endif const bool symlinkAlias = !error; Check(caseAlias || symlinkAlias, "a host alias is available to check mount identity"); @@ -185,7 +184,12 @@ void CheckEquivalentMounts() { if (caseAlias) MountAndCheck("IDENTITY", MountReadWrite, 0u, "case alias after unmount"); if (symlinkAlias) { MountAndCheck("linked", MountReadWrite, 0u, "symlink alias after unmount"); +#ifdef _WIN32 + error.clear(); + if (!RemoveDirectoryW((std::filesystem::path("_sd") / "linked").c_str())) error = std::error_code(GetLastError(), std::system_category()); +#else std::filesystem::remove(std::filesystem::path("_sd") / "linked", error); +#endif Check(!error, "symlink alias is removed"); } } diff --git a/core/libs/tests/GuestSaveDataPs4.cpp b/core/libs/tests/GuestSaveDataPs4.cpp index d795b28195..d707094961 100644 --- a/core/libs/tests/GuestSaveDataPs4.cpp +++ b/core/libs/tests/GuestSaveDataPs4.cpp @@ -1,3 +1,5 @@ +#include "prx/libSceSaveData/include/Api.hpp" +#include "prx/libSceSaveData.native/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "SceTypes.hpp" #include @@ -8,29 +10,6 @@ #include #include -struct SaveDataMountPs4 { - std::int32_t user_id; - std::int32_t pad; - const void* title_id; - const SceSaveDataDirName* dir_name; - const void* fingerprint; - std::uint64_t blocks; - std::uint32_t mount_mode; - std::uint8_t reserved[32]; -}; - -extern "C" int APS5_VABI sceSaveDataTransferringMount(const SaveDataTransferringMount*, SaveDataMountResult*); -extern "C" int APS5_VABI sceSaveDataTransferringMountPs4(const SaveDataTransferringMount*, SaveDataMountResult*); -extern "C" int APS5_VABI sceSaveDataMount(const SaveDataMountPs4*, SaveDataMountResult*); -extern "C" int APS5_VABI sceSaveDataUmount(const SaveDataMountPoint*); -extern "C" int APS5_VABI sceSaveDataDirNameSearchPs4(const SaveDataDirNameSearchCond*, SaveDataDirNameSearchResult*); -extern "C" int APS5_VABI sceSaveDataDirNameSearch(const SaveDataDirNameSearchCond*, SaveDataDirNameSearchResult*); -extern "C" int APS5_VABI sceSaveDataInitialize(const void*); -extern "C" int APS5_VABI sceSaveDataTerminate(); -extern "C" int APS5_VABI sceSaveDataSetupSaveDataMemory(std::int32_t, std::size_t, const SaveDataParam*); -extern "C" int APS5_VABI sceSaveDataSetSaveDataMemory(std::int32_t, void*, std::size_t, std::int64_t); -extern "C" int APS5_VABI sceSaveDataGetSaveDataMemory(std::int32_t, void*, std::size_t, std::int64_t); - namespace { constexpr int SaveDataErrorNotFound = -2137063416; diff --git a/core/libs/tests/GuestSaveDataSearch.cpp b/core/libs/tests/GuestSaveDataSearch.cpp index 47613690d3..f3b0b4382a 100644 --- a/core/libs/tests/GuestSaveDataSearch.cpp +++ b/core/libs/tests/GuestSaveDataSearch.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceSaveData.native/include/Api.hpp" #include "SceTypes.hpp" #include "prx/libc/include/general/VabiMacros.hpp" @@ -12,15 +13,6 @@ #include #include -extern "C" { -int APS5_VABI sceSaveDataDirNameSearch(const SaveDataDirNameSearchCond*, SaveDataDirNameSearchResult*); -int APS5_VABI sceSaveDataDirNameSearch2(const SaveDataDirNameSearchCond*, SaveDataDirNameSearchResult*); -int APS5_VABI sceSaveDataMount3(const SaveDataMount3*, SaveDataMountResult*); -int APS5_VABI sceSaveDataUmount2(std::uint32_t, const SaveDataMountPoint*); -int APS5_VABI sceSaveDataSetParam(const SaveDataMountPoint*, std::uint32_t, const void*, std::size_t); -int APS5_VABI sceSaveDataGetMountInfo(const SaveDataMountPoint*, SaveDataMountInfo*); -} - static constexpr int SaveDataErrorParameter = -2137063424; static void Require(bool value, const char* message) { diff --git a/core/libs/tests/GuestScanCount.cpp b/core/libs/tests/GuestScanCount.cpp index 1ddfe19674..9c2df500c0 100644 --- a/core/libs/tests/GuestScanCount.cpp +++ b/core/libs/tests/GuestScanCount.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "SceTypes.hpp" #include @@ -8,9 +9,6 @@ #include #include -extern "C" int APS5_VABI sscanf_s_nid_postfix(const char*, const char*, ...); -extern "C" int APS5_VABI vsscanf_s_nid_postfix(const char*, const char*, VaList*); - static int APS5_VABI ScanList(const char* input, const char* format, ...) { #ifdef _WIN32 __builtin_sysv_va_list args; diff --git a/core/libs/tests/GuestSceNet.cpp b/core/libs/tests/GuestSceNet.cpp index 4e5f27cab2..8e4b902c1c 100644 --- a/core/libs/tests/GuestSceNet.cpp +++ b/core/libs/tests/GuestSceNet.cpp @@ -1,3 +1,7 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" +#include "prx/libSceNetCtl/include/NetCtl.hpp" +#include "prx/libSceNet/include/Net.hpp" #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN #include @@ -32,124 +36,14 @@ extern "C" { extern const std::uint8_t in6addr_any_nid_postfix[16]; extern const std::uint8_t in6addr_loopback_nid_postfix[16]; -int APS5_VABI sceNetInit_nid_postfix(void); -int APS5_VABI sceNetShowNetstatWithMemory(int); -int APS5_VABI sceNetShowRouteWithMemory(int); -int APS5_VABI sceNetShowNetstat(void); -int APS5_VABI sceNetShowNetstatEx(std::uint32_t); -int APS5_VABI sceNetShowIfconfig(void); -int APS5_VABI sceNetShowPolicy(void); -int APS5_VABI sceNetShowRoute(void); -int APS5_VABI sceNetShowRoute6(void); -int APS5_VABI sceNetSocket(const char*, int, int, int); -int APS5_VABI sceNetBind_nid_postfix(int, const void*, std::uint32_t); -int APS5_VABI sceNetListen(int, int); -int APS5_VABI sceNetGetsockname(int, void*, std::uint32_t*); -int APS5_VABI sceNetGetpeername(int, void*, std::uint32_t*); -int APS5_VABI sceNetGetSockInfo(int, void*, int, int); -int APS5_VABI sceNetGetSockInfo6(int, void*, int, int); -int APS5_VABI sceNetConnect(int, const void*, std::uint32_t); -int APS5_VABI sceNetAccept(int, void*, std::uint32_t*); -std::int64_t APS5_VABI sceNetSend(int, const void*, std::size_t, int); -std::int64_t APS5_VABI sceNetRecv(int, void*, std::size_t, int); -std::int64_t APS5_VABI sceNetSendto(int, const void*, std::size_t, int, const void*, std::uint32_t); -std::int64_t APS5_VABI sceNetRecvfrom(int, void*, std::size_t, int, void*, std::uint32_t*); -int APS5_VABI sceNetSocketClose(int); -int APS5_VABI sceNetSocketAbort(int, int); -int APS5_VABI sceNetShutdown(int, int); -int APS5_VABI sceNetSetsockopt(int, int, int, const void*, std::uint32_t); -int APS5_VABI sceNetGetsockopt(int, int, int, void*, std::uint32_t*); -int APS5_VABI sceNetIoctl(int, std::uint32_t, void*); -int* APS5_VABI sceNetErrnoLoc(void); -int APS5_VABI sceNetEtherNtostr(const NetEtherAddr*, char*, std::size_t); -int APS5_VABI sceNetEtherStrton(const char*, NetEtherAddr*); -int APS5_VABI sceNetEpollCreate(const char*, int); -int APS5_VABI sceNetEpollControl(int, int, int, const NetEpollEvent*); -int APS5_VABI sceNetEpollWait(int, NetEpollEvent*, int, int); -int APS5_VABI sceNetEpollDestroy(int); -int APS5_VABI sceNetEpollAbort(int, int); -int APS5_VABI sceNetGetsockopt(int, int, int, void*, std::uint32_t*); + extern const std::uint32_t sce_net_in6addr_any[4]; extern const std::uint8_t sce_net_in6addr_linklocal_allnodes[16]; -int APS5_VABI sceNetResolverCreate(const char*, int, int); -int APS5_VABI sceNetResolverStartNtoa(int, const char*, void*, int, int, int); -int APS5_VABI sceNetResolverStartNtoa6(int, const char*, void*, int, int, int); -int APS5_VABI sceNetResolverStartNtoaMultipleRecordsEx(int, const char*, void*, int, int, int); -int APS5_VABI sceNetResolverStartNtoaMultipleRecords(int, const char*, void*, int, int, int); -int APS5_VABI sceNetResolverStartAton(int, const void*, char*, int, int, int, int); -int APS5_VABI sceNetResolverStartAton6(int, const void*, char*, int, int, int, int); -int APS5_VABI sceNetResolverAbort(int, int); -int APS5_VABI sceNetResolverDestroy(int); -int APS5_VABI sceNetResolverGetError(int, int*); -int APS5_VABI sceNetClearDnsCache(int); -int APS5_VABI sceNetGetDnsInfo(std::uint32_t*, int); -int APS5_VABI sceNetCtlInit(void); -int APS5_VABI sceNetCtlGetState(int*); -int APS5_VABI sceNetCtlGetInfo(int, NetCtlInfo*); -int APS5_VABI sceNetCtlGetIfStat(NetCtlIfStat*); -int APS5_VABI sceNetCtlRegisterCallback(NetCtlCallback, void*, int*); -int APS5_VABI sceNetCtlUnregisterCallback(int); -int APS5_VABI sceNetCtlRegisterCallbackV6(NetCtlCallback, void*, int*); -int APS5_VABI sceNetCtlUnregisterCallbackV6(int); -int APS5_VABI sceNetCtlCheckCallback(void); -int APS5_VABI sceNetCtlRegisterCallbackForNpToolkit(NetCtlCallback, void*, int*); -int APS5_VABI sceNetCtlUnregisterCallbackForNpToolkit(int); -int APS5_VABI sceNetCtlCheckCallbackForNpToolkit(void); + std::uint64_t NetCtlReadByteCounter_nid_no_patch(const char*); -int APS5_VABI select_nid_postfix(int, void*, void*, void*, const void*); -int APS5_VABI open_nid_postfix(const char*, int, int); -int APS5_VABI socket_nid_postfix(int, int, int); -int APS5_VABI bind_nid_postfix(int, const void*, std::uint32_t); -int APS5_VABI close_nid_postfix(int); + bool GuestSocketIsOpen_nid_no_patch(int); -int APS5_VABI setsockopt_nid_postfix(int, int, int, const void*, std::uint32_t); -int APS5_VABI fcntl_nid_postfix(int, int, ...); -struct GuestPollEntry { - int descriptor; - short events; - short revents; -}; -int APS5_VABI poll_nid_postfix(GuestPollEntry*, std::uint32_t, int); -int* APS5_VABI __error_nid_postfix(); -int APS5_VABI sceNetInetPton(int, const char*, void*); -int APS5_VABI sceNetInetPtonEx(int, const char*, void*, int); -int APS5_VABI sceNetUsleep(int); -void APS5_VABI sceNetGetSystemTime(std::uint64_t*); -const char* APS5_VABI sceNetInetNtop(int, const void*, char*, std::uint32_t); -int* APS5_VABI sceNetErrnoLoc(void); -} -struct NetIovec { - void* base; - std::uint64_t length; -}; - -struct NetMsghdr { - void* name; - std::uint32_t name_length; - NetIovec* iov; - int iov_length; - void* control; - std::uint32_t control_length; - int flags; -}; - -struct NetMemoryPoolStats { - std::size_t pool_size; - std::size_t max_inuse_size; - std::size_t current_inuse_size; -}; - -extern "C" { -std::int64_t APS5_VABI sceNetSendmsg(int, const NetMsghdr*, int); -std::int64_t APS5_VABI sceNetRecvmsg(int, NetMsghdr*, int); -int APS5_VABI sceNetPoolCreate(const char*, int, int); -int APS5_VABI sceNetPoolDestroy(int); -int APS5_VABI sceNetGetMemoryPoolStats(int, NetMemoryPoolStats*); -const char* APS5_VABI sceNetGetIfName(std::uint32_t); -int APS5_VABI sceNetGetRandom(std::uint32_t*); -void* APS5_VABI sceNetMemoryAllocate(std::int32_t, int); -void APS5_VABI sceNetMemoryFree(void*); } static void Require(bool condition) { @@ -192,6 +86,34 @@ static bool Failed(std::int64_t result, int error) { return result == static_cast(0x80410100u | static_cast(error)) && *sceNetErrnoLoc() == error; } +template +static std::string CaptureStdout(TBody body) { + std::fflush(stdout); + std::FILE* capture = std::tmpfile(); + Require(capture != nullptr); +#ifdef _WIN32 + const int saved = _dup(_fileno(stdout)); + Require(saved >= 0 && _dup2(_fileno(capture), _fileno(stdout)) == 0); +#else + const int saved = dup(fileno(stdout)); + Require(saved >= 0 && dup2(fileno(capture), fileno(stdout)) >= 0); +#endif + body(); + std::fflush(stdout); +#ifdef _WIN32 + Require(_dup2(saved, _fileno(stdout)) == 0); + _close(saved); +#else + Require(dup2(saved, fileno(stdout)) >= 0); + close(saved); +#endif + std::string text; + std::rewind(capture); + for (int character = std::fgetc(capture); character != EOF; character = std::fgetc(capture)) text.push_back(static_cast(character)); + std::fclose(capture); + return text; +} + static void CheckSocketHostErrors() { Require(Failed(sceNetSocket(nullptr, 2, 1, 17), 43)); } @@ -866,7 +788,7 @@ static void CheckIoctl() { Require(sceNetIoctl(socket, 0x4004667f, &readable) == 0 && readable == 0); const char payload[5] = {'i', 'o', 'c', 't', 'l'}; Require(sceNetSendto(socket, payload, sizeof(payload), 0, address.data(), address.size()) == sizeof(payload)); - GuestPollEntry entry{socket, 1, 0}; + GuestPollDescriptor entry{socket, 1, 0}; Require(poll_nid_postfix(&entry, 1, 1000) == 1 && entry.revents == 1); Require(sceNetIoctl(socket, 0x4004667f, &readable) == 0 && readable == sizeof(payload)); Require(sceNetRecv(socket, buffer, sizeof(buffer), 0) == sizeof(payload)); @@ -1147,14 +1069,17 @@ static void CheckSystemTime() { } static void CheckUsleep() { - Require(sceNetUsleep(0) == 0); + Require(CaptureStdout([] { Require(sceNetUsleep(0) == 0); }).empty()); const auto start = std::chrono::steady_clock::now(); Require(sceNetUsleep(2000) == 0); Require(std::chrono::steady_clock::now() - start >= std::chrono::microseconds(2000)); - *sceNetErrnoLoc() = 0; - Require(Failed(sceNetUsleep(-1), 22)); - *sceNetErrnoLoc() = 0; - Require(Failed(sceNetUsleep(INT32_MIN), 22)); + const std::string printed = CaptureStdout([] { + *sceNetErrnoLoc() = 0; + Require(Failed(sceNetUsleep(-1), 22)); + *sceNetErrnoLoc() = 0; + Require(Failed(sceNetUsleep(INT32_MIN), 22)); + }); + Require(printed == "[LIBNET] usleep -1\n[LIBNET] usleep -2147483648\n"); } static void CheckEpollIdent() { @@ -1579,7 +1504,7 @@ static std::vector RequireSockInfoList(int flags) { int socket = 0; std::memcpy(&socket, &listed[0x24], sizeof(socket)); Require(sockets.empty() || socket > sockets.back()); - std::array single; + alignas(NetSockInfo6) std::array single; Require(sceNetGetSockInfo(socket, single.data(), 1, 0) == 1 && std::equal(single.begin(), single.end(), listed)); sockets.push_back(socket); } @@ -1626,7 +1551,7 @@ static void CheckSockInfo() { Require(sceNetSetsockopt(datagram, 0xffff, 0x1001, &buffers[1], sizeof(buffers[1])) == 0); const auto configured = RequireSockInfo(datagram, 2, 0x200001, datagramAddress, listening); Require(std::memcmp(configured.data() + 0x64, buffers.data(), sizeof(buffers)) == 0); - std::array record; + alignas(NetSockInfo6) std::array record; record.fill(0xa5); Require(Failed(sceNetGetSockInfo(datagram, nullptr, 1, 0), 22)); Require(Failed(sceNetGetSockInfo(datagram, record.data(), 0, 0), 22)); @@ -1653,7 +1578,7 @@ static std::array RequireSockInfo6(int socket, int type, boo const std::array& remote, int requestFlags) { std::array records; records.fill(0xa5); - Require(sceNetGetSockInfo6(socket, records.data(), 2, requestFlags) == 1); + Require(sceNetGetSockInfo6(socket, reinterpret_cast(records.data()), 2, requestFlags) == 1); std::array expected{}; std::memcpy(expected.data() + 0x24, &socket, sizeof(socket)); expected[0x28] = static_cast(type); @@ -1683,10 +1608,10 @@ static std::vector RequireSockInfo6List(int flags) { const int count = sceNetGetSockInfo6(-1, nullptr, 0, flags); Require(count >= 0); std::vector records(static_cast(count + 1) * 0xa0, 0xa5); - Require(sceNetGetSockInfo6(-1, records.data(), count + 1, flags) == count); + Require(sceNetGetSockInfo6(-1, reinterpret_cast(records.data()), count + 1, flags) == count); Require(std::all_of(records.end() - 0xa0, records.end(), [](auto byte) { return byte == 0xa5; })); std::vector unbounded(records.size(), 0xa5); - Require(sceNetGetSockInfo6(-1, unbounded.data(), INT32_MAX, flags) == count && unbounded == records); + Require(sceNetGetSockInfo6(-1, reinterpret_cast(unbounded.data()), INT32_MAX, flags) == count && unbounded == records); std::vector sockets; for (int index = 0; index < count; ++index) { const auto listed = records.begin() + index * 0xa0; @@ -1696,14 +1621,14 @@ static std::vector RequireSockInfo6List(int flags) { std::memcpy(&status, &listed[0x48], sizeof(status)); Require(sockets.empty() || socket > sockets.back()); Require((flags & 0x1000) != 0 || (status & 0x400000) != 0); - std::array single; - Require(sceNetGetSockInfo6(socket, single.data(), 1, flags) == 1 && std::equal(single.begin(), single.end(), listed)); + alignas(NetSockInfo6) std::array single; + Require(sceNetGetSockInfo6(socket, reinterpret_cast(single.data()), 1, flags) == 1 && std::equal(single.begin(), single.end(), listed)); sockets.push_back(socket); } for (const int limit : {1, 2}) { const int written = std::min(count, limit); std::vector limited(records.size(), 0xa5); - Require(sceNetGetSockInfo6(-1, limited.data(), limit, flags) == written); + Require(sceNetGetSockInfo6(-1, reinterpret_cast(limited.data()), limit, flags) == written); Require(std::equal(limited.begin(), limited.begin() + written * 0xa0, records.begin())); Require(std::all_of(limited.begin() + written * 0xa0, limited.end(), [](auto byte) { return byte == 0xa5; })); } @@ -1734,27 +1659,27 @@ static void CheckSockInfo6() { RequireSockInfo6(datagram, 2, false, true, inetAddress, unnamed, 0x1000); RequireSockInfo6(datagram, 2, false, true, inetAddress, unnamed, 0x1040); - std::array record; + alignas(NetSockInfo6) std::array record; record.fill(0xa5); const auto untouched = [&record] { return std::all_of(record.begin(), record.end(), [](auto byte) { return byte == 0xa5; }); }; Require(Failed(sceNetGetSockInfo6(datagram, nullptr, 1, 0x1000), 22)); - Require(Failed(sceNetGetSockInfo6(datagram, record.data(), 0, 0x1000), 22)); - Require(Failed(sceNetGetSockInfo6(datagram, record.data(), -1, 0x1000), 22)); - Require(Failed(sceNetGetSockInfo6(-1, record.data(), 0, 0), 22)); - Require(Failed(sceNetGetSockInfo6(-1, record.data(), -5, 0x1000), 22)); + Require(Failed(sceNetGetSockInfo6(datagram, reinterpret_cast(record.data()), 0, 0x1000), 22)); + Require(Failed(sceNetGetSockInfo6(datagram, reinterpret_cast(record.data()), -1, 0x1000), 22)); + Require(Failed(sceNetGetSockInfo6(-1, reinterpret_cast(record.data()), 0, 0), 22)); + Require(Failed(sceNetGetSockInfo6(-1, reinterpret_cast(record.data()), -5, 0x1000), 22)); for (const int flags : {1, 0x41, 0x80, 0x1001, 0x2000, 0x400000, 0x1048}) { - Require(Failed(sceNetGetSockInfo6(datagram, record.data(), 1, flags), 22)); + Require(Failed(sceNetGetSockInfo6(datagram, reinterpret_cast(record.data()), 1, flags), 22)); Require(Failed(sceNetGetSockInfo6(-1, nullptr, 0, flags), 22)); - Require(Failed(sceNetGetSockInfo6(-1, record.data(), 1, flags), 22)); + Require(Failed(sceNetGetSockInfo6(-1, reinterpret_cast(record.data()), 1, flags), 22)); } - Require(Failed(sceNetGetSockInfo6(datagram, record.data(), 1, 0), 47)); - Require(Failed(sceNetGetSockInfo6(datagram, record.data(), 1, 0x40), 47)); + Require(Failed(sceNetGetSockInfo6(datagram, reinterpret_cast(record.data()), 1, 0), 47)); + Require(Failed(sceNetGetSockInfo6(datagram, reinterpret_cast(record.data()), 1, 0x40), 47)); Require(untouched()); const int closed = sceNetSocket("sockinfo6-closed", 2, 2, 17); Require(closed >= 0 && sceNetSocketClose(closed) == 0); for (const int flags : {0, 0x40, 0x1000, 0x1040}) { - Require(Failed(sceNetGetSockInfo6(closed, record.data(), 1, flags), 9)); - Require(Failed(sceNetGetSockInfo6(INT32_MAX, record.data(), 1, flags), 9)); + Require(Failed(sceNetGetSockInfo6(closed, reinterpret_cast(record.data()), 1, flags), 9)); + Require(Failed(sceNetGetSockInfo6(INT32_MAX, reinterpret_cast(record.data()), 1, flags), 9)); } Require(untouched()); Require(RequireSockInfo6List(0) == earlier); @@ -1762,7 +1687,7 @@ static void CheckSockInfo6() { if (ipv6Unavailable) { Require(sceNetSocketClose(datagram) == 0); - Require(Failed(sceNetGetSockInfo6(datagram, record.data(), 1, 0x1000), 9)); + Require(Failed(sceNetGetSockInfo6(datagram, reinterpret_cast(record.data()), 1, 0x1000), 9)); Require(RequireSockInfo6List(0x1000) == earlierAll); return; } @@ -1814,15 +1739,15 @@ static void CheckSockInfo6() { const auto configured = RequireSockInfo6(peer, 2, true, true, peerAddress, udpAddress, 0); Require(std::memcmp(configured.data() + 0x64, buffers.data(), sizeof(buffers)) == 0); Require(std::all_of(configured.begin() + 0x34, configured.begin() + 0x3c, [](auto byte) { return byte == 0; })); - Require(sceNetGetSockInfo6(peer, record.data(), 1, 0x1040) == 1 && std::equal(configured.begin(), configured.end(), record.begin())); + Require(sceNetGetSockInfo6(peer, reinterpret_cast(record.data()), 1, 0x1040) == 1 && std::equal(configured.begin(), configured.end(), record.begin())); Require(RequireSockInfo6List(0) == WithSockets(earlier, {udp, listener, client, accepted, peer})); Require(RequireSockInfo6List(0x40) == WithSockets(earlier, {udp, listener, client, accepted, peer})); Require(RequireSockInfo6List(0x1000) == WithSockets(earlierAll, {datagram, udp, listener, client, accepted, peer})); - Require(Failed(sceNetGetSockInfo6(datagram, record.data(), 1, 0), 47)); + Require(Failed(sceNetGetSockInfo6(datagram, reinterpret_cast(record.data()), 1, 0), 47)); for (const int descriptor : {peer, accepted, client, listener, udp}) Require(sceNetSocketClose(descriptor) == 0); - Require(Failed(sceNetGetSockInfo6(udp, record.data(), 1, 0), 9)); + Require(Failed(sceNetGetSockInfo6(udp, reinterpret_cast(record.data()), 1, 0), 9)); Require(RequireSockInfo6List(0) == earlier); Require(sceNetSocketClose(datagram) == 0); Require(RequireSockInfo6List(0x1000) == earlierAll); @@ -2086,12 +2011,12 @@ int main() { Require(select_nid_postfix(std::max(kernel_socket, udp_sender) + 1, nullptr, mixed_writable, nullptr, wait_second) == 2); Require(((mixed_writable[kernel_socket / 64] >> (kernel_socket % 64)) & 1u) != 0); Require(((mixed_writable[udp_sender / 64] >> (udp_sender % 64)) & 1u) != 0); - GuestPollEntry net_read{udp_receiver, 1, 0}; + GuestPollDescriptor net_read{udp_receiver, 1, 0}; Require(poll_nid_postfix(&net_read, 1, 0) == 0 && net_read.revents == 0); Require(sceNetSendto(udp_sender, datagram, sizeof(datagram), 0, address.data(), address.size()) == sizeof(datagram)); Require(poll_nid_postfix(&net_read, 1, 1000) == 1 && net_read.revents == 1); Require(sceNetRecvfrom(udp_receiver, datagram_result, sizeof(datagram_result), 0, nullptr, nullptr) == sizeof(datagram_result)); - GuestPollEntry mixed_poll[2]{{kernel_socket, 4, 0}, {udp_sender, 4, 0}}; + GuestPollDescriptor mixed_poll[2]{{kernel_socket, 4, 0}, {udp_sender, 4, 0}}; Require(poll_nid_postfix(mixed_poll, 2, 1000) == 2 && mixed_poll[0].revents == 4 && mixed_poll[1].revents == 4); Require(close_nid_postfix(kernel_socket) == 0); std::uint64_t stdio_readable[16]{1}; @@ -2138,9 +2063,9 @@ int main() { Require(sceNetResolverGetError(resolver, &resolver_error) == 0 && resolver_error == static_cast(0x804101E1)); Require(sceNetResolverStartNtoa(resolver, "localhost", ipv4.data(), 5000000, 1, 0) == 0); Require(sceNetResolverGetError(resolver, &resolver_error) == 0 && resolver_error == 0); - std::array records{}; + alignas(NetResolverInfo) std::array records{}; records.fill(0xA5); - Require(sceNetResolverStartNtoaMultipleRecordsEx(resolver, "localhost", records.data(), 5000000, 1, 0) == 0); + Require(sceNetResolverStartNtoaMultipleRecordsEx(resolver, "localhost", reinterpret_cast(records.data()), 5000000, 1, 0) == 0); std::int32_t record_family = 0; std::int32_t record_count = 0; std::int32_t record_count4 = 0; @@ -2158,37 +2083,37 @@ int main() { } } const auto resolved = records; - Require(sceNetResolverStartNtoaMultipleRecordsEx(resolver, nullptr, records.data(), 5000000, 1, 0) == + Require(sceNetResolverStartNtoaMultipleRecordsEx(resolver, nullptr, reinterpret_cast(records.data()), 5000000, 1, 0) == static_cast(0x80410116) && *sceNetErrnoLoc() == 22 && records == resolved); Require(sceNetResolverStartNtoaMultipleRecordsEx(resolver, "localhost", nullptr, 5000000, 1, 0) == static_cast(0x80410116) && *sceNetErrnoLoc() == 22); { ScopedResolverLookupOverride lookupOverride(FailResolverLookup); - Require(sceNetResolverStartNtoaMultipleRecordsEx(resolver, "guest-sce-net.invalid.", records.data(), 5000000, 1, 0) == + Require(sceNetResolverStartNtoaMultipleRecordsEx(resolver, "guest-sce-net.invalid.", reinterpret_cast(records.data()), 5000000, 1, 0) == static_cast(0x804101E1)); } Require(records == resolvedRecords); - std::array plain{}; + alignas(NetResolverInfo) std::array plain{}; plain.fill(0xA5); - Require(sceNetResolverStartNtoaMultipleRecords(resolver, "localhost", plain.data(), 5000000, 1, 0) == 0); + Require(sceNetResolverStartNtoaMultipleRecords(resolver, "localhost", reinterpret_cast(plain.data()), 5000000, 1, 0) == 0); Require(plain == resolved); Require(sceNetResolverGetError(resolver, &resolver_error) == 0 && resolver_error == 0); - Require(sceNetResolverStartNtoaMultipleRecords(resolver, nullptr, plain.data(), 5000000, 1, 0) == + Require(sceNetResolverStartNtoaMultipleRecords(resolver, nullptr, reinterpret_cast(plain.data()), 5000000, 1, 0) == static_cast(0x80410116) && *sceNetErrnoLoc() == 22 && plain == resolved); Require(sceNetResolverStartNtoaMultipleRecords(resolver, "localhost", nullptr, 5000000, 1, 0) == static_cast(0x80410116) && *sceNetErrnoLoc() == 22); const auto resolvedPlain = plain; { ScopedResolverLookupOverride lookupOverride(FailResolverLookup); - Require(sceNetResolverStartNtoaMultipleRecords(resolver, "guest-sce-net.invalid", plain.data(), 5000000, 1, 0) == + Require(sceNetResolverStartNtoaMultipleRecords(resolver, "guest-sce-net.invalid", reinterpret_cast(plain.data()), 5000000, 1, 0) == static_cast(0x804101E1)); } Require(plain == resolvedPlain); Require(sceNetResolverGetError(resolver, &resolver_error) == 0 && resolver_error == static_cast(0x804101E1)); for (const int flags : {0x1, 0x10000}) { bool threw = false; - try { sceNetResolverStartNtoaMultipleRecords(resolver, "localhost", plain.data(), 5000000, 1, flags); } + try { sceNetResolverStartNtoaMultipleRecords(resolver, "localhost", reinterpret_cast(plain.data()), 5000000, 1, flags); } catch (const std::runtime_error&) { threw = true; } Require(threw && plain == resolved); } @@ -2212,11 +2137,11 @@ int main() { Require(sceNetResolverStartNtoa(resolver, "localhost", ipv4.data(), 5000000, 1, 0) == 0 && ipv4[0] == 127); Require(sceNetResolverGetError(resolver, &resolver_error) == 0 && resolver_error == 0); Require(sceNetResolverAbort(resolver, 1) == 0); - Require(sceNetResolverStartNtoaMultipleRecords(resolver, "localhost", plain.data(), 5000000, 1, 0) == + Require(sceNetResolverStartNtoaMultipleRecords(resolver, "localhost", reinterpret_cast(plain.data()), 5000000, 1, 0) == static_cast(0x80410104) && *sceNetErrnoLoc() == 4); - Require(sceNetResolverStartNtoaMultipleRecords(resolver, "localhost", plain.data(), 5000000, 1, 0) == 0 && plain == resolved); + Require(sceNetResolverStartNtoaMultipleRecords(resolver, "localhost", reinterpret_cast(plain.data()), 5000000, 1, 0) == 0 && plain == resolved); Require(sceNetResolverAbort(resolver, 2) == 0); - Require(sceNetResolverStartNtoaMultipleRecordsEx(resolver, "localhost", records.data(), 5000000, 1, 0) == 0 && records == resolved); + Require(sceNetResolverStartNtoaMultipleRecordsEx(resolver, "localhost", reinterpret_cast(records.data()), 5000000, 1, 0) == 0 && records == resolved); std::memset(reverse, 0x5A, sizeof(reverse)); Require(sceNetResolverStartAton(resolver, loopback.data(), reverse, sizeof(reverse), 5000000, 1, 0) == static_cast(0x80410104) && *sceNetErrnoLoc() == 4 && reverse[0] == 0x5A); @@ -2225,7 +2150,7 @@ int main() { Require(sceNetResolverAbort(resolver, 3) == 0); Require(sceNetResolverStartAton(resolver, loopback.data(), reverse, sizeof(reverse), 5000000, 1, 0) == static_cast(0x80410104) && *sceNetErrnoLoc() == 4); - Require(sceNetResolverStartNtoaMultipleRecordsEx(resolver, "localhost", records.data(), 5000000, 1, 0) == + Require(sceNetResolverStartNtoaMultipleRecordsEx(resolver, "localhost", reinterpret_cast(records.data()), 5000000, 1, 0) == static_cast(0x80410104) && *sceNetErrnoLoc() == 4 && records == resolved); Require(sceNetResolverStartNtoa(resolver, "localhost", ipv4.data(), 5000000, 1, 0) == 0); for (const int flags : {0x4, -1}) { @@ -2285,7 +2210,7 @@ int main() { const int other = sceNetResolverCreate("guest-sce-net-other", 0, 0); Require(other >= 0 && other != resolver); Require(sceNetResolverAbort(other, 3) == 0); - Require(sceNetResolverStartNtoaMultipleRecords(resolver, "localhost", plain.data(), 5000000, 1, 0) == 0); + Require(sceNetResolverStartNtoaMultipleRecords(resolver, "localhost", reinterpret_cast(plain.data()), 5000000, 1, 0) == 0); Require(sceNetResolverDestroy(other) == 0); Require(sceNetResolverAbort(other, 0) == static_cast(0x80410109) && *sceNetErrnoLoc() == 9); Require(sceNetResolverAbort(-1, 1) == static_cast(0x80410109) && *sceNetErrnoLoc() == 9); @@ -2302,9 +2227,9 @@ int main() { resolver_error = -1; Require(sceNetResolverGetError(resolver, &resolver_error) == static_cast(0x80410109) && *sceNetErrnoLoc() == 9 && resolver_error == -1); - Require(sceNetResolverStartNtoaMultipleRecordsEx(resolver, "localhost", records.data(), 5000000, 1, 0) == + Require(sceNetResolverStartNtoaMultipleRecordsEx(resolver, "localhost", reinterpret_cast(records.data()), 5000000, 1, 0) == static_cast(0x80410109) && *sceNetErrnoLoc() == 9 && records == resolved); - Require(sceNetResolverStartNtoaMultipleRecords(resolver, "localhost", plain.data(), 5000000, 1, 0) == + Require(sceNetResolverStartNtoaMultipleRecords(resolver, "localhost", reinterpret_cast(plain.data()), 5000000, 1, 0) == static_cast(0x80410109) && *sceNetErrnoLoc() == 9 && plain == resolved); Require(sceNetResolverAbort(resolver, 1) == static_cast(0x80410109) && *sceNetErrnoLoc() == 9); @@ -2341,7 +2266,7 @@ int main() { { std::array dns{}; dns.fill(0xA5A5A5A5u); - const int count = sceNetGetDnsInfo(dns.data(), 0); + const int count = sceNetGetDnsInfo(reinterpret_cast(dns.data()), 0); Require(count >= 0 && count <= 2 && dns[2] == 0xA5A5A5A5u); Require(count == 0 || state == 3); for (int index = count; index < 2; ++index) Require(dns[index] == 0); @@ -2359,7 +2284,7 @@ int main() { } for (const int flags : {0x1, -1}) { bool threw = false; - try { sceNetGetDnsInfo(dns.data(), flags); } catch (const std::runtime_error&) { threw = true; } + try { sceNetGetDnsInfo(reinterpret_cast(dns.data()), flags); } catch (const std::runtime_error&) { threw = true; } Require(threw); } bool threw = false; diff --git a/core/libs/tests/GuestSceV2Exceptions.cpp b/core/libs/tests/GuestSceV2Exceptions.cpp index b7f21db666..60765c0a45 100644 --- a/core/libs/tests/GuestSceV2Exceptions.cpp +++ b/core/libs/tests/GuestSceV2Exceptions.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -6,13 +7,9 @@ #include struct TypeRecord { const void* vtable; const char* name; const TypeRecord* base; }; -struct Category { const void* const* vtable; }; -struct ErrorCode { int reserved; int value; const Category* category; }; -struct Exception { const void* const* vtable; const char* message; }; -struct SystemError { Exception base; ErrorCode code; }; -static_assert(sizeof(Exception) == 16 && sizeof(SystemError) == 32); +static_assert(sizeof(LibcException::ExceptionObject) == 16 && sizeof(LibcException::SystemErrorObject) == 32); -using GuestWhat = const char* (APS5_VABI *)(const Exception*); +using GuestWhat = const char* (APS5_VABI *)(const LibcException::ExceptionObject*); using Thrower = void (APS5_VABI *)(const void*); extern "C" { @@ -21,31 +18,7 @@ extern const TypeRecord _ZTISt9bad_alloc_nid_postfix; extern const TypeRecord _ZTISt12length_error_nid_postfix; extern const TypeRecord _ZTISt12system_error_nid_postfix; extern const TypeRecord _ZTINSt13__sce_cxxvers16_Error_exceptionE_nid_postfix; -const Category* APS5_VABI _ZSt16generic_categoryv_nid_postfix(); -void APS5_VABI _ZNSt13__sce_cxxvers16_Error_exceptionC1EPKc_nid_postfix(Exception* self, const char* message); -void APS5_VABI _ZNSt13__sce_cxxvers16_Error_exceptionC2EPKc_nid_postfix(Exception* self, const char* message); -void APS5_VABI _ZNSt13__sce_cxxvers16_Error_exceptionC1ERKS0__nid_postfix(Exception* self, const Exception* source); -void APS5_VABI _ZNSt13__sce_cxxvers16_Error_exceptionD1Ev_nid_postfix(Exception* self); -void APS5_VABI _ZNSt13__sce_cxxvers16_Error_exceptionD2Ev_nid_postfix(Exception* self); -const char* APS5_VABI _ZNKSt13__sce_cxxvers16_Error_exception4whatEv_nid_postfix(const Exception* self); -void APS5_VABI _ZNSt8__sce_v214_Xlength_errorEPKc_nid_postfix(const char* message); -void APS5_VABI _ZNSt8__sce_v214_Xout_of_rangeEPKc_nid_postfix(const char* message); -void APS5_VABI _ZNSt8__sce_v218_Xinvalid_argumentEPKc_nid_postfix(const char* message); -void APS5_VABI _ZNSt8__sce_v215_Xruntime_errorEPKc_nid_postfix(const char* message); -void APS5_VABI _ZNSt8__sce_v216_Xoverflow_errorEPKc_nid_postfix(const char* message); -void APS5_VABI _ZNSt8__sce_v211_Xbad_allocEv_nid_postfix(const void*); -void APS5_VABI _ZNSt8__sce_v219_Xbad_function_callEv_nid_postfix(const void*); -void APS5_VABI _ZNSt8__sce_v26_ThrowERKNS_19bad_optional_accessE_nid_postfix(const void*); -void APS5_VABI _ZNSt8__sce_v26_ThrowERKNS_12bad_weak_ptrE_nid_postfix(const void*); -void APS5_VABI _ZNSt8__sce_v26_ThrowERKNS_18bad_variant_accessE_nid_postfix(const void*); -void APS5_VABI _ZNSt8__sce_v26_ThrowERKNS_11range_errorE_nid_postfix(const void* error); -void APS5_VABI _ZNSt8__sce_v26_ThrowERKNS_12system_errorE_nid_postfix(const void* error); -void APS5_VABI _ZNSt8__sce_v28ios_base6_ThrowERKNS0_7failureE_nid_postfix(const void* failure); -void APS5_VABI _ZNSt8__sce_v216_Throw_Cpp_errorEi_nid_postfix(std::intptr_t code); -const char* APS5_VABI _ZNSt8__sce_v213_Syserror_mapEi_nid_postfix(int value); -const char* APS5_VABI _ZSt13_Syserror_mapi_nid_postfix(int value); -std::int64_t APS5_VABI _ZNSt8__sce_v216_Xtime_get_ticksEv_nid_postfix(); -std::int64_t APS5_VABI _Xtime_get_ticks_nid_postfix(); + void APS5_VABI SceV2Catch(Thrower thrower, const void* argument); const void* SceV2CatchType = nullptr; @@ -62,12 +35,12 @@ static void Require(bool value, const char* what) { ++failures; } -static const TypeRecord* TypeOf(const Exception* object) { - return static_cast(object->vtable[-1]); +static const TypeRecord* TypeOf(const LibcException::ExceptionObject* object) { + return static_cast(static_cast(object->vtable)[-1]); } -static const char* What(const Exception* object) { - return reinterpret_cast(const_cast(object->vtable[2]))(object); +static const char* What(const LibcException::ExceptionObject* object) { + return reinterpret_cast(const_cast(static_cast(object->vtable)[2]))(object); } static TypeRecord Named(const char* name) { @@ -75,11 +48,11 @@ static TypeRecord Named(const char* name) { } static char inspected[256]; -static std::size_t inspectBytes = sizeof(Exception); -static SystemError inspectedSystem {}; +static std::size_t inspectBytes = sizeof(LibcException::ExceptionObject); +static LibcException::SystemErrorObject inspectedSystem {}; extern "C" void APS5_VABI SceV2Inspect(void* object) { - const auto* exception = static_cast(object); + const auto* exception = static_cast(object); std::snprintf(inspected, sizeof(inspected), "%s|%s", TypeOf(exception)->name, What(exception)); std::memcpy(&inspectedSystem, object, inspectBytes); } @@ -146,17 +119,17 @@ static void CheckCopies() { const TypeRecord systemError = Named("NSt8__sce_v212system_errorE"); const TypeRecord logicError = Named("NSt8__sce_v211logic_errorE"); - Exception range {}; + LibcException::ExceptionObject range {}; _ZNSt13__sce_cxxvers16_Error_exceptionC2EPKc_nid_postfix(&range, "range copy"); Run({"_Throw(range_error)", AsThrower(_ZNSt8__sce_v26_ThrowERKNS_11range_errorE_nid_postfix), &range, &runtimeError, &logicError, 2, "NSt8__sce_v211range_errorE|range copy"}); Require(inspectedSystem.base.message == range.message, "_Throw(range_error) shares the message"); _ZNSt13__sce_cxxvers16_Error_exceptionD2Ev_nid_postfix(&range); - SystemError error {}; + LibcException::SystemErrorObject error {}; _ZNSt13__sce_cxxvers16_Error_exceptionC2EPKc_nid_postfix(&error.base, "system copy"); error.code = {0, 5, _ZSt16generic_categoryv_nid_postfix()}; - inspectBytes = sizeof(SystemError); + inspectBytes = sizeof(LibcException::SystemErrorObject); SceV2CatchType = &runtimeError; SceV2OtherType = &logicError; SceV2Catch(AsThrower(_ZNSt8__sce_v26_ThrowERKNS_12system_errorE_nid_postfix), &error); @@ -168,20 +141,20 @@ static void CheckCopies() { SceV2Catch(AsThrower(_ZNSt8__sce_v28ios_base6_ThrowERKNS0_7failureE_nid_postfix), &error); Require(std::strcmp(inspected, "NSt8__sce_v28ios_base7failureE|system copy") == 0, "ios_base::_Throw(failure) type and message"); Require(inspectedSystem.code.value == 5, "ios_base::_Throw(failure) copies the code"); - inspectBytes = sizeof(Exception); + inspectBytes = sizeof(LibcException::ExceptionObject); _ZNSt13__sce_cxxvers16_Error_exceptionD2Ev_nid_postfix(&error.base); } static void CheckErrorException() { - Exception empty {}; + LibcException::ExceptionObject empty {}; _ZNSt13__sce_cxxvers16_Error_exceptionC1EPKc_nid_postfix(&empty, nullptr); Require(std::strcmp(_ZNKSt13__sce_cxxvers16_Error_exception4whatEv_nid_postfix(&empty), "") == 0, "_Error_exception(nullptr) has an empty message"); Require(std::strcmp(TypeOf(&empty)->name, "NSt13__sce_cxxvers16_Error_exceptionE") == 0, "_Error_exception type name"); Require(TypeOf(&empty)->base == &_ZTISt9exception_nid_postfix, "_Error_exception derives from std::exception"); - Exception text {}; + LibcException::ExceptionObject text {}; _ZNSt13__sce_cxxvers16_Error_exceptionC2EPKc_nid_postfix(&text, "text"); - Exception copy {}; + LibcException::ExceptionObject copy {}; _ZNSt13__sce_cxxvers16_Error_exceptionC1ERKS0__nid_postfix(©, &text); Require(std::strcmp(_ZNKSt13__sce_cxxvers16_Error_exception4whatEv_nid_postfix(©), "text") == 0, "_Error_exception copy keeps the message"); _ZNSt13__sce_cxxvers16_Error_exceptionD2Ev_nid_postfix(&text); diff --git a/core/libs/tests/GuestSchedPriority.cpp b/core/libs/tests/GuestSchedPriority.cpp index f83d5a751e..34e03f1f99 100644 --- a/core/libs/tests/GuestSchedPriority.cpp +++ b/core/libs/tests/GuestSchedPriority.cpp @@ -1,29 +1,15 @@ +#include "prx/libkernel_sys/include/Api.hpp" +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include #include #include #include -extern "C" int* APS5_VABI __error_nid_postfix(); + extern "C" { -int APS5_VABI sched_get_priority_max_nid_postfix(int policy); -int APS5_VABI sched_get_priority_min_nid_postfix(int policy); -int APS5_VABI getpriority_nid_postfix(int which, int who); -int APS5_VABI setpriority_nid_postfix(int which, int who, int niceval); -struct GuestRtPrio { - std::uint16_t type; - std::uint16_t prio; -}; -int APS5_VABI rtprio_thread_nid_postfix(int function, int lwpid, GuestRtPrio* priority); -int APS5_VABI pthread_setconcurrency_nid_postfix(int newLevel); -int APS5_VABI pthread_getconcurrency_nid_postfix(void); -struct GuestTimespec { - std::int64_t tv_sec; - std::int64_t tv_nsec; -}; -int APS5_VABI sched_rr_get_interval_nid_postfix(int pid, GuestTimespec* interval); -int APS5_VABI getpid_nid_postfix(void); -int* APS5_VABI __error_nid_postfix(); + } static constexpr int PrioProcess = 0; static constexpr int PrioGroup = 1; @@ -54,7 +40,7 @@ static void RequireSetError(int which, int who, int nice, int error) { int main() { Require(Rejects(-1) && Rejects(2) && Rejects(5)); const int self = getpid_nid_postfix(); - GuestTimespec interval{}; + KernelTimespec interval{}; *__error_nid_postfix() = 13; Require(sched_rr_get_interval_nid_postfix(0, &interval) == 0 && interval.tv_sec == 0 && interval.tv_nsec == 94000000 && *__error_nid_postfix() == 13); interval.tv_sec = -1; diff --git a/core/libs/tests/GuestScreenShot.cpp b/core/libs/tests/GuestScreenShot.cpp index 836b70da94..fe9a121fed 100644 --- a/core/libs/tests/GuestScreenShot.cpp +++ b/core/libs/tests/GuestScreenShot.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceScreenShot/include/Api.hpp" #include "ProcessParametersFixture.hpp" #include "SceTypes.hpp" #include @@ -11,16 +12,6 @@ #include #include -extern "C" { -int APS5_VABI sceScreenShotDisable(); -int APS5_VABI sceScreenShotEnable(); -int APS5_VABI sceScreenShotIsDisabled(int id, int* isDisabled); -int APS5_VABI sceScreenShotDisableNotification(); -int APS5_VABI sceScreenShotEnableNotification(); -int APS5_VABI sceScreenShotSetOverlayImage(const char* path, int offsetX, int offsetY); -int APS5_VABI sceScreenShotSetOverlayImageWithOrigin(const char* path, int offsetX, int offsetY, int origin); -} - namespace { constexpr int ErrorArgument = static_cast(0x80BE0001); diff --git a/core/libs/tests/GuestSearch.cpp b/core/libs/tests/GuestSearch.cpp index f1572c3640..55d2862aba 100644 --- a/core/libs/tests/GuestSearch.cpp +++ b/core/libs/tests/GuestSearch.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -7,7 +8,7 @@ #include #include using Comparator = int (APS5_VABI *)(const void*, const void*); -extern "C" void* APS5_VABI bsearch_nid_postfix(const void*, const void*, std::size_t, std::size_t, Comparator); + static void Require(bool value, std::source_location location = std::source_location::current()) { if (!value) { std::fprintf(stderr, "Guest search failed at line %u\n", location.line()); std::abort(); } } diff --git a/core/libs/tests/GuestSelect.cpp b/core/libs/tests/GuestSelect.cpp index 979415e15d..23cb18d6cf 100644 --- a/core/libs/tests/GuestSelect.cpp +++ b/core/libs/tests/GuestSelect.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "SceTypes.hpp" #include @@ -24,25 +26,6 @@ struct GuestDescriptorSet { } }; -extern "C" { -int APS5_VABI select_nid_postfix(int, void*, void*, void*, const void*); -int APS5_VABI pipe_nid_postfix(int*); -int APS5_VABI close_nid_postfix(int); -int APS5_VABI socket_nid_postfix(int, int, int); -int APS5_VABI bind_nid_postfix(int, const void*, std::uint32_t); -int APS5_VABI getsockname_nid_postfix(int, void*, std::uint32_t*); -int APS5_VABI connect_nid_postfix(int, const void*, std::uint32_t); -std::int64_t APS5_VABI send_nid_postfix(int, const void*, std::uint64_t, int); -std::int64_t APS5_VABI recv_nid_postfix(int, void*, std::uint64_t, int); -std::int64_t APS5_VABI write_nid_postfix(int, const char*, std::int64_t); -std::int64_t APS5_VABI read_nid_postfix(int, void*, std::uint64_t); -int APS5_VABI open_nid_postfix(const char*, int, int); -int APS5_VABI unlink_nid_postfix(const char*); -int APS5_VABI kqueue_nid_postfix(); -int APS5_VABI kevent_nid_postfix(int, const KernelEvent*, int, KernelEvent*, int, const KernelTimespec*); -int* APS5_VABI __error_nid_postfix(); -} - static void Require(bool value) { if (!value) std::abort(); } constexpr int GuestEbadf = 9; @@ -202,14 +185,43 @@ int main() { Require(read.Has(reader) && write.Has(writer)); } + Require(reader < 63); + + { + GuestDescriptorSet read{}; + GuestDescriptorSet except{}; + read.Add(reader); + read.Add(63); + read.Add(64); + except.Add(63); + GuestTimeval limit{0, 100000}; + Require(select_nid_postfix(reader, read.words.data(), nullptr, except.words.data(), &limit) == 0); + Require(!read.Has(reader) && !read.Has(63) && read.Has(64) && !except.Has(63)); + } + { GuestDescriptorSet read{}; read.Add(reader); - GuestTimeval limit{0, 100000}; - Require(select_nid_postfix(reader, read.words.data(), nullptr, nullptr, &limit) == 0); + const GuestTimeval zero{0, 0}; + Require(select_nid_postfix(0, read.words.data(), nullptr, nullptr, &zero) == 0); Require(read.Has(reader)); } + { + const char byte = 'n'; + Require(write_nid_postfix(writer, &byte, 1) == 1); + GuestDescriptorSet read{}; + read.Add(reader); + read.Add(63); + read.Add(64); + GuestTimeval limit{0, 200000}; + Require(select_nid_postfix(reader + 1, read.words.data(), nullptr, nullptr, &limit) == 1); + Require(read.Has(reader) && !read.Has(63) && read.Has(64)); + char buffer[8]{}; + const auto count = read_nid_postfix(reader, buffer, sizeof(buffer)); + Require(count >= 1 && buffer[count - 1] == byte); + } + { GuestDescriptorSet read{}; read.Add(reader); diff --git a/core/libs/tests/GuestSelectWait.cpp b/core/libs/tests/GuestSelectWait.cpp index a21b7b320a..e5dd072cd4 100644 --- a/core/libs/tests/GuestSelectWait.cpp +++ b/core/libs/tests/GuestSelectWait.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -10,11 +12,6 @@ struct GuestTimeval { std::int64_t microseconds; }; -extern "C" { -int APS5_VABI select_nid_postfix(int, void*, void*, void*, const void*); -int* APS5_VABI __error_nid_postfix(); -} - static void Require(bool value, const char* message) { if (!value) { std::fprintf(stderr, "%s\n", message); @@ -56,14 +53,17 @@ int main() { } std::array read{}; read[0] = 1 | (std::uint64_t{1} << 63); + read[1] = 1; const GuestTimeval limit{0, 500}; const auto start = Clock::now(); Require(select_nid_postfix(1, read.data(), nullptr, nullptr, &limit) == 0, "select with no ready device did not time out"); Require(Clock::now() - start >= std::chrono::microseconds(limit.microseconds), "select with no ready device returned before its deadline"); - Require(read[0] == (std::uint64_t{1} << 63), - "select did not preserve bits outside the descriptor limit"); + Require(read[0] == 0, + "select did not clear the bits up to the end of the last copied word"); + Require(read[1] == 1, + "select did not preserve the words past the descriptor limit"); std::array write{}; write[0] = 2; const GuestTimeval longLimit{1, 0}; diff --git a/core/libs/tests/GuestSemCanceledWake.cpp b/core/libs/tests/GuestSemCanceledWake.cpp index 526888bcb0..8bf56c413a 100644 --- a/core/libs/tests/GuestSemCanceledWake.cpp +++ b/core/libs/tests/GuestSemCanceledWake.cpp @@ -1,3 +1,4 @@ +#include "prx/libkernel/include/Api.hpp" #include "prx/libkernel/Pthread/include/Pthread.hpp" #include "prx/libkernel/Pthread/include/Cancel.hpp" #include @@ -6,19 +7,6 @@ #include #include -extern "C" { -int APS5_VABI scePthreadCreate(Pthread*, const PthreadAttr*, PthreadEntry, void*, const char*); -int APS5_VABI scePthreadJoin(Pthread, void**); -int APS5_VABI scePthreadCancel(Pthread); -int APS5_VABI scePthreadSetcancelstate(int, int*); -int APS5_VABI scePthreadSemInit(PthreadSem*, int, unsigned, const char*); -int APS5_VABI scePthreadSemDestroy(PthreadSem*); -int APS5_VABI scePthreadSemPost(PthreadSem*); -int APS5_VABI scePthreadSemWait(PthreadSem*); -int APS5_VABI scePthreadSemTimedwait(PthreadSem*, KernelUseconds); -int APS5_VABI scePthreadSemGetvalue(PthreadSem*, int*); -} - namespace { void Require(bool value, const char* message) { diff --git a/core/libs/tests/GuestSemaphore.cpp b/core/libs/tests/GuestSemaphore.cpp index 4ee50ec2ea..bc843e1a5a 100644 --- a/core/libs/tests/GuestSemaphore.cpp +++ b/core/libs/tests/GuestSemaphore.cpp @@ -1,25 +1,12 @@ +#include "prx/libkernel/KernelErrors.hpp" +#include "prx/libkernel/include/Api.hpp" +#include "prx/libkernel/Semaphore/include/Semaphore.hpp" #include "SceTypes.hpp" #include #include #include -extern "C" { -int APS5_VABI scePthreadCreate(Pthread* thread, const PthreadAttr* attr, PthreadEntry entry, void* arg, const char* name); -int APS5_VABI scePthreadJoin(Pthread thread, void** retval); -int APS5_VABI sceKernelCreateSema(KernelSema* sem, const char* name, uint32_t attr, int init, int max, void* opt); -int APS5_VABI sceKernelDeleteSema(KernelSema sem); -int APS5_VABI sceKernelPollSema(KernelSema sem, int need); -int APS5_VABI sceKernelSignalSema(KernelSema sem, int count); -int APS5_VABI sceKernelWaitSema(KernelSema sem, int need, KernelUseconds* time); -int APS5_VABI sceKernelCancelSema(KernelSema sem, int count, int* threads); -} - static constexpr int SCE_OK = 0; -static constexpr int SCE_KERNEL_ERROR_ESRCH = static_cast(0x80020003); -static constexpr int SCE_KERNEL_ERROR_EBUSY = static_cast(0x80020010); -static constexpr int SCE_KERNEL_ERROR_EINVAL = static_cast(0x80020016); -static constexpr int SCE_KERNEL_ERROR_ECANCELED = static_cast(0x80020055); -static constexpr int SCE_KERNEL_ERROR_ETIMEDOUT = static_cast(0x8002003C); static void Require(bool value) { if (!value) std::abort(); } diff --git a/core/libs/tests/GuestSendfile.cpp b/core/libs/tests/GuestSendfile.cpp index 9759531b34..f2fac5d3cc 100644 --- a/core/libs/tests/GuestSendfile.cpp +++ b/core/libs/tests/GuestSendfile.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -6,27 +8,7 @@ #include #include #include -struct Iovec { - const void* base; - std::uint64_t length; -}; -struct Hdtr { - const Iovec* headers; - int headerCount; - const Iovec* trailers; - int trailerCount; -}; -extern "C" { -int APS5_VABI open_nid_postfix(const char*, int, int); -int APS5_VABI close_nid_postfix(int); -std::int64_t APS5_VABI lseek_nid_postfix(int, std::int64_t, int); -int APS5_VABI socket_nid_postfix(int, int, int); -int APS5_VABI socketpair_nid_postfix(int, int, int, int*); -std::int64_t APS5_VABI recv_nid_postfix(int, void*, std::uint64_t, int); -int APS5_VABI ioctl_nid_postfix(int, std::uint64_t, void*); -int APS5_VABI sendfile_nid_postfix(int, int, std::int64_t, std::uint64_t, const Hdtr*, std::int64_t*, int); -int* APS5_VABI __error_nid_postfix(); -} + static void Require(bool value) { if (!value) std::abort(); } static bool Fails(int result, int error) { return result == -1 && *__error_nid_postfix() == error; } static std::string Receive(int descriptor, std::size_t length) { @@ -59,9 +41,9 @@ int main() { const int file = OpenWritten("sendfile_probe.bin", content); int pair[2]; Require(socketpair_nid_postfix(1, 1, 0, pair) == 0); - const Iovec header[] = {{"GET", 3}, {" ", 1}}; - const Iovec trailer[] = {{"END", 3}}; - const Hdtr parts{header, 2, trailer, 1}; + KernelIovec header[] = {{const_cast("GET"), 3}, {const_cast(" "), 1}}; + KernelIovec trailer[] = {{const_cast("END"), 3}}; + const GuestSendfileHeaders parts{header, 2, trailer, 1}; std::int64_t sent = -1; Require(sendfile_nid_postfix(file, pair[0], 5, 10, &parts, &sent, 0) == 0 && sent == 17); Require(Receive(pair[1], 17) == "GET " + content.substr(5, 10) + "END"); @@ -75,17 +57,17 @@ int main() { Require(Receive(pair[1], 4) == content.substr(content.size() - 4)); Require(sendfile_nid_postfix(file, pair[0], size + 10, 0, &parts, &sent, 0) == 0 && sent == 7); Require(Receive(pair[1], 7) == "GET END"); - const Hdtr nullHeaders{nullptr, 5, trailer, 1}; + const GuestSendfileHeaders nullHeaders{nullptr, 5, trailer, 1}; Require(sendfile_nid_postfix(file, pair[0], 0, 3, &nullHeaders, nullptr, 0) == 0); Require(Receive(pair[1], 6) == content.substr(0, 3) + "END"); Require(lseek_nid_postfix(file, 0, 1) == 0); sent = 77; Require(Fails(sendfile_nid_postfix(file, pair[0], -1, 0, nullptr, &sent, 0), 22) && sent == 77); - const std::vector many(1025, Iovec{"x", 1}); - const Hdtr tooMany{many.data(), 1025, nullptr, 0}; + std::vector many(1025, KernelIovec{const_cast("x"), 1}); + const GuestSendfileHeaders tooMany{many.data(), 1025, nullptr, 0}; Require(Fails(sendfile_nid_postfix(file, pair[0], 0, 0, &tooMany, &sent, 0), 22) && sent == 77); - const Hdtr negative{nullptr, 0, trailer, -1}; + const GuestSendfileHeaders negative{nullptr, 0, trailer, -1}; Require(Fails(sendfile_nid_postfix(file, pair[0], 0, 0, &negative, &sent, 0), 22) && sent == 77); Require(Fails(sendfile_nid_postfix(pair[1], pair[0], 0, 0, nullptr, &sent, 0), 22) && sent == 0); sent = 77; @@ -98,6 +80,17 @@ int main() { Require(unconnected >= 0); sent = 77; Require(Fails(sendfile_nid_postfix(file, unconnected, size + 10, 0, nullptr, &sent, 0), 57) && sent == 0); + const int random = open_nid_postfix("/dev/urandom", 0, 0); + Require(random >= 0); + sent = 77; + Require(Fails(sendfile_nid_postfix(random, pair[0], 0, 16, &parts, &sent, 0), 22) && sent == 0); + sent = 77; + Require(Fails(sendfile_nid_postfix(random, pair[0], 0, 0, nullptr, &sent, 0), 22) && sent == 0); + const int queue = kqueue_nid_postfix(); + Require(queue >= 0); + sent = 77; + Require(Fails(sendfile_nid_postfix(queue, pair[0], 0, 0, nullptr, &sent, 0), 22) && sent == 0); + Require(close_nid_postfix(queue) == 0 && close_nid_postfix(random) == 0); const std::string large = Content(32 << 20); const int largeFile = OpenWritten("sendfile_large.bin", large); diff --git a/core/libs/tests/GuestServiceDatabase.cpp b/core/libs/tests/GuestServiceDatabase.cpp index 30caec9095..e89a3d5985 100644 --- a/core/libs/tests/GuestServiceDatabase.cpp +++ b/core/libs/tests/GuestServiceDatabase.cpp @@ -1,3 +1,4 @@ +#include "prx/libScePosixForWebKit/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libScePosixForWebKit/GuestResolver.hpp" #include @@ -8,8 +9,6 @@ #include #include -extern "C" GuestResolver::ServiceEntry* APS5_VABI getservbyname_nid_postfix(const char*, const char*); - void Require(bool condition, std::source_location location = std::source_location::current()) { if (!condition) { std::fprintf(stderr, "Service database check failed at line %u\n", location.line()); diff --git a/core/libs/tests/GuestSetrlimit.cpp b/core/libs/tests/GuestSetrlimit.cpp index 0691db0980..f86c83edfb 100644 --- a/core/libs/tests/GuestSetrlimit.cpp +++ b/core/libs/tests/GuestSetrlimit.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -5,17 +7,6 @@ #include #include -struct ResourceLimit { - std::int64_t rlim_cur; - std::int64_t rlim_max; -}; - -extern "C" { -int APS5_VABI getrlimit_nid_postfix(int, ResourceLimit*); -int APS5_VABI setrlimit_nid_postfix(int, const ResourceLimit*); -int* APS5_VABI __error_nid_postfix(); -} - static constexpr int GUEST_EFAULT = 14; static constexpr int GUEST_EINVAL = 22; static constexpr int GUEST_RLIMIT_DATA = 2; @@ -29,23 +20,24 @@ static constexpr std::int64_t GUEST_RLIM_INFINITY = std::numeric_limits 0) { - const ResourceLimit changed{current.rlim_cur - 1, current.rlim_max}; + const GuestResourceLimit changed{current.rlim_cur - 1, current.rlim_max}; Require(Throws(GUEST_RLIMIT_DATA, changed)); } - const ResourceLimit softAboveHard{GUEST_RLIM_INFINITY, current.rlim_max}; + const GuestResourceLimit softAboveHard{GUEST_RLIM_INFINITY, current.rlim_max}; if (current.rlim_cur == current.rlim_max) Require(setrlimit_nid_postfix(GUEST_RLIMIT_DATA, &softAboveHard) == 0); else Require(Throws(GUEST_RLIMIT_DATA, softAboveHard)); - const ResourceLimit negative{-1, -2}; + const GuestResourceLimit negative{-1, -2}; if (current.rlim_cur == GUEST_RLIM_INFINITY && current.rlim_max == GUEST_RLIM_INFINITY) Require(setrlimit_nid_postfix(GUEST_RLIMIT_DATA, &negative) == 0); else diff --git a/core/libs/tests/GuestShaderLink.cpp b/core/libs/tests/GuestShaderLink.cpp index f5b510652b..5c39b6fffe 100644 --- a/core/libs/tests/GuestShaderLink.cpp +++ b/core/libs/tests/GuestShaderLink.cpp @@ -1,3 +1,5 @@ +#include "prx/libSceAgc/Shader/include/LinkShaders.hpp" +#include "prx/libSceAgc/Misc/include/RegisterDefaults.hpp" #include "SceShaders.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libSceAgc/Shader/include/ShaderConstants.hpp" @@ -6,9 +8,7 @@ #include #include #include -extern "C" int APS5_VABI sceAgcLinkShaders(ShaderRegister*, ShaderRegister*, const void*, const Shader*, const Shader*, std::uint32_t); -extern "C" void* APS5_VABI sceAgcGetRegisterDefaults(); -extern "C" void* APS5_VABI sceAgcGetRegisterDefaults2(std::uint32_t); + static void Require(bool value) { if (!value) std::abort(); } static unsigned preparations = 0; static unsigned mappings = 0; diff --git a/core/libs/tests/GuestShare.cpp b/core/libs/tests/GuestShare.cpp index 0ef5a51bc5..a3e197e8a4 100644 --- a/core/libs/tests/GuestShare.cpp +++ b/core/libs/tests/GuestShare.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceShare/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -5,17 +6,6 @@ #include #include -extern "C" { -int APS5_VABI sceShareCaptureScreenshotExtended(const void* extended_param, std::int32_t* req_id); -int APS5_VABI sceShareCaptureScreenshot(const void* param, std::int32_t* req_id); -int APS5_VABI sceShareCaptureVideoClip(const void* param, std::int32_t* req_id); -int APS5_VABI sceShareCaptureVideoClipExtended(const void* extended_param, std::int32_t* req_id); -int APS5_VABI sceShareGetCurrentStatus(std::uint32_t feature_flag, void* status); -int APS5_VABI sceShareOpenMenuForContent(const void* content_id); -int APS5_VABI sceShareGetRunningStatus(std::uint32_t* status); -int APS5_VABI sceShareSetContentParamForApplicationTitle(const char* application_title); -} - namespace { void Require(bool value) { if (!value) std::abort(); } @@ -29,25 +19,26 @@ int main() { using Capture = int (APS5_VABI*)(const void*, std::int32_t*); std::int32_t reqId = 7; constexpr std::int32_t invalidParam = static_cast(0x81960002); - for (Capture capture : {sceShareCaptureScreenshotExtended, sceShareCaptureVideoClipExtended}) { + const auto checkExtended = [&](int (APS5_VABI* capture)(const TParam*, std::int32_t*), std::uint64_t size) { std::uint64_t fields[5]{}; - const std::uint64_t size = capture == sceShareCaptureScreenshotExtended ? 24 : 40; reqId = 7; - Require(capture(fields, &reqId) == invalidParam && reqId == 7); + Require(capture(reinterpret_cast(fields), &reqId) == invalidParam && reqId == 7); Require(capture(nullptr, &reqId) == invalidParam && reqId == 7); fields[0] = size; - Require(capture(fields, &reqId) == notSupported && reqId == -1); - Require(capture(fields, nullptr) == notSupported); + Require(capture(reinterpret_cast(fields), &reqId) == notSupported && reqId == -1); + Require(capture(reinterpret_cast(fields), nullptr) == notSupported); if (size == 40) { fields[2] = 1; reqId = 7; - Require(capture(fields, &reqId) == invalidParam && reqId == -1); + Require(capture(reinterpret_cast(fields), &reqId) == invalidParam && reqId == -1); fields[3] = 1; - Require(capture(fields, nullptr) == notSupported); + Require(capture(reinterpret_cast(fields), nullptr) == notSupported); fields[3] |= std::uint64_t{1} << 32; - Require(capture(fields, nullptr) == invalidParam); + Require(capture(reinterpret_cast(fields), nullptr) == invalidParam); } - } + }; + checkExtended(sceShareCaptureScreenshotExtended, 24); + checkExtended(sceShareCaptureVideoClipExtended, 40); for (Capture capture : {sceShareCaptureScreenshot, sceShareCaptureVideoClip}) { reqId = 7; @@ -64,13 +55,13 @@ int main() { std::uint8_t status[18]; std::memset(status, 0x5a, sizeof(status)); - Require(sceShareGetCurrentStatus(1, status) == 0); + Require(sceShareGetCurrentStatus(1, reinterpret_cast(status)) == 0); for (std::size_t index = 0; index < sizeof(status); ++index) Require(status[index] == (index < 16 ? 0 : 0x5a)); std::memset(status, 0x5a, sizeof(status)); - Require(sceShareGetCurrentStatus(0xffffffffu, status) == 0); + Require(sceShareGetCurrentStatus(0xffffffffu, reinterpret_cast(status)) == 0); Require(status[0] == 0 && status[15] == 0 && status[16] == 0x5a); std::memset(status, 0x5a, sizeof(status)); - Require(sceShareGetCurrentStatus(0, status) == invalidParam); + Require(sceShareGetCurrentStatus(0, reinterpret_cast(status)) == invalidParam); Require(status[0] == 0x5a); Require(sceShareGetCurrentStatus(1, nullptr) == invalidParam); std::uint32_t running[2]{0xffffffffu, 0x5a5a5a5au}; diff --git a/core/libs/tests/GuestSharePlay.cpp b/core/libs/tests/GuestSharePlay.cpp index 4d1b7f1199..1bb330a5a8 100644 --- a/core/libs/tests/GuestSharePlay.cpp +++ b/core/libs/tests/GuestSharePlay.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceSharePlay/include/Api.hpp" #include "SceTypes.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -6,13 +7,6 @@ #include #include -extern "C" { -int APS5_VABI sceSharePlayInitialize(void*, std::size_t); -int APS5_VABI sceSharePlayTerminate(void); -int APS5_VABI sceSharePlayGetCurrentConnectionInfoA(SharePlayConnectionInfoA*); -int APS5_VABI sceSharePlayProhibitController(std::uint8_t); -} - static void Require(bool value) { if (!value) std::abort(); } template diff --git a/core/libs/tests/GuestShmOpen.cpp b/core/libs/tests/GuestShmOpen.cpp index c81cfc704d..6d6461d725 100644 --- a/core/libs/tests/GuestShmOpen.cpp +++ b/core/libs/tests/GuestShmOpen.cpp @@ -1,19 +1,12 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include #include #include #include -extern "C" { -int APS5_VABI shm_open_nid_postfix(const char*, int, int); -int APS5_VABI ftruncate_nid_postfix(int, std::int64_t); -std::int64_t APS5_VABI pread_nid_postfix(int, void*, std::size_t, std::int64_t); -std::int64_t APS5_VABI pwrite_nid_disambig1_nid_postfix(int, const void*, std::size_t, std::int64_t); -int APS5_VABI close_nid_postfix(int); -void* APS5_VABI mmap_nid_postfix(void*, std::size_t, int, int, int, std::int64_t) noexcept; -int APS5_VABI munmap_nid_postfix(void*, std::size_t) noexcept; -int* APS5_VABI __error_nid_postfix(); -} + static void Require(bool value) { if (!value) std::abort(); } static const char* const anonymous = reinterpret_cast(1); static void RequireInvalid(const char* path, int flags) { diff --git a/core/libs/tests/GuestSigaltstack.cpp b/core/libs/tests/GuestSigaltstack.cpp index 6260846fd8..afd3787ccc 100644 --- a/core/libs/tests/GuestSigaltstack.cpp +++ b/core/libs/tests/GuestSigaltstack.cpp @@ -1,17 +1,11 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include #include #include -struct GuestStack { - void* sp; - std::size_t size; - int flags; -}; -extern "C" { -int APS5_VABI sigaltstack_nid_postfix(const GuestStack*, GuestStack*); -int* APS5_VABI __error_nid_postfix(); -} + static void Require(bool value) { if (!value) std::abort(); } static GuestStack Query() { GuestStack current; diff --git a/core/libs/tests/GuestSignalInterrupt.cpp b/core/libs/tests/GuestSignalInterrupt.cpp new file mode 100644 index 0000000000..d520e1954a --- /dev/null +++ b/core/libs/tests/GuestSignalInterrupt.cpp @@ -0,0 +1,98 @@ +#include "SceTypes.hpp" +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" +#include +#include +#include +#include +#include +#include +#include + +using Handler = void (APS5_VABI *)(int); + +static_assert(sizeof(GuestSignalSet) == 16 && alignof(GuestSignalSet) == 4); +static_assert(sizeof(GuestSigaction) == 32 && offsetof(GuestSigaction, flags) == 8 && offsetof(GuestSigaction, mask) == 12); + +extern "C" { +extern GuestSignalSet _sigintr_nid_postfix; +} + +namespace { + +void Require(bool condition, const char* message) { + if (condition) return; + std::fprintf(stderr, "%s\n", message); + std::abort(); +} + +bool Same(const GuestSigaction& first, const GuestSigaction& second) { + return first.handler == second.handler && first.flags == second.flags && + std::memcmp(&first.mask, &second.mask, sizeof(first.mask)) == 0; +} + +void APS5_VABI HandlerFunction(int) {} + +} + +int main() { + const GuestSignalSet initial = _sigintr_nid_postfix; + Require(initial.bits[0] == 0 && initial.bits[1] == 0 && initial.bits[2] == 0 && initial.bits[3] == 0, "initial interrupt set"); + for (int guest : {1, 32, 33, 64, 65, 96, 97, 128}) { + GuestSigaction original{}; + Require(sigaction_nid_postfix(guest, nullptr, &original) == 0, "read original disposition"); + GuestSigaction custom{reinterpret_cast(HandlerFunction), 0x42, + {{0x11111111, 0x22222222, 0x33333333, 0x44444444}}}; + Require(sigaction_nid_postfix(guest, &custom, nullptr) == 0, "install custom disposition"); + Require(sigaction_nid_postfix(guest, nullptr, &custom) == 0, "read installed disposition"); + const auto word = static_cast(guest - 1) / 32; + const auto bit = std::uint32_t{1} << (static_cast(guest - 1) % 32); + GuestSignalSet expected{{0x55555555, 0xaaaaaaaa, 0x55555555, 0xaaaaaaaa}}; + expected.bits[word] &= ~bit; + _sigintr_nid_postfix = expected; + for (int flag : {1, -1, std::numeric_limits::min(), std::numeric_limits::max()}) { + *__error_nid_postfix() = 12345; + Require(siginterrupt_nid_postfix(guest, flag) == 0, "nonzero flag"); + Require(*__error_nid_postfix() == 12345, "successful errno preservation"); + expected.bits[word] |= bit; + Require(std::memcmp(&_sigintr_nid_postfix, &expected, sizeof(expected)) == 0, "set bit without changing neighboring bits"); + GuestSigaction actual{}; + Require(sigaction_nid_postfix(guest, nullptr, &actual) == 0, "read interrupted disposition"); + auto interrupted = custom; + interrupted.flags &= ~0x2; + Require(Same(actual, interrupted), "preserve handler, mask and other flags"); + } + for (int repeat = 0; repeat < 2; ++repeat) { + *__error_nid_postfix() = 23456; + Require(siginterrupt_nid_postfix(guest, 0) == 0, "clear interrupt bit"); + Require(*__error_nid_postfix() == 23456, "zero flag errno preservation"); + expected.bits[word] &= ~bit; + Require(std::memcmp(&_sigintr_nid_postfix, &expected, sizeof(expected)) == 0, "clear bit without changing neighboring bits"); + GuestSigaction actual{}; + Require(sigaction_nid_postfix(guest, nullptr, &actual) == 0 && Same(actual, custom), "restore restart without changing disposition"); + } + Require(siginterrupt_nid_postfix(guest, -1) == 0, "make later signal interruptible"); + Require(signal_nid_postfix(guest, HandlerFunction) == HandlerFunction, "subsequent signal preserves previous handler"); + GuestSigaction actual{}; + Require(sigaction_nid_postfix(guest, nullptr, &actual) == 0 && actual.flags == 0, "signal consults shared interrupt set"); + Require(siginterrupt_nid_postfix(guest, 0) == 0, "make later signal restartable"); + Require(signal_nid_postfix(guest, HandlerFunction) == HandlerFunction, "repeat signal registration"); + Require(sigaction_nid_postfix(guest, nullptr, &actual) == 0 && actual.flags == 0x2, "signal restores restart"); + Require(sigaction_nid_postfix(guest, &original, nullptr) == 0, "restore original disposition"); + _sigintr_nid_postfix = initial; + } + const GuestSignalSet sentinels{{0x12345678, 0xabcdef01, 0x23456789, 0xbcdef012}}; + _sigintr_nid_postfix = sentinels; + GuestSigaction before{}; + Require(sigaction_nid_postfix(30, nullptr, &before) == 0, "read invalid-call control"); + for (int guest : {0, -1, 129, std::numeric_limits::min(), std::numeric_limits::max()}) { + for (int flag : {0, 1, -1}) { + *__error_nid_postfix() = 34567; + Require(siginterrupt_nid_postfix(guest, flag) == -1 && *__error_nid_postfix() == 22, "invalid signal reports EINVAL"); + Require(std::memcmp(&_sigintr_nid_postfix, &sentinels, sizeof(sentinels)) == 0, "invalid signal leaves all words unchanged"); + } + } + GuestSigaction after{}; + Require(sigaction_nid_postfix(30, nullptr, &after) == 0 && Same(before, after), "invalid calls preserve dispositions"); + _sigintr_nid_postfix = initial; +} diff --git a/core/libs/tests/GuestSignalSets.cpp b/core/libs/tests/GuestSignalSets.cpp index 786ddae94b..4cce1b63a4 100644 --- a/core/libs/tests/GuestSignalSets.cpp +++ b/core/libs/tests/GuestSignalSets.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/AsmMacros.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -7,21 +9,8 @@ #include #include -struct GuestSignalSet { - std::uint32_t bits[4]; -}; - extern "C" { -int APS5_VABI sigemptyset_nid_postfix(GuestSignalSet*); -int APS5_VABI sigfillset_nid_postfix(GuestSignalSet*); -int APS5_VABI sigaddset_nid_postfix(GuestSignalSet*, int); -int APS5_VABI sigdelset_nid_postfix(GuestSignalSet*, int); -int APS5_VABI sigismember_nid_postfix(const GuestSignalSet*, int); -int* APS5_VABI __error_nid_postfix(); -int APS5_VABI _sigprocmask_nid_postfix(int, const GuestSignalSet*, GuestSignalSet*); -int APS5_VABI sigprocmask_nid_postfix(int, const void*, void*); -[[gnu::returns_twice]] int APS5_VABI sigsetjmp_nid_postfix(std::uint64_t* buffer, int saveMask); -[[noreturn]] void APS5_VABI siglongjmp_nid_postfix(std::uint64_t* buffer, int value); + int APS5_VABI JumpKeepingCalleeSaved(std::uint64_t* buffer); } diff --git a/core/libs/tests/GuestSignals.cpp b/core/libs/tests/GuestSignals.cpp index 9879994a1a..715ff0478c 100644 --- a/core/libs/tests/GuestSignals.cpp +++ b/core/libs/tests/GuestSignals.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -9,33 +11,13 @@ #include #include using Handler = void (APS5_VABI *)(int); -struct GuestSignalSet { - std::uint32_t bits[4]; -}; + extern "C" { -Handler APS5_VABI signal_nid_postfix(int, Handler); -int APS5_VABI raise_nid_postfix(int); -int APS5_VABI kill_nid_postfix(int, int); -int APS5_VABI getpid_nid_postfix(); -int APS5_VABI pthread_kill_nid_postfix(void*, int); -void* APS5_VABI scePthreadSelf(); -int APS5_VABI scePthreadCreate(void** thread, const void* attr, void* (APS5_VABI *entry)(void*), void* arg, const char* name); -int APS5_VABI scePthreadJoin(void* thread, void** retval); -int APS5_VABI sigaction_nid_postfix(int, const void*, void*); -int APS5_VABI sigprocmask_nid_postfix(int, const void*, void*); -int APS5_VABI pthread_sigmask_nid_postfix(int, const void*, void*); -int* APS5_VABI __error_nid_postfix(); -int APS5_VABI sigsuspend_nid_postfix(const GuestSignalSet*); -int APS5_VABI _is_signal_return_nid_postfix(std::uint64_t); + unsigned int APS5_VABI GuestAlarm_nid_no_patch(unsigned int); -int APS5_VABI sigpending_nid_postfix(GuestSignalSet*); -int APS5_VABI siginterrupt_nid_postfix(int, int); + } -struct GuestSigaction { - std::uintptr_t handler; - int flags; - GuestSignalSet mask; -}; + static_assert(sizeof(GuestSigaction) == 32); extern GuestSignalSet _sigintr_nid_postfix; static bool Same(const GuestSigaction& left, const GuestSigaction& right) { @@ -56,7 +38,7 @@ void* APS5_VABI SuspendEntry(void* arg) { return nullptr; } struct SuspendSender { - void* target = nullptr; + Pthread target = nullptr; int result = -1; }; struct EndingThread { @@ -81,6 +63,7 @@ GuestSignalSet maskInHandler{}; void APS5_VABI MaskCallback(int value) { received = value; sigprocmask_nid_postfix(1, nullptr, &maskInHandler); + } static void Require(bool value) { if (!value) std::abort(); } int main() { @@ -104,11 +87,11 @@ int main() { Require(pthread_kill_nid_postfix(nullptr, 15) == 3); Require(pthread_kill_nid_postfix(nullptr, 128) == 3); Require(pthread_kill_nid_postfix(nullptr, 129) == 22); - Require(pthread_kill_nid_postfix(reinterpret_cast(std::uintptr_t{0x10}), 15) == 3); - Require(pthread_kill_nid_postfix(reinterpret_cast(std::uintptr_t{0x10}), 0) == 3); + Require(pthread_kill_nid_postfix(reinterpret_cast(std::uintptr_t{0x10}), 15) == 3); + Require(pthread_kill_nid_postfix(reinterpret_cast(std::uintptr_t{0x10}), 0) == 3); { EndingThread ending; - void* thread = nullptr; + Pthread thread = nullptr; Require(scePthreadCreate(&thread, nullptr, EndingEntry, &ending, nullptr) == 0); Require(pthread_kill_nid_postfix(thread, 0) == 0); ending.release.store(true); @@ -200,6 +183,7 @@ int main() { bool rejected = false; try { raise_nid_postfix(6); + } catch (const std::runtime_error&) { rejected = true; } @@ -252,10 +236,10 @@ int main() { Require(signal_nid_postfix(30, Callback) != invalid); received = 0; SuspendWait wait{&empty, 0, 0}; - void* suspender = nullptr; + Pthread suspender = nullptr; Require(scePthreadCreate(&suspender, nullptr, SuspendEntry, &wait, nullptr) == 0); SuspendSender sender{suspender, -1}; - void* senderThread = nullptr; + Pthread senderThread = nullptr; Require(scePthreadCreate(&senderThread, nullptr, SuspendSend, &sender, nullptr) == 0); Require(scePthreadJoin(senderThread, nullptr) == 0 && sender.result == 0); Require(scePthreadJoin(suspender, nullptr) == 0); @@ -270,10 +254,10 @@ int main() { Require(signal_nid_postfix(73, Callback) != invalid); received = 0; SuspendWait highWait{&suspendMask, 0, 0}; - void* highSuspender = nullptr; + Pthread highSuspender = nullptr; Require(scePthreadCreate(&highSuspender, nullptr, SuspendEntry, &highWait, nullptr) == 0); SuspendSender highSender{highSuspender, -1}; - void* highSenderThread = nullptr; + Pthread highSenderThread = nullptr; Require(scePthreadCreate(&highSenderThread, nullptr, SuspendSend, &highSender, nullptr) == 0); Require(scePthreadJoin(highSenderThread, nullptr) == 0 && highSender.result == 0); Require(scePthreadJoin(highSuspender, nullptr) == 0); @@ -458,6 +442,7 @@ int main() { Require(sigaction_nid_postfix(30, nullptr, &interruptible) == 0 && interruptible.handler == reinterpret_cast(Callback) && interruptible.flags == 0); signal_nid_postfix(31, Callback); + Require(sigaction_nid_postfix(31, nullptr, &interruptible) == 0 && interruptible.flags == 0x2); _sigintr_nid_postfix.bits[3] = 1u << 31; Require(signal_nid_postfix(128, Callback) == nullptr); diff --git a/core/libs/tests/GuestSigninDialog.cpp b/core/libs/tests/GuestSigninDialog.cpp index d8410fcbd5..0082e506f1 100644 --- a/core/libs/tests/GuestSigninDialog.cpp +++ b/core/libs/tests/GuestSigninDialog.cpp @@ -1,18 +1,9 @@ +#include "prx/libSceSigninDialog/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include #include -extern "C" { -int APS5_VABI sceSigninDialogInitialize(void); -int APS5_VABI sceSigninDialogOpen(const void* param); -int APS5_VABI sceSigninDialogUpdateStatus(void); -int APS5_VABI sceSigninDialogGetStatus(void); -int APS5_VABI sceSigninDialogGetResult(void* result); -int APS5_VABI sceSigninDialogClose(void); -int APS5_VABI sceSigninDialogTerminate(void); -} - namespace { void Require(bool value) { if (!value) std::abort(); } diff --git a/core/libs/tests/GuestSigtimedwait.cpp b/core/libs/tests/GuestSigtimedwait.cpp index 0663a3ce2f..4c0101000c 100644 --- a/core/libs/tests/GuestSigtimedwait.cpp +++ b/core/libs/tests/GuestSigtimedwait.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "SceTypes.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -6,13 +8,7 @@ #include #include #include -struct GuestSignalSet { - std::uint32_t bits[4]; -}; -struct GuestTimespec { - std::int64_t seconds; - std::int64_t nanoseconds; -}; + struct GuestSiginfo { std::int32_t signo; std::int32_t error; @@ -28,22 +24,7 @@ struct GuestSiginfo { std::int32_t tail; }; using Handler = void (APS5_VABI *)(int); -extern "C" { -int APS5_VABI sigtimedwait_nid_postfix(const GuestSignalSet*, void*, const GuestTimespec*); -int APS5_VABI sigwaitinfo_nid_postfix(const GuestSignalSet*, void*); -int APS5_VABI sigwait_nid_postfix(const GuestSignalSet*, int*); -int APS5_VABI pause_nid_postfix(void); -Handler APS5_VABI signal_nid_postfix(int, Handler); -int APS5_VABI raise_nid_postfix(int); -int APS5_VABI kill_nid_postfix(int, int); -int APS5_VABI _sigprocmask_nid_postfix(int, const GuestSignalSet*, GuestSignalSet*); -int APS5_VABI getpid_nid_postfix(void); -Pthread APS5_VABI scePthreadSelf(void); -int APS5_VABI scePthreadCreate(Pthread* thread, const PthreadAttr* attr, PthreadEntry entry, void* arg, const char* name); -int APS5_VABI scePthreadJoin(Pthread thread, void** retval); -int APS5_VABI pthread_kill_nid_postfix(Pthread thread, int guest); -int* APS5_VABI __error_nid_postfix(); -} + volatile int received = 0; void APS5_VABI Callback(int value) { received = value; } static void Require(bool value) { if (!value) std::abort(); } @@ -97,8 +78,8 @@ static void CheckTimeoutWithUnrelatedSignals() { const GuestSignalSet blocked{{(1u << 1) | (1u << 12), 0, 0, 0}}; const GuestSignalSet pipe{{1u << 12, 0, 0, 0}}; const GuestSignalSet interrupt{{1u << 1, 0, 0, 0}}; - const GuestTimespec timeout{0, 200000000}; - const GuestTimespec poll{0, 0}; + const KernelTimespec timeout{0, 200000000}; + const KernelTimespec poll{0, 0}; GuestSignalSet previous{}; Require(_sigprocmask_nid_postfix(1, &blocked, &previous) == 0); TimeoutSender sender{scePthreadSelf()}; @@ -122,8 +103,8 @@ int main() { const GuestSignalSet empty{{0, 0, 0, 0}}; const GuestSignalSet pipe{{1u << 12, 0, 0, 0}}; const GuestSignalSet interrupt{{1u << 1, 0, 0, 0}}; - const GuestTimespec poll{0, 0}; - const GuestTimespec expired{0, 1000000000}; + const KernelTimespec poll{0, 0}; + const KernelTimespec expired{0, 1000000000}; GuestSiginfo info{}; int taken = -1; *__error_nid_postfix() = 0; @@ -189,7 +170,7 @@ int main() { Require(sigtimedwait_nid_postfix(&pipe, nullptr, nullptr) == 13); JoinSender(senderThread, sender); senderThread = StartSender(sender); - const GuestTimespec patience{1, 0}; + const KernelTimespec patience{1, 0}; Require(sigtimedwait_nid_postfix(&pipe, &info, &patience) == 13 && info.signo == 13); JoinSender(senderThread, sender); Require(signal_nid_postfix(15, Callback) != reinterpret_cast(static_cast(-1))); diff --git a/core/libs/tests/GuestSleepCancel.cpp b/core/libs/tests/GuestSleepCancel.cpp index 463a4a0cbe..a77fbe126f 100644 --- a/core/libs/tests/GuestSleepCancel.cpp +++ b/core/libs/tests/GuestSleepCancel.cpp @@ -1,3 +1,4 @@ +#include "prx/libkernel/include/Api.hpp" #include "SceTypes.hpp" #include "prx/libkernel/Pthread/include/Pthread.hpp" #include @@ -9,15 +10,6 @@ #include #include -extern "C" { -int APS5_VABI scePthreadCreate(Pthread* thread, const PthreadAttr* attr, PthreadEntry entry, void* arg, const char* name); -int APS5_VABI scePthreadJoin(Pthread thread, void** result); -int APS5_VABI scePthreadCancel(Pthread thread); -int APS5_VABI scePthreadSetcancelstate(int state, int* oldState); -void APS5_VABI scePthreadTestcancel(); -unsigned int APS5_VABI sleep_nid_postfix(unsigned int seconds); -} - static void Require(bool value, std::source_location location = std::source_location::current()) { if (value) return; std::fprintf(stderr, "%s:%u: requirement failed\n", location.file_name(), location.line()); @@ -46,6 +38,7 @@ static void* APS5_VABI Sleeper(void*) { if (disabled) { Require(scePthreadSetcancelstate(0, nullptr) == 0); scePthreadTestcancel(); + Require(false); } return nullptr; diff --git a/core/libs/tests/GuestSleepWake.cpp b/core/libs/tests/GuestSleepWake.cpp index 177ef4b990..d4477301c6 100644 --- a/core/libs/tests/GuestSleepWake.cpp +++ b/core/libs/tests/GuestSleepWake.cpp @@ -1,3 +1,4 @@ +#include "prx/libkernel/Time/include/Time.hpp" #include "SceTypes.hpp" #include #include @@ -6,7 +7,7 @@ #include extern "C" { -int APS5_VABI sceKernelUsleep_nid_postfix(KernelUseconds microseconds); + void KernelWakeSleepers_nid_no_patch(); void KernelNoteGpuSubmit_nid_no_patch(); } diff --git a/core/libs/tests/GuestSocialScreenDialog.cpp b/core/libs/tests/GuestSocialScreenDialog.cpp index 61d42e6488..dcbb9c085e 100644 --- a/core/libs/tests/GuestSocialScreenDialog.cpp +++ b/core/libs/tests/GuestSocialScreenDialog.cpp @@ -1,17 +1,8 @@ +#include "prx/libSceSocialScreenDialog/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include -extern "C" { -int APS5_VABI sceSocialScreenDialogInitialize(void); -int APS5_VABI sceSocialScreenDialogOpen(const void* param); -int APS5_VABI sceSocialScreenDialogUpdateStatus(void); -int APS5_VABI sceSocialScreenDialogGetStatus(void); -int APS5_VABI sceSocialScreenDialogGetResult(void* result); -int APS5_VABI sceSocialScreenDialogClose(void); -int APS5_VABI sceSocialScreenDialogTerminate(void); -} - namespace { void Require(bool value) { if (!value) std::abort(); } diff --git a/core/libs/tests/GuestSocketAddressLength.cpp b/core/libs/tests/GuestSocketAddressLength.cpp index 8ffc2d8c75..e2b7017eec 100644 --- a/core/libs/tests/GuestSocketAddressLength.cpp +++ b/core/libs/tests/GuestSocketAddressLength.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -5,24 +7,13 @@ #include #include -extern "C" { -int APS5_VABI socket_nid_postfix(int, int, int); -int APS5_VABI bind_nid_postfix(int, const void*, std::uint32_t); -int APS5_VABI connect_nid_postfix(int, const void*, std::uint32_t); -int APS5_VABI listen_nid_postfix(int, int); -int APS5_VABI getsockname_nid_postfix(int, void*, std::uint32_t*); -int APS5_VABI setsockopt_nid_postfix(int, int, int, const void*, std::uint32_t); -std::int64_t APS5_VABI sendto_nid_postfix(int, const void*, std::uint64_t, int, const void*, std::uint32_t); -int APS5_VABI close_nid_postfix(int); -int* APS5_VABI __error_nid_postfix(); -} - namespace { constexpr int Stream = 1; constexpr int Datagram = 2; constexpr int ErrorFault = 14; constexpr int ErrorInvalid = 22; +constexpr int ErrorAddressFamilyNotSupported = 47; constexpr int ErrorNameTooLong = 63; void Require(bool condition, const char* what) { @@ -54,6 +45,7 @@ void ShortAddressesAreInvalid() { const int stream6 = socket_nid_postfix(28, Stream, 0); Require(stream6 >= 0, "socket failed"); Require(Fails(connect_nid_postfix(stream6, v6.data(), 20), ErrorInvalid), "connect with an AF_INET6 address shorter than sockaddr_in6 must fail with EINVAL (22)"); + Require(Fails(bind_nid_postfix(stream6, v6.data(), 20), ErrorInvalid), "bind with an AF_INET6 address shorter than sockaddr_in6 must fail with EINVAL (22)"); Require(Fails(bind_nid_postfix(stream, address.data(), 256), ErrorNameTooLong), "an address longer than SOCK_MAXADDRLEN (255) must fail with ENAMETOOLONG (63)"); Require(Fails(bind_nid_postfix(stream, nullptr, address.size()), ErrorFault), "a null address must fail with EFAULT (14)"); Require(close_nid_postfix(stream) == 0 && close_nid_postfix(datagram) == 0 && close_nid_postfix(stream6) == 0, "close failed"); @@ -72,6 +64,70 @@ void ArgumentsAreCheckedBeforeTheDescriptor() { Require(Fails(sendto_nid_postfix(-1, "x", 1, 0, address.data(), address.size()), ErrorBadDescriptor), "sendto(-1) with a valid address must fail with EBADF (9)"); } +void LongAddressesAndOtherFamiliesFail() { + const int datagram = socket_nid_postfix(2, Datagram, 0); + const int stream6 = socket_nid_postfix(28, Stream, 0); + const int datagram6 = socket_nid_postfix(28, Datagram, 0); + Require(datagram >= 0 && stream6 >= 0 && datagram6 >= 0, "socket failed"); + std::array address{16, 2}; + address[4] = 127; + address[7] = 1; + for (const std::uint32_t length : {17u, 28u, 255u}) { + Require(Fails(bind_nid_postfix(datagram, address.data(), length), ErrorInvalid), "bind with an AF_INET address longer than sockaddr_in must fail with EINVAL (22)"); + Require(Fails(connect_nid_postfix(datagram, address.data(), length), ErrorInvalid), "connect with an AF_INET address longer than sockaddr_in must fail with EINVAL (22)"); + Require(Fails(sendto_nid_postfix(datagram, "x", 1, 0, address.data(), length), ErrorInvalid), "sendto with an AF_INET address longer than sockaddr_in must fail with EINVAL (22)"); + } + std::array v6{28, 28}; + v6[23] = 1; + Require(Fails(bind_nid_postfix(stream6, v6.data(), 29), ErrorInvalid), "bind with an AF_INET6 address longer than sockaddr_in6 must fail with EINVAL (22)"); + Require(Fails(connect_nid_postfix(stream6, v6.data(), 64), ErrorInvalid), "connect with an AF_INET6 address longer than sockaddr_in6 must fail with EINVAL (22)"); + for (const std::uint8_t family : {std::uint8_t{28}, std::uint8_t{1}, std::uint8_t{0}}) { + address[1] = family; + Require(Fails(bind_nid_postfix(datagram, address.data(), 16), ErrorAddressFamilyNotSupported), "bind of another family on an AF_INET socket must fail with EAFNOSUPPORT (47)"); + } + address[1] = 28; + Require(Fails(sendto_nid_postfix(datagram, "x", 1, 0, address.data(), 28), ErrorInvalid), "sendto checks the length before the family"); + Require(Fails(sendto_nid_postfix(datagram, "x", 1, 0, address.data(), 16), ErrorAddressFamilyNotSupported), "sendto of another family fails with EAFNOSUPPORT (47)"); + address[1] = 2; + Require(Fails(bind_nid_postfix(datagram6, address.data(), 16), ErrorInvalid), "an AF_INET6 socket checks the length before the family"); + Require(Fails(connect_nid_postfix(datagram6, address.data(), 28), ErrorAddressFamilyNotSupported), "an AF_INET address of the AF_INET6 length fails with EAFNOSUPPORT (47)"); + Require(close_nid_postfix(datagram) == 0 && close_nid_postfix(stream6) == 0 && close_nid_postfix(datagram6) == 0, "close failed"); +} + +void ConnectedStreamSendtoIgnoresTheAddress() { + const int listener = socket_nid_postfix(2, Stream, 0); + const int client = socket_nid_postfix(2, Stream, 0); + Require(listener >= 0 && client >= 0, "socket failed"); + auto address = Loopback(); + Require(bind_nid_postfix(listener, address.data(), address.size()) == 0 && listen_nid_postfix(listener, 1) == 0, "listen failed"); + std::uint32_t size = address.size(); + Require(getsockname_nid_postfix(listener, address.data(), &size) == 0, "getsockname failed"); + Require(connect_nid_postfix(client, address.data(), address.size()) == 0, "connect failed"); + std::array padded{}; + std::memcpy(padded.data(), address.data(), address.size()); + Require(sendto_nid_postfix(client, "x", 1, 0, padded.data(), padded.size()) == 1, "tcp_usr_send ignores the address of a connected stream socket, so sendto must send"); + Require(Fails(sendto_nid_postfix(client, "x", 1, 0, padded.data(), 1), ErrorInvalid), "getsockaddr still checks the length of a connected stream socket's address"); + Require(close_nid_postfix(client) == 0 && close_nid_postfix(listener) == 0, "close failed"); +} + +void MismatchedAndUnknownFamiliesFail() { + const int stream = socket_nid_postfix(2, Stream, 0); + const int datagram = socket_nid_postfix(2, Datagram, 0); + const int stream6 = socket_nid_postfix(28, Stream, 0); + const int datagram6 = socket_nid_postfix(28, Datagram, 0); + Require(stream >= 0 && datagram >= 0 && stream6 >= 0 && datagram6 >= 0, "socket failed"); + const auto address = Loopback(); + Require(Fails(bind_nid_postfix(stream6, address.data(), address.size()), ErrorInvalid), "bind with an AF_INET address on an AF_INET6 socket must fail with EINVAL (22)"); + std::array unknownFamily{16, 99}; + Require(Fails(connect_nid_postfix(stream, unknownFamily.data(), unknownFamily.size()), ErrorAddressFamilyNotSupported), "connect with an unknown family must fail with EAFNOSUPPORT (47)"); + Require(Fails(sendto_nid_postfix(datagram, "x", 1, 0, unknownFamily.data(), unknownFamily.size()), ErrorAddressFamilyNotSupported), "sendto with an unknown family must fail with EAFNOSUPPORT (47)"); + std::array unknownFamily6{28, 99}; + Require(Fails(bind_nid_postfix(stream6, unknownFamily6.data(), unknownFamily6.size()), ErrorAddressFamilyNotSupported), "bind with an unknown family must fail with EAFNOSUPPORT (47)"); + Require(Fails(connect_nid_postfix(stream6, unknownFamily6.data(), unknownFamily6.size()), ErrorAddressFamilyNotSupported), "connect with an unknown family must fail with EAFNOSUPPORT (47)"); + Require(Fails(sendto_nid_postfix(datagram6, "x", 1, 0, unknownFamily6.data(), unknownFamily6.size()), ErrorAddressFamilyNotSupported), "sendto with an unknown family must fail with EAFNOSUPPORT (47)"); + Require(close_nid_postfix(stream) == 0 && close_nid_postfix(datagram) == 0 && close_nid_postfix(stream6) == 0 && close_nid_postfix(datagram6) == 0, "close failed"); +} + void FullAddressesStillWork() { const int stream = socket_nid_postfix(2, Stream, 0); Require(stream >= 0, "socket failed"); @@ -133,6 +189,8 @@ void LongMappedAddressesBindOnlyDualStackDatagramSockets() { Require(setsockopt_nid_postfix(datagram, 41, 27, &off, sizeof(off)) == 0, "clearing IPV6_V6ONLY failed"); Require(bind_nid_postfix(datagram, mapped.data(), mapped.size()) == 0, "udp6_bind passes a long IPv4-mapped address to in_pcbbind without IPV6_V6ONLY, so bind must succeed"); Require(Fails(sendto_nid_postfix(datagram, "x", 1, 0, mapped.data(), mapped.size()), ErrorInvalid), "udp6_send checks the length before the IPv4-mapped case, so sendto must fail with EINVAL (22)"); + mapped[3] = 9; + Require(connect_nid_postfix(datagram, mapped.data(), mapped.size()) == 0, "udp6_connect passes a long IPv4-mapped address to in_pcbconnect without IPV6_V6ONLY, so connect must succeed"); Require(close_nid_postfix(datagram) == 0, "close failed"); } @@ -141,6 +199,9 @@ void LongMappedAddressesBindOnlyDualStackDatagramSockets() { int main() { ShortAddressesAreInvalid(); ArgumentsAreCheckedBeforeTheDescriptor(); + LongAddressesAndOtherFamiliesFail(); + ConnectedStreamSendtoIgnoresTheAddress(); + MismatchedAndUnknownFamiliesFail(); FullAddressesStillWork(); LongAddressesAreInvalid(2, Stream); LongAddressesAreInvalid(2, Datagram); diff --git a/core/libs/tests/GuestSocketConnectListening.cpp b/core/libs/tests/GuestSocketConnectListening.cpp index 0f42c12bdb..fb5e900c3d 100644 --- a/core/libs/tests/GuestSocketConnectListening.cpp +++ b/core/libs/tests/GuestSocketConnectListening.cpp @@ -1,20 +1,11 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include #include #include -extern "C" { -int APS5_VABI socket_nid_postfix(int, int, int); -int APS5_VABI bind_nid_postfix(int, const void*, std::uint32_t); -int APS5_VABI listen_nid_postfix(int, int); -int APS5_VABI getsockname_nid_postfix(int, void*, std::uint32_t*); -int APS5_VABI connect_nid_postfix(int, const void*, std::uint32_t); -int APS5_VABI accept_nid_postfix(int, void*, std::uint32_t*); -int APS5_VABI close_nid_postfix(int); -int* APS5_VABI __error_nid_postfix(); -} - namespace { constexpr int Inet = 2; diff --git a/core/libs/tests/GuestSocketDescriptorFlags.cpp b/core/libs/tests/GuestSocketDescriptorFlags.cpp index ef8772f738..6d14f3997a 100644 --- a/core/libs/tests/GuestSocketDescriptorFlags.cpp +++ b/core/libs/tests/GuestSocketDescriptorFlags.cpp @@ -1,18 +1,10 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include #include -extern "C" { -int APS5_VABI socket_nid_postfix(int, int, int); -int APS5_VABI close_nid_postfix(int); -int APS5_VABI dup_nid_postfix(int); -int APS5_VABI dup2_nid_postfix(int, int); -int APS5_VABI pipe_nid_postfix(int*); -int APS5_VABI fcntl_nid_postfix(int, int, ...); -int* APS5_VABI __error_nid_postfix(); -} - namespace { constexpr int DuplicateDescriptor = 0; diff --git a/core/libs/tests/GuestSocketDescriptors.cpp b/core/libs/tests/GuestSocketDescriptors.cpp index 9a0ac4f5e6..3a66b41464 100644 --- a/core/libs/tests/GuestSocketDescriptors.cpp +++ b/core/libs/tests/GuestSocketDescriptors.cpp @@ -1,3 +1,6 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libkernel/File/include/File.hpp" +#include "prx/libc/include/Api.hpp" #include "SceTypes.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -25,32 +28,6 @@ struct GuestDescriptorSet { } }; -struct PollDescriptor { - int descriptor; - short events; - short revents; -}; - -extern "C" { -int APS5_VABI socket_nid_postfix(int, int, int); -int APS5_VABI bind_nid_postfix(int, const void*, std::uint32_t); -int APS5_VABI getsockname_nid_postfix(int, void*, std::uint32_t*); -int APS5_VABI connect_nid_postfix(int, const void*, std::uint32_t); -std::int64_t APS5_VABI send_nid_postfix(int, const void*, std::uint64_t, int); -std::int64_t APS5_VABI recv_nid_postfix(int, void*, std::uint64_t, int); -int APS5_VABI close_nid_postfix(int); -int APS5_VABI sceKernelClose(int); -std::int64_t APS5_VABI fstat_nid_disambig1_nid_postfix(int, FileStat*); -int APS5_VABI dup_nid_postfix(int); -int APS5_VABI dup2_nid_postfix(int, int); -int APS5_VABI fcntl_nid_postfix(int, int, ...); -int APS5_VABI open_nid_postfix(const char*, int, int); -std::int64_t APS5_VABI read_nid_postfix(int, void*, std::uint64_t); -int APS5_VABI select_nid_postfix(int, void*, void*, void*, const void*); -int APS5_VABI poll_nid_postfix(PollDescriptor*, std::uint32_t, int); -int* APS5_VABI __error_nid_postfix(); -} - static void Check(bool value, int line) { if (!value) { std::fprintf(stderr, "socket descriptor check failed at line %d, errno %d\n", line, *__error_nid_postfix()); @@ -159,7 +136,7 @@ static void CloseReleasesNumber() { Require(files.back() == socket); unsigned char bytes[4]{}; Require(read_nid_postfix(socket, bytes, sizeof(bytes)) == sizeof(bytes)); - PollDescriptor entry{socket, In, 0}; + GuestPollDescriptor entry{socket, In, 0}; Require(poll_nid_postfix(&entry, 1, 0) == 1 && entry.revents == In); for (const int file : files) Require(close_nid_postfix(file) == 0); const int kernelClosed = Socket(); diff --git a/core/libs/tests/GuestSocketEvents.cpp b/core/libs/tests/GuestSocketEvents.cpp index 20ecb18f99..59bd2bb4ad 100644 --- a/core/libs/tests/GuestSocketEvents.cpp +++ b/core/libs/tests/GuestSocketEvents.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/KernelErrors.hpp" +#include "prx/libkernel/include/Api.hpp" #include "SceTypes.hpp" #include #include @@ -9,34 +11,7 @@ #include #include -extern "C" { -int APS5_VABI socket_nid_postfix(int, int, int); -int APS5_VABI bind_nid_postfix(int, const void*, std::uint32_t); -int APS5_VABI listen_nid_postfix(int, int); -int APS5_VABI getsockname_nid_postfix(int, void*, std::uint32_t*); -int APS5_VABI connect_nid_postfix(int, const void*, std::uint32_t); -int APS5_VABI accept_nid_postfix(int, void*, std::uint32_t*); -std::int64_t APS5_VABI send_nid_postfix(int, const void*, std::uint64_t, int); -std::int64_t APS5_VABI recv_nid_postfix(int, void*, std::uint64_t, int); -int APS5_VABI close_nid_postfix(int); -int APS5_VABI pipe_nid_postfix(int*); -std::int64_t APS5_VABI read_nid_postfix(int, void*, std::uint64_t); -std::int64_t APS5_VABI write_nid_postfix(int, const char*, std::int64_t); -int APS5_VABI open_nid_postfix(const char*, int, int); -std::int64_t APS5_VABI lseek_nid_postfix(int, std::int64_t, int); -int APS5_VABI sceKernelCreateEqueue(KernelEqueue* eq, const char* name); -int APS5_VABI sceKernelDeleteEqueue(KernelEqueue eq); -int APS5_VABI sceKernelWaitEqueue(KernelEqueue eq, KernelEvent* ev, int num, int* out, const KernelUseconds* timo); -int APS5_VABI sceKernelAddReadEvent(KernelEqueue eq, int fd, std::size_t size, void* udata); -int APS5_VABI sceKernelDeleteReadEvent(KernelEqueue eq, int fd); -int APS5_VABI sceKernelAddWriteEvent(KernelEqueue eq, int fd, std::size_t size, void* udata); -int APS5_VABI sceKernelDeleteWriteEvent(KernelEqueue eq, int fd); -} - static constexpr int SCE_OK = 0; -static constexpr int SCE_KERNEL_ERROR_ENOENT = static_cast(0x80020002); -static constexpr int SCE_KERNEL_ERROR_EBADF = static_cast(0x80020009); -static constexpr int SCE_KERNEL_ERROR_ETIMEDOUT = static_cast(0x8002003c); static constexpr int EVFILT_READ = -1; static constexpr int EVFILT_WRITE = -2; static constexpr std::uint16_t EV_EOF = 0x8000; diff --git a/core/libs/tests/GuestSocketHostWrite.cpp b/core/libs/tests/GuestSocketHostWrite.cpp index df022d1f8a..a49e49d08d 100644 --- a/core/libs/tests/GuestSocketHostWrite.cpp +++ b/core/libs/tests/GuestSocketHostWrite.cpp @@ -1,3 +1,7 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libkernel/File/include/File.hpp" +#include "prx/libc/include/Api.hpp" +#include "prx/libSceNet/include/Net.hpp" #define WIN32_LEAN_AND_MEAN #include #include "prx/libc/include/GuestArena.hpp" @@ -12,57 +16,8 @@ #include #include -struct NetIovec { - void* base; - std::uint64_t length; -}; - -struct NetMsghdr { - void* name; - std::uint32_t nameLength; - NetIovec* iov; - int iovLength; - void* control; - std::uint32_t controlLength; - int flags; -}; static_assert(sizeof(NetMsghdr) == 48 && offsetof(NetMsghdr, iov) == 16 && offsetof(NetMsghdr, flags) == 44); -extern "C" { -int APS5_VABI socket_nid_postfix(int, int, int); -int APS5_VABI bind_nid_postfix(int, const void*, std::uint32_t); -int APS5_VABI getsockname_nid_postfix(int, void*, std::uint32_t*); -int APS5_VABI listen_nid_postfix(int, int); -int APS5_VABI connect_nid_postfix(int, const void*, std::uint32_t); -int APS5_VABI accept_nid_postfix(int, void*, std::uint32_t*); -int APS5_VABI fcntl_nid_postfix(int, int, ...); -std::int64_t APS5_VABI sendto_nid_postfix(int, const void*, std::uint64_t, int, const void*, std::uint32_t); -std::int64_t APS5_VABI recv_nid_postfix(int, void*, std::uint64_t, int); -std::int64_t APS5_VABI recvfrom_nid_postfix(int, void*, std::uint64_t, int, void*, std::uint32_t*); -std::int64_t APS5_VABI read_nid_postfix(int, void*, std::uint64_t); -std::int64_t APS5_VABI sceKernelRead(int, void*, std::size_t); -int APS5_VABI close_nid_postfix(int); -int* APS5_VABI __error_nid_postfix(); -int APS5_VABI sceNetSocket(const char*, int, int, int); -int APS5_VABI sceNetBind_nid_postfix(int, const void*, std::uint32_t); -int APS5_VABI sceNetGetsockname(int, void*, std::uint32_t*); -int APS5_VABI sceNetListen(int, int); -int APS5_VABI sceNetConnect(int, const void*, std::uint32_t); -int APS5_VABI sceNetAccept(int, void*, std::uint32_t*); -int APS5_VABI sceNetSetsockopt(int, int, int, const void*, std::uint32_t); -std::int64_t APS5_VABI sceNetSendto(int, const void*, std::size_t, int, const void*, std::uint32_t); -std::int64_t APS5_VABI sceNetRecv(int, void*, std::size_t, int); -std::int64_t APS5_VABI sceNetRecvfrom(int, void*, std::size_t, int, void*, std::uint32_t*); -std::int64_t APS5_VABI sceNetRecvmsg(int, NetMsghdr*, int); -int APS5_VABI sceNetSocketClose(int); -int* APS5_VABI sceNetErrnoLoc(); -int APS5_VABI sceKernelAllocateDirectMemory(std::int64_t, std::int64_t, std::size_t, std::size_t, int, std::int64_t*); -int APS5_VABI sceKernelMapDirectMemory(void**, std::size_t, int, int, std::int64_t, std::size_t); -int APS5_VABI sceKernelMprotect(void*, std::size_t, int); -int APS5_VABI sceKernelMunmap(void*, std::size_t); -int APS5_VABI sceKernelReleaseDirectMemory(std::int64_t, std::size_t); -} - static void Require(bool value, const char* message) { if (!value) { std::fprintf(stderr, "%s\n", message); @@ -94,6 +49,7 @@ int main(int argc, char** argv) { const auto create = [&] { return net ? sceNetSocket(nullptr, 2, stream ? 1 : 2, stream ? 6 : 17) : socket_nid_postfix(2, stream ? 1 : 2, stream ? 6 : 17); + }; int receiver = create(); const int sender = create(); @@ -156,6 +112,7 @@ int main(int argc, char** argv) { do { result = net ? sceNetRecv(receiver, buffer.data(), buffer.size(), 2) : recv_nid_postfix(receiver, buffer.data(), buffer.size(), 2); + if (result == sizeof(payload) || (result < 0 && *error != 35)) break; std::this_thread::sleep_for(std::chrono::milliseconds(1)); } while (std::chrono::steady_clock::now() < deadline); @@ -312,8 +269,8 @@ int main(int argc, char** argv) { Require(sceKernelMprotect(static_cast(outputMapping) + page, page, 3) == 0, "restore bytes beyond the sender address"); } - Require(sceKernelMunmap(outputTwin, page * 2) == 0, "unmap the second sender output mapping"); - Require(sceKernelMunmap(outputMapping, page * 2) == 0, "unmap sender outputs"); + Require(sceKernelMunmap(reinterpret_cast(outputTwin), page * 2) == 0, "unmap the second sender output mapping"); + Require(sceKernelMunmap(reinterpret_cast(outputMapping), page * 2) == 0, "unmap sender outputs"); Require(sceKernelReleaseDirectMemory(outputPhysical, page * 2) == 0, "release sender output memory"); } reset(); @@ -355,7 +312,7 @@ int main(int argc, char** argv) { waitForPacket(); Require(sceNetRecvmsg(receiver, message, 0) == static_cast(0x8041010eu) && *error == 14, "read-only message outputs fail with EFAULT"); - Require(message->flags == -1 && message->controlLength == 123, "rejected message outputs unchanged"); + Require(message->flags == -1 && message->control_length == 123, "rejected message outputs unchanged"); Require(receive(recovery.data(), recovery.size(), 0, nullptr, nullptr) == sizeof(payload), "a rejected message preserves queued data"); Require(sceKernelMprotect(twin, page, 3) == 0, "restore receive message write permission"); @@ -411,7 +368,7 @@ int main(int argc, char** argv) { Require(Protection(buffer) == PAGE_READONLY, "completed receive can be rearmed"); Require((net ? sceNetSocketClose(sender) : close_nid_postfix(sender)) == 0, "close sender"); Require((net ? sceNetSocketClose(receiver) : close_nid_postfix(receiver)) == 0, "close receiver"); - Require(sceKernelMunmap(twin, page * 2) == 0, "unmap the second direct memory mapping"); - Require(sceKernelMunmap(mapping, page * 2) == 0, "unmap direct memory"); + Require(sceKernelMunmap(reinterpret_cast(twin), page * 2) == 0, "unmap the second direct memory mapping"); + Require(sceKernelMunmap(reinterpret_cast(mapping), page * 2) == 0, "unmap direct memory"); Require(sceKernelReleaseDirectMemory(physical, page * 2) == 0, "release direct memory"); } diff --git a/core/libs/tests/GuestSocketOnNonSocket.cpp b/core/libs/tests/GuestSocketOnNonSocket.cpp index 953bd473d0..49c9d54ea0 100644 --- a/core/libs/tests/GuestSocketOnNonSocket.cpp +++ b/core/libs/tests/GuestSocketOnNonSocket.cpp @@ -1,25 +1,11 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include #include #include -extern "C" { -int APS5_VABI bind_nid_postfix(int, const void*, std::uint32_t); -int APS5_VABI listen_nid_postfix(int, int); -int APS5_VABI accept_nid_postfix(int, void*, std::uint32_t*); -int APS5_VABI connect_nid_postfix(int, const void*, std::uint32_t); -int APS5_VABI shutdown_nid_postfix(int, int); -int APS5_VABI getsockname_nid_postfix(int, void*, std::uint32_t*); -int APS5_VABI setsockopt_nid_postfix(int, int, int, const void*, std::uint32_t); -int APS5_VABI getsockopt_nid_postfix(int, int, int, void*, std::uint32_t*); -std::int64_t APS5_VABI send_nid_postfix(int, const void*, std::uint64_t, int); -std::int64_t APS5_VABI recv_nid_postfix(int, void*, std::uint64_t, int); -int APS5_VABI pipe_nid_postfix(int*); -int APS5_VABI close_nid_postfix(int); -int* APS5_VABI __error_nid_postfix(); -} - namespace { constexpr int ErrorBadDescriptor = 9; diff --git a/core/libs/tests/GuestSocketOptions.cpp b/core/libs/tests/GuestSocketOptions.cpp index f3d2decabc..7c73a6f364 100644 --- a/core/libs/tests/GuestSocketOptions.cpp +++ b/core/libs/tests/GuestSocketOptions.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -5,22 +7,6 @@ #include #include -extern "C" { -int APS5_VABI socket_nid_postfix(int, int, int); -int APS5_VABI bind_nid_postfix(int, const void*, std::uint32_t); -int APS5_VABI listen_nid_postfix(int, int); -int APS5_VABI getsockname_nid_postfix(int, void*, std::uint32_t*); -int APS5_VABI connect_nid_postfix(int, const void*, std::uint32_t); -int APS5_VABI accept_nid_postfix(int, void*, std::uint32_t*); -int APS5_VABI setsockopt_nid_postfix(int, int, int, const void*, std::uint32_t); -int APS5_VABI getsockopt_nid_postfix(int, int, int, void*, std::uint32_t*); -int APS5_VABI socketpair_nid_postfix(int, int, int, int*); -int APS5_VABI fcntl_nid_postfix(int, int, ...); -int APS5_VABI poll_nid_postfix(void*, std::uint32_t, int); -int APS5_VABI close_nid_postfix(int); -int* APS5_VABI __error_nid_postfix(); -} - namespace { constexpr int Stream = 1; @@ -52,12 +38,6 @@ struct Linger { std::int32_t seconds; }; -struct PollDescriptor { - std::int32_t descriptor; - std::int16_t events; - std::int16_t revents; -}; - void Require(bool condition, const char* what) { if (condition) return; std::fprintf(stderr, "%s (errno %d)\n", what, *__error_nid_postfix()); @@ -99,7 +79,7 @@ std::array Listen(int* listener) { } void WaitUntilSettled(int descriptor) { - PollDescriptor entry{descriptor, 0x1 | 0x4, 0}; + GuestPollDescriptor entry{descriptor, 0x1 | 0x4, 0}; Require(poll_nid_postfix(&entry, 1, 6000) == 1, "the nonblocking connect did not settle within 6 s"); } @@ -337,6 +317,11 @@ void IpLevelFollowsThePs5() { size = sizeof(value); Require(getsockopt_nid_postfix(datagram, 99, 1, &value, &size) == -1 && *__error_nid_postfix() == ErrorInvalid, "an unknown level must fail with EINVAL (22)"); Require(SetFails(datagram, 99, 1, &value, sizeof(value), ErrorInvalid), "setsockopt at an unknown level must fail with EINVAL (22)"); + for (const int option : {7, 20, 65}) { + Require(GetIp(datagram, option) == 0, "a receive option starts off"); + Require(SetIp(datagram, option, 5) && GetIp(datagram, option) == 1, "a receive option reads back as 1"); + Require(SetIp(datagram, option, 0) && GetIp(datagram, option) == 0, "a receive option turns off"); + } Require(close_nid_postfix(datagram) == 0 && close_nid_postfix(datagram6) == 0, "close failed"); } diff --git a/core/libs/tests/GuestSocketPair.cpp b/core/libs/tests/GuestSocketPair.cpp index 0b827364c4..367ebff08d 100644 --- a/core/libs/tests/GuestSocketPair.cpp +++ b/core/libs/tests/GuestSocketPair.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "SceTypes.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -7,47 +9,6 @@ #include #include -struct PollDescriptor { - int descriptor; - short events; - short revents; -}; - -struct Iovec { - void* base; - std::uint64_t length; -}; - -struct Msghdr { - void* name; - std::uint32_t nameLength; - Iovec* iov; - int iovLength; - void* control; - std::uint32_t controlLength; - int flags; -}; - -extern "C" { -int APS5_VABI socketpair_nid_postfix(int, int, int, int*); -std::int64_t APS5_VABI send_nid_postfix(int, const void*, std::uint64_t, int); -std::int64_t APS5_VABI recv_nid_postfix(int, void*, std::uint64_t, int); -std::int64_t APS5_VABI recvfrom_nid_postfix(int, void*, std::uint64_t, int, void*, std::uint32_t*); -std::int64_t APS5_VABI recvmsg_nid_postfix(int, Msghdr*, int); -int APS5_VABI getsockname_nid_postfix(int, void*, std::uint32_t*); -int APS5_VABI getpeername_nid_postfix(int, void*, std::uint32_t*); -int APS5_VABI shutdown_nid_postfix(int, int); -int APS5_VABI fcntl_nid_postfix(int, int, ...); -int APS5_VABI poll_nid_postfix(PollDescriptor*, std::uint32_t, int); -int APS5_VABI close_nid_postfix(int); -std::int64_t APS5_VABI fstat_nid_disambig1_nid_postfix(int, FileStat*); -int APS5_VABI sceKernelFstat(int, FileStat*); -int APS5_VABI sceKernelMapFlexibleMemory(void**, std::size_t, int, int); -int APS5_VABI sceKernelMprotect(const void*, std::size_t, int); -int APS5_VABI sceKernelMunmap(void*, std::size_t); -int* APS5_VABI __error_nid_postfix(); -} - static void Require(bool value) { if (!value) std::abort(); } template @@ -81,7 +42,7 @@ static bool Fails(int domain, int type, int protocol, int error) { } static bool Readable(int descriptor, short accepted = In) { - PollDescriptor waited{descriptor, In, 0}; + GuestPollDescriptor waited{descriptor, In, 0}; return poll_nid_postfix(&waited, 1, 2000) == 1 && (waited.revents & accepted) != 0; } @@ -104,7 +65,15 @@ static bool Unnamed(int descriptor, int (APS5_VABI *query)(int, void*, std::uint return query(descriptor, name, &length) == 0 && length == 4 && name[0] == 16 && name[1] == 1 && name[4] == 0xaa; } -static bool ReceiveFaults(int descriptor, Msghdr* message) { +static bool NotConnected(int descriptor) { + std::uint8_t name[16]; + std::memset(name, 0xaa, sizeof(name)); + std::uint32_t length = sizeof(name); + *__error_nid_postfix() = 0; + return getpeername_nid_postfix(descriptor, name, &length) == -1 && *__error_nid_postfix() == 57 && length == sizeof(name) && name[0] == 0xaa; +} + +static bool ReceiveFaults(int descriptor, GuestMsghdr* message) { *__error_nid_postfix() = 0; return recvmsg_nid_postfix(descriptor, message, 0) == -1 && *__error_nid_postfix() == 14; } @@ -122,26 +91,26 @@ static void CheckReceiveMessageFaults() { auto* readOnly = writable + page; auto* inaccessible = writable + 2 * page; char data[16]{}; - Iovec good{data, sizeof(data)}; - auto* readOnlyMessage = reinterpret_cast(readOnly); + KernelIovec good{data, sizeof(data)}; + auto* readOnlyMessage = reinterpret_cast(readOnly); *readOnlyMessage = {nullptr, 0, &good, 1, nullptr, 0, -1}; - auto* readOnlyVector = reinterpret_cast(readOnly + 64); + auto* readOnlyVector = reinterpret_cast(readOnly + 64); *readOnlyVector = {data, sizeof(data)}; Require(sceKernelMprotect(readOnly, page, 1) == 0 && sceKernelMprotect(inaccessible, page, 0) == 0); int pair[2] = {-1, -1}; Require(socketpair_nid_postfix(Unix, Datagram, 0, pair) == 0); Require(Queue(pair[0], pair[1], "x")); - Require(ReceiveFaults(pair[1], reinterpret_cast(0x1000))); - Require(ReceiveFaults(pair[1], reinterpret_cast(inaccessible))); - Msghdr message{nullptr, 0, reinterpret_cast(0x1000), 1, nullptr, 0, -1}; + Require(ReceiveFaults(pair[1], reinterpret_cast(0x1000))); + Require(ReceiveFaults(pair[1], reinterpret_cast(inaccessible))); + GuestMsghdr message{nullptr, 0, reinterpret_cast(0x1000), 1, nullptr, 0, -1}; Require(ReceiveFaults(pair[1], &message)); - message.iov = reinterpret_cast(inaccessible); + message.iov = reinterpret_cast(inaccessible); Require(ReceiveFaults(pair[1], &message)); char peeked[4]{}; Require(recv_nid_postfix(pair[1], peeked, sizeof(peeked), Peek) == 1 && peeked[0] == 'x'); - Iovec vector{reinterpret_cast(0x1000), sizeof(data)}; + KernelIovec vector{reinterpret_cast(0x1000), sizeof(data)}; message = {nullptr, 0, &vector, 1, nullptr, 0, -1}; Require(ReceiveFaults(pair[1], &message)); vector.base = inaccessible; @@ -164,7 +133,7 @@ static void CheckReceiveMessageFaults() { Require(Queue(pair[0], pair[1], "abcd") && recvmsg_nid_postfix(pair[1], &message, 0) == 4); Require(std::memcmp(writable, "abcd", 4) == 0 && message.flags == 0 && message.controlLength == 0); Require(message.nameLength == 16 && name[0] == 16 && name[1] == Unix && name[16] == 0xa5); - Iovec vectors[2]{{writable, 2}, {inaccessible, 16}}; + KernelIovec vectors[2]{{writable, 2}, {inaccessible, 16}}; message = {nullptr, 0, vectors, 2, nullptr, 0, -1}; Require(Queue(pair[0], pair[1], "ef") && recvmsg_nid_postfix(pair[1], &message, 0) == 2 && std::memcmp(writable, "ef", 2) == 0); message = {readOnly + 128, 0, readOnlyVector, 1, nullptr, 0, -1}; @@ -172,7 +141,7 @@ static void CheckReceiveMessageFaults() { Require(std::memcmp(data, "gh", 2) == 0 && message.nameLength == 0); Require(close_nid_postfix(pair[0]) == 0 && close_nid_postfix(pair[1]) == 0); - Require(sceKernelMprotect(memory, page * 3, 3) == 0 && sceKernelMunmap(memory, page * 3) == 0); + Require(sceKernelMprotect(memory, page * 3, 3) == 0 && sceKernelMunmap(reinterpret_cast(memory), page * 3) == 0); } int main(int argc, char** argv) { @@ -188,7 +157,7 @@ int main(int argc, char** argv) { Require(Exchange(pair[1], pair[0], "other way")); Require(Unnamed(pair[0], getsockname_nid_postfix) && Unnamed(pair[1], getpeername_nid_postfix)); - PollDescriptor polled[2] = {{pair[1], In, 0}, {pair[0], Out, 0}}; + GuestPollDescriptor polled[2] = {{pair[1], In, 0}, {pair[0], Out, 0}}; Require(poll_nid_postfix(polled, 2, 0) == 1 && polled[0].revents == 0 && (polled[1].revents & Out) != 0); const char ping[] = "ping"; Require(send_nid_postfix(pair[0], ping, sizeof(ping), 0) == sizeof(ping)); @@ -211,7 +180,9 @@ int main(int argc, char** argv) { Require(shutdown_nid_postfix(pair[0], 1) == 0); Require(Readable(pair[1], In | Hup) && recv_nid_postfix(pair[1], received, sizeof(received), 0) == 0); Require(Exchange(pair[1], pair[0], "still open")); + Require(Unnamed(pair[0], getpeername_nid_postfix) && Unnamed(pair[1], getpeername_nid_postfix)); Require(close_nid_postfix(pair[0]) == 0); + Require(NotConnected(pair[1]) && Unnamed(pair[1], getsockname_nid_postfix)); Require(Readable(pair[1], In | Hup) && recv_nid_postfix(pair[1], received, sizeof(received), 0) == 0); std::int64_t sent = 0; for (int i = 0; i < 100 && sent >= 0; ++i) sent = send_nid_postfix(pair[1], ping, sizeof(ping), NoSignal); @@ -260,7 +231,11 @@ int main(int argc, char** argv) { Require(senderLength == 16 && sender[0] == 16 && sender[1] == 1); Require(recv_nid_postfix(pair[1], datagram, sizeof(datagram), 0) == 2 && datagram[0] == 'b' && datagram[1] == 'b'); Require(Exchange(pair[1], pair[0], "back")); - Require(close_nid_postfix(pair[0]) == 0 && close_nid_postfix(pair[1]) == 0); + const int copy = dup_nid_postfix(pair[0]); + Require(copy >= 0 && close_nid_postfix(pair[0]) == 0); + Require(Unnamed(pair[1], getpeername_nid_postfix) && Exchange(pair[1], copy, "copy")); + Require(close_nid_postfix(copy) == 0 && NotConnected(pair[1])); + Require(close_nid_postfix(pair[1]) == 0); #ifdef __APPLE__ Require(ThrowsRuntimeError([&] { socketpair_nid_postfix(Unix, SequencedPacket, 0, pair); })); @@ -273,8 +248,8 @@ int main(int argc, char** argv) { Require(send_nid_postfix(pair[0], "record", 6, 0) == 6); Require(send_nid_postfix(pair[0], "next", 4, 0) == 4); char part[2]{}; - Iovec piece{part, sizeof(part)}; - Msghdr message{nullptr, 0, &piece, 1, nullptr, 0, -1}; + KernelIovec piece{part, sizeof(part)}; + GuestMsghdr message{nullptr, 0, &piece, 1, nullptr, 0, -1}; const auto truncated = recvmsg_nid_postfix(pair[1], &message, 0); if (truncated != 2 || message.flags != 0x10) { std::fprintf(stderr, "recvmsg of a 6-byte SOCK_SEQPACKET record into 2 bytes returned %lld with msg_flags 0x%x, expected 2 with MSG_TRUNC (0x10)\n", diff --git a/core/libs/tests/GuestSocketPortZero.cpp b/core/libs/tests/GuestSocketPortZero.cpp index 36857ee65e..f450f75277 100644 --- a/core/libs/tests/GuestSocketPortZero.cpp +++ b/core/libs/tests/GuestSocketPortZero.cpp @@ -1,21 +1,11 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include #include #include #include -extern "C" { -int APS5_VABI socket_nid_postfix(int, int, int); -int APS5_VABI connect_nid_postfix(int, const void*, std::uint32_t); -int APS5_VABI bind_nid_postfix(int, const void*, std::uint32_t); -int APS5_VABI listen_nid_postfix(int, int); -int APS5_VABI getsockname_nid_postfix(int, void*, std::uint32_t*); -int APS5_VABI getpeername_nid_postfix(int, void*, std::uint32_t*); -std::int64_t APS5_VABI send_nid_postfix(int, const void*, std::uint64_t, int); -std::int64_t APS5_VABI sendto_nid_postfix(int, const void*, std::uint64_t, int, const void*, std::uint32_t); -int APS5_VABI close_nid_postfix(int); -int* APS5_VABI __error_nid_postfix(); -} static void Require(bool value, const char* message) { if (!value) { diff --git a/core/libs/tests/GuestSocketReadWrite.cpp b/core/libs/tests/GuestSocketReadWrite.cpp index 4af5913b09..f320cf6569 100644 --- a/core/libs/tests/GuestSocketReadWrite.cpp +++ b/core/libs/tests/GuestSocketReadWrite.cpp @@ -1,3 +1,6 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libkernel/File/include/File.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -9,47 +12,6 @@ #include #endif -struct PollDescriptor { - int descriptor; - short events; - short revents; -}; - -struct Iovec { - void* base; - std::size_t length; -}; - -extern "C" { -int APS5_VABI socket_nid_postfix(int, int, int); -int APS5_VABI bind_nid_postfix(int, const void*, std::uint32_t); -int APS5_VABI listen_nid_postfix(int, int); -int APS5_VABI getsockname_nid_postfix(int, void*, std::uint32_t*); -int APS5_VABI connect_nid_postfix(int, const void*, std::uint32_t); -int APS5_VABI accept_nid_postfix(int, void*, std::uint32_t*); -int APS5_VABI fcntl_nid_postfix(int, int, ...); -int APS5_VABI poll_nid_postfix(PollDescriptor*, std::uint32_t, int); -int APS5_VABI close_nid_postfix(int); -int APS5_VABI sceKernelClose(int); -std::int64_t APS5_VABI read_nid_postfix(int, void*, std::uint64_t); -std::int64_t APS5_VABI write_nid_postfix(int, const char*, std::int64_t); -std::int64_t APS5_VABI _read_nid_postfix(int, void*, std::size_t); -std::int64_t APS5_VABI _write_nid_postfix(int, const void*, std::size_t); -std::int64_t APS5_VABI sceKernelRead(int, void*, std::size_t); -std::int64_t APS5_VABI sceKernelWrite(int, const void*, std::size_t); -std::int64_t APS5_VABI sceKernelReadv(int, const Iovec*, int); -std::int64_t APS5_VABI sceKernelWritev(int, const Iovec*, int); -std::int64_t APS5_VABI pread_nid_postfix(int, void*, std::size_t, std::int64_t); -std::int64_t APS5_VABI pwrite_nid_disambig1_nid_postfix(int, const void*, std::size_t, std::int64_t); -std::int64_t APS5_VABI preadv_nid_postfix(int, const Iovec*, int, std::int64_t); -std::int64_t APS5_VABI pwritev_nid_postfix(int, const Iovec*, int, std::int64_t); -std::int64_t APS5_VABI sceKernelPread(int, void*, std::size_t, std::int64_t); -std::int64_t APS5_VABI sceKernelPwrite(int, const void*, std::size_t, std::int64_t); -std::int64_t APS5_VABI sceKernelPreadv(int, const Iovec*, int, std::int64_t); -std::int64_t APS5_VABI sceKernelPwritev(int, const Iovec*, int, std::int64_t); -int* APS5_VABI __error_nid_postfix(); -} - static void Check(bool value, int line) { if (!value) { std::fprintf(stderr, "socket read/write check failed at line %d, errno %d\n", line, *__error_nid_postfix()); @@ -65,7 +27,7 @@ constexpr int KernelBadDescriptor = static_cast(0x80020009u); constexpr int KernelIllegalSeek = static_cast(0x8002001du); static bool Readable(int descriptor, short accepted = In) { - PollDescriptor waited{descriptor, In, 0}; + GuestPollDescriptor waited{descriptor, In, 0}; return poll_nid_postfix(&waited, 1, 2000) == 1 && (waited.revents & accepted) != 0; } @@ -105,28 +67,28 @@ int main() { const char vectorFirst[] = "vector "; const char vectorSecond[] = "write"; - Iovec vectorWrite[] = {{const_cast(vectorFirst), sizeof(vectorFirst) - 1}, + KernelIovec vectorWrite[] = {{const_cast(vectorFirst), sizeof(vectorFirst) - 1}, {const_cast(vectorSecond), sizeof(vectorSecond)}}; Require(sceKernelWritev(client, vectorWrite, 2) == sizeof(vectorFirst) + sizeof(vectorSecond) - 1); char vectorReadFirst[sizeof(vectorFirst) - 1]{}; char vectorReadSecond[sizeof(vectorSecond)]{}; - Iovec vectorRead[] = {{vectorReadFirst, sizeof(vectorReadFirst)}, {vectorReadSecond, sizeof(vectorReadSecond)}}; + KernelIovec vectorRead[] = {{vectorReadFirst, sizeof(vectorReadFirst)}, {vectorReadSecond, sizeof(vectorReadSecond)}}; Require(Readable(server) && sceKernelReadv(server, vectorRead, 2) == sizeof(vectorFirst) + sizeof(vectorSecond) - 1); Require(std::memcmp(vectorReadFirst, "vector ", sizeof(vectorReadFirst)) == 0 && std::strcmp(vectorReadSecond, "write") == 0); const char sceVectorFirst[] = "sceKernel"; const char sceVectorSecond[] = "Writev"; - Iovec sceVectorWrite[] = {{const_cast(sceVectorFirst), sizeof(sceVectorFirst) - 1}, + KernelIovec sceVectorWrite[] = {{const_cast(sceVectorFirst), sizeof(sceVectorFirst) - 1}, {const_cast(sceVectorSecond), sizeof(sceVectorSecond)}}; Require(sceKernelWritev(client, sceVectorWrite, 2) == sizeof(sceVectorFirst) + sizeof(sceVectorSecond) - 1); char sceVectorReadFirst[sizeof(sceVectorFirst) - 1]{}; char sceVectorReadSecond[sizeof(sceVectorSecond)]{}; - Iovec sceVectorRead[] = {{sceVectorReadFirst, sizeof(sceVectorReadFirst)}, {sceVectorReadSecond, sizeof(sceVectorReadSecond)}}; + KernelIovec sceVectorRead[] = {{sceVectorReadFirst, sizeof(sceVectorReadFirst)}, {sceVectorReadSecond, sizeof(sceVectorReadSecond)}}; Require(Readable(server) && sceKernelReadv(server, sceVectorRead, 2) == sizeof(sceVectorFirst) + sizeof(sceVectorSecond) - 1); Require(std::memcmp(sceVectorReadFirst, "sceKernel", sizeof(sceVectorReadFirst)) == 0 && std::strcmp(sceVectorReadSecond, "Writev") == 0); const char positionedWrite[] = "positioned"; - Iovec positionedIov[] = {{const_cast(positionedWrite), sizeof(positionedWrite)}}; + KernelIovec positionedIov[] = {{const_cast(positionedWrite), sizeof(positionedWrite)}}; *__error_nid_postfix() = 0; Require(pread_nid_postfix(server, received, 1, 0) == -1 && *__error_nid_postfix() == 29); Require(pwrite_nid_disambig1_nid_postfix(client, positionedWrite, 1, 0) == -1 && *__error_nid_postfix() == 29); @@ -141,7 +103,7 @@ int main() { *__error_nid_postfix() = 0; Require(read_nid_postfix(server, received, sizeof(received)) == -1 && *__error_nid_postfix() == 35); Require(sceKernelRead(server, received, sizeof(received)) == KernelAgain); - Iovec emptyRead[] = {{received, sizeof(received)}}; + KernelIovec emptyRead[] = {{received, sizeof(received)}}; Require(sceKernelReadv(server, emptyRead, 1) == KernelAgain); Require(read_nid_postfix(server, received, 0) == 0 && sceKernelRead(server, received, 0) == 0); diff --git a/core/libs/tests/GuestSocketStreamOptions.cpp b/core/libs/tests/GuestSocketStreamOptions.cpp index 58c21ea728..08434c8ae8 100644 --- a/core/libs/tests/GuestSocketStreamOptions.cpp +++ b/core/libs/tests/GuestSocketStreamOptions.cpp @@ -1,29 +1,13 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include +#include #include #include #include #include -extern "C" { -int APS5_VABI socket_nid_postfix(int, int, int); -int APS5_VABI socketpair_nid_postfix(int, int, int, int*); -int APS5_VABI bind_nid_postfix(int, const void*, std::uint32_t); -int APS5_VABI listen_nid_postfix(int, int); -int APS5_VABI getsockname_nid_postfix(int, void*, std::uint32_t*); -int APS5_VABI connect_nid_postfix(int, const void*, std::uint32_t); -int APS5_VABI accept_nid_postfix(int, void*, std::uint32_t*); -int APS5_VABI shutdown_nid_postfix(int, int); -int APS5_VABI setsockopt_nid_postfix(int, int, int, const void*, std::uint32_t); -int APS5_VABI getsockopt_nid_postfix(int, int, int, void*, std::uint32_t*); -int APS5_VABI fcntl_nid_postfix(int, int, ...); -int APS5_VABI close_nid_postfix(int); -std::int64_t APS5_VABI send_nid_postfix(int, const void*, std::uint64_t, int); -std::int64_t APS5_VABI recv_nid_postfix(int, void*, std::uint64_t, int); -std::int64_t APS5_VABI write_nid_postfix(int, const char*, std::int64_t); -int* APS5_VABI __error_nid_postfix(); -} - static void Check(bool value, int line) { if (!value) { std::fprintf(stderr, "socket stream option check failed at line %d, errno %d\n", line, *__error_nid_postfix()); @@ -91,13 +75,14 @@ int main() { Require(client >= 0 && connect_nid_postfix(client, address.data(), address.size()) == 0); const int server = accept_nid_postfix(listener, nullptr, nullptr); Require(server >= 0); - Require(Set(listener, SocketLevel, NoSigpipe, 1) && Set(listener, TcpLevel, TcpNoDelay, 1) && Set(listener, TcpLevel, 0x100, 60)); + Require(Set(listener, SocketLevel, NoSigpipe, 1) && Set(listener, TcpLevel, TcpNoDelay, 1) && Set(listener, TcpLevel, 0x100, 60) && Set(listener, TcpLevel, 4, 1) && Set(listener, TcpLevel, 8, 1)); const int secondClient = socket_nid_postfix(2, 1, 0); Require(secondClient >= 0 && connect_nid_postfix(secondClient, address.data(), address.size()) == 0); const int inheriting = accept_nid_postfix(listener, nullptr, nullptr); Require(inheriting >= 0); Require(Get(inheriting, SocketLevel, NoSigpipe) == NoSigpipe && Get(inheriting, TcpLevel, TcpNoDelay) == 4); Require(Get(inheriting, TcpLevel, 0x100) == 60 && Get(server, TcpLevel, 0x100) == 7200); + Require(Get(inheriting, TcpLevel, 4) == 0x1000 && Get(inheriting, TcpLevel, 8) == 0); Require(Get(server, SocketLevel, NoSigpipe) == 0 && Get(server, TcpLevel, TcpNoDelay) == 0); Require(close_nid_postfix(inheriting) == 0 && close_nid_postfix(secondClient) == 0); const int datagram = socket_nid_postfix(2, 2, 0); @@ -129,6 +114,12 @@ int main() { Require(Set(fresh, TcpLevel, 0x400, 3) && Get(fresh, TcpLevel, 0x400) == 3); Require(Set(fresh, TcpLevel, 0x400, -1) && Get(fresh, TcpLevel, 0x400) == -1); Require(Fails(setsockopt_nid_postfix(fresh, TcpLevel, 0x7777, &one, sizeof(one)), NoProtocolOption)); + for (const auto& [option, bit] : {std::pair{4, 0x1000}, std::pair{8, 0x8}, std::pair{0x80, 0x10000}}) { + Require(Get(fresh, TcpLevel, option) == 0); + Require(Set(fresh, TcpLevel, option, 5) && Get(fresh, TcpLevel, option) == bit); + Require(Set(fresh, TcpLevel, option, -1) && Get(fresh, TcpLevel, option) == bit); + Require(Set(fresh, TcpLevel, option, 0) && Get(fresh, TcpLevel, option) == 0); + } Require(close_nid_postfix(fresh) == 0); length = sizeof(value); Require(Fails(setsockopt_nid_postfix(datagram, TcpLevel, TcpNoDelay, &one, sizeof(one)), Invalid)); diff --git a/core/libs/tests/GuestSocketTimeouts.cpp b/core/libs/tests/GuestSocketTimeouts.cpp index 2ff28a2173..104d70406e 100644 --- a/core/libs/tests/GuestSocketTimeouts.cpp +++ b/core/libs/tests/GuestSocketTimeouts.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -11,40 +13,6 @@ struct Timeval { std::int64_t microseconds; }; -struct Iovec { - void* base; - std::uint64_t length; -}; - -struct Msghdr { - void* name; - std::uint32_t nameLength; - Iovec* iov; - int iovLength; - void* control; - std::uint32_t controlLength; - int flags; -}; - -extern "C" { -int APS5_VABI socket_nid_postfix(int, int, int); -int APS5_VABI bind_nid_postfix(int, const void*, std::uint32_t); -int APS5_VABI listen_nid_postfix(int, int); -int APS5_VABI getsockname_nid_postfix(int, void*, std::uint32_t*); -int APS5_VABI connect_nid_postfix(int, const void*, std::uint32_t); -int APS5_VABI accept_nid_postfix(int, void*, std::uint32_t*); -int APS5_VABI setsockopt_nid_postfix(int, int, int, const void*, std::uint32_t); -int APS5_VABI getsockopt_nid_postfix(int, int, int, void*, std::uint32_t*); -int APS5_VABI close_nid_postfix(int); -std::int64_t APS5_VABI send_nid_postfix(int, const void*, std::uint64_t, int); -std::int64_t APS5_VABI sendto_nid_postfix(int, const void*, std::uint64_t, int, const void*, std::uint32_t); -std::int64_t APS5_VABI recv_nid_postfix(int, void*, std::uint64_t, int); -std::int64_t APS5_VABI recvfrom_nid_postfix(int, void*, std::uint64_t, int, void*, std::uint32_t*); -std::int64_t APS5_VABI recvmsg_nid_postfix(int, Msghdr*, int); -std::int64_t APS5_VABI read_nid_postfix(int, void*, std::uint64_t); -int* APS5_VABI __error_nid_postfix(); -} - static void Check(bool value, int line) { if (!value) { std::fprintf(stderr, "socket timeout check failed at line %d, errno %d\n", line, *__error_nid_postfix()); @@ -115,8 +83,8 @@ int main() { Require(Fails(recv_nid_postfix(datagram, &byte, sizeof(byte), 0), WouldBlock)); Require(Clock::now() - started >= std::chrono::milliseconds(59)); Require(Fails(recvfrom_nid_postfix(datagram, &byte, sizeof(byte), 0, nullptr, nullptr), WouldBlock)); - Iovec part{&byte, sizeof(byte)}; - Msghdr message{nullptr, 0, &part, 1, nullptr, 0, 0}; + KernelIovec part{&byte, sizeof(byte)}; + GuestMsghdr message{nullptr, 0, &part, 1, nullptr, 0, 0}; Require(Fails(recvmsg_nid_postfix(datagram, &message, 0), WouldBlock)); Require(Fails(read_nid_postfix(datagram, &byte, sizeof(byte)), WouldBlock)); Require(Set(datagram, ReceiveTimeout, 60, 0) == 0); diff --git a/core/libs/tests/GuestSoftwareVersion.cpp b/core/libs/tests/GuestSoftwareVersion.cpp index d572e1722b..1343316e32 100644 --- a/core/libs/tests/GuestSoftwareVersion.cpp +++ b/core/libs/tests/GuestSoftwareVersion.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libkernel/KernelErrors.hpp" #include @@ -5,22 +7,10 @@ #include #include -struct SceKernelProsperoSystemSwVersion { - std::uint64_t size; - char versionString[0x1C]; - std::uint32_t version; -}; - static_assert(offsetof(SceKernelProsperoSystemSwVersion, versionString) == 0x08); static_assert(offsetof(SceKernelProsperoSystemSwVersion, version) == 0x24); static_assert(sizeof(SceKernelProsperoSystemSwVersion) == 0x28); -extern "C" { -int* APS5_VABI __error_nid_postfix(); -int APS5_VABI sceKernelGetProsperoSystemSwVersion_nid_postfix(SceKernelProsperoSystemSwVersion*); -int APS5_VABI sceKernelGetAllowedSdkVersionOnSystem_nid_postfix(std::uint32_t*); -} - static void Require(bool value) { if (!value) std::abort(); } static void CheckProsperoSystemSwVersion() { diff --git a/core/libs/tests/GuestSpSysCallWrapper.cpp b/core/libs/tests/GuestSpSysCallWrapper.cpp new file mode 100644 index 0000000000..1d22c59592 --- /dev/null +++ b/core/libs/tests/GuestSpSysCallWrapper.cpp @@ -0,0 +1,153 @@ +#include "SceTypes.hpp" +#include "prx/libSceSpSysCallWrapper/libSceSpSysCallWrapper.hpp" +#include "prx/libSceNet/libSceNet.hpp" +#include "prx/libkernel/libkernel.hpp" +#include +#include +#include + +namespace { + +void Require(bool value) { if (!value) std::abort(); } + +struct Shared { + PthreadMutex mutex = nullptr; + PthreadCond cond = nullptr; + bool ready = false; +}; + +void* APS5_VABI ExitWithArgument(void* arg) { + sceSpPthreadExit(arg); + return nullptr; +} + +void* APS5_VABI SignalReady(void* arg) { + auto* shared = static_cast(arg); + Require(sceSpPthreadMutexLock(&shared->mutex) == 0); + shared->ready = true; + Require(sceSpPthreadCondSignal(&shared->cond) == 0); + Require(sceSpPthreadMutexUnlock(&shared->mutex) == 0); + return nullptr; +} + +void Threads() { + PthreadAttr attr = nullptr; + Require(sceSpPthreadAttrInit(&attr) == 0); + Require(sceSpPthreadAttrSetstacksize(&attr, 0x10000) == 0); + Require(sceSpPthreadAttrSetinheritsched(&attr, 0) == scePthreadAttrSetinheritsched(&attr, 0)); + const KernelSchedParam param{700}; + Require(sceSpPthreadAttrSetschedparam(&attr, ¶m) == scePthreadAttrSetschedparam(&attr, ¶m)); + + Pthread thread = nullptr; + int marker = 0; + Require(sceSpPthreadCreate(&thread, &attr, ExitWithArgument, &marker, "sp_exit") == 0); + void* result = nullptr; + Require(sceSpPthreadJoin(thread, &result) == 0); + Require(result == &marker); + + Pthread detached = nullptr; + Require(sceSpPthreadCreate(&detached, &attr, ExitWithArgument, nullptr, "sp_detach") == 0); + Require(sceSpPthreadDetach(detached) == 0); + Require(sceSpPthreadAttrDestroy(&attr) == 0); + + PthreadMutexattr mutexAttr = nullptr; + Require(sceSpPthreadMutexattrInit(&mutexAttr) == 0); + Require(sceSpPthreadMutexattrSettype(&mutexAttr, 2) == 0); + Require(sceSpPthreadMutexattrSetprotocol(&mutexAttr, 0) == scePthreadMutexattrSetprotocol(&mutexAttr, 0)); + Require(sceSpPthreadSetprio(scePthreadSelf(), 700) == scePthreadSetprio(scePthreadSelf(), 700)); + PthreadCondattr condAttr = nullptr; + Require(sceSpPthreadCondattrInit(&condAttr) == 0); + + Shared shared; + Require(sceSpPthreadMutexInit(&shared.mutex, &mutexAttr, "sp_mutex") == 0); + Require(sceSpPthreadCondInit(&shared.cond, &condAttr, "sp_cond") == 0); + Require(sceSpPthreadMutexattrDestroy(&mutexAttr) == 0); + Require(sceSpPthreadCondattrDestroy(&condAttr) == 0); + + Require(sceSpPthreadMutexLock(&shared.mutex) == 0); + Pthread signaller = nullptr; + Require(sceSpPthreadCreate(&signaller, nullptr, SignalReady, &shared, "sp_signal") == 0); + while (!shared.ready) Require(sceSpPthreadCondWait(&shared.cond, &shared.mutex) == 0); + Require(sceSpPthreadMutexUnlock(&shared.mutex) == 0); + Require(sceSpPthreadJoin(signaller, nullptr) == 0); + Require(sceSpPthreadCondDestroy(&shared.cond) == 0); + Require(sceSpPthreadMutexDestroy(&shared.mutex) == 0); +} + +void Time() { + KernelTimeval now{}; + Require(sceSpKernelGettimeofday(&now) == 0); + Require(now.tv_sec > 0 && now.tv_usec >= 0 && now.tv_usec < 1000000); + const KernelTimespec delay{0, 1000000}; + Require(sceSpKernelNanosleep(&delay, nullptr) == 0); +} + +template +void SameError(TWrapped wrapped, TDirect direct) { + const auto wrappedResult = wrapped(); + const int wrappedErrno = *sceNetErrnoLoc(); + const auto directResult = direct(); + Require(wrappedResult == directResult); + Require(wrappedErrno == *sceNetErrnoLoc()); +} + +void Net() { + Require(sceSpNetErrnoLoc() == sceNetErrnoLoc()); + + const int pool = sceSpNetPoolCreate("sp_pool", 0x4000, 0); + Require(pool >= 0); + const int resolver = sceSpNetResolverCreate("sp_resolver", pool, 0); + Require(resolver >= 0); + int status = 0; + Require(sceSpNetResolverGetError(resolver, &status) == sceNetResolverGetError(resolver, &status)); + Require(sceSpNetResolverDestroy(resolver) == 0); + Require(sceSpNetPoolDestroy(pool) == 0); + + const int epoll = sceSpNetEpollCreate("sp_epoll", 0); + Require(epoll >= 0); + Require(sceSpNetEpollDestroy(epoll) == 0); + + const int socket = sceSpNetSocket("sp_socket", 2, 2, 0); + Require(socket >= 0); + const int enable = 1; + Require(sceSpNetSetsockopt(socket, 0xffff, 0x4, &enable, sizeof(enable)) == sceNetSetsockopt(socket, 0xffff, 0x4, &enable, sizeof(enable))); + Require(sceSpNetSocketClose(socket) == 0); + + char byte = 0; + const std::uint8_t address[16]{16, 2}; + SameError([&] { return sceSpNetSend(-1, &byte, 1, 0); }, [&] { return sceNetSend(-1, &byte, 1, 0); }); + SameError([&] { return sceSpNetRecv(-1, &byte, 1, 0); }, [&] { return sceNetRecv(-1, &byte, 1, 0); }); + SameError([&] { return sceSpNetConnect(-1, address, sizeof(address)); }, [&] { return sceNetConnect(-1, address, sizeof(address)); }); + SameError([&] { return sceSpNetEpollControl(-1, 1, 0, nullptr); }, [&] { return sceNetEpollControl(-1, 1, 0, nullptr); }); + SameError([&] { return sceSpNetEpollWait(-1, nullptr, 0, 0); }, [&] { return sceNetEpollWait(-1, nullptr, 0, 0); }); + SameError([&] { return sceSpNetEpollAbort(-1, 0); }, [&] { return sceNetEpollAbort(-1, 0); }); + SameError([&] { return sceSpNetResolverAbort(-1, 0); }, [&] { return sceNetResolverAbort(-1, 0); }); + std::uint32_t resolved = 0; + SameError([&] { return sceSpNetResolverStartNtoa(-1, "localhost", &resolved, 0, 0, 0); }, [&] { return sceNetResolverStartNtoa(-1, "localhost", &resolved, 0, 0, 0); }); +} + +void Posix() { + Require(sceSpGetPid() > 0); + Require(sceSpGetPid() == getpid_nid_postfix()); + + const std::int64_t zero[2]{0, 0}; + Require(sceSpSelect(0, nullptr, nullptr, nullptr, zero) == 0); + const std::int64_t invalid[2]{0, 1000000}; + *__error_nid_postfix() = 0; + Require(sceSpSelect(0, nullptr, nullptr, nullptr, invalid) == -1); + const int wrappedErrno = *__error_nid_postfix(); + *__error_nid_postfix() = 0; + Require(select_nid_postfix(0, nullptr, nullptr, nullptr, invalid) == -1); + Require(wrappedErrno == 22 && *__error_nid_postfix() == 22); + *__error_nid_postfix() = 0; + Require(sceSpSelect(-1, nullptr, nullptr, nullptr, nullptr) == -1 && *__error_nid_postfix() == 22); +} + +} + +int main() { + Threads(); + Time(); + Net(); + Posix(); +} diff --git a/core/libs/tests/GuestSsl.cpp b/core/libs/tests/GuestSsl.cpp index 4aa00482b6..f4d57bc7a2 100644 --- a/core/libs/tests/GuestSsl.cpp +++ b/core/libs/tests/GuestSsl.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceSsl/include/Ssl.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "ProcessParametersFixture.hpp" #include @@ -8,37 +9,6 @@ #include #include -extern "C" { -int APS5_VABI sceSslInit_nid_postfix(std::size_t); -int APS5_VABI sceSslTerm_nid_postfix(int); -int APS5_VABI sceSslGetCaCerts(int, void*); -int APS5_VABI sceSslFreeCaCerts(int, void*); -int APS5_VABI sceSslGetCaList(int, void*); -int APS5_VABI sceSslFreeCaList(int, void*); -int APS5_VABI sceSslUnloadCert(int); -int APS5_VABI sceSslCreateConnection(int, int, const char*); -int APS5_VABI sceSslDeleteConnection(int); -int APS5_VABI sceSslSetVerifyCallback(int, int (APS5_VABI *)(int, unsigned int, void**, int, void*), void*); -int APS5_VABI sceSslConnect(int); -int APS5_VABI sceSslRead(int, void*, std::size_t, int); -int APS5_VABI sceSslWrite(int, void*, std::size_t, int); -int APS5_VABI sceSslClose(int); -int APS5_VABI sceSslEnableVerifyOption(int, std::uint32_t); -int APS5_VABI sceSslDisableVerifyOption(int, std::uint32_t); -int APS5_VABI sceSslSetMinSslVersion(int, int); -int APS5_VABI sceSslSetAlpn(int, const char*); -const char* APS5_VABI sceSslGetAlpnSelected(int); -} - -struct SslMemoryPoolStats { - std::size_t pool_size; - std::size_t max_inuse_size; - std::size_t current_inuse_size; - std::int32_t reserved; -}; - -extern "C" int APS5_VABI sceSslGetMemoryPoolStats(int, SslMemoryPoolStats*); - static void Require(bool value) { if (!value) std::abort(); } template @@ -53,17 +23,6 @@ static bool Throws(TCall call) { static int APS5_VABI VerifyCallback(int, unsigned int, void**, int, void*) { return 0; } -struct SslCaCerts { - void* certs; - std::size_t num; - void* pool; -}; - -struct SslCaList { - void** certs; - int num; -}; - int main() { static std::array parameters{}; const std::uint64_t processSize = parameters.size(); @@ -77,17 +36,18 @@ int main() { int marker = 0; const int context = sceSslInit_nid_postfix(0x10000); Require(context > 0); - SslMemoryPoolStats stats{1, 1, 1, 1}; + SceSsl::MemoryPoolStats stats{1, 1, 1, 1}; Require(sceSslGetMemoryPoolStats(context, &stats) == 0); - Require(stats.pool_size == 0x10000 && stats.max_inuse_size == 0 && stats.current_inuse_size == 0 && stats.reserved == 0); + Require(stats.poolSize == 0x10000 && stats.maxInuseSize == 0 && stats.currentInuseSize == 0 && stats.reserved == 0); Require(sceSslGetCaCerts(context, nullptr) == invalidValue); Require(sceSslFreeCaCerts(context, nullptr) == invalidArg); - SslCaCerts certs{&marker, 3, &marker}; + SceSsl::Data certificateMarker{}; + SceSsl::CaCerts certs{&certificateMarker, 3, &marker}; Require(sceSslGetCaCerts(context, &certs) == notFound); Require(certs.certs == nullptr && certs.num == 0 && certs.pool == nullptr); - certs = {&marker, 3, &marker}; + certs = {&certificateMarker, 3, &marker}; Require(sceSslFreeCaCerts(context, &certs) == 0); Require(certs.certs == nullptr && certs.num == 0 && certs.pool == nullptr); @@ -95,13 +55,13 @@ int main() { Require(sceSslFreeCaList(context, nullptr) == invalidArg); void* handle = ▮ - SslCaList list{&handle, 3}; + SceSsl::CaList list{&handle, 3}; Require(sceSslGetCaList(context, &list) == notFound); Require(list.certs == nullptr && list.num == 0); Require(sceSslFreeCaList(context, &list) == 0); Require(list.certs == nullptr && list.num == 0); - SslCaList foreign{&handle, 1}; + SceSsl::CaList foreign{&handle, 1}; Require(Throws([&] { sceSslFreeCaList(context, &foreign); })); foreign = {nullptr, 1}; Require(Throws([&] { sceSslFreeCaList(context, &foreign); })); @@ -187,9 +147,9 @@ int main() { Require(sceSslGetCaList(context, &list) == invalidId); Require(list.certs == &handle && list.num == 3); Require(sceSslGetCaCerts(context, nullptr) == invalidId); - certs = {&marker, 3, &marker}; + certs = {&certificateMarker, 3, &marker}; Require(sceSslGetCaCerts(context, &certs) == invalidId); - Require(certs.certs == &marker && certs.num == 3 && certs.pool == &marker); + Require(certs.certs == &certificateMarker && certs.num == 3 && certs.pool == &marker); Require(Throws([&] { sceSslFreeCaList(context, &list); })); for (const std::uint32_t sdkVersion : {0u, 0x074fffffu, 0x07500000u, 0x09000000u}) { std::memcpy(parameters.data() + 16, &sdkVersion, sizeof(sdkVersion)); diff --git a/core/libs/tests/GuestSslLoad.cpp b/core/libs/tests/GuestSslLoad.cpp index b59ad7c6c5..92507f0183 100644 --- a/core/libs/tests/GuestSslLoad.cpp +++ b/core/libs/tests/GuestSslLoad.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceSsl/include/Ssl.hpp" #include "prx/libSceSsl/SslTypes.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "SslCertificateFixture.hpp" @@ -10,32 +11,6 @@ #include #include -extern "C" { -int APS5_VABI sceSslInit_nid_postfix(std::uint64_t); -int APS5_VABI sceSslTerm_nid_postfix(int); -int APS5_VABI sceSslGetMemoryPoolStats(int, SceSsl::MemoryPoolStats*); -int APS5_VABI sceSslLoadCert(int, int, SceSsl::Data**, SceSsl::Data*, SceSsl::Data*); -int APS5_VABI sceSslUnloadCert(int); -int APS5_VABI sceSslGetCaList(int, SceSsl::CaList*); -int APS5_VABI sceSslFreeCaList(int, SceSsl::CaList*); -int APS5_VABI sceSslGetCaCerts(int, SceSsl::CaCerts*); -int APS5_VABI sceSslFreeCaCerts(int, SceSsl::CaCerts*); -int APS5_VABI sceSslCreateConnection(int, int, const char*); -int APS5_VABI sceSslDeleteConnection(int); -int APS5_VABI sceSslSetVerifyCallback(int, int (APS5_VABI *)(int, unsigned int, void**, int, void*), void*); -int APS5_VABI sceSslGetSerialNumber(int, void*, unsigned char*, std::size_t*); -void* APS5_VABI sceSslGetSubjectName(int, void*); -void* APS5_VABI sceSslGetIssuerName(int, void*); -int APS5_VABI sceSslGetNameEntryCount(int, void*); -int APS5_VABI sceSslGetNameEntryInfo(int, void*, int, char*, std::size_t, char*, std::size_t, std::size_t*); -int APS5_VABI sceSslFreeSslCertName(int, void*); -int APS5_VABI sceSslClose(int); -int APS5_VABI sceSslGetNotBefore(int, void*, SceSsl::RtcTick*); -int APS5_VABI sceSslGetNotAfter(int, void*, SceSsl::RtcTick*); -int APS5_VABI sceSslGetFingerprint(int, void*, int, unsigned char*); -int APS5_VABI sceSslGetPem(int, void*, char*, std::size_t*); -} - namespace { constexpr int NotFound = static_cast(0x8095F004); diff --git a/core/libs/tests/GuestSslPs5Readers.cpp b/core/libs/tests/GuestSslPs5Readers.cpp index 3075a601e9..60aeebcbde 100644 --- a/core/libs/tests/GuestSslPs5Readers.cpp +++ b/core/libs/tests/GuestSslPs5Readers.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceSsl/include/Ssl.hpp" #include "prx/libSceSsl/SslTypes.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "SslCertificateFixture.hpp" @@ -11,22 +12,6 @@ #include #include -extern "C" { -int APS5_VABI sceSslInit_nid_postfix(std::uint64_t); -int APS5_VABI sceSslTerm_nid_postfix(int); -int APS5_VABI sceSslLoadCert(int, int, SceSsl::Data**, SceSsl::Data*, SceSsl::Data*); -int APS5_VABI sceSslUnloadCert(int); -int APS5_VABI sceSslGetCaList(int, SceSsl::CaList*); -int APS5_VABI sceSslFreeCaList(int, SceSsl::CaList*); -int APS5_VABI sceSslGetSerialNumber(int, void*, unsigned char*, std::size_t*); -void* APS5_VABI sceSslGetSubjectName(int, void*); -void* APS5_VABI sceSslGetIssuerName(int, void*); -int APS5_VABI sceSslGetNameEntryCount(int, void*); -int APS5_VABI sceSslGetNameEntryInfo(int, void*, int, char*, std::size_t, char*, std::size_t, std::size_t*); -int APS5_VABI sceSslFreeSslCertName(int, void*); -int APS5_VABI sceSslGetPem(int, void*, char*, std::size_t*); -} - namespace { void Check(bool value, const char* message) { diff --git a/core/libs/tests/GuestSslTransport.cpp b/core/libs/tests/GuestSslTransport.cpp index 4d956c68be..94aafaf622 100644 --- a/core/libs/tests/GuestSslTransport.cpp +++ b/core/libs/tests/GuestSslTransport.cpp @@ -1,3 +1,6 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libSceSsl/include/Ssl.hpp" +#include "prx/libSceNet/include/Net.hpp" #ifdef _WIN32 #include #else @@ -28,40 +31,6 @@ #include #include -extern "C" { -int APS5_VABI sceSslInit_nid_postfix(std::uint64_t); -int APS5_VABI sceSslTerm_nid_postfix(int); -int APS5_VABI sceSslGetMemoryPoolStats(int, SceSsl::MemoryPoolStats*); -int APS5_VABI sceSslLoadCert(int, int, SceSsl::Data**, SceSsl::Data*, SceSsl::Data*); -int APS5_VABI sceSslCreateConnection(int, int, const char*); -int APS5_VABI sceSslDeleteConnection(int); -int APS5_VABI sceSslSetVerifyCallback(int, int (APS5_VABI *)(int, unsigned int, void**, int, void*), void*); -int APS5_VABI sceSslConnect(int); -int APS5_VABI sceSslRead(int, void*, std::size_t, int); -int APS5_VABI sceSslWrite(int, void*, std::size_t, int); -int APS5_VABI sceSslRecv(int, void*, std::size_t); -int APS5_VABI sceSslSend(int, void*, std::size_t); -int APS5_VABI sceSslClose(int); -int APS5_VABI sceSslEnableVerifyOption(int, std::uint32_t); -int APS5_VABI sceSslDisableVerifyOption(int, std::uint32_t); -int APS5_VABI sceSslSetMinSslVersion(int, int); -int APS5_VABI sceSslSetAlpn(int, const char*); -const char* APS5_VABI sceSslGetAlpnSelected(int); -void* APS5_VABI sceSslGetSubjectName(int, void*); -int APS5_VABI sceSslGetNameEntryCount(int, void*); -int APS5_VABI sceSslGetNameEntryInfo(int, void*, int, char*, std::size_t, char*, std::size_t, std::size_t*); -int APS5_VABI sceSslFreeSslCertName(int, void*); -int APS5_VABI socket_nid_postfix(int, int, int); -int APS5_VABI connect_nid_postfix(int, const void*, std::uint32_t); -int APS5_VABI setsockopt_nid_postfix(int, int, int, const void*, std::uint32_t); -int APS5_VABI close_nid_postfix(int); -int APS5_VABI sceNetInit_nid_postfix(); -int APS5_VABI sceNetSocket(const char*, int, int, int); -int APS5_VABI sceNetConnect(int, const void*, std::uint32_t); -int APS5_VABI sceNetSetsockopt(int, int, int, const void*, std::uint32_t); -int APS5_VABI sceNetSocketClose(int); -} - namespace { constexpr int ParallelConnections = 4; @@ -314,6 +283,7 @@ struct Sockets { int Set(int descriptor, int option, const void* value, std::uint32_t length) const { return net ? sceNetSetsockopt(descriptor, GuestSocketLevel, option, value, length) : setsockopt_nid_postfix(descriptor, GuestSocketLevel, option, value, length); + } int Close(int descriptor) const { return net ? sceNetSocketClose(descriptor) : close_nid_postfix(descriptor); } diff --git a/core/libs/tests/GuestStandardStreams.cpp b/core/libs/tests/GuestStandardStreams.cpp index 70fd7600b2..f2d65cf2a4 100644 --- a/core/libs/tests/GuestStandardStreams.cpp +++ b/core/libs/tests/GuestStandardStreams.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/FileStream.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -22,64 +23,12 @@ #include #endif extern "C" { -FileStream* APS5_VABI fopen_nid_postfix(const char*, const char*); -void APS5_VABI clearerr_unlocked_nid_postfix(FileStream*); -int APS5_VABI fileno_unlocked_nid_postfix(FileStream*); -char* APS5_VABI fgetln_nid_postfix(FileStream*, std::size_t*); -std::size_t APS5_VABI fread_nid_postfix(void*, std::size_t, std::size_t, FileStream*); -std::size_t APS5_VABI fwrite_nid_postfix(const void*, std::size_t, std::size_t, FileStream*); -FileStream* APS5_VABI freopen_nid_postfix(const char*, const char*, FileStream*); -int APS5_VABI fseeko_nid_postfix(FileStream*, std::int64_t, int); -std::int64_t APS5_VABI ftello_nid_postfix(FileStream*); -int APS5_VABI fseek_nid_postfix(FileStream*, std::int64_t, int); -std::int64_t APS5_VABI ftell_nid_postfix(FileStream*); -int* APS5_VABI __error_nid_postfix(); + extern FileStream* __stdinp_nid_postfix; extern FileStream* __stdoutp_nid_postfix; extern FileStream* __stderrp_nid_postfix; extern int __isthreaded_nid_postfix; -int APS5_VABI fprintf_nid_postfix(FileStream*, const char*, ...); -int APS5_VABI fputs_nid_postfix(const char*, FileStream*); -int APS5_VABI printf_nid_postfix(const char*, ...); -int APS5_VABI vprintf_nid_postfix(const char*, void*); -int APS5_VABI puts_nid_postfix(const char*); -int APS5_VABI vfprintf_nid_postfix(FileStream*, const char*, void*); -int APS5_VABI vsprintf_nid_postfix(char*, const char*, void*); -int APS5_VABI fgetc_nid_postfix(FileStream*); -int APS5_VABI fputc_nid_postfix(int, FileStream*); -int APS5_VABI getc_unlocked_nid_postfix(FileStream*); -int APS5_VABI putc_unlocked_nid_postfix(int, FileStream*); -int APS5_VABI fputwc_nid_postfix(char16_t, FileStream*); -int APS5_VABI fputws_nid_postfix(const char16_t*, FileStream*); -std::int32_t APS5_VABI getwc_nid_postfix(FileStream*); -std::int32_t APS5_VABI getwchar_nid_postfix(); -int APS5_VABI putwc_nid_postfix(char16_t, FileStream*); -int APS5_VABI putwchar_nid_postfix(char16_t); -char16_t* APS5_VABI fgetws_nid_postfix(char16_t*, int, FileStream*); -int APS5_VABI getchar_unlocked_nid_postfix(); -int APS5_VABI putchar_unlocked_nid_postfix(int); -int APS5_VABI fscanf_nid_postfix(FileStream*, const char*, ...); -int APS5_VABI __srget_nid_postfix(FileStream*); -int APS5_VABI __swbuf_nid_postfix(int, FileStream*); -int APS5_VABI ungetc_nid_postfix(int, FileStream*); -char* APS5_VABI fgets_nid_postfix(char*, int, FileStream*); -int APS5_VABI feof_nid_postfix(FileStream*); -int APS5_VABI ferror_nid_postfix(FileStream*); -int APS5_VABI feof_unlocked_nid_postfix(FileStream*); -int APS5_VABI ferror_unlocked_nid_postfix(FileStream*); -int APS5_VABI fileno_nid_postfix(FileStream*); -void APS5_VABI clearerr_nid_postfix(FileStream*); -void APS5_VABI rewind_nid_postfix(FileStream*); -int APS5_VABI setvbuf_nid_postfix(FileStream*, char*, int, std::size_t); -void APS5_VABI setbuf_nid_postfix(FileStream*, char*); -FileStream* APS5_VABI fdopen_nid_postfix(int, const char*); -int APS5_VABI fclose_nid_postfix(FileStream*); -int APS5_VABI fflush_nid_postfix(FileStream*); -int APS5_VABI _Getmbcurmax_nid_postfix(); -int APS5_VABI ___mb_cur_max_nid_postfix(); -void APS5_VABI flockfile_nid_postfix(FileStream*); -void APS5_VABI funlockfile_nid_postfix(FileStream*); -int APS5_VABI ftrylockfile_nid_postfix(FileStream*); + } static void Require(bool value) { if (!value) std::abort(); } static int APS5_VABI WriteFormatted(FileStream* stream, const char* format, ...) { @@ -90,7 +39,7 @@ static int APS5_VABI WriteFormatted(FileStream* stream, const char* format, ...) std::va_list args; va_start(args, format); #endif - const int result = vfprintf_nid_postfix(stream, format, args); + const int result = vfprintf_nid_postfix(stream, format, reinterpret_cast(args)); #ifdef _WIN32 __builtin_sysv_va_end(args); #else @@ -106,7 +55,7 @@ static int APS5_VABI PrintStandard(const char* format, ...) { std::va_list args; va_start(args, format); #endif - const int result = vprintf_nid_postfix(format, args); + const int result = vprintf_nid_postfix(format, reinterpret_cast(args)); #ifdef _WIN32 __builtin_sysv_va_end(args); #else @@ -122,7 +71,7 @@ static int APS5_VABI FormatString(char* buffer, const char* format, ...) { std::va_list args; va_start(args, format); #endif - const int result = vsprintf_nid_postfix(buffer, format, args); + const int result = vsprintf_nid_postfix(buffer, format, reinterpret_cast(args)); #ifdef _WIN32 __builtin_sysv_va_end(args); #else @@ -163,6 +112,7 @@ static void CheckUnlockedStreams() { stream.SetError(); Require(putc_unlocked_nid_postfix('R', &stream) == 'R' && (guest.flags & 0x40)); clearerr_nid_postfix(&stream); + Require(!(guest.flags & 0x40)); stream.Close(); @@ -172,6 +122,7 @@ static void CheckUnlockedStreams() { Require(putc_unlocked_nid_postfix('X', &readOnly) == EOF && (readOnly.GuestState().flags & 0x40)); Require(ferror_unlocked_nid_postfix(&readOnly) == 1 && feof_unlocked_nid_postfix(&readOnly) == 0); clearerr_unlocked_nid_postfix(&readOnly); + Require(ferror_unlocked_nid_postfix(&readOnly) == 0); readOnly.Close(); Require(CheckFileBytes(filename, "A", "rb", false)); @@ -187,6 +138,7 @@ static void CheckUnlockedQueries() { stream.SetError(); Require(feof_unlocked_nid_postfix(&stream) == 1 && ferror_unlocked_nid_postfix(&stream) == 1); clearerr_unlocked_nid_postfix(&stream); + Require(feof_unlocked_nid_postfix(&stream) == 0 && ferror_unlocked_nid_postfix(&stream) == 0); Require(std::fgetc(stream.GetHandle()) == EOF && std::ungetc('Q', stream.GetHandle()) == 'Q'); Require(feof_unlocked_nid_postfix(&stream) == 0 && ferror_unlocked_nid_postfix(&stream) == 0); @@ -196,6 +148,7 @@ static void CheckUnlockedQueries() { Require(fgetc_nid_postfix(&stream) == 0x7f && feof_nid_postfix(&stream) == 0); Require(fgetc_nid_postfix(&stream) == -1 && feof_nid_postfix(&stream) != 0); clearerr_unlocked_nid_postfix(&stream); + Require(feof_nid_postfix(&stream) == 0 && ferror_nid_postfix(&stream) == 0); Require(fileno_unlocked_nid_postfix(&stream) == fileno_nid_postfix(&stream) && fileno_unlocked_nid_postfix(&stream) >= 0); Require(fileno_unlocked_nid_postfix(nullptr) == -1); @@ -220,6 +173,7 @@ static void CheckTryLock() { Require(ftrylockfile_nid_postfix(&stream) == 0); Require(tryFromOtherThread() == -1); funlockfile_nid_postfix(&stream); + Require(tryFromOtherThread() == -1); std::atomic written = false; std::thread writer([&] { @@ -229,14 +183,17 @@ static void CheckTryLock() { std::this_thread::sleep_for(std::chrono::milliseconds(50)); Require(!written && fputc_nid_postfix('A', &stream) == 'A'); funlockfile_nid_postfix(&stream); + writer.join(); Require(written && tryFromOtherThread() == 0); std::atomic held = false, release = false; std::thread owner([&] { flockfile_nid_postfix(&stream); + held = true; while (!release) std::this_thread::yield(); funlockfile_nid_postfix(&stream); + }); while (!held) std::this_thread::yield(); const int contended = ftrylockfile_nid_postfix(&stream); @@ -244,6 +201,7 @@ static void CheckTryLock() { owner.join(); Require(contended == -1 && ftrylockfile_nid_postfix(&stream) == 0); funlockfile_nid_postfix(&stream); + Require(tryFromOtherThread() == 0); Require(fseeko_nid_postfix(&stream, 0, SEEK_SET) == 0); Require(fgetc_nid_postfix(&stream) == 'A' && fgetc_nid_postfix(&stream) == 'B'); @@ -264,9 +222,11 @@ static void CheckUnlockedStreamLock(bool write, int (APS5_VABI *query)(FileStrea int result = EOF; std::thread owner([&] { flockfile_nid_postfix(&stream); + held = true; while (!release) std::this_thread::yield(); funlockfile_nid_postfix(&stream); + }); const auto deadline = std::chrono::steady_clock::now() + std::chrono::seconds(1); while (!held && std::chrono::steady_clock::now() < deadline) std::this_thread::yield(); @@ -302,6 +262,7 @@ static void CheckFgetsSize() { FileStream stream(std::tmpfile()); Require(fwrite_nid_postfix("line\n", 1, 5, &stream) == 5); rewind_nid_postfix(&stream); + for (const int size : {0, -1, std::numeric_limits::min()}) { char buffer[8]; std::memset(buffer, '!', sizeof(buffer)); @@ -311,6 +272,7 @@ static void CheckFgetsSize() { Require(buffer[0] == '!' && ftello_nid_postfix(&stream) == 0); Require(ferror_nid_postfix(&stream) != 0); clearerr_nid_postfix(&stream); + Require(ferror_nid_postfix(&stream) == 0); } char line[8]{}; @@ -324,14 +286,17 @@ static void CheckRewind() { Require(fwrite_nid_postfix("ab", 1, 2, &stream) == 2); *__error_nid_postfix() = 7; rewind_nid_postfix(&stream); + Require(*__error_nid_postfix() == 7 && ftello_nid_postfix(&stream) == 0); Require(fgetc_nid_postfix(&stream) == 'a' && ungetc_nid_postfix('z', &stream) == 'z'); rewind_nid_postfix(&stream); + Require(fgetc_nid_postfix(&stream) == 'a' && fgetc_nid_postfix(&stream) == 'b' && fgetc_nid_postfix(&stream) == EOF); Require(feof_nid_postfix(&stream) != 0); stream.SetError(); Require(ferror_nid_postfix(&stream) != 0); rewind_nid_postfix(&stream); + Require(feof_nid_postfix(&stream) == 0 && ferror_nid_postfix(&stream) == 0 && fgetc_nid_postfix(&stream) == 'a'); stream.Close(); int pipeEnds[2]; @@ -354,6 +319,7 @@ static void CheckRewind() { Require(fgetc_nid_postfix(&pipe) == 'q' && fgetc_nid_postfix(&pipe) == EOF && feof_nid_postfix(&pipe) != 0); *__error_nid_postfix() = 0; rewind_nid_postfix(&pipe); + Require(*__error_nid_postfix() == 29 && feof_nid_postfix(&pipe) == 0 && ferror_nid_postfix(&pipe) == 0); pipe.Close(); } @@ -573,6 +539,16 @@ static void CheckClosedStreamWrites() { Require(fseeko_nid_postfix(&stream, 0, SEEK_SET) == -1 && *__error_nid_postfix() == 9); Require(ftello_nid_postfix(&stream) == -1 && *__error_nid_postfix() == 9); Require(fileno_nid_postfix(&stream) == -1 && *__error_nid_postfix() == 9); + *__error_nid_postfix() = 0; + Require(fputwc_nid_postfix(u't', &stream) == -1 && *__error_nid_postfix() == 9); + *__error_nid_postfix() = 0; + Require(putwc_nid_postfix(u't', &stream) == -1 && *__error_nid_postfix() == 9); + *__error_nid_postfix() = 0; + Require(fputws_nid_postfix(u"text", &stream) == -1 && *__error_nid_postfix() == 9); + *__error_nid_postfix() = 0; + Require(ungetwc_nid_postfix('t', &stream) == -1 && *__error_nid_postfix() == 9); + *__error_nid_postfix() = 0; + Require(ungetwc_nid_postfix(0x100, &stream) == -1 && *__error_nid_postfix() == 9); Require(ferror_nid_postfix(&stream) == 0 && feof_nid_postfix(&stream) == 0); Require(fclose_nid_postfix(&stream) == -1 && *__error_nid_postfix() == 9); } @@ -583,6 +559,10 @@ static int CheckClosedStandardOutput() { Require(puts_nid_postfix("text") == -1 && *__error_nid_postfix() == 9); Require(PrintStandard("%d", 1) == -1 && *__error_nid_postfix() == 9); Require(fputs_nid_postfix("text", __stdoutp_nid_postfix) == -1 && *__error_nid_postfix() == 9); + *__error_nid_postfix() = 0; + Require(wprintf_nid_postfix(u"%d", 1) == -1 && *__error_nid_postfix() == 9); + *__error_nid_postfix() = 0; + Require(putwchar_nid_postfix(u't') == -1 && *__error_nid_postfix() == 9); Require(std::fputs("host output\n", stdout) >= 0 && std::fflush(stdout) == 0 && !std::ferror(stdout)); Require(freopen_nid_postfix("missing-closed-stream-dir/err.log", "a", __stderrp_nid_postfix) == nullptr); Require(std::fputs("host error\n", stderr) >= 0 && std::fflush(stderr) == 0 && !std::ferror(stderr)); @@ -642,6 +622,7 @@ int main(int argc, char** argv) { auto* wrapped = fdopen_nid_postfix(descriptor, "r+b"); Require(wrapped != nullptr && fileno_nid_postfix(wrapped) == descriptor); setbuf_nid_postfix(wrapped, nullptr); + Require(fseek_nid_postfix(wrapped, 0, SEEK_SET) == 0); char contents[32]{}; Require(fgets_nid_postfix(contents, sizeof(contents), wrapped) == contents && std::strcmp(contents, "retained") == 0); @@ -714,6 +695,7 @@ int main(int argc, char** argv) { Require(fgetc_nid_postfix(&stream) == EOF); Require(feof_nid_postfix(&stream) && (guest.flags & 0x20)); clearerr_nid_postfix(&stream); + Require(!feof_nid_postfix(&stream) && !(guest.flags & 0x20)); stream.Close(); Require(guest.flags == 0 && guest.descriptor == -1); @@ -746,6 +728,7 @@ int main(int argc, char** argv) { Require(fgetws_nid_postfix(wideBuf, 16, &wideIo) == nullptr); Require(feof_nid_postfix(&wideIo)); clearerr_nid_postfix(&wideIo); + *__error_nid_postfix() = 0; Require(fgetws_nid_postfix(wideBuf, 0, &wideIo) == nullptr && *__error_nid_postfix() == 0); Require(fgetws_nid_postfix(wideBuf, -1, &wideIo) == nullptr && *__error_nid_postfix() == 0); @@ -753,6 +736,7 @@ int main(int argc, char** argv) { Require(fgetws_nid_postfix(nullptr, 16, &wideIo) == nullptr && *__error_nid_postfix() == 22); Require(ferror_nid_postfix(&wideIo)); clearerr_nid_postfix(&wideIo); + Require(fgetws_nid_postfix(wideBuf, 16, nullptr) == nullptr && *__error_nid_postfix() == 22); wideBuf[0] = u'X'; wideBuf[1] = u'Y'; @@ -894,6 +878,7 @@ int main(int argc, char** argv) { FileStream locked(std::tmpfile()); flockfile_nid_postfix(&locked); flockfile_nid_postfix(&locked); + std::atomic lockedWrite = false; std::thread writer([&] { Require(fputc_nid_postfix('B', &locked) == 'B'); @@ -902,9 +887,11 @@ int main(int argc, char** argv) { std::this_thread::sleep_for(std::chrono::milliseconds(50)); Require(!lockedWrite && fputc_nid_postfix('A', &locked) == 'A'); funlockfile_nid_postfix(&locked); + std::this_thread::sleep_for(std::chrono::milliseconds(50)); Require(!lockedWrite); funlockfile_nid_postfix(&locked); + writer.join(); Require(lockedWrite && fseeko_nid_postfix(&locked, 0, SEEK_SET) == 0); Require(fgetc_nid_postfix(&locked) == 'A' && fgetc_nid_postfix(&locked) == 'B'); diff --git a/core/libs/tests/GuestStatvfs.cpp b/core/libs/tests/GuestStatvfs.cpp index 2019801dc0..ba87a280b0 100644 --- a/core/libs/tests/GuestStatvfs.cpp +++ b/core/libs/tests/GuestStatvfs.cpp @@ -1,3 +1,5 @@ +#include "prx/libc/include/Api.hpp" +#include "prx/libSceLibcInternal/include/Api.hpp" #include "prx/libc/include/General.hpp" #include #include @@ -18,9 +20,6 @@ #include #endif -extern "C" int APS5_VABI statvfs_nid_postfix(const char*, void*); -extern "C" int* APS5_VABI __error_nid_postfix(); - static void Check(bool value, int line) { if (!value) { std::fprintf(stderr, "statvfs check failed at line %d\n", line); @@ -33,7 +32,7 @@ static void RequireVolume(const char* path, const std::filesystem::path& native) std::array output; output.fill(0xA5A5A5A5A5A5A5A5ull); *__error_nid_postfix() = 12345; - Require(statvfs_nid_postfix(path, output.data() + 1) == 0); + Require(statvfs_nid_postfix(path, reinterpret_cast(output.data() + 1)) == 0); Require(*__error_nid_postfix() == 12345); Require(output.front() == 0xA5A5A5A5A5A5A5A5ull && output.back() == output.front()); const auto* fields = output.data() + 1; @@ -49,7 +48,7 @@ static void RequireError(const char* path, int error) { output.fill(0x5A5A5A5A5A5A5A5Aull); const auto saved = output; *__error_nid_postfix() = 0; - const int result = statvfs_nid_postfix(path, output.data()); + const int result = statvfs_nid_postfix(path, reinterpret_cast(output.data())); if (result != -1) std::fprintf(stderr, "path %s: expected failure, got %d\n", path ? path : "(null)", result); Require(result == -1); diff --git a/core/libs/tests/GuestStdExecuteOnce.cpp b/core/libs/tests/GuestStdExecuteOnce.cpp index d189ddcd71..9bead6d3e1 100644 --- a/core/libs/tests/GuestStdExecuteOnce.cpp +++ b/core/libs/tests/GuestStdExecuteOnce.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -5,7 +6,7 @@ #include using Callback = int (APS5_VABI *)(void*, void*, void**); -extern "C" int APS5_VABI std_execute_once_nid_postfix(int*, Callback, void*); + static void Require(bool value) { if (!value) std::abort(); } static std::atomic calls{0}, arrived{0}; @@ -53,6 +54,7 @@ int main() { try { std_execute_once_nid_postfix(&throwing, Throw, nullptr); + std::abort(); } catch (int value) { Require(value == 7 && throwing == 0); diff --git a/core/libs/tests/GuestStdThreadHardwareConcurrency.cpp b/core/libs/tests/GuestStdThreadHardwareConcurrency.cpp index 6b53d172cf..a0e900ce98 100644 --- a/core/libs/tests/GuestStdThreadHardwareConcurrency.cpp +++ b/core/libs/tests/GuestStdThreadHardwareConcurrency.cpp @@ -1,9 +1,8 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include -extern "C" unsigned APS5_VABI _ZNSt6thread20hardware_concurrencyEv_nid_postfix(); - int main() { const unsigned result = _ZNSt6thread20hardware_concurrencyEv_nid_postfix(); if (result != std::thread::hardware_concurrency()) { diff --git a/core/libs/tests/GuestStdioVariadic.cpp b/core/libs/tests/GuestStdioVariadic.cpp index 99e28777ff..0fa24de842 100644 --- a/core/libs/tests/GuestStdioVariadic.cpp +++ b/core/libs/tests/GuestStdioVariadic.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/FileStream.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -9,14 +10,7 @@ extern "C" { extern FileStream* __stdinp_nid_postfix; -int APS5_VABI vfscanf_nid_postfix(FileStream*, const char*, void*); -int APS5_VABI vscanf_nid_postfix(const char*, void*); -int APS5_VABI scanf_nid_postfix(const char*, ...); -int APS5_VABI vfwprintf_nid_postfix(FileStream*, const char16_t*, void*); -int APS5_VABI fwprintf_nid_postfix(FileStream*, const char16_t*, ...); -int APS5_VABI vswscanf_nid_postfix(const char16_t*, const char16_t*, void*); -int APS5_VABI vswscanf_s_nid_postfix(const char16_t*, const char16_t*, void*); -void APS5_VABI _Vacopy_nid_postfix(void*, const void*); + } #ifdef _WIN32 @@ -35,35 +29,35 @@ static void Require(bool value, const char* what) { static int APS5_VABI ScanStream(FileStream* stream, const char* format, ...) { APS5_VA_BEGIN(format); - const int result = vfscanf_nid_postfix(stream, format, args); + const int result = vfscanf_nid_postfix(stream, format, reinterpret_cast(args)); APS5_VA_END(); return result; } static int APS5_VABI ScanInput(const char* format, ...) { APS5_VA_BEGIN(format); - const int result = vscanf_nid_postfix(format, args); + const int result = vscanf_nid_postfix(format, reinterpret_cast(args)); APS5_VA_END(); return result; } static int APS5_VABI PrintWide(FileStream* stream, const char16_t* format, ...) { APS5_VA_BEGIN(format); - const int result = vfwprintf_nid_postfix(stream, format, args); + const int result = vfwprintf_nid_postfix(stream, format, reinterpret_cast(args)); APS5_VA_END(); return result; } static int APS5_VABI ScanWide(const char16_t* input, const char16_t* format, ...) { APS5_VA_BEGIN(format); - const int result = vswscanf_nid_postfix(input, format, args); + const int result = vswscanf_nid_postfix(input, format, reinterpret_cast(args)); APS5_VA_END(); return result; } static int APS5_VABI ScanWideSized(const char16_t* input, const char16_t* format, ...) { APS5_VA_BEGIN(format); - const int result = vswscanf_s_nid_postfix(input, format, args); + const int result = vswscanf_s_nid_postfix(input, format, reinterpret_cast(args)); APS5_VA_END(); return result; } @@ -77,7 +71,8 @@ static long APS5_VABI SumThroughCopy(int count, ...) { #else std::va_list copy; #endif - _Vacopy_nid_postfix(©, &args); + _Vacopy_nid_postfix(reinterpret_cast(©), reinterpret_cast(&args)); + Require(std::memcmp(©, &args, sizeof(before)) == 0, "_Vacopy copies all 24 bytes"); long sum = 0; for (int index = 0; index < count; ++index) sum += __builtin_va_arg(copy, long) * (index + 1); @@ -94,6 +89,7 @@ static void CheckVacopy() { unsigned char overlap[32]; for (int index = 0; index < 32; ++index) overlap[index] = static_cast(index); _Vacopy_nid_postfix(overlap + 8, overlap); + const unsigned char shifted[32] = {0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23}; Require(std::memcmp(overlap, shifted, sizeof(overlap)) == 0, "_Vacopy copies the overflow area before the offsets"); } diff --git a/core/libs/tests/GuestStrftime.cpp b/core/libs/tests/GuestStrftime.cpp index eef399eda0..cf18e7c687 100644 --- a/core/libs/tests/GuestStrftime.cpp +++ b/core/libs/tests/GuestStrftime.cpp @@ -1,95 +1,253 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libc/include/GuestTime.hpp" #include #include #include - -extern "C" { -std::size_t APS5_VABI strftime_nid_postfix(char*, std::size_t, const char*, const GuestTm*); -char* APS5_VABI asctime_nid_postfix(const GuestTm*); -} +#include namespace { -GuestTm MakeTime(int year, int hour, int wday, int yday, int isdst) { +bool correct = true; + +GuestTm MakeTime() { GuestTm time{}; - time.tm_sec = 5; - time.tm_min = 4; - time.tm_hour = hour; + time.tm_year = 126; + time.tm_mon = 9; time.tm_mday = 2; - time.tm_mon = 0; - time.tm_year = year; - time.tm_wday = wday; - time.tm_yday = yday; - time.tm_isdst = isdst; + time.tm_hour = 13; + time.tm_min = 5; + time.tm_sec = 9; + time.tm_wday = 5; + time.tm_yday = 274; time.tm_gmtoff = 19800; - time.tm_zone = "IST"; + time.tm_zone = "XYZ"; return time; } +void Check(const char* name, const GuestTm& time, const char* format, const char* expected) { + char text[256]; + const std::size_t length = strftime_nid_postfix(text, sizeof(text), format, &time); + if (length != std::strlen(expected) || std::strcmp(text, expected) != 0) { + std::fprintf(stderr, "strftime %s (\"%s\"): expected \"%s\", received \"%s\" (%zu)\n", name, format, expected, length == 0 ? "" : text, length); + correct = false; + } +} + +void CheckAsctime(const char* name, const GuestTm& time, const char* expected) { + const char* result = asctime_nid_postfix(&time); + if (std::strcmp(result, expected) != 0) { + std::fprintf(stderr, "asctime %s: expected \"%s\", received \"%s\"\n", name, expected, result); + correct = false; + } +} + } int main() { - struct Case { - const char* name; - int year; - int hour; - int wday; - int yday; - int isdst; - const char* format; + if (setenv_nid_postfix("TZ", "UTC+3", 1) != 0) return 1; + tzset_nid_postfix(); + const GuestTm base = MakeTime(); + Check("names", base, "%a|%A|%b|%B|%h", "Fri|Friday|Oct|October|Oct"); + Check("composites", base, "%c|%D|%x|%X|%T|%r|%R|%F", "Fri Oct 2 13:05:09 2026|10/02/26|10/02/26|13:05:09|13:05:09|01:05:09 PM|13:05|2026-10-02"); + Check("numbers", base, "%C|%d|%e|%g|%G|%H|%I|%j|%m|%M|%p|%S|%u|%U|%V|%w|%W|%y|%Y", "20|02| 2|26|2026|13|01|275|10|05|PM|09|5|39|40|5|39|26|2026"); + Check("whitespace and percent", base, "%n%t%%", "\n\t%"); + Check("alternative forms", base, "%Ec|%EC|%Ex|%EX|%Ey|%EY|%Od|%Oe|%OH|%OI|%Om|%OM|%OS|%Ou|%OU|%OV|%Ow|%OW|%Oy|%Ez", "Fri Oct 2 13:05:09 2026|20|10/02/26|13:05:09|26|2026|02| 2|13|01|10|05|09|5|39|40|5|39|26|-0300"); + Check("other conversions", base, "%k|%l|%P|%s|%+|%v|%Q|%q", "%k|%l|%P|%s|%+|%v|%Q|%q"); + Check("flags and widths", base, "%-d|%_d|%0e|%^a|%#b|%10Y", "%-d|%_d|%0e|%^a|%#b|%10Y"); + Check("modifier before an unknown conversion", base, "%Ea|%Oa|%EE|%OO|%Ek|%EY", "Fri|Fri|%E|%O|%k|2026"); + Check("trailing percent", base, "ab%", "ab%"); + Check("zone", base, "%z|%Z", "-0300|UTC"); + + GuestTm zone = base; + zone.tm_isdst = 1; + zone.tm_gmtoff = -1; + Check("zone in daylight time", zone, "%z", "-0200"); + zone.tm_isdst = -1; + Check("zone with unknown daylight time", zone, "%z", "-0300"); + + for (int value = -3; value <= 14; ++value) { + GuestTm time = base; + time.tm_wday = value; + time.tm_mon = value; + static const char* const expected[] = { + "Sun|Sun|Jan|Jan|00|0|0", "Sun|Sun|Jan|Jan|00|0|0", "Sun|Sun|Jan|Jan|00|0|0", "Sun|Sunday|Jan|January|01|7|0", + "Mon|Monday|Feb|February|02|1|1", "Tue|Tuesday|Mar|March|03|2|2", "Wed|Wednesday|Apr|April|04|3|3", "Thu|Thursday|May|May|05|4|4", + "Fri|Friday|Jun|June|06|5|5", "Sat|Saturday|Jul|July|07|6|6", "||Aug|August|08|7|7", "||Sep|September|09|8|8", + "||Oct|October|10|9|9", "||Nov|November|11|0|0", "||Dec|December|12|1|1", "||||13|2|2", "||||14|3|3", "||||15|4|4", + }; + char name[24]; + std::snprintf(name, sizeof(name), "index %d", value); + Check(name, time, "%a|%A|%b|%B|%m|%u|%w", expected[value + 3]); + } + + struct Field { + int value; const char* expected; }; - constexpr Case cases[] = { - {"alternative", 126, 3, 5, 1, 0, "%Ea %OX %OD %EF %EEY", "Fri 03:04:05 01/02/26 2026-01-02 EY"}, - {"padding", 126, 3, 5, 1, 0, "%-d|%_d|%0e|%-k|%_+|%--d", "2| 2|02|3|Fri Jan 2 03:04:05 IST 2026|-d"}, - {"zone", 126, 3, 5, 1, 0, "%z %Z %0z", "+0530 IST +0530"}, - {"year 899", -1001, 3, 5, 1, 0, "%Y %C %y %G %g %F", "0899 08 99 0899 99 0899-01-02"}, - {"year -1", -1901, 3, 5, 1, 0, "%Y %C %y %c", "-001 -0 01 Fri Jan 2 03:04:05 -001"}, - {"year 12345", 10445, 3, 5, 1, 0, "%Y %C %y %D %v", "12345 123 45 01/02/45 2-Jan-12345"}, - {"out of range", 126, 100, 8, 400, 0, "%I %l %u %W %U %j %a %p", "04 4 8 57 57 401 ? PM"}, - {"unknown dst", 126, 3, 5, 1, -1, "[%z][%Z]", "[][IST]"}, - {"literals", 126, 3, 5, 1, 0, "%q %% %", "q % %"}, + constexpr Field fields[] = { + {-25, "00|00|AM|00|00|00| 0|000|00|00"}, {-13, "00|00|AM|00|00|00| 0|000|00|00"}, {-12, "00|00|AM|00|00|00| 0|000|00|00"}, + {-1, "00|11|AM|00|00|00| 0|000|00|00"}, {0, "00|12|AM|00|00|00| 0|001|00|00"}, {1, "01|01|AM|01|01|01| 1|002|00|00"}, + {11, "11|11|AM|11|11|11|11|012|01|02"}, {12, "12|12|PM|12|12|12|12|013|02|02"}, {13, "13|01|PM|13|13|13|13|014|02|02"}, + {25, "25|01|PM|25|25|25|25|026|03|04"}, {99, "99|03|PM|99|99|99|99|100|14|14"}, {100, "00|04|PM|00|00|00| 0|101|14|14"}, }; - bool correct = true; - for (const auto& test : cases) { - const GuestTm time = MakeTime(test.year, test.hour, test.wday, test.yday, test.isdst); - char text[128]; - const std::size_t length = strftime_nid_postfix(text, sizeof(text), test.format, &time); - if (length != std::strlen(test.expected) || std::strcmp(text, test.expected) != 0) { - std::fprintf(stderr, "strftime %s (\"%s\"): expected \"%s\", received \"%s\" (%zu)\n", - test.name, test.format, test.expected, length == 0 ? "" : text, length); - correct = false; - } + for (const auto& field : fields) { + GuestTm time = base; + time.tm_hour = field.value; + time.tm_min = field.value; + time.tm_sec = field.value; + time.tm_mday = field.value; + time.tm_yday = field.value; + char name[24]; + std::snprintf(name, sizeof(name), "field %d", field.value); + Check(name, time, "%H|%I|%p|%M|%S|%d|%e|%j|%U|%W", field.expected); } - const GuestTm now = MakeTime(126, 3, 5, 1, 0); - char text[32]; - if (strftime_nid_postfix(text, 10, "%Y-%m-%d", &now) != 0 || strftime_nid_postfix(text, 11, "%Y-%m-%d", &now) != 10) { - std::fprintf(stderr, "strftime does not return 0 when the result and its terminator do not fit\n"); - correct = false; + + constexpr Field numbers[] = { + {-10, "00| 0|000|00|00|00"}, {9, "09| 9|010|09|09|09"}, {101, "01| 1|102|01|01|01"}, {999, "99|99|000|99|99|99"}, + {1000, "00| 0|001|00|00|00"}, {123456, "56|56|457|56|56|56"}, + }; + for (const auto& field : numbers) { + GuestTm time = base; + time.tm_hour = field.value; + time.tm_min = field.value; + time.tm_sec = field.value; + time.tm_mday = field.value; + time.tm_yday = field.value; + char name[24]; + std::snprintf(name, sizeof(name), "number %d", field.value); + Check(name, time, "%d|%e|%j|%H|%M|%S", field.expected); } - if (strftime_nid_postfix(text, sizeof(text), nullptr, &now) == 0 || std::strcmp(text, "Fri Jan 2 03:04:05 2026") != 0) { - std::fprintf(stderr, "strftime with a null format does not format %%c\n"); - correct = false; - } - struct AsctimeCase { - int year; + GuestTm leap = base; + leap.tm_sec = 61; + Check("leap second", leap, "%S|%T", "61|13:05:61"); + + struct Year { + int tmYear; const char* expected; }; - constexpr AsctimeCase asctimeCases[] = { - {126, "Fri Jan 2 03:04:05 2026\n"}, - {-1001, "Fri Jan 2 03:04:05 0899\n"}, - {-1901, "Fri Jan 2 03:04:05 -001\n"}, - {10445, "Fri Jan 2 03:04:05 12345\n"}, - {-2147483647 - 1, "Fri Jan 2 03:04:05 -2147481748\n"}, + constexpr Year years[] = { + {-14245, "0000|00|55|0000|55"}, {-11900, "0000|00|00|0000|00"}, {-2001, "0000|00|99|0000|99"}, {-1999, "0000|00|01|0000|01"}, + {-1901, "0000|00|99|0000|99"}, {-1900, "0000|00|00|0000|00"}, {-1899, "0001|01|01|0001|01"}, {-1800, "0100|01|00|0100|00"}, + {-1, "1899|19|99|1899|99"}, {0, "1900|19|00|1900|00"}, {8099, "9999|99|99|9999|99"}, {8100, "0000|00|00|0000|00"}, + {8101, "0001|00|01|0001|01"}, {10099, "1999|19|99|1999|99"}, {10445, "2345|23|45|2345|45"}, }; - for (const auto& test : asctimeCases) { - const GuestTm time = MakeTime(test.year, 3, 5, 1, 0); - const char* result = asctime_nid_postfix(&time); - if (std::strcmp(result, test.expected) != 0) { - std::fprintf(stderr, "asctime of tm_year %d: expected \"%s\", received \"%s\"\n", test.year, test.expected, result); - correct = false; - } + for (const auto& year : years) { + GuestTm time = base; + time.tm_year = year.tmYear; + char name[24]; + std::snprintf(name, sizeof(name), "year %d", year.tmYear); + Check(name, time, "%Y|%C|%y|%G|%g", year.expected); } + + struct Iso { + int year, mon, mday, wday, yday; + const char* expected; + }; + constexpr Iso weeks[] = { + {126, 0, 1, 4, 0, "2026|26|01|00|00"}, {126, 0, 4, 0, 3, "2026|26|01|01|00"}, {126, 0, 5, 1, 4, "2026|26|02|01|01"}, + {120, 11, 31, 4, 365, "2020|20|53|52|52"}, {121, 0, 3, 0, 2, "2020|20|53|01|00"}, {121, 0, 4, 1, 3, "2021|21|01|01|01"}, + {124, 11, 30, 1, 364, "2025|25|01|52|53"}, {104, 11, 31, 5, 365, "2004|04|53|52|52"}, {105, 0, 2, 0, 1, "2004|04|53|01|00"}, + {126, 0, 1, 9, 10, "2026|26|02|02|02"}, {126, 0, 1, -2, 10, "2026|26|02|01|01"}, {-1901, 0, 1, 4, 0, "0000|99|01|00|00"}, + }; + for (const auto& week : weeks) { + GuestTm time = base; + time.tm_year = week.year; + time.tm_mon = week.mon; + time.tm_mday = week.mday; + time.tm_wday = week.wday; + time.tm_yday = week.yday; + char name[48]; + std::snprintf(name, sizeof(name), "week %d/%d wday %d yday %d", week.year, week.mon, week.wday, week.yday); + Check(name, time, "%G|%g|%V|%U|%W", week.expected); + } + + constexpr Iso outOfRangeWeeks[] = { + {126, 0, 11, -2, 10, "01|01"}, {126, 1, 5, 4, 400, "57|57"}, {126, 3, 11, -19, 100, "16|16"}, {126, 9, 5, -16, 277, "40|41"}, + {126, 0, 19, -12, 18, "04|04"}, {126, 0, 1, 6, 1365, "95|95"}, {97, 0, 1, 6, 415, "59|59"}, {113, 11, 31, 1, 365, "53|53"}, + {7, 11, 31, 1, 365, "53|53"}, {126, 9, 24, 6, 296, "42|42"}, + }; + for (const auto& week : outOfRangeWeeks) { + GuestTm time = base; + time.tm_year = week.year; + time.tm_mon = week.mon; + time.tm_mday = week.mday; + time.tm_wday = week.wday; + time.tm_yday = week.yday; + char name[48]; + std::snprintf(name, sizeof(name), "week number wday %d yday %d", week.wday, week.yday); + Check(name, time, "%U|%W", week.expected); + } + + char text[8]; + std::memset(text, '#', sizeof(text)); + if (strftime_nid_postfix(text, 5, "%Y", &base) != 4 || std::strcmp(text, "2026") != 0) { + std::fprintf(stderr, "strftime does not fill a buffer that holds the result and its terminator\n"); + correct = false; + } + std::memset(text, '#', sizeof(text)); + if (strftime_nid_postfix(text, 4, "%Y", &base) != 0 || std::memcmp(text, "2026#", 5) != 0) { + std::fprintf(stderr, "strftime with no room for the terminator does not return 0 after writing the conversion\n"); + correct = false; + } + std::memset(text, '#', sizeof(text)); + if (strftime_nid_postfix(text, 5, "ab%Ycd", &base) != 0 || std::memcmp(text, "ab####", 6) != 0) { + std::fprintf(stderr, "strftime writes part of a conversion that does not fit\n"); + correct = false; + } + std::memset(text, '#', sizeof(text)); + if (strftime_nid_postfix(text, 8, "%t%D", &base) != 0 || std::memcmp(text, "\t10/02/#", 8) != 0) { + std::fprintf(stderr, "strftime does not write the parts of a composite conversion that fit\n"); + correct = false; + } + std::memset(text, '#', sizeof(text)); + if (strftime_nid_postfix(text, 2, "%X%#H", &base) != 0 || std::memcmp(text, "13#", 3) != 0) { + std::fprintf(stderr, "strftime does not stop a composite conversion at the first part that does not fit\n"); + correct = false; + } + std::memset(text, '#', sizeof(text)); + if (strftime_nid_postfix(text, 3, "abc", &base) != 0 || std::memcmp(text, "abc#", 4) != 0) { + std::fprintf(stderr, "strftime does not write the literals that fit\n"); + correct = false; + } + std::memset(text, '#', sizeof(text)); + if (strftime_nid_postfix(text, 0, "%Y", &base) != 0 || text[0] != '#') { + std::fprintf(stderr, "strftime writes to a zero-size buffer\n"); + correct = false; + } + bool threw = false; + try { + strftime_nid_postfix(text, sizeof(text), "%E", &base); + } catch (const std::invalid_argument&) { + threw = true; + } + if (!threw) { + std::fprintf(stderr, "strftime does not throw for a format ending after a modifier\n"); + correct = false; + } + + CheckAsctime("base", base, "Fri Oct 2 13:05:09 2026\n"); + GuestTm negative = base; + negative.tm_wday = -1; + negative.tm_mon = -1; + CheckAsctime("negative names", negative, "Sun Jan 2 13:05:09 2026\n"); + GuestTm past = base; + past.tm_wday = 7; + past.tm_mon = 12; + CheckAsctime("names past the tables", past, " 2 13:05:09 2026\n"); + GuestTm big = base; + big.tm_mday = 40; + big.tm_hour = 25; + big.tm_min = 61; + big.tm_sec = 61; + CheckAsctime("large fields", big, "Fri Oct 40 25:61:61 2026\n"); + big.tm_mday = 123456; + big.tm_hour = -10; + CheckAsctime("wrapped and negative fields", big, "Fri Oct 56 00:61:61 2026\n"); + GuestTm year = base; + year.tm_year = 8100; + CheckAsctime("year 10000", year, "Fri Oct 2 13:05:09 0000\n"); + year.tm_year = -1901; + CheckAsctime("year -1", year, "Fri Oct 2 13:05:09 0000\n"); return correct ? 0 : 1; } diff --git a/core/libs/tests/GuestStringCompare.cpp b/core/libs/tests/GuestStringCompare.cpp new file mode 100644 index 0000000000..9fc7691c39 --- /dev/null +++ b/core/libs/tests/GuestStringCompare.cpp @@ -0,0 +1,44 @@ +#include "prx/libc/include/Api.hpp" +#include "prx/libc/include/general/VabiMacros.hpp" +#include +#include + +namespace { + +void Require(bool value) { + if (!value) std::abort(); +} + +} + +int main() { + Require(strcmp_nid_postfix("abc", "abc") == 0); + Require(strcmp_nid_postfix("abc", "abd") == -1); + Require(strcmp_nid_postfix("abd", "abc") == 1); + Require(strcmp_nid_postfix("a", "z") == -25); + Require(strcmp_nid_postfix("abc", "abcd") == -100); + Require(strcmp_nid_postfix("abcd", "abc") == 100); + Require(strcmp_nid_postfix("\x80", "a") == 31); + Require(strcmp_nid_postfix("", "") == 0); + + Require(strncmp_nid_postfix("abcdef", "abcxyz", 3) == 0); + Require(strncmp_nid_postfix("abcdef", "abcxyz", 4) == -20); + Require(strncmp_nid_postfix("abc", "xyz", 0) == 0); + Require(strncmp_nid_postfix("abc\0x", "abc\0y", 6) == 0); + Require(strncmp_nid_postfix("ab", "abc", 8) == -99); + + const unsigned char base[] = {0x01, 0x02, 0x03}; + const unsigned char higher[] = {0x01, 0x02, 0x04}; + const unsigned char top[] = {0x01, 0x02, 0xff}; + const unsigned char low[] = {0x01, 0x02, 0x01}; + Require(memcmp_nid_postfix(base, base, 3) == 0); + Require(memcmp_nid_postfix(base, higher, 3) == -1); + Require(memcmp_nid_postfix(top, low, 3) == 254); + Require(memcmp_nid_postfix(top, low, 2) == 0); + const unsigned char sign[] = {0x80}; + const unsigned char one[] = {0x01}; + Require(memcmp_nid_postfix(sign, one, 1) == 127); + const unsigned char withNul[] = {0x00, 0x05}; + const unsigned char withNulLow[] = {0x00, 0x02}; + Require(memcmp_nid_postfix(withNul, withNulLow, 2) == 3); +} diff --git a/core/libs/tests/GuestStrings.cpp b/core/libs/tests/GuestStrings.cpp index 89aec886ab..e0effe010e 100644 --- a/core/libs/tests/GuestStrings.cpp +++ b/core/libs/tests/GuestStrings.cpp @@ -1,3 +1,5 @@ +#include "prx/libc/include/Api.hpp" +#include "prx/libScePosixForWebKit/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -8,46 +10,6 @@ #include #include -extern "C" { -void APS5_VABI bcopy_nid_postfix(const void*, void*, std::size_t); -char* APS5_VABI basename_nid_postfix(const char*); -char* APS5_VABI basename_r_nid_postfix(const char*, char*); -char* APS5_VABI __inet_ntoa_nid_postfix(unsigned int); -char* APS5_VABI dirname_nid_postfix(const char*); -int* APS5_VABI __error_nid_postfix(); -long long APS5_VABI strtonum_nid_postfix(const char*, long long, long long, const char**); -int APS5_VABI strcasecmp_nid_postfix(const char*, const char*); -int APS5_VABI strncasecmp_nid_postfix(const char*, const char*, std::size_t); -std::size_t APS5_VABI strnlen_nid_postfix(const char*, std::size_t); -std::size_t APS5_VABI strnlen_s_nid_postfix(const char*, std::size_t); -char* APS5_VABI strncat_nid_postfix(char*, const char*, std::size_t); -char* APS5_VABI strpbrk_nid_postfix(const char*, const char*); -const char* APS5_VABI strchr_nid_postfix(const char*, int); -char* APS5_VABI strrchr_nid_postfix(const char*, int); -std::size_t APS5_VABI strcspn_nid_postfix(const char*, const char*); -std::size_t APS5_VABI strlcat_nid_postfix(char*, const char*, std::size_t); -char* APS5_VABI stpcpy_nid_postfix(char*, const char*); -char* APS5_VABI strtok_r_nid_postfix(char*, const char*, char**); -char* APS5_VABI strtok_nid_postfix(char*, const char*); -char* APS5_VABI strsep_nid_postfix(char**, const char*); -char* APS5_VABI strcasestr_nid_postfix(const char*, const char*); -int APS5_VABI strcpy_s_nid_postfix(char*, std::size_t, const char*); -int APS5_VABI strncpy_s_nid_postfix(char*, std::size_t, const char*, std::size_t); -int APS5_VABI strcat_s_nid_postfix(char*, std::size_t, const char*); -int APS5_VABI strncat_s_nid_postfix(char*, std::size_t, const char*, std::size_t); -int APS5_VABI memcpy_s_nid_postfix(void*, std::size_t, const void*, std::size_t); -int APS5_VABI memmove_s_nid_postfix(void*, std::size_t, const void*, std::size_t); -int APS5_VABI memset_s_nid_postfix(void*, std::size_t, int, std::size_t); -void* APS5_VABI memccpy_nid_postfix(void*, const void*, int, std::size_t); -void* APS5_VABI memmem_nid_postfix(const void*, std::size_t, const void*, std::size_t); -char* APS5_VABI strnstr_nid_postfix(const char*, const char*, std::size_t); -std::size_t APS5_VABI strxfrm_nid_postfix(char*, const char*, std::size_t); -int APS5_VABI snprintf_s_nid_postfix(char*, std::size_t, const char*, ...); -int APS5_VABI sscanf_s_nid_postfix(const char*, const char*, ...); -int APS5_VABI __inet_aton_nid_postfix(const char*, void*); -std::uint32_t APS5_VABI __inet_addr_nid_postfix(const char*); -} - static void Require(bool condition) { if (!condition) { std::fputs("Guest string check failed\n", stderr); @@ -82,6 +44,40 @@ static bool CheckMemcpyOverlap() { return correct; } +static int Sign(int value) { + return value < 0 ? -1 : value > 0 ? 1 : 0; +} + +static void CheckStandardStrings() { + Require(strcmp_nid_postfix("abc", "abc") == 0 && Sign(strcmp_nid_postfix("abc", "abd")) == -1 && Sign(strcmp_nid_postfix("abc", "ab")) == 1); + Require(Sign(strcmp_nid_postfix("\x80", "\x7f")) == 1); + Require(strncmp_nid_postfix("abcX", "abcY", 3) == 0 && Sign(strncmp_nid_postfix("abcX", "abcY", 4)) == -1 && strncmp_nid_postfix("a", "b", 0) == 0); + Require(strcoll_nid_postfix("same", "same") == 0 && Sign(strcoll_nid_postfix("B", "a")) == -1); + Require(strlen_nid_postfix("") == 0 && strlen_nid_postfix("seven 7") == 7); + + char buffer[16]; + std::memset(buffer, 'x', sizeof(buffer)); + Require(strcpy_nid_postfix(buffer, "ab") == buffer && std::memcmp(buffer, "ab\0x", 4) == 0); + Require(strcat_nid_postfix(buffer, "cd") == buffer && std::strcmp(buffer, "abcd") == 0); + + std::memset(buffer, 'x', sizeof(buffer)); + Require(strncpy_nid_postfix(buffer, "ab", 5) == buffer && std::memcmp(buffer, "ab\0\0\0x", 6) == 0); + std::memset(buffer, 'x', sizeof(buffer)); + Require(strncpy_nid_postfix(buffer, "abcdef", 3) == buffer && std::memcmp(buffer, "abcx", 4) == 0); + + const char* text = "needle in a haystack"; + Require(strstr_nid_postfix(text, "hay") == text + 12 && strstr_nid_postfix(text, "") == text && strstr_nid_postfix(text, "hey") == nullptr); + Require(strspn_nid_postfix("aabbc", "ab") == 4 && strspn_nid_postfix("xyz", "ab") == 0 && strspn_nid_postfix("ab", "") == 0); + + unsigned char bytes[6] = {1, 2, 3, 4, 5, 6}; + const unsigned char same[6] = {1, 2, 3, 4, 5, 6}; + Require(bcmp_nid_postfix(bytes, same, 6) == 0 && bcmp_nid_postfix(bytes, "zz", 0) == 0); + bytes[5] = 9; + Require(bcmp_nid_postfix(bytes, same, 6) != 0 && bcmp_nid_postfix(bytes, same, 5) == 0); + bzero_nid_postfix(bytes + 1, 4); + Require(bytes[0] == 1 && bytes[1] == 0 && bytes[4] == 0 && bytes[5] == 9); +} + static void CheckSecureCopySizeLimits() { using Copy = int (APS5_VABI*)(void*, std::size_t, const void*, std::size_t); constexpr std::size_t RsizeMax = SIZE_MAX >> 1; @@ -263,6 +259,7 @@ static void CheckBcopy() { auto expected = original; for (std::size_t i = 0; i < count; ++i) expected[destination + i] = original[source + i]; bcopy_nid_postfix(actual.data() + source, actual.data() + destination, count); + Require(actual == expected); } } @@ -270,8 +267,10 @@ static void CheckBcopy() { auto destination = original; destination.fill(0xff); bcopy_nid_postfix(original.data(), destination.data(), original.size()); + Require(destination == original); bcopy_nid_postfix(nullptr, nullptr, 0); + } static void CheckStrtonum() { @@ -332,6 +331,7 @@ static void CheckCharacterConversionInSearches() { } int main() { + CheckStandardStrings(); CheckStrtonum(); CheckBcopy(); if (!CheckDirnameLengths()) return 1; diff --git a/core/libs/tests/GuestSulphaConfig.cpp b/core/libs/tests/GuestSulphaConfig.cpp new file mode 100644 index 0000000000..007930e68a --- /dev/null +++ b/core/libs/tests/GuestSulphaConfig.cpp @@ -0,0 +1,46 @@ +#include "prx/libSceSulphaDrv/libSceSulphaDrv.hpp" +#include +#include +#include +#include +#include +#include +#include + +static void Require(bool condition, const char* message) { + if (condition) return; + std::fprintf(stderr, "%s\n", message); + std::abort(); +} + +int main() { + errno = 7; + Require(sceSulphaGetDefaultConfig(nullptr) == static_cast(0x804d0003u) && errno == 7, + "A null configuration must return the native argument error without changing errno"); + struct Config { + std::uint64_t size; + std::uint64_t capacity; + std::uint32_t setting; + std::uint32_t port; + }; + static_assert(sizeof(Config) == 24); + for (const auto shift : {0u, 1u}) for (const auto initial : std::array{0, 24, 560, UINT64_MAX}) { + for (const unsigned char pattern : {0xa5, 0x5a}) { + std::array storage; + storage.fill(pattern); + auto* config = storage.data() + 8 + shift; + std::memcpy(config, &initial, sizeof(initial)); + errno = 7; + Require(sceSulphaGetDefaultConfig(config) == 0 && errno == 7, + "Default configuration must accept non-null storage regardless of its incoming size"); + Config result; + std::memcpy(&result, config, sizeof(result)); + Require(result.size == 24 && result.capacity == 4194304 && result.setting == 3 && result.port == 4001, + "Default configuration must match the native 24-byte record"); + for (std::size_t i = 0; i < storage.size(); ++i) { + if (i < 8 + shift || i >= 8 + shift + sizeof(Config)) + Require(storage[i] == pattern, "Default configuration must preserve bytes outside its record"); + } + } + } +} diff --git a/core/libs/tests/GuestSyncOnAddress.cpp b/core/libs/tests/GuestSyncOnAddress.cpp index c43e7a66fe..e320373917 100644 --- a/core/libs/tests/GuestSyncOnAddress.cpp +++ b/core/libs/tests/GuestSyncOnAddress.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/KernelErrors.hpp" +#include "prx/libkernel/include/Api.hpp" #include "SceTypes.hpp" #include #include @@ -8,17 +10,7 @@ #include #include -extern "C" { -int APS5_VABI sceKernelSyncOnAddressWait(std::uint32_t* address, std::uint32_t expected, const KernelUseconds* timeout, const char* name); -int APS5_VABI sceKernelSyncOnAddressWait32(std::uint32_t* address, std::uint32_t expected, const KernelUseconds* timeout, const char* name); -int APS5_VABI sceKernelSyncOnAddressWait64(std::uint64_t* address, std::uint64_t expected, const KernelUseconds* timeout, const char* name); -int APS5_VABI sceKernelSyncOnAddressWait8(std::uint8_t* address, std::uint8_t expected, const KernelUseconds* timeout, const char* name); -int APS5_VABI sceKernelSyncOnAddressWait16(std::uint16_t* address, std::uint16_t expected, const KernelUseconds* timeout, const char* name); -int APS5_VABI sceKernelSyncOnAddressWake(void* address, std::int32_t count); -} - static constexpr int SCE_OK = 0; -static constexpr int SCE_KERNEL_ERROR_ETIMEDOUT = static_cast(0x8002003C); static constexpr KernelUseconds FAILSAFE_TIMEOUT = 10000000; static constexpr auto SETTLE = std::chrono::milliseconds(100); diff --git a/core/libs/tests/GuestSysarch.cpp b/core/libs/tests/GuestSysarch.cpp index f2c4551138..b6533c2e65 100644 --- a/core/libs/tests/GuestSysarch.cpp +++ b/core/libs/tests/GuestSysarch.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "SceTypes.hpp" #include @@ -6,13 +8,6 @@ #include #include -extern "C" { -int APS5_VABI sysarch(int number, void* args); -int* APS5_VABI __error_nid_postfix(); -int APS5_VABI scePthreadCreate(Pthread* thread, const PthreadAttr* attr, PthreadEntry entry, void* arg, const char* name); -int APS5_VABI scePthreadJoin(Pthread thread, void** retval); -} - static void Require(bool value) { if (!value) std::abort(); } template static std::string Thrown(TCall call) { diff --git a/core/libs/tests/GuestSyslog.cpp b/core/libs/tests/GuestSyslog.cpp index 0d55e1a440..c0a954c07a 100644 --- a/core/libs/tests/GuestSyslog.cpp +++ b/core/libs/tests/GuestSyslog.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -11,13 +12,6 @@ #include #endif -extern "C" { -void APS5_VABI syslog_nid_postfix(int, const char*, ...); -void APS5_VABI openlog_nid_postfix(const char*, int, int); -void APS5_VABI closelog_nid_postfix(); -int APS5_VABI setlogmask_nid_postfix(int); -int* APS5_VABI __error_nid_postfix(); -} static void Require(bool value) { if (!value) std::abort(); } int main() { auto* captured = std::tmpfile(); @@ -33,33 +27,42 @@ int main() { *__error_nid_postfix() = 2; Require(setlogmask_nid_postfix(0) == 0xff); syslog_nid_postfix(6, "station %s at %d kbps", "radio", 128); + const int afterFirst = *__error_nid_postfix(); syslog_nid_postfix(16 | 3, "open: %m, %%m kept, %d%%\n", 50); syslog_nid_postfix(0x10000 | 4, "masked"); syslog_nid_postfix(7, ""); + Require(setlogmask_nid_postfix(1 << 3) == 0xff); Require(setlogmask_nid_postfix(0) == (1 << 3)); int count = -1; syslog_nid_postfix(7, "suppressed %m%n", &count); + Require(count == -1 && *__error_nid_postfix() == 2); syslog_nid_postfix(16 | 3, "allowed: %m"); + Require(*__error_nid_postfix() == 2); syslog_nid_postfix(0x10000 | 7, "suppressed %n", &count); + Require(count == -1 && *__error_nid_postfix() == 2); Require(setlogmask_nid_postfix(1 << 4) == (1 << 3)); syslog_nid_postfix(0x10000 | 4, "warning without diagnostic"); syslog_nid_postfix(0x10000 | 7, "both suppressed %n", &count); + Require(count == -1 && *__error_nid_postfix() == 2); Require(setlogmask_nid_postfix(0x100) == (1 << 4)); Require(setlogmask_nid_postfix(0) == 0x100); syslog_nid_postfix(0x10000 | 3, "no priorities enabled %n", &count); + Require(count == -1 && *__error_nid_postfix() == 2); Require(setlogmask_nid_postfix(-1) == 0x100); Require(setlogmask_nid_postfix(0) == -1); syslog_nid_postfix(7, "negative mask"); + Require(setlogmask_nid_postfix(0x55) == -1); for (int priority = 0; priority < 8; ++priority) syslog_nid_postfix(16 | priority, "level %d", priority); + std::thread([] { Require(setlogmask_nid_postfix(0xff) == 0x55); }).join(); Require(setlogmask_nid_postfix(0) == 0xff); syslog_nid_postfix(7, "mask shared across threads"); @@ -73,6 +76,7 @@ int main() { openlog_nid_postfix("closing", 1, 0); closelog_nid_postfix(); syslog_nid_postfix(6, "identity cleared, options and facility retained"); + std::fflush(stderr); #ifdef _WIN32 Require(::_dup2(saved, ::_fileno(stderr)) == 0 && ::_close(saved) == 0); diff --git a/core/libs/tests/GuestSysmodule.cpp b/core/libs/tests/GuestSysmodule.cpp index f98548f2ce..b416232025 100644 --- a/core/libs/tests/GuestSysmodule.cpp +++ b/core/libs/tests/GuestSysmodule.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libSceSysmodule/include/Api.hpp" #include "SceTypes.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libSceSysmodule/ModuleTable.hpp" @@ -18,20 +20,6 @@ #include #endif -extern "C" { -int APS5_VABI sceSysmoduleIsLoaded(std::uint16_t id); -int APS5_VABI sceSysmoduleLoadModule(std::uint16_t id); -int APS5_VABI sceSysmoduleUnloadModule(std::uint16_t id); -int APS5_VABI sceSysmoduleLoadModuleInternal(std::uint32_t id); -int APS5_VABI sceSysmoduleUnloadModuleInternal(std::uint32_t id); -int APS5_VABI sceSysmoduleIsLoadedInternal(std::uint32_t id); -int APS5_VABI sceSysmoduleLoadModuleInternalWithArg(std::uint32_t id, int argc, void* argv, std::uint64_t unk, int* ret); -int APS5_VABI sceSysmoduleUnloadModuleInternalWithArg(std::uint32_t id, int argc, void* argv, std::uint64_t unk, int* ret); -int APS5_VABI sceSysmoduleGetModuleInfoForUnwind(std::uint64_t addr, int flags, ModuleInfoForUnwind* info); -int APS5_VABI sceSysmoduleGetModuleHandleInternal(std::uint32_t id, std::int32_t* handle); -int APS5_VABI sceKernelDlsym(std::int32_t handle, const char* symbol, void** addr); -} - namespace { void Require(bool value) { if (!value) std::abort(); } @@ -110,6 +98,7 @@ void CheckUnwindInfo() { bool threw = false; try { sceSysmoduleGetModuleInfoForUnwind(reinterpret_cast(gap), 0, &info); + } catch (const std::runtime_error&) { threw = true; } diff --git a/core/libs/tests/GuestSystemCommand.cpp b/core/libs/tests/GuestSystemCommand.cpp index 23290b0822..9eb03d0240 100644 --- a/core/libs/tests/GuestSystemCommand.cpp +++ b/core/libs/tests/GuestSystemCommand.cpp @@ -1,9 +1,8 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include -extern "C" { -int APS5_VABI system_nid_postfix(const char*); -int* APS5_VABI __error_nid_postfix(); -} + static void Require(bool value) { if (!value) std::abort(); } int main() { *__error_nid_postfix() = 13; diff --git a/core/libs/tests/GuestSystemConfiguration.cpp b/core/libs/tests/GuestSystemConfiguration.cpp index e1d7bc3d57..ec022beb6f 100644 --- a/core/libs/tests/GuestSystemConfiguration.cpp +++ b/core/libs/tests/GuestSystemConfiguration.cpp @@ -1,3 +1,6 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libkernel/Time/include/Time.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libkernel/KernelErrors.hpp" #include @@ -8,35 +11,13 @@ #include #include #include -struct SceKernelSystemSwVersion { - std::uint64_t size; - char versionString[0x1C]; - std::uint32_t version; -}; + static_assert(offsetof(SceKernelSystemSwVersion, size) == 0x00); static_assert(offsetof(SceKernelSystemSwVersion, versionString) == 0x08); static_assert(offsetof(SceKernelSystemSwVersion, version) == 0x24); static_assert(sizeof(SceKernelSystemSwVersion) == 0x28); extern "C" { -std::int64_t APS5_VABI sysconf_nid_postfix(int); -int APS5_VABI getpagesize_nid_postfix(); -int* APS5_VABI __error_nid_postfix(); -int APS5_VABI sysctl_nid_postfix(const int*, std::uint32_t, void*, std::size_t*, const void*, std::size_t); -int APS5_VABI sysctlbyname_nid_postfix(const char*, void*, std::size_t*, const void*, std::size_t); -int APS5_VABI sysctlnametomib_nid_postfix(const char*, int*, std::size_t*); -int APS5_VABI sceKernelGetSystemSwVersion_nid_postfix(SceKernelSystemSwVersion*); -int APS5_VABI sceKernelGetSystemExVersion(char*, char*); -int APS5_VABI sysKernelGetLowerLimitSysexVersion_nid_postfix(char*); -int APS5_VABI sysKernelGetLowerLimitUpdVersion_nid_postfix(std::uint32_t*); -int APS5_VABI getpid_nid_postfix(); -void* APS5_VABI mmap_nid_postfix(void*, std::size_t, int, int, int, std::int64_t); -int APS5_VABI munmap_nid_postfix(void*, std::size_t); -std::uint64_t APS5_VABI sceKernelGetTscFrequency(void); -struct GuestRlimitTest { - std::int64_t rlim_cur; - std::int64_t rlim_max; -}; -int APS5_VABI getrlimit_nid_postfix(int resource, GuestRlimitTest* limit); + extern char** environ_nid_postfix; } static void Require(bool value) { if (!value) std::abort(); } @@ -68,6 +49,7 @@ static void CheckProcessorCountSysctl() { const int unknown[] = {6, 99}; try { sysctl_nid_postfix(unknown, 2, &value, &length, nullptr, 0); + } catch (const std::runtime_error&) { threw = true; } @@ -415,11 +397,7 @@ struct BootTimeval { std::int64_t tv_usec; }; static_assert(sizeof(BootTimeval) == 16); -struct BootTimespec { - std::int64_t tv_sec; - std::int64_t tv_nsec; -}; -extern "C" int APS5_VABI clock_gettime_nid_postfix(int, BootTimespec*); + static void CheckBootTimeSysctl() { const int mib[] = {1, 21}; *__error_nid_postfix() = 13; @@ -432,8 +410,8 @@ static void CheckBootTimeSysctl() { Require(sysctl_nid_postfix(mib, 2, &first, &length, nullptr, 0) == 0 && length == sizeof(first)); Require(first.tv_sec > 0 && first.tv_sec <= static_cast(std::time(nullptr))); Require(first.tv_usec >= 0 && first.tv_usec < 1000000); - BootTimespec now{}; - BootTimespec uptime{}; + KernelTimespec now{}; + KernelTimespec uptime{}; Require(clock_gettime_nid_postfix(5, &uptime) == 0 && clock_gettime_nid_postfix(0, &now) == 0); const std::int64_t drift = (first.tv_sec + uptime.tv_sec - now.tv_sec) * 1000000 + first.tv_usec + uptime.tv_nsec / 1000 - now.tv_nsec / 1000; Require(drift > -1000000 && drift < 1000000); @@ -515,6 +493,7 @@ static void CheckMeasuredAbsentSysctlMibs() { bool threw = false; try { sysctl_nid_postfix(entry.mib, entry.length, buffer, &length, buffer, sizeof(buffer)); + } catch (const std::runtime_error&) { threw = true; } @@ -631,6 +610,7 @@ static void CheckOvercommitSysctl() { length = sizeof(value); try { sysctlbyname_nid_postfix("vm.overcommit", &value, &length, &value, sizeof(value)); + } catch (const std::runtime_error&) { threw = true; } @@ -799,6 +779,7 @@ static void CheckPseudoRandomMibSysctl() { bool threw = false; try { sysctl_nid_postfix(mib, 2, &value, &length, &value, sizeof(value)); + } catch (const std::runtime_error&) { threw = true; } @@ -890,6 +871,7 @@ static void CheckNameToMib() { bool threw = false; try { sysctlnametomib_nid_postfix(nullptr, mib, &size); + } catch (const std::invalid_argument&) { threw = true; } @@ -897,6 +879,7 @@ static void CheckNameToMib() { threw = false; try { sysctlnametomib_nid_postfix("hw.ncpu", mib, nullptr); + } catch (const std::invalid_argument&) { threw = true; } @@ -935,7 +918,7 @@ int main() { *__error_nid_postfix() = 13; Require(sysconf_nid_postfix(1) == 262144); Require(sysconf_nid_postfix(3) == 128); - GuestRlimitTest nofileLimit{}; + GuestResourceLimit nofileLimit{}; Require(getrlimit_nid_postfix(8, &nofileLimit) == 0); Require(sysconf_nid_postfix(5) == nofileLimit.rlim_cur); Require(sysconf_nid_postfix(47) == 0x4000); diff --git a/core/libs/tests/GuestSystemExit.cpp b/core/libs/tests/GuestSystemExit.cpp index 612272c35b..a760b7a5b9 100644 --- a/core/libs/tests/GuestSystemExit.cpp +++ b/core/libs/tests/GuestSystemExit.cpp @@ -1,3 +1,5 @@ +#include "prx/libc/include/Api.hpp" +#include "prx/libSceSystemService/include/SystemService.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libc/include/Shutdown.hpp" #include "prx/libSceSystemService/SystemService.hpp" @@ -22,14 +24,9 @@ #include #include #endif -extern "C" int APS5_VABI sceSystemServiceLoadExec(const char*, const char* const*); -extern "C" int APS5_VABI __cxa_atexit_nid_postfix(void (APS5_VABI *func)(void*), void* arg, void* dsoHandle); -extern "C" void APS5_VABI _Exit_nid_postfix(int); -extern "C" void APS5_VABI exit_nid_postfix(int); -extern "C" void APS5_VABI catchReturnFromMain_nid_postfix(int); + using GuestQuickExitCallback = void (APS5_VABI*)(); -extern "C" int APS5_VABI at_quick_exit_nid_postfix(GuestQuickExitCallback); -extern "C" void APS5_VABI quick_exit_nid_postfix(int); + namespace { std::atomic awaiting{false}; void AwaitExit() { @@ -243,6 +240,7 @@ int main(int argc, char** argv) { LibcSetEndFlush_nid_no_patch(ExitFlushAfterDrain); } _Exit_nid_postfix(7); + } if (argc > firstArgument && std::strcmp(argv[firstArgument], "--requested-exit-driver") == 0) { Require(RunChild(OwnExecutable(), "--requested-exit") == 0); @@ -256,16 +254,19 @@ int main(int argc, char** argv) { Require(slot != FLS_OUT_OF_INDEXES && FlsSetValue(slot, &slot)); #endif _Exit_nid_postfix(0); + return 2; } if (argc > firstArgument && std::strcmp(argv[firstArgument], "--return-from-main") == 0) { catchReturnFromMain_nid_postfix(0); + return 2; } if (argc > firstArgument && std::strcmp(argv[firstArgument], "--quick-exit") == 0) { Require(at_quick_exit_nid_postfix(QuickFirst) == 0); Require(at_quick_exit_nid_postfix(QuickSecond) == 0); quick_exit_nid_postfix(0); + return 2; } if (argc > firstArgument && std::strcmp(argv[firstArgument], "--nested-exit-driver") == 0) { @@ -277,6 +278,7 @@ int main(int argc, char** argv) { Require(__cxa_atexit_nid_postfix(CheckShutdownStillRunning, nullptr, nullptr) == 0); Require(__cxa_atexit_nid_postfix(ExitingHandler, nullptr, nullptr) == 0); exit_nid_postfix(0); + return 2; } if (argc > firstArgument && std::strcmp(argv[firstArgument], "--exit-order-driver") == 0) { @@ -286,6 +288,7 @@ int main(int argc, char** argv) { LibcRegisterShutdown_nid_postfix(GuestExitShutdown); Require(__cxa_atexit_nid_postfix(CheckShutdownStillRunning, nullptr, nullptr) == 0); exit_nid_postfix(0); + return 2; } if (argc > firstArgument && std::strcmp(argv[firstArgument], "--relaunch-driver") == 0) { diff --git a/core/libs/tests/GuestSystemFont.cpp b/core/libs/tests/GuestSystemFont.cpp index f11c62d607..5195bee16c 100644 --- a/core/libs/tests/GuestSystemFont.cpp +++ b/core/libs/tests/GuestSystemFont.cpp @@ -1,3 +1,5 @@ +#include "prx/libSceFontFt/include/Api.hpp" +#include "prx/libSceFont/include/Api.hpp" #include "prx/libSceFont/include/FontTypes.hpp" #include #include @@ -17,31 +19,6 @@ #include #endif -extern "C" { -int APS5_VABI sceFontMemoryInit(FontMemory*, void*, std::uint32_t, const FontMemoryInterface*, void*, FontMemoryDestroyFunction, void*); -int APS5_VABI sceFontCreateLibrary(const FontMemory*, const void*, FontLibrary*); -int APS5_VABI sceFontDestroyLibrary(FontLibrary*); -int APS5_VABI sceFontSupportSystemFonts(FontLibrary); -int APS5_VABI sceFontSupportExternalFonts(FontLibrary, std::uint32_t, std::uint32_t); -int APS5_VABI sceFontOpenFontSet(FontLibrary, std::uint32_t, std::uint32_t, const FontOpenDetail*, FontHandle*); -int APS5_VABI sceFontOpenFontMemory(FontLibrary, const void*, std::uint32_t, const FontOpenDetail*, FontHandle*); -int APS5_VABI sceFontOpenFontInstance(FontHandle, FontHandle, FontHandle*); -int APS5_VABI sceFontCloseFont(FontHandle); -int APS5_VABI sceFontSetScalePixel(FontHandle, float, float); -int APS5_VABI sceFontGetCharGlyphMetrics(FontHandle, std::uint32_t, FontGlyphMetrics*); -int APS5_VABI sceFontGetHorizontalLayout(FontHandle, FontHorizontalLayout*); -int APS5_VABI sceFontGetKerning(FontHandle, std::uint32_t, std::uint32_t, FontKerning*); -int APS5_VABI sceFontCreateRenderer(const FontMemory*, const void*, FontRenderer*); -int APS5_VABI sceFontDestroyRenderer(FontRenderer*); -int APS5_VABI sceFontBindRenderer(FontHandle, FontRenderer); -int APS5_VABI sceFontUnbindRenderer(FontHandle); -int APS5_VABI sceFontSetupRenderScalePixel(FontHandle, float, float); -void APS5_VABI sceFontRenderSurfaceInit(FontRenderSurface*, void*, int, int, int, int); -int APS5_VABI sceFontRenderCharGlyphImageHorizontal(FontHandle, std::uint32_t, FontRenderSurface*, float, float, FontGlyphMetrics*, FontRenderOutput*); -const void* APS5_VABI sceFontSelectLibraryFt(int); -const void* APS5_VABI sceFontSelectRendererFt(int); -} - static void Check(bool value, int line) { if (!value) { std::fprintf(stderr, "System font check failed at line %d\n", line); @@ -187,6 +164,7 @@ static int RenderedPixels(FontHandle font, std::uint32_t code, float& advance) { std::vector pixels(128 * 128); FontRenderSurface surface{}; sceFontRenderSurfaceInit(&surface, pixels.data(), 128, 1, 128, 128); + FontGlyphMetrics metrics{}; FontRenderOutput result{}; const int rc = sceFontRenderCharGlyphImageHorizontal(font, code, &surface, 10.0f, 100.0f, &metrics, &result); @@ -239,6 +217,7 @@ int main() { bool threw = false; try { sceFontOpenFontSet(library, EuropeanBold, 1, nullptr, &font); + } catch (const std::runtime_error&) { threw = true; } @@ -341,6 +320,7 @@ int main() { std::vector untouched(128 * 128); FontRenderSurface measuring{}; sceFontRenderSurfaceInit(&measuring, untouched.data(), 0, 1, 0, 31); + FontGlyphMetrics measured{}; FontRenderOutput measuredResult{}; Require(sceFontRenderCharGlyphImageHorizontal(mixed, 'A', &measuring, 10.0f, 100.0f, &measured, &measuredResult) == SCE_FONT_OK); @@ -348,13 +328,17 @@ int main() { Require(measuredResult.UpdateRect.w == 0 && measuredResult.UpdateRect.h == 0); for (const std::uint8_t pixel : untouched) Require(pixel == 0); sceFontRenderSurfaceInit(&measuring, untouched.data(), 128, 1, 128, 0); + Require(sceFontRenderCharGlyphImageHorizontal(mixed, 'A', &measuring, 10.0f, 100.0f, &measured, &measuredResult) == SCE_FONT_OK && measured.Horizontal.advance == 60.0f); sceFontRenderSurfaceInit(&measuring, untouched.data(), 128, 1, 128, 128); + measuring.width = -1; Require(sceFontRenderCharGlyphImageHorizontal(mixed, 'A', &measuring, 10.0f, 100.0f, &measured, &measuredResult) == SCE_FONT_ERROR_NO_SUPPORT_SURFACE); sceFontRenderSurfaceInit(&measuring, untouched.data(), 0, 1, 128, 128); + Require(sceFontRenderCharGlyphImageHorizontal(mixed, 'A', &measuring, 10.0f, 100.0f, &measured, &measuredResult) == SCE_FONT_ERROR_NO_SUPPORT_SURFACE); sceFontRenderSurfaceInit(&measuring, nullptr, 0, 1, 0, 31); + Require(sceFontRenderCharGlyphImageHorizontal(mixed, 'A', &measuring, 10.0f, 100.0f, &measured, &measuredResult) == SCE_FONT_ERROR_NO_SUPPORT_SURFACE); Require(sceFontUnbindRenderer(mixed) == SCE_FONT_OK); Require(sceFontDestroyRenderer(&renderer) == SCE_FONT_OK); diff --git a/core/libs/tests/GuestSystemGesture.cpp b/core/libs/tests/GuestSystemGesture.cpp index c1e62e8934..23970e8b82 100644 --- a/core/libs/tests/GuestSystemGesture.cpp +++ b/core/libs/tests/GuestSystemGesture.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceSystemGesture/include/Api.hpp" #include "SceTypes.hpp" #include "prx/libc/include/general/VabiMacros.hpp" @@ -9,31 +10,6 @@ #include #include -extern "C" { -int APS5_VABI sceSystemGestureClose(std::int32_t); -std::int32_t APS5_VABI sceSystemGestureOpen(std::int32_t, const void*); -int APS5_VABI sceSystemGestureGetPrimitiveTouchEvents(std::int32_t, void*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceSystemGestureGetPrimitiveTouchEventsCount(std::int32_t); -int APS5_VABI sceSystemGestureGetTouchEvents(std::int32_t, const void*, void*, std::uint32_t, std::uint32_t*); -int APS5_VABI sceSystemGestureGetPrimitiveTouchEventByIndex(std::int32_t, std::uint32_t, void*); -int APS5_VABI sceSystemGestureGetTouchEventByIndex(std::int32_t, const void*, std::uint32_t, void*); -int APS5_VABI sceSystemGestureGetTouchEventByEventID(std::int32_t, const void*, std::uint32_t, void*); -int APS5_VABI sceSystemGestureAppendTouchRecognizer(std::int32_t, void*); -int APS5_VABI sceSystemGestureCreateTouchRecognizer(std::int32_t, void*, std::int32_t, const void*, const void*); -int APS5_VABI sceSystemGestureGetTouchRecognizerInformation(std::int32_t, const void*, void*); -int APS5_VABI sceSystemGestureRemoveTouchRecognizer(std::int32_t, void*); -int APS5_VABI sceSystemGestureResetTouchRecognizer(std::int32_t, void*); -int APS5_VABI sceSystemGestureUpdateTouchRecognizer(std::int32_t, void*); -int APS5_VABI sceSystemGestureUpdateTouchRecognizerRectangle(std::int32_t, void*, const void*); -int APS5_VABI sceSystemGestureResetPrimitiveTouchRecognizer(std::int32_t); -int APS5_VABI sceSystemGestureUpdateAllTouchRecognizer(std::int32_t); -int APS5_VABI sceSystemGestureUpdatePrimitiveTouchRecognizer(std::int32_t, const SystemGestureTouchPadData*); -int APS5_VABI sceSystemGestureInitializePrimitiveTouchRecognizer(); -int APS5_VABI sceSystemGestureFinalizePrimitiveTouchRecognizer(void); -int APS5_VABI sceSystemGestureGetPrimitiveTouchEventByPrimitiveID(std::int32_t, std::uint16_t, void*); -int APS5_VABI sceSystemGestureDebugGetVersion(void); -} - static void Require(bool value) { if (!value) std::abort(); } static bool SameRectangle(const SystemGestureRectangle& left, const SystemGestureRectangle& right) { @@ -229,13 +205,13 @@ int main() { buffer.fill(0x5a); const auto original = buffer; std::uint32_t count = 7; - Require(sceSystemGestureGetPrimitiveTouchEvents(handle, buffer.data(), 4, &count) == 0); + Require(sceSystemGestureGetPrimitiveTouchEvents(handle, reinterpret_cast(buffer.data()), 4, &count) == 0); Require(count == 0); Require(buffer == original); count = 7; - Require(sceSystemGestureGetPrimitiveTouchEvents(handle, buffer.data(), 4, nullptr) == invalidArgument); - Require(sceSystemGestureGetPrimitiveTouchEvents(handle + 1, buffer.data(), 4, &count) == invalidHandle); + Require(sceSystemGestureGetPrimitiveTouchEvents(handle, reinterpret_cast(buffer.data()), 4, nullptr) == invalidArgument); + Require(sceSystemGestureGetPrimitiveTouchEvents(handle + 1, reinterpret_cast(buffer.data()), 4, &count) == invalidHandle); Require(count == 7); Require(sceSystemGestureGetPrimitiveTouchEventsCount(handle) == 0); @@ -245,17 +221,17 @@ int main() { SystemGestureTouchRecognizer recognizer{}; SystemGestureRectangle rectangle{}; count = 7; - Require(sceSystemGestureGetTouchEvents(handle, &recognizer, buffer.data(), 4, &count) == 0 && count == 0); - Require(sceSystemGestureGetTouchEvents(handle, &recognizer, buffer.data(), 4, nullptr) == invalidArgument); - Require(sceSystemGestureGetTouchEvents(handle + 1, &recognizer, buffer.data(), 4, &count) == invalidHandle); - Require(sceSystemGestureGetPrimitiveTouchEventByIndex(handle, 0, buffer.data()) == indexOutOfArray); - Require(sceSystemGestureGetPrimitiveTouchEventByIndex(handle + 1, 0, buffer.data()) == invalidHandle); - Require(sceSystemGestureGetTouchEventByIndex(handle, &recognizer, 0, buffer.data()) == indexOutOfArray); - Require(sceSystemGestureGetTouchEventByIndex(handle + 1, &recognizer, 0, buffer.data()) == invalidHandle); - Require(sceSystemGestureGetTouchEventByIndex(handle, nullptr, 0, buffer.data()) == invalidArgument); - Require(sceSystemGestureGetTouchEventByEventID(handle, &recognizer, 0, buffer.data()) == indexOutOfArray); - Require(sceSystemGestureGetTouchEventByEventID(handle + 1, &recognizer, 0, buffer.data()) == invalidHandle); - Require(sceSystemGestureGetTouchEventByEventID(handle, nullptr, 0, buffer.data()) == invalidArgument); + Require(sceSystemGestureGetTouchEvents(handle, &recognizer, reinterpret_cast(buffer.data()), 4, &count) == 0 && count == 0); + Require(sceSystemGestureGetTouchEvents(handle, &recognizer, reinterpret_cast(buffer.data()), 4, nullptr) == invalidArgument); + Require(sceSystemGestureGetTouchEvents(handle + 1, &recognizer, reinterpret_cast(buffer.data()), 4, &count) == invalidHandle); + Require(sceSystemGestureGetPrimitiveTouchEventByIndex(handle, 0, reinterpret_cast(buffer.data())) == indexOutOfArray); + Require(sceSystemGestureGetPrimitiveTouchEventByIndex(handle + 1, 0, reinterpret_cast(buffer.data())) == invalidHandle); + Require(sceSystemGestureGetTouchEventByIndex(handle, &recognizer, 0, reinterpret_cast(buffer.data())) == indexOutOfArray); + Require(sceSystemGestureGetTouchEventByIndex(handle + 1, &recognizer, 0, reinterpret_cast(buffer.data())) == invalidHandle); + Require(sceSystemGestureGetTouchEventByIndex(handle, nullptr, 0, reinterpret_cast(buffer.data())) == invalidArgument); + Require(sceSystemGestureGetTouchEventByEventID(handle, &recognizer, 0, reinterpret_cast(buffer.data())) == indexOutOfArray); + Require(sceSystemGestureGetTouchEventByEventID(handle + 1, &recognizer, 0, reinterpret_cast(buffer.data())) == invalidHandle); + Require(sceSystemGestureGetTouchEventByEventID(handle, nullptr, 0, reinterpret_cast(buffer.data())) == invalidArgument); Require(buffer == original); Require(sceSystemGestureAppendTouchRecognizer(handle, &recognizer) == 0); diff --git a/core/libs/tests/GuestSystemKillApp.cpp b/core/libs/tests/GuestSystemKillApp.cpp index 3ebfe28013..b42f9d8de6 100644 --- a/core/libs/tests/GuestSystemKillApp.cpp +++ b/core/libs/tests/GuestSystemKillApp.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceSystemService/include/SystemService.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libc/include/Shutdown.hpp" #include @@ -5,10 +6,7 @@ #include #include #include -extern "C" int APS5_VABI sceSystemServiceGetAppIdOfRunningBigApp(void); -extern "C" int APS5_VABI sceSystemServiceKillApp(int, int, int, int); -extern "C" int APS5_VABI sceLncUtilKillApp(unsigned); -extern "C" int APS5_VABI sceLncUtilKillAppWithReason(unsigned, int); + namespace { bool cleaned = false; bool finished = false; diff --git a/core/libs/tests/GuestSystemService.cpp b/core/libs/tests/GuestSystemService.cpp index 9ad6c43d4c..8a197d97b5 100644 --- a/core/libs/tests/GuestSystemService.cpp +++ b/core/libs/tests/GuestSystemService.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceSystemService/include/SystemService.hpp" #include "SceTypes.hpp" #include "prx/libSceSystemService/SystemService.hpp" #include @@ -7,12 +8,6 @@ #include #include -extern "C" int APS5_VABI sceSystemServiceGetHdrToneMapLuminance(SystemServiceHdrToneMapLuminance* luminance); -extern "C" int APS5_VABI sceSystemServiceParamGetString(int paramId, char* buf, std::size_t bufSize); -extern "C" int APS5_VABI sceSystemServiceLaunchApp(const char* titleId, const char* const* arguments, const void* param); -extern "C" int APS5_VABI sceSystemServiceAddLocalProcessForPsmKit(const char* path, const char* const* arguments, const void* param); -extern "C" int APS5_VABI sceSystemServiceKillLocalProcessForPsmKit(int handle); - namespace { constexpr int browserUnavailable = static_cast(0x8002002Du); @@ -40,27 +35,6 @@ bool LaunchAppThrows(const char* titleId, const char* const* arguments, const vo } -extern "C" int APS5_VABI sceSystemServicePowerTick(void); -extern "C" int APS5_VABI sceSystemServiceIsBgmPlaying(void); -extern "C" int APS5_VABI sceShellCoreUtilIsBgmPlaying(void); -extern "C" int APS5_VABI sceSystemServiceReportAbnormalTermination(const void* info); -extern "C" int APS5_VABI sceSystemServiceDisableMusicPlayer(void); -extern "C" int APS5_VABI sceSystemServiceReenableMusicPlayer(void); -extern "C" int APS5_VABI sceSystemServiceDisableMediaPlay(void); -extern "C" int APS5_VABI sceSystemServiceReenableMediaPlay(void); -extern "C" int APS5_VABI sceSystemServiceLaunchWebBrowser(const char* uri); -extern "C" int APS5_VABI sceSystemServiceShowControllerSettings(void); -extern "C" int APS5_VABI sceSystemServiceShowDisplaySafeAreaSettings(void); -extern "C" int APS5_VABI sceSystemServiceOpenChallengeActivity(void); -extern "C" int APS5_VABI sceSystemServiceGetStatus(SystemServiceStatus* status); -extern "C" int APS5_VABI sceSystemServiceGetDisplaySafeAreaInfo(SystemServiceDisplaySafeAreaInfo* info); -extern "C" int APS5_VABI sceSystemServiceGetNoticeScreenSkipFlag(bool* value); -extern "C" int APS5_VABI sceSystemServiceSetNoticeScreenSkipFlag(void); -extern "C" int APS5_VABI sceSystemServiceDisableNoticeScreenSkipFlagAutoSet(void); -extern "C" int APS5_VABI sceSystemServiceHideSplashScreen(void); -extern "C" int APS5_VABI sceSystemServiceReceiveEvent(SystemServiceEvent* event); -extern "C" void APS5_VABI sceSystemServiceInitializePlayerDialogParam(SystemServicePlayerDialogParam* param); - namespace { void TestPlayerDialogParam() { diff --git a/core/libs/tests/GuestSystemServiceAppTitleId.cpp b/core/libs/tests/GuestSystemServiceAppTitleId.cpp index 2331f59411..7fee52ec8e 100644 --- a/core/libs/tests/GuestSystemServiceAppTitleId.cpp +++ b/core/libs/tests/GuestSystemServiceAppTitleId.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceSystemService/include/SystemService.hpp" #include "SceTypes.hpp" #include #include @@ -7,11 +8,6 @@ #include #include -extern "C" int APS5_VABI sceSystemServiceGetAppIdOfRunningBigApp(void); -extern "C" int APS5_VABI sceSystemServiceGetAppId(const char* titleId); -extern "C" int APS5_VABI sceSystemServiceGetAppTitleId(int appId, char* titleId); -extern "C" int APS5_VABI sceLncUtilGetAppTitleId(std::int32_t appId, char* titleId); - namespace { constexpr char Sentinel = 0x5A; diff --git a/core/libs/tests/GuestSystemServiceLanguage.cpp b/core/libs/tests/GuestSystemServiceLanguage.cpp index 2be7c170c6..8e1aefdf3a 100644 --- a/core/libs/tests/GuestSystemServiceLanguage.cpp +++ b/core/libs/tests/GuestSystemServiceLanguage.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceSystemService/include/SystemService.hpp" #include "SceTypes.hpp" #include "prx/libSceSystemService/SystemService.hpp" #include @@ -6,8 +7,6 @@ #include #include -extern "C" int APS5_VABI sceSystemServiceParamGetInt(int paramId, int* value); - namespace { void Require(bool value) { if (!value) std::abort(); } diff --git a/core/libs/tests/GuestSystemServiceLoadExecStandardError.cpp b/core/libs/tests/GuestSystemServiceLoadExecStandardError.cpp index ec83ac1c10..777c63ba32 100644 --- a/core/libs/tests/GuestSystemServiceLoadExecStandardError.cpp +++ b/core/libs/tests/GuestSystemServiceLoadExecStandardError.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libSceSystemService/include/SystemService.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -6,11 +8,6 @@ #include #include -extern "C" { -int APS5_VABI sceSystemServiceLoadExec(const char*, const char* const*); -int APS5_VABI dup2_nid_postfix(int, int); -} - namespace { constexpr const char* Marker = "APS5_LOAD_EXEC_STANDARD_ERROR"; diff --git a/core/libs/tests/GuestSystemServicePathBoundary.cpp b/core/libs/tests/GuestSystemServicePathBoundary.cpp index da8e6927f0..8d80cb489a 100644 --- a/core/libs/tests/GuestSystemServicePathBoundary.cpp +++ b/core/libs/tests/GuestSystemServicePathBoundary.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceSystemService/include/SystemService.hpp" #include "prx/libc/include/Shutdown.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -8,8 +9,6 @@ #include #include -extern "C" int APS5_VABI sceSystemServiceLoadExec(const char*, const char* const*); - namespace { void Require(bool value) { diff --git a/core/libs/tests/GuestSystemServiceTimeZone.cpp b/core/libs/tests/GuestSystemServiceTimeZone.cpp index 7f61bcf1fe..cb0e4c65c8 100644 --- a/core/libs/tests/GuestSystemServiceTimeZone.cpp +++ b/core/libs/tests/GuestSystemServiceTimeZone.cpp @@ -1,10 +1,9 @@ +#include "prx/libSceSystemService/include/SystemService.hpp" #include "SceTypes.hpp" #include "prx/libSceSystemService/SystemService.hpp" #include #include -extern "C" int APS5_VABI sceSystemServiceParamGetInt(int paramId, int* value); - namespace { void Require(bool value) { if (!value) std::abort(); } diff --git a/core/libs/tests/GuestTcp.cpp b/core/libs/tests/GuestTcp.cpp index 11fe4a9366..71878e7021 100644 --- a/core/libs/tests/GuestTcp.cpp +++ b/core/libs/tests/GuestTcp.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -8,24 +10,6 @@ #include #include -extern "C" { -int APS5_VABI socket_nid_postfix(int, int, int); -int APS5_VABI bind_nid_postfix(int, const void*, std::uint32_t); -int APS5_VABI listen_nid_postfix(int, int); -int APS5_VABI getsockname_nid_postfix(int, void*, std::uint32_t*); -int APS5_VABI connect_nid_postfix(int, const void*, std::uint32_t); -int APS5_VABI accept_nid_postfix(int, void*, std::uint32_t*); -std::int64_t APS5_VABI send_nid_postfix(int, const void*, std::uint64_t, int); -std::int64_t APS5_VABI recv_nid_postfix(int, void*, std::uint64_t, int); -std::int64_t APS5_VABI sendto_nid_postfix(int, const void*, std::uint64_t, int, const void*, std::uint32_t); -int APS5_VABI getpeername_nid_postfix(int, void*, std::uint32_t*); -int APS5_VABI shutdown_nid_postfix(int, int); -std::int64_t APS5_VABI recvfrom_nid_postfix(int, void*, std::uint64_t, int, void*, std::uint32_t*); -int APS5_VABI fcntl_nid_postfix(int, int, ...); -int APS5_VABI close_nid_postfix(int); -int* APS5_VABI __error_nid_postfix(); -} - static void Require(bool condition) { if (!condition) std::abort(); } diff --git a/core/libs/tests/GuestTerminal.cpp b/core/libs/tests/GuestTerminal.cpp index ad27b96a30..8fabd1454f 100644 --- a/core/libs/tests/GuestTerminal.cpp +++ b/core/libs/tests/GuestTerminal.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -8,24 +10,6 @@ #include #include -extern "C" { -int APS5_VABI tcgetattr_nid_postfix(int, void*); -int APS5_VABI tcsetattr_nid_postfix(int, int, const void*); -int APS5_VABI tcsendbreak_nid_postfix(int, int); -int APS5_VABI tcdrain_nid_postfix(int); -int APS5_VABI tcflush_nid_postfix(int, int); -int APS5_VABI tcflow_nid_postfix(int, int); -int APS5_VABI tcgetpgrp_nid_postfix(int); -int APS5_VABI tcsetpgrp_nid_postfix(int, int); -int APS5_VABI open_nid_postfix(const char*, int, int); -int APS5_VABI pipe_nid_postfix(int*); -int APS5_VABI socket_nid_postfix(int, int, int); -int APS5_VABI socketpair_nid_postfix(int, int, int, int*); -int APS5_VABI mkdir_nid_postfix(const char*, unsigned short); -int APS5_VABI close_nid_postfix(int); -int* APS5_VABI __error_nid_postfix(); -} - static void Check(bool value, int line) { if (!value) { std::fprintf(stderr, "terminal check failed at line %d, errno %d\n", line, *__error_nid_postfix()); diff --git a/core/libs/tests/GuestTermiosSpeed.cpp b/core/libs/tests/GuestTermiosSpeed.cpp index cc0a4c76b4..1ad51b5903 100644 --- a/core/libs/tests/GuestTermiosSpeed.cpp +++ b/core/libs/tests/GuestTermiosSpeed.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -14,8 +15,6 @@ #include #endif -extern "C" int* APS5_VABI __error_nid_postfix(); - namespace { using SetSpeed = int (APS5_VABI*)(void*, std::uint32_t); diff --git a/core/libs/tests/GuestTextToSpeech2.cpp b/core/libs/tests/GuestTextToSpeech2.cpp index 93de9dc755..13cab7e16c 100644 --- a/core/libs/tests/GuestTextToSpeech2.cpp +++ b/core/libs/tests/GuestTextToSpeech2.cpp @@ -1,24 +1,14 @@ +#include "prx/libSceTextToSpeech2/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include #include -extern "C" { -std::int32_t APS5_VABI sceTextToSpeech2Initialize(const void* param); -int APS5_VABI sceTextToSpeech2Open(const void* parameter); -int APS5_VABI sceTextToSpeech2Cancel(); -int APS5_VABI sceTextToSpeech2Close(); -int APS5_VABI sceTextToSpeech2GetSpeechStatus(std::int32_t* status); -int APS5_VABI sceTextToSpeech2Speak(const void* parameter); -int APS5_VABI sceTextToSpeech2Terminate(); -int APS5_VABI sceTextToSpeech2GetSystemStatus(std::int32_t* status); -} - int main() { constexpr std::int32_t unsupported = static_cast(0x8002002D); const std::uint32_t param[16]{0x2000000, 0x26c}; - if (sceTextToSpeech2Initialize(param) != unsupported) { + if (sceTextToSpeech2Initialize(reinterpret_cast(param)) != unsupported) { std::puts("TextToSpeech2: initialization did not report the unsupported operation"); std::abort(); } diff --git a/core/libs/tests/GuestThermalSensors.cpp b/core/libs/tests/GuestThermalSensors.cpp index 3c051911a6..2fcdb8a5a7 100644 --- a/core/libs/tests/GuestThermalSensors.cpp +++ b/core/libs/tests/GuestThermalSensors.cpp @@ -1,3 +1,4 @@ +#include "prx/libkernel/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libkernel/KernelErrors.hpp" #include @@ -11,9 +12,7 @@ extern "C" { void ReadThermalSensors_nid_no_patch(const char* root, int celsius[3]); -int APS5_VABI sceKernelGetCpuTemperature(int* outCelsius); -int APS5_VABI sceKernelGetSocSensorTemperature(int sensorId, int* outCelsius); -int APS5_VABI sceKernelGetSocPowerConsumption(void* consumption); + } static void Require(bool value) { diff --git a/core/libs/tests/GuestThreadAtexit.cpp b/core/libs/tests/GuestThreadAtexit.cpp index f37fd5d526..ebcfc1eeeb 100644 --- a/core/libs/tests/GuestThreadAtexit.cpp +++ b/core/libs/tests/GuestThreadAtexit.cpp @@ -1,17 +1,11 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libSceLibcInternal/include/Api.hpp" #include "SceTypes.hpp" #include #include #include #include -extern "C" { -int APS5_VABI scePthreadCreate(Pthread* thread, const PthreadAttr* attr, PthreadEntry entry, void* arg, const char* name); -int APS5_VABI scePthreadJoin(Pthread thread, void** retval); -Pthread APS5_VABI scePthreadSelf(); -int APS5_VABI _sceLibcInternalThreadAtexit_nid_postfix(void (APS5_VABI* destructor)(void*), void* object, void* dsoSymbol); -void APS5_VABI _sceLibcInternalThreadDtors_nid_postfix(); -} - namespace { using Destructor = void (APS5_VABI*)(void*); @@ -47,6 +41,7 @@ void* APS5_VABI Worker(void*) { bool DestructorsThrow() { try { _sceLibcInternalThreadDtors_nid_postfix(); + } catch (const std::runtime_error&) { return true; } @@ -61,9 +56,11 @@ int main() { Require(Register(RecordAndRegister, 2) == 0); Require(Register(Record, 3) == 0); _sceLibcInternalThreadDtors_nid_postfix(); + Require(calls == std::vector{3, 2, 9, 1}); Require(callers == std::vector(4, mainThread)); _sceLibcInternalThreadDtors_nid_postfix(); + Require(calls.size() == 4); calls.clear(); @@ -83,5 +80,6 @@ int main() { Require(DestructorsThrow()); Require(calls.empty()); _sceLibcInternalThreadDtors_nid_postfix(); + Require(calls == std::vector{6}); } diff --git a/core/libs/tests/GuestThreadCallbackAbi.cpp b/core/libs/tests/GuestThreadCallbackAbi.cpp index 4fe7aa04ca..a5e6abb9f6 100644 --- a/core/libs/tests/GuestThreadCallbackAbi.cpp +++ b/core/libs/tests/GuestThreadCallbackAbi.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -12,12 +13,6 @@ using GuestDestructor = void(APS5_VABI *)(void*); -extern "C" { -int APS5_VABI __cxa_thread_atexit_impl_nid_postfix(GuestDestructor, void*, void*); -int APS5_VABI __cxa_thread_atexit_nid_postfix(GuestDestructor, void*, void*); -int APS5_VABI LibcInternalExtCxaThreadAtexit_nid_postfix(GuestDestructor, void*, void*); -} - namespace { struct Call { diff --git a/core/libs/tests/GuestThreadCpuClock.cpp b/core/libs/tests/GuestThreadCpuClock.cpp index 15946c4aec..5d5aabcff7 100644 --- a/core/libs/tests/GuestThreadCpuClock.cpp +++ b/core/libs/tests/GuestThreadCpuClock.cpp @@ -1,3 +1,7 @@ +#include "prx/libkernel/KernelErrors.hpp" +#include "prx/libkernel/include/Api.hpp" +#include "prx/libkernel/Time/include/Time.hpp" +#include "prx/libc/include/Api.hpp" #include "SceTypes.hpp" #include #include @@ -5,20 +9,8 @@ #include #include -extern "C" { -int APS5_VABI pthread_getcpuclockid_nid_postfix(Pthread thread, int* clockId); -Pthread APS5_VABI pthread_self_nid_postfix(void); -int APS5_VABI clock_gettime_nid_postfix(int clockId, KernelTimespec* tp); -int APS5_VABI clock_getres_nid_postfix(int clockId, KernelTimespec* res); -int APS5_VABI scePthreadCreate(Pthread* thread, const PthreadAttr* attr, PthreadEntry entry, void* arg, const char* name); -int APS5_VABI scePthreadJoin(Pthread thread, void** retval); -int APS5_VABI sceKernelClockGettime(KernelClockid clockId, KernelTimespec* tp); -int* APS5_VABI __error_nid_postfix(); -} - static constexpr int GUEST_EFAULT = 14; static constexpr int GUEST_EINVAL = 22; -static constexpr int SCE_KERNEL_ERROR_EINVAL = static_cast(0x80020016); static constexpr int GUEST_CLOCK_MONOTONIC = 4; static constexpr int GUEST_CLOCK_THREAD_CPUTIME_ID = 14; static constexpr std::int64_t NANOS_PER_SECOND = 1000000000LL; diff --git a/core/libs/tests/GuestThreadSanitizer.cpp b/core/libs/tests/GuestThreadSanitizer.cpp index 4403a31564..7c69247cd9 100644 --- a/core/libs/tests/GuestThreadSanitizer.cpp +++ b/core/libs/tests/GuestThreadSanitizer.cpp @@ -1,8 +1,7 @@ +#include "prx/libkernel/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include -extern "C" int APS5_VABI sceKernelIsThreadSanitizerEnabled(void); - int main() { if (sceKernelIsThreadSanitizerEnabled() != 0) std::abort(); return 0; diff --git a/core/libs/tests/GuestThreadSelf.cpp b/core/libs/tests/GuestThreadSelf.cpp index 87e38f6c0a..ae09ff38d4 100644 --- a/core/libs/tests/GuestThreadSelf.cpp +++ b/core/libs/tests/GuestThreadSelf.cpp @@ -1,3 +1,7 @@ +#include "prx/libkernel/KernelErrors.hpp" +#include "prx/libkernel/include/Api.hpp" +#include "prx/libkernel/Pthread/include/ThreadLifecycle.hpp" +#include "prx/libkernel/Pthread/include/Mutex.hpp" #include "SceTypes.hpp" #include #include @@ -9,38 +13,6 @@ #include #endif -extern "C" { -int APS5_VABI scePthreadCreate(Pthread* thread, const PthreadAttr* attr, PthreadEntry entry, void* arg, const char* name); -int APS5_VABI scePthreadJoin(Pthread thread, void** retval); -int APS5_VABI scePthreadDetach(Pthread thread); -int APS5_VABI pthread_join_nid_postfix(Pthread thread, void** value); -int APS5_VABI pthread_detach_nid_postfix(Pthread thread); -void APS5_VABI scePthreadExit(void* retval); -Pthread APS5_VABI scePthreadSelf(); -int APS5_VABI scePthreadGetthreadid(void); -int APS5_VABI pthread_getthreadid_np_nid_postfix(void); -void APS5_VABI scePthreadTestcancel(); -void APS5_VABI pthread_testcancel_nid_postfix(void); -int APS5_VABI scePthreadSetcancelstate(int state, int* old_state); -int APS5_VABI scePthreadSetcanceltype(int type, int* old_type); -void APS5_VABI pthread_set_name_np_nid_postfix(Pthread thread, const char* name); -int APS5_VABI scePthreadGetname(Pthread thread, char* name); -int APS5_VABI scePthreadMutexattrInit(PthreadMutexattr* attr); -int APS5_VABI scePthreadMutexattrDestroy(PthreadMutexattr* attr); -int APS5_VABI scePthreadMutexattrSettype(PthreadMutexattr* attr, int type); -int APS5_VABI scePthreadMutexInit(PthreadMutex* mutex, const PthreadMutexattr* attr, const char* name); -int APS5_VABI scePthreadMutexDestroy(PthreadMutex* mutex); -int APS5_VABI scePthreadMutexLock(PthreadMutex* mutex); -int APS5_VABI scePthreadMutexUnlock(PthreadMutex* mutex); -int APS5_VABI scePthreadAttrInit(PthreadAttr* attr); -int APS5_VABI scePthreadAttrDestroy(PthreadAttr* attr); -int APS5_VABI scePthreadAttrGet(Pthread thread, PthreadAttr* attr); -int APS5_VABI scePthreadAttrGetstackaddr(const PthreadAttr* attr, void** stack_addr); -int APS5_VABI scePthreadAttrGetstacksize(const PthreadAttr* attr, size_t* stack_size); -int APS5_VABI mprotect_nid_postfix(void* address, std::size_t length, int protection) noexcept; -int APS5_VABI sceKernelIsStack(void* addr, void** start, void** end); -} - static bool StackContains(Pthread thread, const void* address) { PthreadAttr attr = nullptr; if (scePthreadAttrInit(&attr) != 0 || scePthreadAttrGet(thread, &attr) != 0) return false; @@ -48,20 +20,18 @@ static bool StackContains(Pthread thread, const void* address) { size_t size = 0; const bool queried = scePthreadAttrGetstackaddr(&attr, &stack) == 0 && scePthreadAttrGetstacksize(&attr, &size) == 0; scePthreadAttrDestroy(&attr); + const auto begin = reinterpret_cast(stack); const auto value = reinterpret_cast(address); return queried && stack != nullptr && size != 0 && value >= begin && value - begin < size; } static constexpr int SCE_OK = 0; -static constexpr int SCE_KERNEL_ERROR_EINVAL = 0x80020016; -static constexpr int SCE_KERNEL_ERROR_EPERM = 0x80020001; -static constexpr int SCE_KERNEL_ERROR_EDEADLK = 0x8002000b; static constexpr int GUEST_EDEADLK = 11; static constexpr int GUEST_EINVAL = 22; static constexpr int MUTEX_TYPE_RECURSIVE = 2; -static constexpr int PTHREAD_CANCEL_ENABLE = 0; -static constexpr int PTHREAD_CANCEL_ASYNCHRONOUS = 2; +static constexpr int GuestPthread_Cancel_Enable = 0; +static constexpr int GuestPthread_Cancel_Asynchronous = 2; static constexpr std::intptr_t WorkerRetval = 0x1234; static void Require(bool value) { if (!value) std::abort(); } @@ -78,6 +48,7 @@ static void ReportedStack(Pthread thread, std::uintptr_t* begin, std::uintptr_t* size_t size = 0; Require(scePthreadAttrGetstackaddr(&attr, &stack) == SCE_OK && scePthreadAttrGetstacksize(&attr, &size) == SCE_OK); scePthreadAttrDestroy(&attr); + *begin = reinterpret_cast(stack); *end = *begin + size; } @@ -165,12 +136,14 @@ static void* APS5_VABI Worker(void* arg) { context.posixJoinSelf = pthread_join_nid_postfix(context.selfFromWorker, nullptr); int oldState = -1; int oldType = -1; - context.testcancelReturned = scePthreadSetcancelstate(PTHREAD_CANCEL_ENABLE, &oldState) == SCE_OK && - scePthreadSetcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldType) == SCE_OK; + context.testcancelReturned = scePthreadSetcancelstate(GuestPthread_Cancel_Enable, &oldState) == SCE_OK && + scePthreadSetcanceltype(GuestPthread_Cancel_Asynchronous, &oldType) == SCE_OK; scePthreadTestcancel(); pthread_testcancel_nid_postfix(); - context.testcancelReturned = context.testcancelReturned && oldState == PTHREAD_CANCEL_ENABLE; + + context.testcancelReturned = context.testcancelReturned && oldState == GuestPthread_Cancel_Enable; scePthreadExit(reinterpret_cast(WorkerRetval)); + return nullptr; } @@ -229,14 +202,15 @@ int main() { scePthreadTestcancel(); pthread_testcancel_nid_postfix(); - Require(scePthreadMutexUnlock(&mutex) == SCE_OK); Require(scePthreadMutexDestroy(&mutex) == SCE_OK); char name[32] = {'x'}; pthread_set_name_np_nid_postfix(mainSelf, "q2-main"); + Require(scePthreadGetname(mainSelf, name) == SCE_OK && std::strcmp(name, "q2-main") == 0); pthread_set_name_np_nid_postfix(mainSelf, nullptr); + Require(scePthreadGetname(mainSelf, name) == SCE_OK && name[0] == '\0'); pthread_set_name_np_nid_postfix(nullptr, "ignored"); diff --git a/core/libs/tests/GuestTimeConversion.cpp b/core/libs/tests/GuestTimeConversion.cpp index 57e14fece0..abc96e55f2 100644 --- a/core/libs/tests/GuestTimeConversion.cpp +++ b/core/libs/tests/GuestTimeConversion.cpp @@ -1,3 +1,5 @@ +#include "prx/libc/include/SonyCrt.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libc/include/GuestTime.hpp" #include @@ -15,24 +17,11 @@ #include extern "C" { -GuestTm* APS5_VABI libc_gmtime_nid_postfix(const std::int64_t*); -GuestTm* APS5_VABI gmtime_nid_postfix(const std::int64_t*); -GuestTm* APS5_VABI libc_localtime_nid_postfix(const std::int64_t*); -GuestTm* APS5_VABI localtime_nid_postfix(const std::int64_t*); -GuestTm* APS5_VABI gmtime_s_nid_postfix(const std::int64_t*, GuestTm*); -GuestTm* APS5_VABI localtime_s_nid_postfix(const std::int64_t*, GuestTm*); -char* APS5_VABI asctime_nid_postfix(const GuestTm*); -std::int64_t APS5_VABI mktime_nid_postfix(GuestTm*); -std::size_t APS5_VABI strftime_nid_postfix(char*, std::size_t, const char*, const GuestTm*); -void APS5_VABI tzset_nid_postfix(void); + extern char* tzname_nid_postfix[2]; extern std::int64_t timezone_nid_postfix; extern int daylight_nid_postfix; -char* APS5_VABI ctime_nid_postfix(const std::int64_t*); -int* APS5_VABI __error_nid_postfix(); -int APS5_VABI setenv_nid_postfix(const char*, const char*, int); -double APS5_VABI libc_difftime_nid_postfix(std::int64_t, std::int64_t); -double APS5_VABI difftime_nid_postfix(std::int64_t, std::int64_t); + } using Converter = GuestTm* (APS5_VABI *)(const std::int64_t*); @@ -140,75 +129,41 @@ static void CheckBufferSize(const GuestTm& guest, const char* format, std::size_ Require(strftime_nid_postfix(buffer, 1, format, &guest) == 0, "strftime accepted a one byte buffer"); } -static const char* HostZoneName(int isdst) { -#ifdef _WIN32 - return _tzname[isdst != 0 ? 1 : 0]; -#else - return tzname[isdst != 0 ? 1 : 0]; -#endif -} -static void CheckFreeBsdConversions() { +static void CheckConsoleConversions() { const std::int64_t timer = 1700000000; GuestTm guest{}; Require(gmtime_s_nid_postfix(&timer, &guest) == &guest, "UTC conversion failed"); - CheckFormat(guest, "%k|%l", "22|10"); - CheckFormat(guest, "%v", "14-Nov-2023"); - CheckFormat(guest, "%+", "Tue Nov 14 22:13:20 UTC 2023"); - CheckFormat(guest, "%s", "1699992800"); + CheckFormat(guest, "%k|%l|%v|%+|%s", "%k|%l|%v|%+|%s"); CheckFormat(guest, "%%k %%l %%s %%v %%+", "%k %l %s %v %+"); - CheckFormat(guest, "%%%k", "%22"); - CheckFormat(guest, "[%k][%l]", "[22][10]"); - CheckFormat(guest, "%Ek|%Ol|%Os|%Ev|%O+", "22|10|1699992800|14-Nov-2023|Tue Nov 14 22:13:20 UTC 2023"); - CheckFormat(guest, "%E%k", "%k"); - CheckFormat(guest, "%O%l", "%l"); - CheckFormat(guest, "%E%s", "%s"); - CheckFormat(guest, "%E%v", "%v"); - CheckFormat(guest, "%O%+", "%+"); - CheckFormat(guest, "%k|%E%l|%l", "22|%l|10"); - CheckFormat(guest, "%E%", "%"); - CheckFormat(guest, "%O%%k", "%22"); - CheckFormat(guest, "%E%k%k", "%k22"); + CheckFormat(guest, "%Ek|%Ol|%Os|%Ev|%O+", "%k|%l|%s|%v|%+"); + CheckFormat(guest, "%Ec|%Ox|%EY|%Om", "Tue Nov 14 22:13:20 2023|11/14/23|2023|11"); + CheckFormat(guest, "%EE|%OO|%EO", "%E|%O|%O"); CheckBufferSize(guest, "%k", 2); - CheckBufferSize(guest, "%k:%l", 5); - CheckBufferSize(guest, "%+", 28); + CheckBufferSize(guest, "%c", 24); CheckBufferSize(guest, "%Ek", 2); + bool threw = false; + try { + char buffer[16]; + strftime_nid_postfix(buffer, sizeof(buffer), "ab%O", &guest); + } catch (const std::invalid_argument&) { + threw = true; + } + Require(threw, "strftime accepted a format ending after a modifier"); guest.tm_zone = "XYZ"; - CheckFormat(guest, "%+", "Tue Nov 14 22:13:20 XYZ 2023"); - CheckFormat(guest, "%O+", "Tue Nov 14 22:13:20 XYZ 2023"); - guest.tm_zone = "A%B"; - CheckFormat(guest, "%+", "Tue Nov 14 22:13:20 A%B 2023"); - guest.tm_zone = nullptr; guest.tm_isdst = 0; - char expected[96]; - std::snprintf(expected, sizeof(expected), "Tue Nov 14 22:13:20 %s 2023", HostZoneName(0)); - CheckFormat(guest, "%+", expected); + CheckFormat(guest, "%Z", tzname_nid_postfix[0]); guest.tm_isdst = 1; - std::snprintf(expected, sizeof(expected), "Tue Nov 14 22:13:20 %s 2023", HostZoneName(1)); - CheckFormat(guest, "%+", expected); + CheckFormat(guest, "%Z", tzname_nid_postfix[1]); guest.tm_isdst = 0; - GuestTm local{}; - Require(localtime_s_nid_postfix(&timer, &local) == &local, "Local conversion failed"); - GuestTm normalized = local; - const std::int64_t mktimeResult = mktime_nid_postfix(&normalized); - Require(mktimeResult == timer, "mktime did not invert localtime"); - std::snprintf(expected, sizeof(expected), "%lld", static_cast(mktimeResult)); - CheckFormat(local, "%s", expected); - CheckFormat(local, "%Os", expected); - guest.tm_hour = 0; - CheckFormat(guest, "%k|%l", " 0|12"); + CheckFormat(guest, "%I|%p", "12|AM"); guest.tm_hour = 12; - CheckFormat(guest, "%k|%l", "12|12"); - guest.tm_hour = 5; - guest.tm_mday = 5; - CheckFormat(guest, "%k|%l|%v", " 5| 5| 5-Nov-2023"); + CheckFormat(guest, "%I|%p", "12|PM"); guest.tm_hour = 13; - CheckFormat(guest, "%k|%l", "13| 1"); - char tooSmall[4]{}; - Require(strftime_nid_postfix(tooSmall, sizeof(tooSmall), "%k:%l", &guest) == 0, "strftime accepted an undersized buffer"); + CheckFormat(guest, "%I|%p", "01|PM"); } static void CheckLiteralConversions() { @@ -220,31 +175,18 @@ static void CheckLiteralConversions() { const char* expected; }; constexpr FormatCase cases[]{ - {"%Q", "Q"}, - {"%P|%f|%N|%1|%#Y", "P|f|N|1|#Y"}, - {"[%Q] %Y-%m-%d", "[Q] 2023-11-14"}, - {"%EQ|%OQ|%_Q|%-Q|%0Q", "Q|Q|Q|Q|Q"}, - {"%E_Q|%_EQ|%O0Q|%-OQ", "Q|Q|Q|Q"}, - {"%EEY|%EOY|%OEY|%OOY", "EY|OY|EY|OY"}, - {"%EE%Y|%OO%k", "E2023|O22"}, - {"%--Y|%__Y|%00Y|%_0Y|%0-Y", "-Y|_Y|0Y|0Y|-Y"}, - {"%E_EY|%_EOY|%O0OY", "EY|OY|OY"}, + {"%Q", "%Q"}, + {"%P|%f|%N|%1|%#Y", "%P|%f|%N|%1|%#Y"}, + {"[%Q] %Y-%m-%d", "[%Q] 2023-11-14"}, + {"%EQ|%OQ|%_Q|%-Q|%0Q", "%Q|%Q|%_Q|%-Q|%0Q"}, + {"%--Y|%__Y|%00Y", "%--Y|%__Y|%00Y"}, {"%", "%"}, {"text%", "text%"}, - {"%E", "E"}, - {"%O", "O"}, - {"%_", "_"}, - {"%-", "-"}, - {"%0", "0"}, - {"%E_", "_"}, - {"%_E", "E"}, - {"%Q%", "Q%"}, - {"%k%", "22%"}, - {"%%Q|%%%Q|%%%%Q", "%Q|%Q|%%Q"}, - {"%E%Q|%O%Q|%_%Q|%0%Q|%-%Q", "%Q|%Q|%Q|%Q|%Q"}, - {"%E%%Q|%O%%%Q", "%Q|%%Q"}, - {"%Q|%Ek|%Ol|%Ev|%Y", "Q|22|10|14-Nov-2023|2023"}, - {"%\xc3\xa5", "\xc3\xa5"}, + {"%_", "%_"}, + {"%Q%", "%Q%"}, + {"%Y%", "2023%"}, + {"%%Q|%%%Q|%%%%Q", "%Q|%%Q|%%Q"}, + {"%\xc3\xa5", "%\xc3\xa5"}, {"%%", "%"}, {"literal text", "literal text"}, }; @@ -383,6 +325,7 @@ static void CheckRegionZones() { } Require(setenv_nid_postfix("TZ", "UTC-2", 1) == 0, "Could not restore the guest time zone"); tzset_nid_postfix(); + } static void CheckGuestZone() { @@ -399,19 +342,23 @@ static void CheckGuestZone() { Require(mktime_nid_postfix(&calendar) == moment, "mktime ignored the guest TZ"); Require(setenv_nid_postfix("TZ", "UTC+3", 1) == 0, "Could not change the guest time zone"); tzset_nid_postfix(); + Require(localtime_s_nid_postfix(&moment, &result) == &result && result.tm_hour == 21 && result.tm_mday == 2 && result.tm_gmtoff == -10800, "tzset ignored the guest TZ"); Require(timezone_nid_postfix == 10800 && daylight_nid_postfix == 1, "tzset did not set timezone and daylight for UTC+3"); Require(setenv_nid_postfix("TZ", "", 1) == 0, "Could not empty the guest time zone"); tzset_nid_postfix(); + Require(localtime_s_nid_postfix(&moment, &result) == &result && result.tm_hour == 0 && result.tm_mday == 3 && result.tm_gmtoff == 0, "An empty guest TZ was not treated as UTC"); Require(timezone_nid_postfix == 0 && daylight_nid_postfix == 1, "tzset did not set timezone and daylight for UTC"); Require(setenv_nid_postfix("TZ", "EST5EDT", 1) == 0, "Could not set a daylight saving guest time zone"); tzset_nid_postfix(); + Require(timezone_nid_postfix == 18000 && daylight_nid_postfix == 1, "timezone is not the standard offset of a daylight saving zone"); Require(setenv_nid_postfix("TZ", "UTC-2", 1) == 0, "Could not restore the guest time zone"); tzset_nid_postfix(); + Require(setenv_nid_postfix("TZ", "EST5", 1) == 0, "Could not set the guest time zone without tzset"); Require(localtime_s_nid_postfix(&moment, &result) == &result && result.tm_hour == 19 && result.tm_gmtoff == -18000, "localtime ignored a guest TZ change made without tzset"); @@ -419,16 +366,16 @@ static void CheckGuestZone() { "Implicit guest TZ update did not refresh tzname"); Require(setenv_nid_postfix("TZ", "UTC-2", 1) == 0, "Could not restore the guest time zone"); tzset_nid_postfix(); + } static bool ZoneFieldsConsistent(const GuestTm& time, std::int64_t instant, int hour) { const std::int64_t localSeconds = ((instant + time.tm_gmtoff) % 86400 + 86400) % 86400; if (time.tm_hour * 3600 + time.tm_min * 60 + time.tm_sec != localSeconds || time.tm_hour != hour) return false; - char expected[16]; - const std::int64_t offset = time.tm_gmtoff < 0 ? -time.tm_gmtoff : time.tm_gmtoff; - std::snprintf(expected, sizeof(expected), "%02d %c%04d", hour, time.tm_gmtoff < 0 ? '-' : '+', static_cast(offset / 3600 * 100)); - char formatted[16]{}; - return strftime_nid_postfix(formatted, sizeof(formatted), "%H %z", &time) == 8 && std::strcmp(formatted, expected) == 0; + char expected[4]; + std::snprintf(expected, sizeof(expected), "%02d", hour); + char formatted[4]{}; + return strftime_nid_postfix(formatted, sizeof(formatted), "%H", &time) == 2 && std::strcmp(formatted, expected) == 0; } static void CheckZoneRace() { @@ -438,6 +385,7 @@ static void CheckZoneRace() { std::thread flipper([&] { for (bool west = false; !stop.load(); west = !west) { setenv_nid_postfix("TZ", west ? "UTC-5" : "UTC+3", 1); + std::this_thread::yield(); } }); @@ -463,6 +411,7 @@ static void CheckZoneRace() { Require(torn == 0, "A time conversion mixed the fields of two time zones while TZ changed"); Require(setenv_nid_postfix("TZ", "UTC-2", 1) == 0, "Could not restore the guest time zone"); tzset_nid_postfix(); + } #ifdef _WIN32 @@ -474,12 +423,14 @@ static void CheckRejectedZone() { bool thrown = false; try { localtime_s_nid_postfix(&moment, &result); + } catch (const std::runtime_error&) { thrown = true; } Require(thrown, "localtime accepted a TZ the host cannot hold"); Require(setenv_nid_postfix("TZ", "UTC-2", 1) == 0, "Could not restore the guest time zone"); tzset_nid_postfix(); + Require(localtime_s_nid_postfix(&moment, &result) == &result && result.tm_gmtoff == 7200, "localtime did not recover after a rejected TZ"); } #endif @@ -487,6 +438,7 @@ static void CheckRejectedZone() { int main() { Require(setenv_nid_postfix("TZ", "UTC-2", 1) == 0, "Could not set the guest time zone"); tzset_nid_postfix(); + constexpr std::array utcCases{{ {0, 70, 0, 1, 0, 0, 0, 4, 0}, {-1, 69, 11, 31, 23, 59, 59, 3, 364}, @@ -566,7 +518,7 @@ int main() { Require(strftime_nid_postfix(formatted, sizeof(formatted), "%Y-%m-%d %H:%M:%S", &utc) == 19 && std::strcmp(formatted, "1970-01-01 00:00:00") == 0, "strftime did not read the guest tm"); - CheckFreeBsdConversions(); + CheckConsoleConversions(); CheckLocalRange(); CheckRegionZones(); #ifdef _WIN32 @@ -585,6 +537,7 @@ int main() { #endif Require(setenv_nid_postfix("TZ", "UTC-5", 1) == 0, "Could not set the guest time zone"); tzset_nid_postfix(); + GuestTm shifted{}; Require(localtime_s_nid_postfix(&epoch, &shifted) == &shifted && shifted.tm_hour == 5 && shifted.tm_gmtoff == 18000, "tzset did not pick up the new TZ"); @@ -593,6 +546,7 @@ int main() { "tzname does not name the zone tzset set and leave the daylight name blank"); Require(setenv_nid_postfix("TZ", "EST5EDT", 1) == 0, "Could not set the guest time zone"); tzset_nid_postfix(); + Require(std::strcmp(tzname_nid_postfix[0], "EST") == 0 && std::strcmp(tzname_nid_postfix[1], "EDT") == 0, "tzname does not name the standard and daylight zones"); } diff --git a/core/libs/tests/GuestTimeExtras.cpp b/core/libs/tests/GuestTimeExtras.cpp index 6fc9d4cde0..f03c36ce64 100644 --- a/core/libs/tests/GuestTimeExtras.cpp +++ b/core/libs/tests/GuestTimeExtras.cpp @@ -1,3 +1,5 @@ +#include "prx/libc/include/SonyCrt.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libc/include/GuestTime.hpp" #include @@ -7,24 +9,6 @@ #include #include -struct Xtime { - std::int64_t sec; - std::int64_t nsec; -}; - -extern "C" { -GuestTm* APS5_VABI gmtime_s_nid_postfix(const std::int64_t*, GuestTm*); -GuestTm* APS5_VABI localtime_s_nid_postfix(const std::int64_t*, GuestTm*); -GuestTm* APS5_VABI gmtime_r_nid_postfix(const std::int64_t*, GuestTm*); -GuestTm* APS5_VABI localtime_r_nid_postfix(const std::int64_t*, GuestTm*); -std::int64_t APS5_VABI timegm_nid_postfix(GuestTm*); -void APS5_VABI tzset_nid_postfix(); -int APS5_VABI setenv_nid_postfix(const char*, const char*, int); -int APS5_VABI xtime_get_nid_postfix(Xtime*, int); -Xtime APS5_VABI _Xtime_to_ts_nid_postfix(const Xtime*); -Xtime APS5_VABI _Xtime_diff_to_ts_nid_postfix(const Xtime*); -} - static void Require(bool value, const char* message) { if (!value) { std::fprintf(stderr, "%s\n", message); @@ -156,6 +140,7 @@ static void CheckXtime() { int main() { Require(setenv_nid_postfix("TZ", "UTC-2", 1) == 0, "Could not set the time zone"); tzset_nid_postfix(); + CheckReentrantConversions(); CheckTimegmCases(); CheckXtime(); diff --git a/core/libs/tests/GuestTimedJoin.cpp b/core/libs/tests/GuestTimedJoin.cpp index 34ce27fdf0..928c3bb73b 100644 --- a/core/libs/tests/GuestTimedJoin.cpp +++ b/core/libs/tests/GuestTimedJoin.cpp @@ -1,3 +1,6 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libkernel/Time/include/Time.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -13,30 +16,21 @@ #include #endif -struct Timespec { std::int64_t seconds, nanoseconds; }; -static_assert(sizeof(Timespec)==16 && alignof(Timespec)==8 && offsetof(Timespec,nanoseconds)==8); -extern "C" { -int APS5_VABI pthread_create_nid_postfix(void**,const void*,void* (APS5_VABI*)(void*),void*); -int APS5_VABI pthread_join_nid_postfix(void*,void**); -int APS5_VABI pthread_detach_nid_postfix(void*); -int APS5_VABI pthread_cancel_nid_postfix(void*); -void* APS5_VABI pthread_self_nid_postfix(); -int APS5_VABI clock_gettime_nid_postfix(int,Timespec*); -int* APS5_VABI __error_nid_postfix(); -} -using TimedJoin=int (APS5_VABI*)(void*,void**,const Timespec*); +static_assert(sizeof(KernelTimespec)==16 && alignof(KernelTimespec)==8 && offsetof(KernelTimespec,tv_nsec)==8); + +using TimedJoin = decltype(&pthread_timedjoin_np_nid_postfix); static TimedJoin timedJoin; void Require(bool value,const char* message) { if (!value) { std::fprintf(stderr,"timed join: %s\n",message); std::abort(); } } -Timespec After(int milliseconds) { - Timespec result{}; +KernelTimespec After(int milliseconds) { + KernelTimespec result{}; Require(clock_gettime_nid_postfix(0,&result)==0,"read realtime"); - result.nanoseconds+=static_cast(milliseconds)*1000000; - result.seconds+=result.nanoseconds/1000000000; - result.nanoseconds%=1000000000; + result.tv_nsec+=static_cast(milliseconds)*1000000; + result.tv_sec+=result.tv_nsec/1000000000; + result.tv_nsec%=1000000000; return result; } @@ -57,14 +51,14 @@ void Wait(const std::atomic& flag) { } } -void* Start(Gate& gate) { - void* thread=nullptr; +Pthread Start(Gate& gate) { + Pthread thread=nullptr; Require(pthread_create_nid_postfix(&thread,nullptr,Worker,&gate)==0,"create worker"); Wait(gate.entered); return thread; } -struct JoinTask { void* target; std::atomic entered{false}; int result=-1; void* value=reinterpret_cast(std::uintptr_t{0x55}); }; +struct JoinTask { Pthread target; std::atomic entered{false}; int result=-1; void* value=reinterpret_cast(std::uintptr_t{0x55}); }; void* APS5_VABI Joiner(void* argument) { auto& task=*static_cast(argument); const auto deadline=After(3000); @@ -73,8 +67,8 @@ void* APS5_VABI Joiner(void* argument) { return nullptr; } -void AwaitClaim(void* target) { - const Timespec past{0,0}; +void AwaitClaim(Pthread target) { + const KernelTimespec past{0,0}; const auto until=std::chrono::steady_clock::now()+std::chrono::seconds(2); for (;;) { const int result=timedJoin(target,nullptr,&past); @@ -86,8 +80,8 @@ void AwaitClaim(void* target) { } void Basic() { - const Timespec valid=After(1000); - for (const Timespec invalid: {Timespec{-1,0},Timespec{0,-1},Timespec{0,1000000000}}) { + const KernelTimespec valid=After(1000); + for (const KernelTimespec invalid: {KernelTimespec{-1,0},KernelTimespec{0,-1},KernelTimespec{0,1000000000}}) { Require(timedJoin(nullptr,nullptr,&invalid)==22,"invalid deadline precedes null thread"); Require(timedJoin(pthread_self_nid_postfix(),nullptr,&invalid)==22,"invalid deadline precedes self join"); } @@ -95,9 +89,9 @@ void Basic() { Require(timedJoin(nullptr,nullptr,&valid)==22,"null thread"); Require(timedJoin(pthread_self_nid_postfix(),nullptr,&valid)==11,"self join"); Gate gate; - void* thread=Start(gate); + Pthread thread=Start(gate); struct { std::uint64_t before=0xa5a5a5a5; void* value=reinterpret_cast(std::uintptr_t{0x55}); std::uint64_t after=0x5a5a5a5a; } result; - const Timespec past{0,0}; + const KernelTimespec past{0,0}; *__error_nid_postfix()=123; Require(timedJoin(thread,&result.value,&past)==60,"past deadline expires"); Require(result.value==reinterpret_cast(std::uintptr_t{0x55}),"timeout preserves return slot"); @@ -107,16 +101,16 @@ void Basic() { const auto started=std::chrono::steady_clock::now(); Require(timedJoin(thread,&result.value,&deadline)==60,"future deadline expires"); Require(std::chrono::steady_clock::now()-started>=std::chrono::milliseconds(25),"wait did not expire immediately"); - Require(deadline.seconds==originalDeadline.seconds && deadline.nanoseconds==originalDeadline.nanoseconds,"deadline input is unchanged"); + Require(deadline.tv_sec==originalDeadline.tv_sec && deadline.tv_nsec==originalDeadline.tv_nsec,"deadline input is unchanged"); gate.release.store(true,std::memory_order_release); - const Timespec distant{std::numeric_limits::max(),999999999}; + const KernelTimespec distant{std::numeric_limits::max(),999999999}; Require(timedJoin(thread,&result.value,&distant)==0,"timeout leaves target joinable; distant deadline does not overflow"); Require(result.value==reinterpret_cast(std::uintptr_t{0x12345678}),"joined return value"); Require(result.before==0xa5a5a5a5 && result.after==0x5a5a5a5a,"return-slot bounds"); Require(timedJoin(thread,nullptr,&valid)==3,"already joined target"); Require(timedJoin(thread,nullptr,nullptr)==22,"deadline validation precedes joined state"); Gate done; - void* completed=Start(done); + Pthread completed=Start(done); done.release.store(true,std::memory_order_release); Wait(done.leaving); const auto until=std::chrono::steady_clock::now()+std::chrono::seconds(2); @@ -127,7 +121,7 @@ void Basic() { std::this_thread::yield(); } Gate detached; - void* detachedThread=Start(detached); + Pthread detachedThread=Start(detached); Require(pthread_detach_nid_postfix(detachedThread)==0,"detach worker"); Require(timedJoin(detachedThread,nullptr,&valid)==22,"detached target"); detached.release.store(true,std::memory_order_release); @@ -136,9 +130,9 @@ void Basic() { void Contention(bool cancel) { Gate gate; - void* target=Start(gate); + Pthread target=Start(gate); JoinTask task{target}; - void* joiner=nullptr; + Pthread joiner=nullptr; Require(pthread_create_nid_postfix(&joiner,nullptr,Joiner,&task)==0,"create competing joiner"); Wait(task.entered); AwaitClaim(target); @@ -147,7 +141,7 @@ void Contention(bool cancel) { void* canceled=nullptr; Require(pthread_join_nid_postfix(joiner,&canceled)==0 && canceled==reinterpret_cast(std::uintptr_t{1}),"joiner is canceled"); Require(task.result==-1 && task.value==reinterpret_cast(std::uintptr_t{0x55}),"canceled join did not return or write result"); - const Timespec past{0,0}; + const KernelTimespec past{0,0}; Require(timedJoin(target,nullptr,&past)==60,"cancellation releases join claim"); gate.release.store(true,std::memory_order_release); const auto deadline=After(1000); diff --git a/core/libs/tests/GuestTlsGetAddr.cpp b/core/libs/tests/GuestTlsGetAddr.cpp new file mode 100644 index 0000000000..e13ef11bde --- /dev/null +++ b/core/libs/tests/GuestTlsGetAddr.cpp @@ -0,0 +1,86 @@ +#include "prx/libkernel/include/Api.hpp" +#include "SceTypes.hpp" +#include "prx/libc/include/general/VabiMacros.hpp" +#include +#include +#include +#include +#if defined(_WIN32) +#include +#else +#include +#endif + +#if defined(_WIN32) +extern "C" ULONG _tls_index; + +namespace { + +using Cell = char; +constexpr Cell Initial = 0; + +KernelTlsIndex CellIndex() { return {reinterpret_cast(&_tls_index), 0}; } + +Cell* ThreadCell() { + auto* blocks = *reinterpret_cast(reinterpret_cast(NtCurrentTeb()) + 0x58); + return blocks[_tls_index]; +} + +} +#else +namespace { + +using Cell = std::uint32_t; +constexpr Cell Initial = 0x5ca1ab1e; +thread_local Cell Value = Initial; + +struct Module { + std::size_t id = 0; + void* data = nullptr; +}; + +Module MainModule() { + Module module; + dl_iterate_phdr([](dl_phdr_info* info, std::size_t, void* out) { + auto& found = *static_cast(out); + found = {info->dlpi_tls_modid, info->dlpi_tls_data}; + return 1; + }, &module); + return module; +} + +KernelTlsIndex CellIndex() { + const auto module = MainModule(); + return {module.id, static_cast(reinterpret_cast(&Value) - static_cast(module.data))}; +} + +Cell* ThreadCell() { return &Value; } + +} +#endif + +namespace { + +void Require(bool value) { if (!value) std::abort(); } + +} + +int main() { + const auto index = CellIndex(); + auto* own = static_cast(__tls_get_addr_nid_postfix(&index)); + Require(own == ThreadCell() && *own == Initial); + *own = 7; + Cell* other = nullptr; + Cell seen = 1; + std::thread([&] { + other = static_cast(__tls_get_addr_nid_postfix(&index)); + Require(other == ThreadCell()); + seen = *other; + *other = 9; + }).join(); + Require(other != own && seen == Initial && *own == 7); + *own = Initial; + bool threw = false; + try { __tls_get_addr_nid_postfix(nullptr); } catch (const std::invalid_argument&) { threw = true; } + Require(threw); +} diff --git a/core/libs/tests/GuestTruncate.cpp b/core/libs/tests/GuestTruncate.cpp index 1e037fd9d8..732a8394be 100644 --- a/core/libs/tests/GuestTruncate.cpp +++ b/core/libs/tests/GuestTruncate.cpp @@ -1,3 +1,6 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libkernel/File/include/File.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -18,16 +21,6 @@ extern "C" _invalid_parameter_handler _set_thread_local_invalid_parameter_handle #include #endif -extern "C" { -int APS5_VABI truncate_nid_postfix(const char*, std::int64_t); -int APS5_VABI sceKernelTruncate_nid_postfix(const char*, std::int64_t); -int APS5_VABI ftruncate_nid_postfix(int, std::int64_t); -int APS5_VABI sceKernelFtruncate(int, std::int64_t); -int APS5_VABI sceKernelOpen(const char*, int, std::uint16_t); -int APS5_VABI sceKernelClose(int); -int* APS5_VABI __error_nid_postfix(); -} - static void Require(bool value) { if (!value) std::abort(); } constexpr int GuestEnoent = 2; diff --git a/core/libs/tests/GuestTruncateExtend.cpp b/core/libs/tests/GuestTruncateExtend.cpp index 66dcffd80e..789105ba61 100644 --- a/core/libs/tests/GuestTruncateExtend.cpp +++ b/core/libs/tests/GuestTruncateExtend.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -8,18 +10,6 @@ #include #endif -extern "C" { -int APS5_VABI open_nid_postfix(const char*, int, int); -int APS5_VABI close_nid_postfix(int); -std::int64_t APS5_VABI write_nid_postfix(int, const void*, std::uint64_t); -std::int64_t APS5_VABI pread_nid_postfix(int, void*, std::uint64_t, std::int64_t); -std::int64_t APS5_VABI lseek_nid_postfix(int, std::int64_t, int); -int APS5_VABI ftruncate_nid_postfix(int, std::int64_t); -int APS5_VABI truncate_nid_postfix(const char*, std::int64_t); -int APS5_VABI unlink_nid_postfix(const char*); -int* APS5_VABI __error_nid_postfix(); -} - namespace { constexpr int ReadOnly = 0; @@ -30,6 +20,7 @@ constexpr char FileName[] = "anyps5_truncate_extend_file"; void Cleanup() { unlink_nid_postfix(FileName); + } void Require(bool condition, const char* what) { diff --git a/core/libs/tests/GuestTruncateRace.cpp b/core/libs/tests/GuestTruncateRace.cpp index 29f2f3a3e1..e4602f6415 100644 --- a/core/libs/tests/GuestTruncateRace.cpp +++ b/core/libs/tests/GuestTruncateRace.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libkernel/File/include/File.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libkernel/File/include/FileFlags.hpp" #include @@ -11,18 +13,6 @@ #include #include -extern "C" { -int APS5_VABI sceKernelOpen(const char*, int, std::uint16_t); -int APS5_VABI sceKernelClose(int); -int APS5_VABI sceKernelFtruncate(int, std::int64_t); -int APS5_VABI ftruncate_nid_postfix(int, std::int64_t); -int APS5_VABI dup_nid_postfix(int); -std::int64_t APS5_VABI sceKernelLseek(int, std::int64_t, int); -std::int64_t APS5_VABI sceKernelPread(int, void*, std::size_t, std::int64_t); -std::int64_t APS5_VABI pread_nid_postfix(int, void*, std::size_t, std::int64_t); -std::int64_t APS5_VABI sceKernelRead(int, void*, std::size_t); -} - static void Check(bool value, int line) { if (!value) { std::fprintf(stderr, "Truncate race check failed at line %d\n", line); diff --git a/core/libs/tests/GuestUdp.cpp b/core/libs/tests/GuestUdp.cpp index a4e6abd15c..ac6d36fa4c 100644 --- a/core/libs/tests/GuestUdp.cpp +++ b/core/libs/tests/GuestUdp.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -7,45 +9,7 @@ #include #include #include -extern "C" { -int APS5_VABI socket_nid_postfix(int, int, int); -int APS5_VABI connect_nid_postfix(int, const void*, std::uint32_t); -int APS5_VABI fcntl_nid_postfix(int, int, ...); -int APS5_VABI setsockopt_nid_postfix(int, int, int, const void*, std::uint32_t); -int APS5_VABI getsockopt_nid_postfix(int, int, int, void*, std::uint32_t*); -int APS5_VABI bind_nid_postfix(int, const void*, std::uint32_t); -int APS5_VABI getsockname_nid_postfix(int, void*, std::uint32_t*); -int APS5_VABI getpeername_nid_postfix(int, void*, std::uint32_t*); -int APS5_VABI ioctl_nid_postfix(int, std::uint64_t, void*); -int APS5_VABI _ioctl_nid_postfix(int, std::uint64_t, void*); -std::int64_t APS5_VABI send_nid_postfix(int, const void*, std::uint64_t, int); -std::int64_t APS5_VABI recv_nid_postfix(int, void*, std::uint64_t, int); -std::int64_t APS5_VABI sendto_nid_postfix(int, const void*, std::uint64_t, int, const void*, std::uint32_t); -std::int64_t APS5_VABI recvfrom_nid_postfix(int, void*, std::uint64_t, int, void*, std::uint32_t*); -int APS5_VABI close_nid_postfix(int); -const char* APS5_VABI inet_ntop_nid_postfix(int, const void*, char*, std::uint32_t); -int APS5_VABI inet_pton_nid_postfix(int, const char*, void*); -int* APS5_VABI __error_nid_postfix(); -} -struct Iovec { - void* base; - std::uint64_t length; -}; -struct Msghdr { - void* name; - std::uint32_t nameLength; - Iovec* iov; - int iovLength; - void* control; - std::uint32_t controlLength; - int flags; -}; -extern "C" { -std::int64_t APS5_VABI sendmsg_nid_postfix(int, const Msghdr*, int); -std::int64_t APS5_VABI recvmsg_nid_postfix(int, Msghdr*, int); -std::int64_t APS5_VABI sceKernelReadv(int, const Iovec*, int); -std::int64_t APS5_VABI sceKernelWritev(int, const Iovec*, int); -} + static void Require(bool value) { if (!value) std::abort(); } static void CheckAddressLengths(int family) { @@ -89,8 +53,8 @@ static void CheckAddressLengths(int family) { Require(size == copied && std::memcmp(address.data(), expected.data(), copied) == 0); Require(std::all_of(address.begin() + copied, address.end(), [](auto byte) { return byte == 0xa5; })); address.fill(0xa5); - Iovec vector{received, sizeof(received)}; - Msghdr message{address.data(), capacity, &vector, 1, nullptr, 0, -1}; + KernelIovec vector{received, sizeof(received)}; + GuestMsghdr message{address.data(), capacity, &vector, 1, nullptr, 0, -1}; Require(recvmsg_nid_postfix(receiver, &message, 0) == sizeof(payload)); Require(message.nameLength == copied && std::memcmp(received, payload, sizeof(payload)) == 0); Require(std::memcmp(address.data(), expected.data(), copied) == 0); @@ -133,8 +97,8 @@ static void CheckDontWait() { std::uint32_t size = address.size(); Require(getsockname_nid_postfix(receiver, address.data(), &size) == 0); char buffer[16]{}; - Iovec vector{buffer, sizeof(buffer)}; - Msghdr message{nullptr, 0, &vector, 1, nullptr, 0, 0}; + KernelIovec vector{buffer, sizeof(buffer)}; + GuestMsghdr message{nullptr, 0, &vector, 1, nullptr, 0, 0}; const auto start = std::chrono::steady_clock::now(); Require(recv_nid_postfix(receiver, buffer, sizeof(buffer), 0x80) == -1 && *__error_nid_postfix() == 35); Require(recvfrom_nid_postfix(receiver, buffer, sizeof(buffer), 0x80, nullptr, nullptr) == -1 && *__error_nid_postfix() == 35); @@ -173,11 +137,11 @@ int main() { Require(connect_nid_postfix(sender, destination.data(), destination.size()) == 0); char vectorHead[] = "atomic "; char vectorTail[] = "datagram"; - Iovec vectorOutput[]{{vectorHead, sizeof(vectorHead) - 1}, {vectorTail, sizeof(vectorTail)}}; + KernelIovec vectorOutput[]{{vectorHead, sizeof(vectorHead) - 1}, {vectorTail, sizeof(vectorTail)}}; Require(sceKernelWritev(sender, vectorOutput, 2) == sizeof(vectorHead) + sizeof(vectorTail) - 1); char vectorFirst[sizeof(vectorHead) - 1]{}; char vectorSecond[sizeof(vectorTail)]{}; - Iovec vectorInput[]{{vectorFirst, sizeof(vectorFirst)}, {vectorSecond, sizeof(vectorSecond)}}; + KernelIovec vectorInput[]{{vectorFirst, sizeof(vectorFirst)}, {vectorSecond, sizeof(vectorSecond)}}; Require(sceKernelReadv(receiver, vectorInput, 2) == sizeof(vectorHead) + sizeof(vectorTail) - 1); Require(std::memcmp(vectorFirst, "atomic ", sizeof(vectorFirst)) == 0 && std::strcmp(vectorSecond, "datagram") == 0); int enabled = 1; @@ -237,8 +201,8 @@ int main() { Require(_ioctl_nid_postfix(receiver, 123, &queued) == -1 && *__error_nid_postfix() == 25); char head[] = "scatter "; char tail[] = "gather"; - Iovec parts[2]{{head, 8}, {tail, 6}}; - Msghdr outgoing{nullptr, 0, parts, 2, nullptr, 0, 0}; + KernelIovec parts[2]{{head, 8}, {tail, 6}}; + GuestMsghdr outgoing{nullptr, 0, parts, 2, nullptr, 0, 0}; Require(sendmsg_nid_postfix(sender, &outgoing, 0) == 14); const auto wait = [&] { queued = 0; @@ -250,10 +214,10 @@ int main() { }; wait(); char first[4]{}, second[16]{}; - Iovec pieces[2]{{first, sizeof(first)}, {second, sizeof(second)}}; + KernelIovec pieces[2]{{first, sizeof(first)}, {second, sizeof(second)}}; source.fill(0); unsigned char control[8]{}; - Msghdr incoming{source.data(), static_cast(source.size()), pieces, 2, control, sizeof(control), -1}; + GuestMsghdr incoming{source.data(), static_cast(source.size()), pieces, 2, control, sizeof(control), -1}; Require(recvmsg_nid_postfix(receiver, &incoming, 2) == 14 && incoming.flags == 2); incoming.nameLength = static_cast(source.size()); incoming.controlLength = sizeof(control); @@ -263,18 +227,18 @@ int main() { Require(sendmsg_nid_postfix(sender, &outgoing, 0) == 14); wait(); char shortBuffer[5]{}; - Iovec single{shortBuffer, sizeof(shortBuffer)}; - Msghdr truncated{nullptr, 0, &single, 1, nullptr, 0, 0}; + KernelIovec single{shortBuffer, sizeof(shortBuffer)}; + GuestMsghdr truncated{nullptr, 0, &single, 1, nullptr, 0, 0}; Require(recvmsg_nid_postfix(receiver, &truncated, 2) == 5 && truncated.flags == 0x12); Require(recvmsg_nid_postfix(receiver, &truncated, 0x80) == 5); Require(std::memcmp(shortBuffer, "scatt", 5) == 0 && truncated.flags == 0x90); Require(recvmsg_nid_postfix(receiver, &truncated, 0) == -1 && *__error_nid_postfix() == 35); - Iovec none{shortBuffer, 0}; - Msghdr empty{nullptr, 0, &none, 1, nullptr, 0, -1}; + KernelIovec none{shortBuffer, 0}; + GuestMsghdr empty{nullptr, 0, &none, 1, nullptr, 0, -1}; Require(fcntl_nid_postfix(receiver, 4, 2) == 0); Require(recvmsg_nid_postfix(receiver, &empty, 0) == 0 && empty.flags == 0); Require(fcntl_nid_postfix(receiver, 4, 6) == 0); - Msghdr oversized{nullptr, 0, parts, 1025, nullptr, 0, 0}; + GuestMsghdr oversized{nullptr, 0, parts, 1025, nullptr, 0, 0}; Require(sendmsg_nid_postfix(sender, &oversized, 0) == -1 && *__error_nid_postfix() == 40); Require(recvmsg_nid_postfix(receiver, nullptr, 0) == -1 && *__error_nid_postfix() == 14); Require(close_nid_postfix(receiver) == 0); diff --git a/core/libs/tests/GuestUlobjmgr.cpp b/core/libs/tests/GuestUlobjmgr.cpp index 0fd79500f7..3f6795a979 100644 --- a/core/libs/tests/GuestUlobjmgr.cpp +++ b/core/libs/tests/GuestUlobjmgr.cpp @@ -1,12 +1,8 @@ +#include "prx/ulobjmgr/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include -extern "C" { -int APS5_VABI _sceUlobjmgrRegisterObject(std::uint64_t object, std::int32_t kind, std::uint32_t* id); -int APS5_VABI _sceUlobjmgrUnregisterObject(std::uint32_t id); -} - namespace { constexpr int einval = 22; diff --git a/core/libs/tests/GuestUltCondition.cpp b/core/libs/tests/GuestUltCondition.cpp index 3922c753ef..2f5c980fe4 100644 --- a/core/libs/tests/GuestUltCondition.cpp +++ b/core/libs/tests/GuestUltCondition.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceUlt/include/Api.hpp" #include "SceTypes.hpp" #include #include @@ -9,19 +10,6 @@ #include #include -extern "C" { -int APS5_VABI sceUltFinalize(); -int APS5_VABI sceUltMutexCreate(void*, const char*, void*, const UltMutexOptParam*, std::uint32_t); -int APS5_VABI sceUltMutexLock(void*); -int APS5_VABI sceUltMutexUnlock(void*); -int APS5_VABI sceUltMutexDestroy(void*); -int APS5_VABI sceUltConditionVariableCreate(void*, const char*, void*, const void*, std::uint32_t); -int APS5_VABI _sceUltConditionVariableCreate(void*, const char*, void*, const void*, std::uint32_t); -int APS5_VABI sceUltConditionVariableWait(void*); -int APS5_VABI sceUltConditionVariableSignal(void*); -int APS5_VABI sceUltConditionVariableDestroy(void*); -} - constexpr int Null = -2139029503; constexpr int Invalid = -2139029500; constexpr int Permission = -2139029499; diff --git a/core/libs/tests/GuestUltQueue.cpp b/core/libs/tests/GuestUltQueue.cpp index 4cfcf13881..7a2a1ef562 100644 --- a/core/libs/tests/GuestUltQueue.cpp +++ b/core/libs/tests/GuestUltQueue.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceUlt/include/Api.hpp" #include "SceTypes.hpp" #include #include @@ -10,21 +11,6 @@ #include #include -extern "C" { -int APS5_VABI sceUltInitialize(); -int APS5_VABI sceUltFinalize(); -std::uint64_t APS5_VABI sceUltWaitingQueueResourcePoolGetWorkAreaSize(std::uint32_t, std::uint32_t); -std::uint64_t APS5_VABI sceUltQueueDataResourcePoolGetWorkAreaSize(std::uint32_t, std::uint64_t, std::uint32_t); -int APS5_VABI sceUltQueueDataResourcePoolCreate(void*, const char*, std::uint32_t, std::uint64_t, std::uint32_t, void*, void*, const void*, std::uint32_t); -int APS5_VABI sceUltQueueDataResourcePoolDestroy(void*); -int APS5_VABI sceUltQueueCreate(void*, const char*, std::uint64_t, void*, void*, const void*, std::uint32_t); -int APS5_VABI sceUltQueueDestroy(void*); -int APS5_VABI sceUltQueuePush(void*, const void*); -int APS5_VABI sceUltQueueTryPush(void*, const void*); -int APS5_VABI sceUltQueuePop(void*, void*); -int APS5_VABI sceUltQueueTryPop(void*, void*); -} - static constexpr int Null = -2139029503; static constexpr int Alignment = -2139029502; static constexpr int Range = -2139029501; diff --git a/core/libs/tests/GuestUltSync.cpp b/core/libs/tests/GuestUltSync.cpp index 7b2e1e51ed..a9d52c921a 100644 --- a/core/libs/tests/GuestUltSync.cpp +++ b/core/libs/tests/GuestUltSync.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceUlt/include/Api.hpp" #include "SceTypes.hpp" #include #include @@ -9,43 +10,6 @@ #include #include -extern "C" { -int APS5_VABI sceUltInitialize(); -int APS5_VABI sceUltFinalize(); -int APS5_VABI sceUltMutexCreate(void*, const char*, void*, const UltMutexOptParam*, std::uint32_t); -int APS5_VABI sceUltMutexLock(void*); -int APS5_VABI sceUltMutexTryLock(void*); -int APS5_VABI sceUltMutexUnlock(void*); -int APS5_VABI sceUltMutexDestroy(void*); -int APS5_VABI sceUltSemaphoreOptParamInitialize(void*, std::uint32_t); -int APS5_VABI sceUltQueueOptParamInitialize(void*, std::uint32_t); -int APS5_VABI sceUltQueueDataResourcePoolOptParamInitialize(void*, std::uint32_t); -int APS5_VABI sceUltWaitingQueueResourcePoolOptParamInitialize(void*, std::uint32_t); -int APS5_VABI sceUltUlthreadOptParamInitialize(void*, std::uint32_t); -int APS5_VABI _sceUltWaitingQueueResourcePoolCreate(void*, const char*, std::uint32_t, std::uint32_t, void*, const void*); -int APS5_VABI sceUltWaitingQueueResourcePoolDestroy(void*); -int APS5_VABI sceUltReaderWriterLockOptParamInitialize(void*, std::uint32_t); -int APS5_VABI sceUltConditionVariableOptParamInitialize(void*, std::uint32_t); -int APS5_VABI _sceUltConditionVariableOptParamInitialize(void*, std::uint32_t); -int APS5_VABI sceUltReaderWriterLockCreate(void*, const char*, void*, const void*, std::uint32_t); -int APS5_VABI sceUltReaderWriterLockDestroy(void*); -int APS5_VABI sceUltReaderWriterLockLockRead(void*); -int APS5_VABI sceUltReaderWriterLockTryLockRead(void*); -int APS5_VABI sceUltReaderWriterLockUnlockRead(void*); -int APS5_VABI sceUltReaderWriterLockLockWrite(void*); -int APS5_VABI sceUltReaderWriterLockTryLockWrite(void*); -int APS5_VABI sceUltReaderWriterLockUnlockWrite(void*); -std::uint64_t APS5_VABI sceUltUlthreadRuntimeGetWorkAreaSize(std::uint32_t, std::uint32_t); -int APS5_VABI sceUltUlthreadRuntimeCreate(void*, const char*, std::uint32_t, std::uint32_t, void*, const void*, std::uint32_t); -int APS5_VABI sceUltUlthreadRuntimeDestroy(void*); -int APS5_VABI sceUltUlthreadCreate(void*, const char*, UltUlthreadEntry, std::uint64_t, void*, std::uint64_t, void*, const void*, std::uint32_t); -int APS5_VABI sceUltUlthreadJoin(void*, std::int32_t*); -int APS5_VABI sceUltUlthreadTryJoin(void*, std::int32_t*); -int APS5_VABI sceUltUlthreadGetSelf(void**); -int APS5_VABI sceUltUlthreadYield(); -int APS5_VABI sceUltUlthreadExit(std::int32_t); -} - namespace { constexpr int Ok = 0; @@ -98,20 +62,19 @@ void MutexTryLock() { } void OptParams() { - using Initializer = int (APS5_VABI *)(void*, std::uint32_t); + using Initializer = decltype(&sceUltSemaphoreOptParamInitialize); for (const Initializer initialize : {sceUltSemaphoreOptParamInitialize, sceUltQueueOptParamInitialize, sceUltQueueDataResourcePoolOptParamInitialize, sceUltWaitingQueueResourcePoolOptParamInitialize, sceUltUlthreadOptParamInitialize, sceUltReaderWriterLockOptParamInitialize, sceUltConditionVariableOptParamInitialize, _sceUltConditionVariableOptParamInitialize}) { - std::uint8_t bytes[136]; + alignas(UltOptParam) std::uint8_t bytes[136]; std::memset(bytes, 0xa5, sizeof(bytes)); CHECK(initialize(nullptr, 0) == Null); - CHECK(initialize(bytes, 0) == Ok); + CHECK(initialize(reinterpret_cast(bytes), 0) == Ok); for (std::size_t index = 0; index < 128; ++index) CHECK(bytes[index] == 0); for (std::size_t index = 128; index < sizeof(bytes); ++index) CHECK(bytes[index] == 0xa5); } } - void WaitUntil(const std::atomic& flag) { const auto deadline = std::chrono::steady_clock::now() + std::chrono::seconds(5); while (!flag.load() && std::chrono::steady_clock::now() < deadline) std::this_thread::sleep_for(std::chrono::milliseconds(1)); @@ -273,6 +236,7 @@ std::int32_t APS5_VABI ExitingEntry(std::uint64_t status) { if (sceUltUlthreadGetSelf(&self) == Ok) gSelf = self; gYield = sceUltUlthreadYield(); sceUltUlthreadExit(static_cast(status)); + gPastExit = true; return -1; } diff --git a/core/libs/tests/GuestUltThread.cpp b/core/libs/tests/GuestUltThread.cpp index 32b8be2972..50fef67d4c 100644 --- a/core/libs/tests/GuestUltThread.cpp +++ b/core/libs/tests/GuestUltThread.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceUlt/include/Api.hpp" #include "SceTypes.hpp" #include #include @@ -11,41 +12,6 @@ struct UltConditionVariableInfo; struct UltWaitingThreadInfo; -extern "C" { -int APS5_VABI sceUltInitialize(); -int APS5_VABI sceUltFinalize(); -std::uint64_t APS5_VABI sceUltUlthreadRuntimeGetWorkAreaSize(std::uint32_t, std::uint32_t); -int APS5_VABI sceUltUlthreadRuntimeCreate(void*, const char*, std::uint32_t, std::uint32_t, void*, const void*, std::uint32_t); -int APS5_VABI sceUltUlthreadCreate(void*, const char*, UltUlthreadEntry, std::uint64_t, void*, std::uint64_t, void*, const void*, std::uint32_t); -int APS5_VABI sceUltUlthreadJoin(void*, std::int32_t*); -int APS5_VABI sceUltUlthreadTryJoin(void*, std::int32_t*); -int APS5_VABI sceUltUlthreadRuntimeDestroy(void*); -int APS5_VABI _sceUltUlthreadRuntimeOptParamInitialize(void*, std::uint32_t); -int APS5_VABI _sceUltUlthreadRuntimeCreate(void*, const char*, std::uint32_t, std::uint32_t, void*, const void*); -int APS5_VABI _sceUltUlthreadCreate(void*, const char*, UltUlthreadEntry, std::uint64_t, void*, std::uint64_t, void*, const void*); -int APS5_VABI _sceUltWaitingQueueResourcePoolCreate(void*, const char*, std::uint32_t, std::uint32_t, void*, const void*); -int APS5_VABI _sceUltSemaphoreCreate(void*, const char*, std::uint32_t, void*, const void*); -int APS5_VABI sceUltSemaphoreTryAcquire(void*, std::int32_t); -int APS5_VABI sceUltSemaphoreAcquire(void*, std::int32_t); -int APS5_VABI sceUltSemaphoreRelease(void*, std::int32_t); -int APS5_VABI _sceUltMutexOptParamInitialize(void*, std::uint32_t); -int APS5_VABI _sceUltMutexCreate(void*, const char*, void*, const void*); -int APS5_VABI sceUltMutexLock(void*); -int APS5_VABI sceUltMutexUnlock(void*); -int APS5_VABI _sceUltQueueDataResourcePoolCreate(void*, const char*, std::uint32_t, std::uint64_t, std::uint32_t, void*, void*, const void*); -int APS5_VABI _sceUltQueueCreate(void*, const char*, std::uint64_t, void*, void*, const void*); -int APS5_VABI sceUltQueuePush(void*, const void*); -int APS5_VABI sceUltQueuePop(void*, void*); -int APS5_VABI sceUltMutexDestroy(void*); -int APS5_VABI sceUltWaitingQueueResourcePoolDestroy(void*); -int APS5_VABI sceUltSemaphoreDestroy(void*); -int APS5_VABI sceUltQueueDestroy(void*); -int APS5_VABI sceUltQueueDataResourcePoolDestroy(void*); -int APS5_VABI sceUltConditionVariableDestroy(void*); -int APS5_VABI sceUltReaderWriterLockDestroy(void*); -int APS5_VABI sceUltGetConditionVariableInfo(void*, UltConditionVariableInfo*, UltWaitingThreadInfo*, std::uint32_t); -} - static constexpr int Ok = 0; static constexpr int Null = -2139029503; static constexpr int Alignment = -2139029502; @@ -123,6 +89,7 @@ static void Validation() { bool threwInfo = false; try { sceUltGetConditionVariableInfo(nullptr, nullptr, nullptr, 0); + } catch (const std::runtime_error&) { threwInfo = true; } @@ -139,7 +106,7 @@ static void TryJoin() { std::uint8_t optParam[128]; std::memset(optParam, 0xff, sizeof(optParam)); CHECK(_sceUltUlthreadRuntimeOptParamInitialize(nullptr, 0) == Null); - CHECK(_sceUltUlthreadRuntimeOptParamInitialize(optParam, 0) == Ok && optParam[0] == 0); + CHECK(_sceUltUlthreadRuntimeOptParamInitialize(reinterpret_cast(optParam), 0) == Ok && optParam[0] == 0); CHECK(_sceUltUlthreadRuntimeCreate(&runtime, "runtime", 1, 1, nullptr, nullptr) == Ok); CHECK(_sceUltUlthreadCreate(&thread, "parked", Parked, 0x3C, nullptr, 0, &runtime, nullptr) == Ok); while (!gStarted.load(std::memory_order_acquire)) std::this_thread::yield(); @@ -217,29 +184,29 @@ static void UnderscoredCreate() { alignas(8) static std::uint8_t mutex[256]; std::memset(mutexOptParam, 0xFF, sizeof(mutexOptParam)); CHECK(_sceUltMutexOptParamInitialize(nullptr, 0) == Null); - CHECK(_sceUltMutexOptParamInitialize(mutexOptParam + 1, 0) == Alignment); + CHECK(_sceUltMutexOptParamInitialize(reinterpret_cast(mutexOptParam + 1), 0) == Alignment); CHECK(mutexOptParam[0] == 0xFF && mutexOptParam[127] == 0xFF); - CHECK(_sceUltMutexOptParamInitialize(mutexOptParam, 0x12345678) == Ok); + CHECK(_sceUltMutexOptParamInitialize(reinterpret_cast(mutexOptParam), 0x12345678) == Ok); UltMutexOptParam options{}; std::memcpy(&options, mutexOptParam, sizeof(options)); CHECK(options.header[0] == 0x6C696275 && options.header[1] == 0x6C746D61 && options.header[2] == 0x67696300); CHECK(options.buildVersion == 0x12345678 && options.attribute == 0); for (std::size_t index = 16; index < 128; ++index) CHECK(mutexOptParam[index] == 0); for (std::size_t index = 128; index < sizeof(mutexOptParam); ++index) CHECK(mutexOptParam[index] == 0xFF); - CHECK(_sceUltMutexCreate(mutex, nullptr, pool, mutexOptParam) == Null); - CHECK(_sceUltMutexCreate(mutex, "mutex", nullptr, mutexOptParam) == Null); - CHECK(_sceUltMutexCreate(mutex, "mutex", pool, mutexOptParam + 1) == Alignment); + CHECK(_sceUltMutexCreate(mutex, nullptr, pool, reinterpret_cast(mutexOptParam)) == Null); + CHECK(_sceUltMutexCreate(mutex, "mutex", nullptr, reinterpret_cast(mutexOptParam)) == Null); + CHECK(_sceUltMutexCreate(mutex, "mutex", pool, reinterpret_cast(mutexOptParam + 1)) == Alignment); mutexOptParam[127] = 1; - CHECK(_sceUltMutexCreate(mutex, "mutex", pool, mutexOptParam) == Invalid); + CHECK(_sceUltMutexCreate(mutex, "mutex", pool, reinterpret_cast(mutexOptParam)) == Invalid); mutexOptParam[127] = 0; mutexOptParam[16] = 2; - CHECK(_sceUltMutexCreate(mutex, "mutex", pool, mutexOptParam) == Invalid); + CHECK(_sceUltMutexCreate(mutex, "mutex", pool, reinterpret_cast(mutexOptParam)) == Invalid); mutexOptParam[16] = 0; mutexOptParam[0] = 0; - CHECK(_sceUltMutexCreate(mutex, "mutex", pool, mutexOptParam) == Invalid); - CHECK(_sceUltMutexOptParamInitialize(mutexOptParam, 0) == Ok); - CHECK(_sceUltMutexCreate(nullptr, "mutex", pool, mutexOptParam) == Null); - CHECK(_sceUltMutexCreate(mutex, "mutex", pool, mutexOptParam) == Ok); + CHECK(_sceUltMutexCreate(mutex, "mutex", pool, reinterpret_cast(mutexOptParam)) == Invalid); + CHECK(_sceUltMutexOptParamInitialize(reinterpret_cast(mutexOptParam), 0) == Ok); + CHECK(_sceUltMutexCreate(nullptr, "mutex", pool, reinterpret_cast(mutexOptParam)) == Null); + CHECK(_sceUltMutexCreate(mutex, "mutex", pool, reinterpret_cast(mutexOptParam)) == Ok); CHECK(sceUltMutexLock(mutex) == Ok); CHECK(sceUltMutexLock(mutex) == State); std::thread foreignUnlock([&] { CHECK(sceUltMutexUnlock(mutex) == Permission); }); @@ -248,7 +215,7 @@ static void UnderscoredCreate() { CHECK(sceUltMutexUnlock(mutex) == Permission); CHECK(sceUltMutexDestroy(mutex) == Ok); mutexOptParam[16] = 1; - CHECK(_sceUltMutexCreate(mutex, "mutex", pool, mutexOptParam) == Ok); + CHECK(_sceUltMutexCreate(mutex, "mutex", pool, reinterpret_cast(mutexOptParam)) == Ok); CHECK(sceUltMutexLock(mutex) == Ok); CHECK(sceUltMutexLock(mutex) == Ok); CHECK(sceUltMutexUnlock(mutex) == Ok); diff --git a/core/libs/tests/GuestUmtxOp.cpp b/core/libs/tests/GuestUmtxOp.cpp index 97eef1d837..ee4befc68f 100644 --- a/core/libs/tests/GuestUmtxOp.cpp +++ b/core/libs/tests/GuestUmtxOp.cpp @@ -1,3 +1,6 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libkernel/Time/include/Time.hpp" +#include "prx/libc/include/Api.hpp" #include "SceTypes.hpp" #include #include @@ -8,12 +11,6 @@ #include #include -extern "C" { -int APS5_VABI _umtx_op_nid_postfix(void* object, int operation, std::uint64_t value, void* sizeArgument, void* timeArgument); -int* APS5_VABI __error_nid_postfix(); -int APS5_VABI clock_gettime_nid_postfix(int clockId, KernelTimespec* tp); -} - static constexpr int UMTX_OP_WAIT = 2; static constexpr int UMTX_OP_WAKE = 3; static constexpr int UMTX_OP_MUTEX_LOCK = 5; diff --git a/core/libs/tests/GuestUnderscoreEntries.cpp b/core/libs/tests/GuestUnderscoreEntries.cpp index a7e94b5e01..6d62580b8f 100644 --- a/core/libs/tests/GuestUnderscoreEntries.cpp +++ b/core/libs/tests/GuestUnderscoreEntries.cpp @@ -1,3 +1,6 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libkernel/File/include/File.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libkernel/File/include/FileFlags.hpp" #include @@ -13,56 +16,9 @@ #include #include -struct GuestSignalSet { - std::uint32_t bits[4]; -}; -struct GuestSigaction { - std::uintptr_t handler; - int flags; - GuestSignalSet mask; -}; static_assert(sizeof(GuestSigaction) == 32); -struct Iovec { - void* base; - std::uint64_t length; -}; -struct Msghdr { - void* name; - std::uint32_t nameLength; - Iovec* iov; - int iovLength; - void* control; - std::uint32_t controlLength; - int flags; -}; -static_assert(sizeof(Msghdr) == 48); -extern "C" { -int APS5_VABI socket_nid_postfix(int, int, int); -int APS5_VABI close_nid_postfix(int); -int* APS5_VABI __error_nid_postfix(); -int APS5_VABI _bind_nid_postfix(int, const void*, std::uint32_t); -int APS5_VABI _listen_nid_postfix(int, int); -int APS5_VABI _accept_nid_postfix(int, void*, std::uint32_t*); -int APS5_VABI _connect_nid_postfix(int, const void*, std::uint32_t); -int APS5_VABI _getsockname_nid_postfix(int, void*, std::uint32_t*); -int APS5_VABI _getpeername_nid_postfix(int, void*, std::uint32_t*); -int APS5_VABI _setsockopt_nid_postfix(int, int, int, const void*, std::uint32_t); -int APS5_VABI _getsockopt_nid_postfix(int, int, int, void*, std::uint32_t*); -std::int64_t APS5_VABI _sendto_nid_postfix(int, const void*, std::uint64_t, int, const void*, std::uint32_t); -std::int64_t APS5_VABI _recvfrom_nid_postfix(int, void*, std::uint64_t, int, void*, std::uint32_t*); -std::int64_t APS5_VABI _sendmsg_nid_postfix(int, const Msghdr*, int); -std::int64_t APS5_VABI _recvmsg_nid_postfix(int, Msghdr*, int); -int APS5_VABI sceKernelOpen(const char*, int, std::uint16_t); -int APS5_VABI sceKernelClose(int); -std::int64_t APS5_VABI sceKernelLseek(int, std::int64_t, int); -int APS5_VABI getdirentries_nid_postfix(int, char*, int, std::int64_t*); -int APS5_VABI _getdirentries_nid_postfix(int, char*, int, std::int64_t*); -int APS5_VABI raise_nid_postfix(int); -int APS5_VABI sigprocmask_nid_postfix(int, const void*, void*); -int APS5_VABI _sigaction_nid_postfix(int, const GuestSigaction*, GuestSigaction*); -int APS5_VABI _sigsuspend_nid_postfix(const GuestSignalSet*); -} +static_assert(sizeof(GuestMsghdr) == 48); static void Check(bool value, int line) { if (!value) { @@ -183,21 +139,21 @@ static void DatagramSockets() { char head[] = "scatter "; char tail[] = "gather"; - Iovec parts[2]{{head, 8}, {tail, 6}}; - Msghdr outgoing{destination.data(), static_cast(destination.size()), parts, 2, nullptr, 0, 0}; + KernelIovec parts[2]{{head, 8}, {tail, 6}}; + GuestMsghdr outgoing{destination.data(), static_cast(destination.size()), parts, 2, nullptr, 0, 0}; Require(_sendmsg_nid_postfix(sender, &outgoing, 0) == 14); char first[4]{}; char second[16]{}; - Iovec pieces[2]{{first, sizeof(first)}, {second, sizeof(second)}}; + KernelIovec pieces[2]{{first, sizeof(first)}, {second, sizeof(second)}}; source.fill(0); - Msghdr incoming{source.data(), static_cast(source.size()), pieces, 2, nullptr, 0, -1}; + GuestMsghdr incoming{source.data(), static_cast(source.size()), pieces, 2, nullptr, 0, -1}; Require(_recvmsg_nid_postfix(receiver, &incoming, 0) == 14); Require(std::memcmp(first, "scat", 4) == 0 && std::memcmp(second, "ter gather", 10) == 0); Require(incoming.flags == 0 && incoming.nameLength == 16 && source[2] == senderName[2] && source[3] == senderName[3] && source[4] == 127); Require(_sendmsg_nid_postfix(sender, &outgoing, 0) == 14); char shortBuffer[5]{}; - Iovec single{shortBuffer, sizeof(shortBuffer)}; - Msghdr truncated{nullptr, 0, &single, 1, nullptr, 0, 0}; + KernelIovec single{shortBuffer, sizeof(shortBuffer)}; + GuestMsghdr truncated{nullptr, 0, &single, 1, nullptr, 0, 0}; Require(_recvmsg_nid_postfix(receiver, &truncated, 0) == 5 && std::memcmp(shortBuffer, "scatt", 5) == 0 && truncated.flags == Truncated); Require(Fails(_sendmsg_nid_postfix(sender, nullptr, 0), BadAddress)); Require(Fails(_recvmsg_nid_postfix(receiver, nullptr, 0), BadAddress)); diff --git a/core/libs/tests/GuestUnwindModuleInfo.cpp b/core/libs/tests/GuestUnwindModuleInfo.cpp index d0519e368b..d863dcfea1 100644 --- a/core/libs/tests/GuestUnwindModuleInfo.cpp +++ b/core/libs/tests/GuestUnwindModuleInfo.cpp @@ -1,3 +1,4 @@ +#include "prx/libkernel/include/Api.hpp" #include "SceTypes.hpp" #include "tests/GuestUnwindModuleInfoFixture.hpp" #include @@ -9,17 +10,13 @@ #include #include -extern "C" int APS5_VABI sceKernelGetModuleInfoForUnwind(uint64_t addr, int flags, ModuleInfoForUnwind* info); -extern "C" void* APS5_VABI dlopen_nid_postfix(const char*, int); -extern "C" void* APS5_VABI dlsym_nid_postfix(void*, const char*); -extern "C" int APS5_VABI dlclose_nid_postfix(void*); - static void Require(bool value) { if (!value) std::abort(); } static bool Throws(std::uint64_t address) { ModuleInfoForUnwind info{}; try { sceKernelGetModuleInfoForUnwind(address, 0, &info); + } catch (const std::runtime_error&) { return true; } diff --git a/core/libs/tests/GuestUnwindModuleInfoFailureLinux.cpp b/core/libs/tests/GuestUnwindModuleInfoFailureLinux.cpp index f164ab2bc5..da327fc32d 100644 --- a/core/libs/tests/GuestUnwindModuleInfoFailureLinux.cpp +++ b/core/libs/tests/GuestUnwindModuleInfoFailureLinux.cpp @@ -1,3 +1,4 @@ +#include "prx/libkernel/include/Api.hpp" #include "SceTypes.hpp" #include "prx/libkernel/KernelErrors.hpp" #include @@ -5,8 +6,6 @@ #include #include -extern "C" int APS5_VABI sceKernelGetModuleInfoForUnwind(std::uint64_t address, int flags, ModuleInfoForUnwind* info); - static std::uint64_t expectedAddress = 0; static int calls = 0; @@ -29,6 +28,7 @@ int main() { bool threw = false; try { sceKernelGetModuleInfoForUnwind(expectedAddress, 1, &info); + } catch (const std::runtime_error& error) { threw = std::string_view(error.what()) == "sceKernelGetModuleInfoForUnwind: failed to query guest module information"; } diff --git a/core/libs/tests/GuestUnwindModuleInfoLinux.cpp b/core/libs/tests/GuestUnwindModuleInfoLinux.cpp index c7c126b26d..22aae73eb4 100644 --- a/core/libs/tests/GuestUnwindModuleInfoLinux.cpp +++ b/core/libs/tests/GuestUnwindModuleInfoLinux.cpp @@ -1,3 +1,4 @@ +#include "prx/libkernel/include/Api.hpp" #include "SceTypes.hpp" #include #include @@ -5,13 +6,6 @@ #include #include -extern "C" { -int APS5_VABI sceKernelGetModuleInfoForUnwind(uint64_t addr, int flags, ModuleInfoForUnwind* info); -void* APS5_VABI dlopen_nid_postfix(const char* path, int flags); -void* APS5_VABI dlsym_nid_postfix(void* handle, const char* name); -int APS5_VABI dlclose_nid_postfix(void* handle); -} - static void Require(bool value, const char* message) { if (!value) throw std::runtime_error(message); } diff --git a/core/libs/tests/GuestUpdateEnv.cpp b/core/libs/tests/GuestUpdateEnv.cpp index 2b25a307da..5de6f53321 100644 --- a/core/libs/tests/GuestUpdateEnv.cpp +++ b/core/libs/tests/GuestUpdateEnv.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -24,8 +25,7 @@ struct Environment { }; static_assert(sizeof(Environment)==32 && offsetof(Environment,mxcsr)==28); using UpdateEnvironment=int (APS5_VABI*)(const Environment*); -extern "C" int* APS5_VABI __error_nid_postfix(); -extern "C" int APS5_VABI fegetenv_nid_postfix(Environment*); + UpdateEnvironment updateEnvironment; void Require(bool condition,const char* message) { @@ -100,9 +100,11 @@ void TagsAndPointers() { const auto after=Read(); Write(original); Require(result==0 && Same(after,desired),"nonempty x87 tag/TOP and instruction pointer restored"); - Environment saved; - Require(fegetenv_nid_postfix(&saved)==0,"save using existing guest fegetenv"); + GuestFloatingPointEnvironment guestSaved; + Require(fegetenv_nid_postfix(&guestSaved)==0,"save using existing guest fegetenv"); asm volatile("fninit" : : : "st","st(1)","st(2)","st(3)","st(4)","st(5)","st(6)","st(7)"); + Environment saved; + std::memcpy(&saved, &guestSaved, sizeof(saved)); Require(updateEnvironment(&saved)==0,"restore guest fegetenv output"); const auto restored=Read(); Write(original); @@ -166,7 +168,6 @@ void BoundsAndErrors() { Write(entry); } - void MasksAndThreads() { const auto original=Read(); auto clean=original; diff --git a/core/libs/tests/GuestUsbStorage.cpp b/core/libs/tests/GuestUsbStorage.cpp index 60254a0076..43a173d247 100644 --- a/core/libs/tests/GuestUsbStorage.cpp +++ b/core/libs/tests/GuestUsbStorage.cpp @@ -7,13 +7,6 @@ #include #include -extern "C" { -int APS5_VABI sceUsbStorageGetMountPointOfShellCore(unsigned int device, char* mountPoint); -int APS5_VABI sceUsbStorageClearFakeWriteProtection(); -int APS5_VABI sceUsbStorageSetFakeMapLockForDebug(); -int APS5_VABI sceUsbStorageSetFakeWriteProtection(); -} - namespace { int g_attr = 0; diff --git a/core/libs/tests/GuestUsbStorageDialog.cpp b/core/libs/tests/GuestUsbStorageDialog.cpp index e21bcc50eb..56615792bb 100644 --- a/core/libs/tests/GuestUsbStorageDialog.cpp +++ b/core/libs/tests/GuestUsbStorageDialog.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceUsbStorageDialog/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -8,18 +9,6 @@ #include "prx/libSceCommonDialog/CommonDialog.hpp" #include "prx/libSceUserService/UserService.hpp" -extern "C" { -int APS5_VABI sceUserServiceInitialize(const UserServiceInitParam* param); -int APS5_VABI sceUserServiceTerminate(); -int APS5_VABI sceUsbStorageDialogInitialize(void); -int APS5_VABI sceUsbStorageDialogOpen(const UsbStorageDialogParam* param); -int APS5_VABI sceUsbStorageDialogUpdateStatus(void); -int APS5_VABI sceUsbStorageDialogGetStatus(void); -int APS5_VABI sceUsbStorageDialogGetResult(UsbStorageDialogResult* result); -int APS5_VABI sceUsbStorageDialogClose(void); -int APS5_VABI sceUsbStorageDialogTerminate(void); -} - namespace { void Require(bool value) { if (!value) std::abort(); } diff --git a/core/libs/tests/GuestUsbd.cpp b/core/libs/tests/GuestUsbd.cpp index 1cbfa48e1e..eb6cc9af44 100644 --- a/core/libs/tests/GuestUsbd.cpp +++ b/core/libs/tests/GuestUsbd.cpp @@ -1,5 +1,7 @@ +#include "prx/libSceUsbd/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" +#include #include #include #include @@ -12,54 +14,15 @@ namespace { -struct UsbdTimeval { - std::int64_t seconds; - std::int64_t microseconds; -}; - -} - -extern "C" { -std::int32_t APS5_VABI sceUsbdInit(); -void APS5_VABI sceUsbdExit(); -std::int64_t APS5_VABI sceUsbdGetDeviceList(void*** list); -void APS5_VABI sceUsbdFreeDeviceList(void** list, std::int32_t unrefDevices); -std::int32_t APS5_VABI sceUsbdHandleEventsTimeout(const UsbdTimeval* timeout); -std::int32_t APS5_VABI sceUsbdOpen(void* device, void** deviceHandle); -void APS5_VABI sceUsbdClose(void* deviceHandle); -void* APS5_VABI sceUsbdRefDevice(void* device); -void APS5_VABI sceUsbdUnrefDevice(void* device); -std::uint8_t APS5_VABI sceUsbdGetBusNumber(void* device); -std::uint8_t APS5_VABI sceUsbdGetDeviceAddress(void* device); -std::int32_t APS5_VABI sceUsbdGetDeviceDescriptor(void* device, void* descriptor); -std::int32_t APS5_VABI sceUsbdGetConfigDescriptor(void* device, std::uint8_t configIndex, void** config); -std::int32_t APS5_VABI sceUsbdGetActiveConfigDescriptor(void* device, void** config); -std::int32_t APS5_VABI sceUsbdClaimInterface(void* deviceHandle, std::int32_t interfaceNumber); -std::int32_t APS5_VABI sceUsbdReleaseInterface(void* deviceHandle, std::int32_t interfaceNumber); -std::int32_t APS5_VABI sceUsbdSetConfiguration(void* deviceHandle, std::int32_t configuration); -std::int32_t APS5_VABI sceUsbdResetDevice(void* deviceHandle); -std::int32_t APS5_VABI sceUsbdCheckConnected(void* deviceHandle); -std::int32_t APS5_VABI sceUsbdKernelDriverActive(void* deviceHandle, std::int32_t interfaceNumber); -std::int32_t APS5_VABI sceUsbdAttachKernelDriver(void* deviceHandle, std::int32_t interfaceNumber); -std::int32_t APS5_VABI sceUsbdControlTransfer(void* deviceHandle, std::uint8_t requestType, std::uint8_t request, std::uint16_t value, std::uint16_t index, std::uint8_t* data, std::uint16_t length, std::uint32_t timeout); -std::int32_t APS5_VABI sceUsbdGetStringDescriptor(void* deviceHandle, std::uint8_t descriptorIndex, std::uint16_t languageId, std::uint8_t* data, std::int32_t length); -std::int32_t APS5_VABI sceUsbdGetStringDescriptorAscii(void* deviceHandle, std::uint8_t descriptorIndex, std::uint8_t* data, std::int32_t length); -std::int32_t APS5_VABI sceUsbdGetDescriptor(void* deviceHandle, std::uint8_t descriptorType, std::uint8_t descriptorIndex, std::uint8_t* data, std::int32_t length); -std::int32_t APS5_VABI sceUsbdGetConfiguration(void* deviceHandle, std::int32_t* configuration); -std::int32_t APS5_VABI sceUsbdGetConfigDescriptorByValue(void* device, std::uint8_t configurationValue, void** config); -std::int32_t APS5_VABI sceUsbdSubmitTransfer(void* transfer); -void* APS5_VABI sceUsbdAllocTransfer(std::int32_t isoPackets); -void APS5_VABI sceUsbdFreeTransfer(void* transfer); -void APS5_VABI sceUsbdFillInterruptTransfer(void* transfer, void* deviceHandle, std::uint8_t endpoint, std::uint8_t* buffer, std::int32_t length, void* callback, void* userData, std::uint32_t timeout); -std::int32_t APS5_VABI sceUsbdCancelTransfer(void* transfer); -std::int32_t APS5_VABI sceUsbdEventHandlingOk(); -void APS5_VABI sceUsbdFreeConfigDescriptor(void* config); -void APS5_VABI sceUsbdFillControlSetup(std::uint8_t* buffer, std::uint8_t requestType, std::uint8_t request, std::uint16_t value, std::uint16_t index, std::uint16_t length); } namespace { constexpr std::int32_t invalidArgument = static_cast(0x80240002); +constexpr std::int32_t noDevice = static_cast(0x80240004); +constexpr std::int32_t notFound = static_cast(0x80240005); +constexpr std::int32_t otherError = static_cast(0x802400FF); +constexpr std::uint8_t absentEndpoint = 0x70; void Require(bool condition, const char* message) { if (!condition) { @@ -78,26 +41,11 @@ bool Throws(TCall call) { return false; } -struct HostTransfer { - void* deviceHandle; - std::uint8_t flags; - std::uint8_t endpoint; - std::uint8_t type; - std::uint32_t timeout; - std::int32_t status; - std::int32_t length; - std::int32_t actualLength; - void (APS5_VABI* callback)(HostTransfer*); - void* userData; - std::uint8_t* buffer; - std::int32_t numIsoPackets; -}; - -void APS5_VABI MarkDone(HostTransfer* transfer) { +void APS5_VABI MarkDone(UsbdTransfer* transfer) { *static_cast(transfer->userData) += 1; } -void APS5_VABI MarkDoneThenSignal(HostTransfer* transfer) { +void APS5_VABI MarkDoneThenSignal(UsbdTransfer* transfer) { auto* notified = static_cast*>(transfer->userData); notified->store(true, std::memory_order_release); } @@ -123,6 +71,7 @@ void Device() { if ((descriptor[8] | descriptor[9] << 8) == vendor && (descriptor[10] | descriptor[11] << 8) == product) device = sceUsbdRefDevice(list[index]); } sceUsbdFreeDeviceList(list, 1); + Require(device != nullptr, "the APS5_USBD_DEVICE device was not listed"); std::printf("device bus %u address %u\n", sceUsbdGetBusNumber(device), sceUsbdGetDeviceAddress(device)); void* config = nullptr; @@ -132,6 +81,7 @@ void Device() { const std::uint8_t interfaces = raw[4]; const std::uint8_t activeValue = raw[5]; sceUsbdFreeConfigDescriptor(config); + Require(Throws([&] { sceUsbdFreeConfigDescriptor(config); }), "a config descriptor was freed twice"); Require(sceUsbdGetConfigDescriptor(device, 0, &config) == 0, "config descriptor 0 failed"); sceUsbdFreeConfigDescriptor(config); @@ -142,6 +92,10 @@ void Device() { void* handle = nullptr; Require(sceUsbdOpen(device, &handle) == 0 && handle != nullptr, "opening the device failed"); Require(sceUsbdCheckConnected(handle) == 0, "an open device was reported disconnected"); + Require(sceUsbdGetDevice(handle) == device, "the device of an open handle is not the device it was opened from"); + const int speed = sceUsbdGetDeviceSpeed(device); + Require(speed >= 1 && speed <= 4, "the device speed is not low, full, high or super speed"); + std::printf("device speed %d\n", speed); std::int32_t configuration = -1; Require(sceUsbdGetConfiguration(handle, &configuration) == 0 && configuration == activeValue, "configuration differs from the active config descriptor"); std::uint8_t text[256] = {}; @@ -186,6 +140,7 @@ void Device() { const std::uint8_t* interfaceArray = *reinterpret_cast(config0 + 16); std::uint8_t interruptAddress = 0; std::uint16_t interruptMax = 0; + std::uint8_t interruptInterface = 0; if (interfaceArray == nullptr) { Require(false, "the active config descriptor has no interface array"); } @@ -199,13 +154,31 @@ void Device() { if ((item[2] & 0x80) != 0 && (item[3] & 3) == 3) { interruptAddress = item[2]; interruptMax = static_cast(item[4] | item[5] << 8); + interruptInterface = alternate[2]; } } } Require(interruptAddress != 0 && interruptMax != 0, "the device has no interrupt IN endpoint"); sceUsbdFreeConfigDescriptor(config); + Require(sceUsbdGetMaxPacketSize(device, interruptAddress) == interruptMax, "the max packet size differs from the endpoint descriptor"); + const int expectedIso = speed <= 2 ? interruptMax : (interruptMax & 0x7FF) * std::min(1 + ((interruptMax >> 11) & 3), 3); + Require(sceUsbdGetMaxIsoPacketSize(device, interruptAddress) == expectedIso, "the max iso packet size differs from the endpoint descriptor"); + Require(sceUsbdGetMaxPacketSize(device, absentEndpoint) == notFound && sceUsbdGetMaxIsoPacketSize(device, absentEndpoint) == notFound, "an absent endpoint has a max packet size"); + Require(sceUsbdSetInterfaceAltSetting(handle, interruptInterface, 0) == notFound, "an unclaimed interface took an alternate setting"); + Require(sceUsbdSetInterfaceAltSetting(handle, 32, 0) == invalidArgument && sceUsbdSetInterfaceAltSetting(handle, -1, 0) == invalidArgument, "an interface number outside 0 to 31 was accepted"); + Require(sceUsbdClaimInterface(handle, interruptInterface) == 0, "claiming the interrupt endpoint's interface failed"); + const std::int32_t alternate = sceUsbdSetInterfaceAltSetting(handle, interruptInterface, 0); + Require(alternate == 0 || alternate == otherError, "alternate setting 0 returned neither success nor the other error"); + std::printf("alternate setting 0 of interface %u: %d\n", interruptInterface, alternate); + Require(sceUsbdClearHalt(handle, interruptAddress) == 0, "clearing the interrupt endpoint's halt failed"); + Require(sceUsbdClearHalt(handle, absentEndpoint) == otherError, "clearing the halt of an absent endpoint did not return the other error"); + const std::int32_t detached = sceUsbdDetachKernelDriver(handle, interruptInterface); + Require(detached == 0 || detached == otherError, "detaching the kernel driver returned neither success nor the other error"); + std::printf("kernel driver detach: %d\n", detached); + Require(sceUsbdReleaseInterface(handle, interruptInterface) == 0, "releasing the interrupt endpoint's interface failed"); + Require(sceUsbdSetInterfaceAltSetting(handle, interruptInterface, 0) == notFound, "a released interface took an alternate setting"); - auto* transfer = static_cast(sceUsbdAllocTransfer(0)); + auto* transfer = reinterpret_cast(sceUsbdAllocTransfer(0)); std::uint8_t setup[8 + 18] = {0x80, 6, 0x00, 0x01, 0x00, 0x00, 18, 0}; int done = 0; transfer->deviceHandle = handle; @@ -215,8 +188,8 @@ void Device() { transfer->length = sizeof(setup); transfer->callback = MarkDone; transfer->userData = &done; - Require(sceUsbdSubmitTransfer(transfer) == 0, "submitting an asynchronous control transfer failed"); - Require(Throws([&] { sceUsbdFreeTransfer(transfer); }), "an in-flight transfer was freed"); + Require(sceUsbdSubmitTransfer(reinterpret_cast(transfer)) == 0, "submitting an asynchronous control transfer failed"); + Require(Throws([&] { sceUsbdFreeTransfer(reinterpret_cast(transfer)); }), "an in-flight transfer was freed"); Pump(done); Require(done == 1 && transfer->status == 0 && transfer->actualLength == 18, "asynchronous control transfer did not complete"); Require(std::memcmp(setup + 8, descriptor, 18) == 0, "asynchronous device descriptor differs from the cached one"); @@ -226,14 +199,15 @@ void Device() { for (int round = 0; round < 300 && !broken; ++round) { std::atomic notified{false}; std::uint8_t blink[64] = {}; - sceUsbdFillInterruptTransfer(transfer, handle, interruptAddress, blink, interruptMax, reinterpret_cast(&MarkDoneThenSignal), ¬ified, 0); - const int submitResult = sceUsbdSubmitTransfer(transfer); + sceUsbdFillInterruptTransfer(reinterpret_cast(transfer), handle, interruptAddress, blink, interruptMax, &MarkDoneThenSignal, ¬ified, 0); + + const int submitResult = sceUsbdSubmitTransfer(reinterpret_cast(transfer)); if (submitResult != 0) { broken = true; break; } std::thread canceller([&] { - const int outcome = sceUsbdCancelTransfer(transfer); + const int outcome = sceUsbdCancelTransfer(reinterpret_cast(transfer)); if (outcome != 0 && outcome != static_cast(0x80240005)) broken = true; }); while (!notified.load(std::memory_order_acquire)) { @@ -245,11 +219,23 @@ void Device() { } Require(!broken, "the cancel race failed"); - Require(sceUsbdCancelTransfer(transfer) == static_cast(0x80240005), "cancelling a completed transfer did not report not found"); - sceUsbdFreeTransfer(transfer); + Require(sceUsbdCancelTransfer(reinterpret_cast(transfer)) == static_cast(0x80240005), "cancelling a completed transfer did not report not found"); + sceUsbdFreeTransfer(reinterpret_cast(transfer)); sceUsbdClose(handle); + Require(Throws([&] { sceUsbdClose(handle); }), "a handle was closed twice"); + Require(Throws([&] { sceUsbdGetDevice(handle); }), "the device of a closed handle was returned"); sceUsbdUnrefDevice(device); + void* byId = sceUsbdOpenDeviceWithVidPid(static_cast(vendor), static_cast(product)); + Require(byId != nullptr, "opening the device by vendor and product failed"); + void* byIdDevice = sceUsbdGetDevice(byId); + std::uint8_t byIdDescriptor[18] = {}; + Require(sceUsbdGetDeviceDescriptor(byIdDevice, byIdDescriptor) == 0, "the device of a handle opened by vendor and product has no descriptor"); + Require((byIdDescriptor[8] | byIdDescriptor[9] << 8) == vendor && (byIdDescriptor[10] | byIdDescriptor[11] << 8) == product, "the device opened by vendor and product has another vendor or product"); + Require(sceUsbdGetMaxPacketSize(byIdDevice, interruptAddress) == interruptMax, "the max packet size through a handle's device differs"); + sceUsbdClose(byId); + Require(Throws([&] { sceUsbdGetDeviceDescriptor(byIdDevice, byIdDescriptor); }), "the device of a closed handle stayed known"); + std::puts("USBD device tests passed"); } @@ -265,8 +251,10 @@ int main(int argc, char** argv) { Require(sceUsbdGetDeviceDescriptor(list[index], deviceDescriptor) == 0 && deviceDescriptor[0] == 18 && deviceDescriptor[1] == 1, "listed device has no device descriptor"); Require(sceUsbdRefDevice(list[index]) == list[index], "listed device was not referenced"); sceUsbdUnrefDevice(list[index]); + } sceUsbdFreeDeviceList(list, 1); + Require(Throws([&] { sceUsbdFreeDeviceList(list, 1); }), "a device list was freed twice"); Require(sceUsbdGetDeviceList(nullptr) == invalidArgument, "null list accepted"); Require(sceUsbdHandleEventsTimeout(nullptr) == invalidArgument, "null timeout accepted"); @@ -282,9 +270,11 @@ int main(int argc, char** argv) { Require(Throws([&] { sceUsbdOpen(nullptr, &handle); }), "opening a null device did not throw"); Require(Throws([&] { sceUsbdOpen(&foreign, &handle); }), "opening a device that was never listed did not throw"); sceUsbdClose(nullptr); + Require(Throws([&] { sceUsbdClose(&foreign); }), "closing a handle that was never opened did not throw"); Require(sceUsbdRefDevice(nullptr) == nullptr, "null device was referenced"); sceUsbdUnrefDevice(nullptr); + Require(Throws([&] { sceUsbdRefDevice(&foreign); }), "referencing a device that was never listed did not throw"); Require(Throws([&] { sceUsbdUnrefDevice(&foreign); }), "unreferencing a device that was never listed did not throw"); Require(sceUsbdGetBusNumber(nullptr) == 0 && sceUsbdGetDeviceAddress(nullptr) == 0, "null device reported a bus or address"); @@ -321,34 +311,56 @@ int main(int argc, char** argv) { Require(sceUsbdGetConfigDescriptorByValue(nullptr, 1, &config) == invalidArgument && sceUsbdGetConfigDescriptorByValue(&foreign, 1, nullptr) == invalidArgument, "null config by value argument accepted"); Require(Throws([&] { sceUsbdGetConfigDescriptorByValue(&foreign, 1, &config); }), "config by value of a device that was never listed did not throw"); Require(Throws([&] { sceUsbdClaimInterface(&foreign, 0); }), "claiming on a handle that was never opened did not throw"); - auto* transfer = static_cast(sceUsbdAllocTransfer(2)); + auto* transfer = reinterpret_cast(sceUsbdAllocTransfer(2)); Require(transfer != nullptr, "transfer allocation failed"); Require(*reinterpret_cast(transfer + 56) == 2, "iso packet count not stored"); Require(sceUsbdAllocTransfer(-1) == nullptr, "negative iso packet count accepted"); std::uint8_t buffer[8] = {}; int user = 0; - sceUsbdFillInterruptTransfer(transfer, nullptr, 0x81, buffer, 8, reinterpret_cast(&Require), &user, 250); + sceUsbdFillInterruptTransfer(reinterpret_cast(transfer), nullptr, 0x81, buffer, 8, reinterpret_cast(&Require), &user, 250); + Require(transfer[9] == 0x81 && transfer[10] == 3, "endpoint or interrupt type not filled"); Require(*reinterpret_cast(transfer + 12) == 250 && *reinterpret_cast(transfer + 20) == 8, "timeout or length not filled"); Require(*reinterpret_cast(transfer + 40) == &user && *reinterpret_cast(transfer + 48) == buffer, "user data or buffer not filled"); - Require(sceUsbdCancelTransfer(transfer) == static_cast(0x80240005), "cancelling an unsubmitted transfer did not report not found"); + Require(sceUsbdCancelTransfer(reinterpret_cast(transfer)) == static_cast(0x80240005), "cancelling an unsubmitted transfer did not report not found"); Require(sceUsbdSubmitTransfer(nullptr) == invalidArgument, "null transfer submitted"); - Require(sceUsbdSubmitTransfer(transfer) == invalidArgument, "transfer without a handle submitted"); - sceUsbdFillInterruptTransfer(transfer, &foreign, 0x81, buffer, 8, reinterpret_cast(&Require), &user, 250); - Require(Throws([&] { sceUsbdSubmitTransfer(transfer); }), "submitting on a handle that was never opened did not throw"); - sceUsbdFreeTransfer(transfer); + Require(sceUsbdSubmitTransfer(reinterpret_cast(transfer)) == invalidArgument, "transfer without a handle submitted"); + sceUsbdFillInterruptTransfer(reinterpret_cast(transfer), &foreign, 0x81, buffer, 8, reinterpret_cast(&Require), &user, 250); + + Require(Throws([&] { sceUsbdSubmitTransfer(reinterpret_cast(transfer)); }), "submitting on a handle that was never opened did not throw"); + sceUsbdFreeTransfer(reinterpret_cast(transfer)); + Require(Throws([&] { sceUsbdClearHalt(nullptr, 0x81); }), "clearing a halt on a null handle did not throw"); + Require(Throws([&] { sceUsbdClearHalt(&foreign, 0x81); }), "clearing a halt on a handle that was never opened did not throw"); + Require(sceUsbdDetachKernelDriver(nullptr, 0) == invalidArgument, "null handle kernel driver detach accepted"); + Require(Throws([&] { sceUsbdDetachKernelDriver(&foreign, 0); }), "kernel driver detach on a handle that was never opened did not throw"); + Require(sceUsbdGetDevice(nullptr) == nullptr, "a null handle has a device"); + Require(Throws([&] { sceUsbdGetDevice(&foreign); }), "the device of a handle that was never opened did not throw"); + Require(sceUsbdGetDeviceSpeed(nullptr) == 0, "a null device has a speed"); + Require(Throws([&] { sceUsbdGetDeviceSpeed(&foreign); }), "the speed of a device that was never listed did not throw"); + Require(sceUsbdGetMaxPacketSize(nullptr, 0x81) == noDevice, "a null device has a max packet size"); + Require(Throws([&] { sceUsbdGetMaxPacketSize(&foreign, 0x81); }), "the max packet size of a device that was never listed did not throw"); + Require(Throws([&] { sceUsbdGetMaxIsoPacketSize(nullptr, 0x81); }), "the max iso packet size of a null device did not throw"); + Require(Throws([&] { sceUsbdGetMaxIsoPacketSize(&foreign, 0x81); }), "the max iso packet size of a device that was never listed did not throw"); + Require(sceUsbdSetInterfaceAltSetting(nullptr, 0, 0) == invalidArgument, "null handle alternate setting accepted"); + Require(Throws([&] { sceUsbdSetInterfaceAltSetting(&foreign, 0, 0); }), "an alternate setting on a handle that was never opened did not throw"); + Require(sceUsbdOpenDeviceWithVidPid(0, 0) == nullptr, "a device with vendor and product 0 was opened"); sceUsbdFreeTransfer(nullptr); + Require(sceUsbdEventHandlingOk() == 1, "event handling not allowed"); sceUsbdFreeConfigDescriptor(nullptr); + Require(Throws([] { sceUsbdFillControlSetup(nullptr, 0x80, 6, 0x0100, 0, 18); }), "null control setup buffer accepted"); std::uint8_t setupBuffer[8] = {}; sceUsbdFillControlSetup(setupBuffer, 0x80, 6, 0x0100, 0x0409, 18); + Require(setupBuffer[0] == 0x80 && setupBuffer[1] == 6, "request type or request not filled"); Require(setupBuffer[2] == 0x00 && setupBuffer[3] == 0x01, "value not filled little-endian"); Require(setupBuffer[4] == 0x09 && setupBuffer[5] == 0x04, "index not filled little-endian"); Require(setupBuffer[6] == 18 && setupBuffer[7] == 0, "length not filled little-endian"); if (argc == 2 && std::strcmp(argv[1], "device") == 0) Device(); sceUsbdExit(); + Require(sceUsbdOpenDeviceWithVidPid(0, 0) == nullptr, "a device was opened after the library exited"); + std::puts("USBD tests passed"); return 0; } diff --git a/core/libs/tests/GuestUserContext.cpp b/core/libs/tests/GuestUserContext.cpp index c616e2260d..46fb68c1d5 100644 --- a/core/libs/tests/GuestUserContext.cpp +++ b/core/libs/tests/GuestUserContext.cpp @@ -1,3 +1,6 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" +#include "prx/libSceLibcInternal/include/Api.hpp" #include "prx/libc/include/general/AsmMacros.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libkernel/System/include/UserContext.hpp" @@ -16,15 +19,6 @@ using ContextEntry = void (APS5_VABI*)(); extern "C" { -[[gnu::returns_twice]] int APS5_VABI getcontext_nid_postfix(UserUcontext* context); -int APS5_VABI setcontext_nid_postfix(const UserUcontext* context); -void APS5_VABI makecontext_nid_postfix(UserUcontext* context, ContextEntry entry, int count, ...); -[[gnu::returns_twice]] int APS5_VABI setjmp_nid_postfix(std::uint64_t* buffer); -[[noreturn]] void APS5_VABI longjmp_nid_postfix(std::uint64_t* buffer, int value); -[[gnu::returns_twice]] int APS5_VABI sigsetjmp_nid_postfix(std::uint64_t* buffer, int saveMask); -[[noreturn]] void APS5_VABI siglongjmp_nid_postfix(std::uint64_t* buffer, int value); -int APS5_VABI sigprocmask_nid_postfix(int how, const void* set, void* previousSet); -int* APS5_VABI __error_nid_postfix(); int APS5_VABI CaptureKnownRegisters(UserUcontext* context); void CaptureReturnAddress(); @@ -238,24 +232,29 @@ void CheckErrors() { invalid.stackPointer = g_contextStack.bytes; invalid.stackSize = StackBytes; makecontext_nid_postfix(&invalid, &EntryThunk, 7); + Require(invalid.mcontext.len == 0, "makecontext invalidates a context with more than six arguments"); invalid = context; invalid.stackPointer = g_contextStack.bytes; invalid.stackSize = 2047; makecontext_nid_postfix(&invalid, &EntryThunk, 0); + Require(invalid.mcontext.len == 0, "makecontext invalidates a context with a stack below MINSIGSTKSZ"); invalid = context; invalid.stackPointer = nullptr; invalid.stackSize = StackBytes; makecontext_nid_postfix(&invalid, &EntryThunk, 0); + Require(invalid.mcontext.len == 0, "makecontext invalidates a context without a stack"); invalid = context; invalid.stackPointer = g_contextStack.bytes; invalid.stackSize = StackBytes; invalid.mcontext.len = 0; makecontext_nid_postfix(&invalid, &EntryThunk, 0); + Require(invalid.mcontext.len == 0 && invalid.mcontext.rip == context.mcontext.rip, "makecontext leaves a context without a valid mc_len untouched"); makecontext_nid_postfix(nullptr, &EntryThunk, 0); + } void CheckCapture() { @@ -331,6 +330,7 @@ void CheckRestore() { std::memcpy(image + FxsaveXmm + index * 8, &value, sizeof(value)); } setcontext_nid_postfix(&target); + Require(false, "setcontext returned from a valid context"); } const auto& machine = target.mcontext; @@ -374,6 +374,7 @@ namespace { if (sigsetjmp_nid_postfix(from->jump, 1) == 0) { if (to->started) siglongjmp_nid_postfix(to->jump, 1); setcontext_nid_postfix(&to->context); + Require(false, "setcontext into the job returned"); } return; @@ -381,6 +382,7 @@ namespace { if (setjmp_nid_postfix(from->jump) == 0) { if (to->started) longjmp_nid_postfix(to->jump, 1); setcontext_nid_postfix(&to->context); + Require(false, "setcontext into the job returned"); } } @@ -415,8 +417,10 @@ void CheckMakecontext() { context.stackSize = StackBytes; context.link = &caller; makecontext_nid_postfix(&context, &EntryThunk, 6, 0x8000000000000001ull, 0x8000000000000002ull, 0x8000000000000003ull, 0x8000000000000004ull, 0x8000000000000005ull, 0x8000000000000006ull); + Require(context.mcontext.len == sizeof(UserMcontext), "makecontext keeps the context valid"); setcontext_nid_postfix(&context); + Require(false, "setcontext into the made context returned"); } Require(g_entries == 1, "the made context runs once and resumes uc_link"); @@ -448,6 +452,7 @@ void CheckJumpBuffers(bool signalJumps) { g_job.context.stackSize = StackBytes; g_job.context.link = nullptr; makecontext_nid_postfix(&g_job.context, &JobEntry, 0); + for (int round = 1; round <= 4; ++round) { Switch(&g_dispatcher, &g_job); Require(g_jobRuns == round, "the job runs once per switch"); @@ -473,6 +478,7 @@ void CheckSignalMask() { phase = 1; Require(sigprocmask_nid_postfix(GuestSigSetmask, second, nullptr) == 0, "set the second mask"); setcontext_nid_postfix(&context); + Require(false, "setcontext returned from a valid context"); } std::uint32_t current[4] = {}; @@ -488,6 +494,7 @@ int ExitFromContext() { context.link = nullptr; makecontext_nid_postfix(&context, &ReturnWithoutLink, 0); setcontext_nid_postfix(&context); + return 1; } diff --git a/core/libs/tests/GuestUserService.cpp b/core/libs/tests/GuestUserService.cpp index 88116c03d8..9b46dffc13 100644 --- a/core/libs/tests/GuestUserService.cpp +++ b/core/libs/tests/GuestUserService.cpp @@ -7,31 +7,6 @@ #include #include -extern "C" { -int APS5_VABI sceUserServiceGetInitialUser(int* user_id); -int APS5_VABI sceUserServiceGetGamePresets(int user_id, UserServiceGamePresets* presets); -int APS5_VABI sceUserServiceGetUserNumber(int user_id, int32_t* number); -int APS5_VABI sceUserServiceGetPlatformPrivacyWs1(int32_t user_id, int32_t* value); -int APS5_VABI sceUserServiceGetForegroundUser(int* user_id); -int APS5_VABI sceUserServiceGetRegisteredUserIdList(UserServiceRegisteredUserIdList* user_id_list); -int APS5_VABI sceUserServiceGetUserColor(int user_id, int* color); -int APS5_VABI sceUserServiceGetKeyboardType(int user_id, std::int32_t* type); -int APS5_VABI sceUserServiceGetJapaneseInputType(int user_id, std::int32_t* type); -int APS5_VABI sceUserServiceGetTraditionalChineseInputType(int user_id, std::int32_t* type); -int APS5_VABI sceUserServiceGetNpAccountId(int user_id, std::uint64_t* account_id); -int APS5_VABI sceUserServiceGetAgeLevel(int user_id, std::uint32_t* age_level); -int APS5_VABI sceUserServiceGetAccessibilityChatTranscription(int user_id, std::int32_t* value); -int APS5_VABI sceUserServiceGetAccessibilityKeyremapEnable(); -int APS5_VABI sceUserServiceGetAccessibilityPressAndHoldDelay(int user_id, std::int32_t* value); -int APS5_VABI sceUserServiceGetAccessibilityTriggerEffect(int user_id, std::int32_t* value); -int APS5_VABI sceUserServiceGetAccessibilityVibration(int user_id, std::int32_t* value); -int APS5_VABI sceUserServiceGetAccessibilityZoom(); -int APS5_VABI sceUserServiceGetAccessibilityZoomEnabled(int user_id, std::int32_t* value); -int APS5_VABI sceUserServiceGetAccessibilityZoomFollowFocus(int user_id, std::int32_t* value); -int APS5_VABI sceUserServiceGetUserName(int user_id, char* name, std::size_t size); -int APS5_VABI sceUserServiceGetUserNumber(int user_id, std::int32_t* number); -} - namespace { void Require(bool value) { if (!value) std::abort(); } @@ -167,9 +142,10 @@ int main() { presets.difficulty = 0x5a; Require(sceUserServiceGetGamePresets(0, &presets) == USER_SERVICE_ERROR_INVALID_ARGUMENT && presets.difficulty == 0x5a); Require(sceUserServiceGetGamePresets(USER_SERVICE_INITIAL_USER_ID, &presets) == USER_SERVICE_OK && presets.difficulty == 0); + std::int32_t accessibilityValue = 0; bool threwKeyremap = false; try { - sceUserServiceGetAccessibilityKeyremapEnable(); + sceUserServiceGetAccessibilityKeyremapEnable(USER_SERVICE_INITIAL_USER_ID, &accessibilityValue); } catch (const std::runtime_error&) { threwKeyremap = true; } @@ -177,7 +153,7 @@ int main() { bool threwZoom = false; try { - sceUserServiceGetAccessibilityZoom(); + sceUserServiceGetAccessibilityZoom(USER_SERVICE_INITIAL_USER_ID, &accessibilityValue); } catch (const std::runtime_error&) { threwZoom = true; } @@ -203,6 +179,15 @@ int main() { Require(sceUserServiceGetUserColor(USER_SERVICE_INITIAL_USER_ID + 1, &color) == USER_SERVICE_OK); Require(color == 1); + Require(sceUserServiceGetAgeLevel(USER_SERVICE_INITIAL_USER_ID + 1, &age_level) == USER_SERVICE_ERROR_NOT_LOGGED_IN); + Require(sceUserServiceGetAgeLevel(USER_SERVICE_INITIAL_USER_ID + 1, nullptr) == USER_SERVICE_ERROR_NOT_LOGGED_IN); + for (const Setting& setting : settings) { + std::int32_t value = 0x5a5a5a5a; + Require(setting.get(USER_SERVICE_INITIAL_USER_ID + 1, &value) == USER_SERVICE_ERROR_NOT_LOGGED_IN); + Require(value == 0x5a5a5a5a); + Require(setting.get(USER_SERVICE_INITIAL_USER_ID + 1, nullptr) == USER_SERVICE_ERROR_NOT_LOGGED_IN); + } + UserServiceSetUserConnected_nid_postfix(1, true); Require(sceUserServiceGetRegisteredUserIdList(®istered) == USER_SERVICE_OK); Require(registered.user_id[0] == USER_SERVICE_INITIAL_USER_ID); @@ -210,10 +195,26 @@ int main() { for (int i = 2; i < 16; ++i) { Require(registered.user_id[i] == USER_SERVICE_USER_ID_INVALID); } + Require(sceUserServiceGetAgeLevel(USER_SERVICE_INITIAL_USER_ID + 1, &age_level) == USER_SERVICE_OK); + Require(age_level == 0xffffffffu); + for (const Setting& setting : settings) { + std::int32_t value = 0x5a5a5a5a; + Require(setting.get(USER_SERVICE_INITIAL_USER_ID + 1, &value) == USER_SERVICE_OK); + Require(value == setting.value); + } + UserServiceSetUserConnected_nid_postfix(1, false); Require(sceUserServiceGetRegisteredUserIdList(®istered) == USER_SERVICE_OK); Require(registered.user_id[0] == USER_SERVICE_INITIAL_USER_ID); for (int i = 1; i < 16; ++i) { Require(registered.user_id[i] == USER_SERVICE_USER_ID_INVALID); } + Require(sceUserServiceGetAgeLevel(USER_SERVICE_INITIAL_USER_ID + 1, &age_level) == USER_SERVICE_ERROR_NOT_LOGGED_IN); + Require(sceUserServiceGetAgeLevel(USER_SERVICE_INITIAL_USER_ID + 1, nullptr) == USER_SERVICE_ERROR_NOT_LOGGED_IN); + for (const Setting& setting : settings) { + std::int32_t value = 0x5a5a5a5a; + Require(setting.get(USER_SERVICE_INITIAL_USER_ID + 1, &value) == USER_SERVICE_ERROR_NOT_LOGGED_IN); + Require(value == 0x5a5a5a5a); + Require(setting.get(USER_SERVICE_INITIAL_USER_ID + 1, nullptr) == USER_SERVICE_ERROR_NOT_LOGGED_IN); + } } diff --git a/core/libs/tests/GuestUserServiceLifecycle.cpp b/core/libs/tests/GuestUserServiceLifecycle.cpp index b1346120f8..99a61cc97b 100644 --- a/core/libs/tests/GuestUserServiceLifecycle.cpp +++ b/core/libs/tests/GuestUserServiceLifecycle.cpp @@ -4,14 +4,6 @@ #include #include -extern "C" { -int APS5_VABI sceUserServiceInitialize(const UserServiceInitParam* params); -int APS5_VABI sceUserServiceInitialize2(std::int32_t priority, KernelCpumask affinityMask); -int APS5_VABI sceUserServiceTerminate(void); -int APS5_VABI sceUserServiceGetLoginUserIdList(UserServiceLoginUserIdList* user_id_list); -int APS5_VABI sceUserServiceGetEvent(SceUserServiceEvent* event); -} - namespace { void Require(bool value) { if (!value) std::abort(); } diff --git a/core/libs/tests/GuestUserServiceUserName.cpp b/core/libs/tests/GuestUserServiceUserName.cpp index f755162970..15ad3469e3 100644 --- a/core/libs/tests/GuestUserServiceUserName.cpp +++ b/core/libs/tests/GuestUserServiceUserName.cpp @@ -5,10 +5,6 @@ #include #include -extern "C" { -int APS5_VABI sceUserServiceGetUserName(int user_id, char* name, std::size_t size); -} - namespace { void Require(bool value) { if (!value) std::abort(); } diff --git a/core/libs/tests/GuestUtime.cpp b/core/libs/tests/GuestUtime.cpp index 884cff4e47..48417ce88f 100644 --- a/core/libs/tests/GuestUtime.cpp +++ b/core/libs/tests/GuestUtime.cpp @@ -1,3 +1,5 @@ +#include "prx/libc/include/Api.hpp" +#include "prx/libSceLibcInternal/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -12,17 +14,8 @@ #include #endif -struct LibcUtimbuf { - std::int64_t actime; - std::int64_t modtime; -}; static_assert(sizeof(LibcUtimbuf) == 16); -extern "C" { -int APS5_VABI utime_nid_postfix(const char*, const LibcUtimbuf*); -int* APS5_VABI __error_nid_postfix(); -} - static void Require(bool condition, int line) { if (!condition) { std::fprintf(stderr, "Utime check failed at line %d\n", line); diff --git a/core/libs/tests/GuestUtimeForwarding.cpp b/core/libs/tests/GuestUtimeForwarding.cpp index 870d83d404..146ca8f7bd 100644 --- a/core/libs/tests/GuestUtimeForwarding.cpp +++ b/core/libs/tests/GuestUtimeForwarding.cpp @@ -1,15 +1,9 @@ +#include "prx/libSceLibcInternal/include/Api.hpp" #include "SceTypes.hpp" #include #include #include -struct LibcUtimbuf { - std::int64_t actime; - std::int64_t modtime; -}; - -extern "C" int APS5_VABI utime_nid_postfix(const char*, const LibcUtimbuf*); - namespace { int guestError; int backendResult; diff --git a/core/libs/tests/GuestVdecsw.cpp b/core/libs/tests/GuestVdecsw.cpp index 6bb929a1e0..d30d2421aa 100644 --- a/core/libs/tests/GuestVdecsw.cpp +++ b/core/libs/tests/GuestVdecsw.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceVdecsw/include/Api.hpp" #include #include #include @@ -11,198 +12,17 @@ #include "H264Fixture.hpp" #include "HevcFixture.hpp" -struct ComputeMemoryInfo { - std::uint64_t thisSize; - std::uint64_t cpuGpuMemorySize; - void* cpuGpuMemory; -}; +using namespace SceVdecsw; -struct ComputeConfigInfo { - std::uint64_t thisSize; - std::uint16_t computePipeId; - std::uint16_t computeQueueId; - bool checkMemoryType; -}; - -struct DecoderConfigInfo { - std::uint64_t thisSize; - std::uint32_t resourceType; - std::uint32_t codecType; - std::uint32_t profile; - std::uint32_t maxLevel; - std::int32_t maxFrameWidth; - std::int32_t maxFrameHeight; - std::int32_t maxDpbFrameCount; - std::uint32_t decodePipelineDepth; - std::uint64_t computeQueue; - std::uint64_t cpuAffinityMask; - std::int32_t cpuThreadPriority; - bool optimizeProgressiveVideo; - std::uint8_t reserved[19]; -}; - -struct DecoderMemoryInfo { - std::uint64_t thisSize; - std::uint64_t cpuMemorySize; - void* cpuMemory; - std::uint64_t gpuMemorySize; - void* gpuMemory; - std::uint64_t cpuGpuMemorySize; - void* cpuGpuMemory; - std::uint64_t maxFrameBufferSize; - std::uint32_t frameBufferAlignment; -}; - -struct InputData { - std::uint64_t thisSize; - const std::uint8_t* auData; - std::uint64_t auSize; - std::uint64_t ptsData; - std::uint64_t dtsData; - std::uint64_t attachedData; -}; - -struct InputResult { - std::uint64_t thisSize; - const void* decodedAu; - std::uint32_t outputFrameCount; - std::uint32_t reserved; -}; - -struct FrameBuffer { - std::uint64_t thisSize; - void* frameBuffer; - std::uint64_t frameBufferSize; -}; - -struct OutputInfo { - std::uint64_t thisSize; - bool isValid; - bool isLastFrame; - bool isErrorFrame; - std::uint8_t pictureCount; - std::uint32_t codecType; - std::uint32_t frameWidth; - std::uint32_t framePitch; - std::uint32_t frameHeight; - bool isDiscardedFrame; - void* frameBuffer; - std::uint64_t frameBufferSize; - std::uint32_t frameFormat; - std::uint32_t framePitchInBytes; -}; - -struct Vp9PictureInfo { - std::uint64_t thisSize; - bool isValid; - std::uint64_t ptsData; - std::uint64_t dtsData; - std::uint64_t attachedData; - std::uint32_t profile; - std::uint32_t level; - std::uint32_t keyFrameFlag; - std::uint32_t intraOnly; - std::uint8_t bitDepth; - std::uint8_t colorRange; - std::uint32_t colorSpace; - std::uint32_t numFrames; - std::uint32_t frameWidth; - std::uint32_t frameHeight; - std::uint32_t renderWidth; - std::uint32_t renderHeight; -}; - -static_assert(sizeof(Vp9PictureInfo) == 0x58 && offsetof(Vp9PictureInfo, ptsData) == 0x10 && offsetof(Vp9PictureInfo, profile) == 0x28 && offsetof(Vp9PictureInfo, bitDepth) == 0x38 && offsetof(Vp9PictureInfo, colorSpace) == 0x3c && offsetof(Vp9PictureInfo, renderHeight) == 0x50); - -struct AvcPictureInfo { - std::uint64_t thisSize; - bool isValid; - std::uint64_t ptsData; - std::uint64_t dtsData; - std::uint64_t attachedData; - std::uint8_t idrPictureFlag; - std::uint8_t profileIdc; - std::uint8_t levelIdc; - std::uint32_t picWidthInMbsMinus1; - std::uint32_t picHeightInMapUnitsMinus1; - std::uint8_t frameMbsOnlyFlag; - std::uint8_t frameCroppingFlag; - std::uint32_t frameCropLeftOffset; - std::uint32_t frameCropRightOffset; - std::uint32_t frameCropTopOffset; - std::uint32_t frameCropBottomOffset; - std::uint8_t vui[44]; -}; - -struct HevcPictureInfo { - std::uint64_t thisSize; - bool isValid; - std::uint64_t ptsData; - std::uint64_t dtsData; - std::uint64_t attachedData; - std::uint32_t picWidthInLumaSamples; - std::uint32_t picHeightInLumaSamples; - std::uint8_t bitDepthLumaMinus8; - std::uint8_t bitDepthChromaMinus8; - std::uint8_t timingInfoPresentFlag; - std::uint32_t numUnitsInTick; - std::uint32_t timeScale; - std::uint32_t aspectRatioInfoPresentFlag; - std::uint8_t aspectRatioIdc; - std::uint16_t sarWidth; - std::uint16_t sarHeight; - std::uint8_t videoSignal[8]; - std::uint32_t picStruct; - std::uint32_t sourceScanType; - std::uint32_t duplicateFlag; - std::uint32_t conformanceWindowFlag; - std::uint32_t confWinLeftOffset; - std::uint32_t confWinRightOffset; - std::uint32_t confWinTopOffset; - std::uint32_t confWinBottomOffset; - std::uint32_t defaultDisplayWindow[5]; - std::uint8_t chromaLocation[4]; - std::uint8_t presentFlags[11]; - std::uint8_t idrPictureFlag; - std::uint8_t irapPictureFlag; - std::uint8_t generalProfileSpace; - std::uint8_t generalTierFlag; - std::uint8_t generalProfileIdc; - std::uint8_t generalSourceFlags[3]; - std::uint8_t generalLevelIdc; - std::uint8_t subLayer[9]; - std::uint8_t frameCroppingFlag; - std::uint32_t frameCropLeftOffset; - std::uint32_t frameCropRightOffset; - std::uint32_t frameCropTopOffset; - std::uint32_t frameCropBottomOffset; -}; +static_assert(sizeof(SceVideodec2::Vp9PictureInfo) == 0x58 && offsetof(SceVideodec2::Vp9PictureInfo, ptsData) == 0x10 && offsetof(SceVideodec2::Vp9PictureInfo, profile) == 0x28 && offsetof(SceVideodec2::Vp9PictureInfo, bitDepth) == 0x38 && offsetof(SceVideodec2::Vp9PictureInfo, colorSpace) == 0x3c && offsetof(SceVideodec2::Vp9PictureInfo, renderHeight) == 0x50); static_assert(sizeof(HevcPictureInfo) == 0xb8 && offsetof(HevcPictureInfo, idrPictureFlag) == 0x93 && offsetof(HevcPictureInfo, frameCroppingFlag) == 0xa5); -static_assert(sizeof(DecoderConfigInfo) == 0x50 && sizeof(OutputInfo) == 0x38 && offsetof(OutputInfo, isLastFrame) == 9 && offsetof(OutputInfo, pictureCount) == 0xb && sizeof(AvcPictureInfo) == 0x78); - -extern "C" { -int APS5_VABI sceVdecswQueryComputeMemoryInfo(ComputeMemoryInfo*); -int APS5_VABI sceVdecswAllocateComputeQueue(const ComputeConfigInfo*, const ComputeMemoryInfo*, std::uint64_t*); -int APS5_VABI sceVdecswReleaseComputeQueue(std::uint64_t); -int APS5_VABI sceVdecswQueryDecoderMemoryInfo(const DecoderConfigInfo*, DecoderMemoryInfo*); -int APS5_VABI sceVdecswCreateDecoder(const DecoderConfigInfo*, const DecoderMemoryInfo*, std::uint64_t*); -int APS5_VABI sceVdecswDeleteDecoder(std::uint64_t); -int APS5_VABI sceVdecswSetDecodeInput(std::uint64_t, const InputData*); -int APS5_VABI sceVdecswTrySyncDecodeInput(std::uint64_t, InputResult*); -int APS5_VABI sceVdecswSyncDecodeInput(std::uint64_t, InputResult*); -int APS5_VABI sceVdecswSetDecodeOutput(std::uint64_t, const FrameBuffer*); -int APS5_VABI sceVdecswTrySyncDecodeOutput(std::uint64_t, OutputInfo*); -int APS5_VABI sceVdecswSyncDecodeOutput(std::uint64_t, OutputInfo*); -int APS5_VABI sceVdecswGetVp9PictureInfo(const OutputInfo*, Vp9PictureInfo*); -int APS5_VABI sceVdecswGetAvcPictureInfo(const OutputInfo*, AvcPictureInfo*, AvcPictureInfo*); -int APS5_VABI sceVdecswGetHevcPictureInfo(const OutputInfo*, HevcPictureInfo*); -int APS5_VABI sceVdecswFinalizeDecodeSequence(std::uint64_t); -int APS5_VABI sceVdecswResetDecoder(std::uint64_t); -} +static_assert(sizeof(SceVdecsw::DecoderConfigInfo) == 0x50 && sizeof(OutputInfo) == 0x38 && offsetof(OutputInfo, isLastFrame) == 9 && offsetof(OutputInfo, pictureCount) == 0xb && sizeof(AvcPictureInfo) == 0x78); namespace { +using namespace SceVdecsw; + using namespace H264Fixture; using namespace HevcFixture; using namespace Vp9Fixture; @@ -221,14 +41,14 @@ void check(bool condition, const std::string& message) { struct Session { std::uint64_t queue = 0; std::uint64_t decoder = 0; - DecoderMemoryInfo memory{sizeof(DecoderMemoryInfo)}; + SceVideodec2::DecoderMemoryInfo memory{sizeof(SceVideodec2::DecoderMemoryInfo)}; explicit Session(std::uint32_t codec = CodecAvc, std::uint32_t profile = 100, std::uint32_t level = 42) { - ComputeMemoryInfo compute{sizeof(ComputeMemoryInfo)}; + SceVideodec2::ComputeMemoryInfo compute{sizeof(SceVideodec2::ComputeMemoryInfo)}; check(sceVdecswQueryComputeMemoryInfo(&compute) == 0 && compute.cpuGpuMemorySize != 0, "compute memory query failed"); - const ComputeConfigInfo computeConfig{sizeof(ComputeConfigInfo), 3, 3, true}; + const SceVideodec2::ComputeConfigInfo computeConfig{sizeof(SceVideodec2::ComputeConfigInfo), 3, 3, true}; check(sceVdecswAllocateComputeQueue(&computeConfig, &compute, &queue) == 0, "compute queue allocation failed"); - DecoderConfigInfo config{sizeof(DecoderConfigInfo), 1, codec, profile, level, static_cast(Width), static_cast(Height), 4, 3, queue, 0x3f, 0, true, {}}; + SceVdecsw::DecoderConfigInfo config{{sizeof(SceVdecsw::DecoderConfigInfo), 1, codec, profile, level, static_cast(Width), static_cast(Height), 4, 3}, queue, 0x3f, 0, true, {}}; check(sceVdecswQueryDecoderMemoryInfo(&config, &memory) == 0 && memory.maxFrameBufferSize != 0, "decoder memory query failed"); check(sceVdecswCreateDecoder(&config, &memory, &decoder) == 0, "decoder creation failed"); } @@ -236,6 +56,7 @@ struct Session { ~Session() { sceVdecswDeleteDecoder(decoder); sceVdecswReleaseComputeQueue(queue); + } }; @@ -280,7 +101,7 @@ void testDecode() { }; std::uint32_t produced = 0; for (std::size_t unit = 0; unit < units.size(); ++unit) { - const InputData input{sizeof(InputData), units[unit].data(), units[unit].size(), 1000 + unit, unit, 0xa0 + unit}; + const SceVideodec2::InputData input{sizeof(SceVideodec2::InputData), units[unit].data(), units[unit].size(), 1000 + unit, unit, 0xa0 + unit}; check(sceVdecswSetDecodeInput(session.decoder, &input) == 0, "decode input was rejected"); InputResult consumed{sizeof(InputResult)}; check(sceVdecswTrySyncDecodeInput(session.decoder, &consumed) == 0 && consumed.decodedAu == units[unit].data(), "an access unit was not consumed"); @@ -326,6 +147,7 @@ void testHevc() { bool avcThrows = false; try { sceVdecswGetAvcPictureInfo(&output, &avc, nullptr); + } catch (const std::exception&) { avcThrows = true; } @@ -335,7 +157,7 @@ void testHevc() { } }; for (std::size_t unit = 0; unit < units.size(); ++unit) { - const InputData input{sizeof(InputData), units[unit].data(), units[unit].size(), 1000 + unit, unit, 0xa0 + unit}; + const SceVideodec2::InputData input{sizeof(SceVideodec2::InputData), units[unit].data(), units[unit].size(), 1000 + unit, unit, 0xa0 + unit}; check(sceVdecswSetDecodeInput(session.decoder, &input) == 0, "HEVC decode input was rejected"); InputResult consumed{sizeof(InputResult)}; check(sceVdecswTrySyncDecodeInput(session.decoder, &consumed) == 0 && consumed.decodedAu == units[unit].data(), "an HEVC access unit was not consumed"); @@ -351,7 +173,7 @@ void testHevcCrop() { std::vector buffer(session.memory.maxFrameBufferSize); const FrameBuffer frame{sizeof(FrameBuffer), buffer.data(), buffer.size()}; check(sceVdecswSetDecodeOutput(session.decoder, &frame) == 0, "cropped HEVC output buffer was rejected"); - const InputData input{sizeof(InputData), HevcCroppedStream.data(), HevcCroppedStream.size(), 1000, 0, 0xa0}; + const SceVideodec2::InputData input{sizeof(SceVideodec2::InputData), HevcCroppedStream.data(), HevcCroppedStream.size(), 1000, 0, 0xa0}; check(sceVdecswSetDecodeInput(session.decoder, &input) == 0, "cropped HEVC decode input was rejected"); InputResult consumed{sizeof(InputResult)}; check(sceVdecswSyncDecodeInput(session.decoder, &consumed) == 0, "the cropped HEVC access unit was not consumed"); @@ -368,7 +190,7 @@ void testHevcCrop() { void testWithoutOutput() { Session session; const auto units = accessUnits(false); - const InputData input{sizeof(InputData), units[0].data(), units[0].size(), 1000, 0, 0xa0}; + const SceVideodec2::InputData input{sizeof(SceVideodec2::InputData), units[0].data(), units[0].size(), 1000, 0, 0xa0}; check(sceVdecswSetDecodeInput(session.decoder, &input) == 0, "decode input was rejected"); InputResult result{sizeof(InputResult)}; check(sceVdecswTrySyncDecodeInput(session.decoder, &result) == 0 && result.decodedAu == units[0].data(), "an input was not decoded before an output buffer was set"); @@ -388,7 +210,7 @@ void testSyncWrappers() { InputResult idle{sizeof(InputResult)}; check(sceVdecswSyncDecodeInput(session.decoder, &idle) == InputQueueEmpty, "sync input on an idle decoder did not report an empty queue"); const auto units = accessUnits(false); - const InputData input{sizeof(InputData), units[0].data(), units[0].size(), 1000, 0, 0xa0}; + const SceVideodec2::InputData input{sizeof(SceVideodec2::InputData), units[0].data(), units[0].size(), 1000, 0, 0xa0}; check(sceVdecswSetDecodeInput(session.decoder, &input) == 0, "decode input was rejected"); InputResult result{sizeof(InputResult)}; check(sceVdecswSyncDecodeInput(session.decoder, &result) == 0 && result.decodedAu == units[0].data(), "sync input did not consume the access unit"); @@ -402,6 +224,7 @@ void testSyncWrappers() { bool hevcThrows = false; try { sceVdecswGetHevcPictureInfo(&output, &hevc); + } catch (const std::exception&) { hevcThrows = true; } @@ -411,14 +234,14 @@ void testSyncWrappers() { struct Vp9Session { std::uint64_t queue = 0; std::uint64_t decoder = 0; - DecoderMemoryInfo memory{sizeof(DecoderMemoryInfo)}; + SceVideodec2::DecoderMemoryInfo memory{sizeof(SceVideodec2::DecoderMemoryInfo)}; Vp9Session() { - ComputeMemoryInfo compute{sizeof(ComputeMemoryInfo)}; + SceVideodec2::ComputeMemoryInfo compute{sizeof(SceVideodec2::ComputeMemoryInfo)}; check(sceVdecswQueryComputeMemoryInfo(&compute) == 0 && compute.cpuGpuMemorySize != 0, "compute memory query failed"); - const ComputeConfigInfo computeConfig{sizeof(ComputeConfigInfo), 3, 3, true}; + const SceVideodec2::ComputeConfigInfo computeConfig{sizeof(SceVideodec2::ComputeConfigInfo), 3, 3, true}; check(sceVdecswAllocateComputeQueue(&computeConfig, &compute, &queue) == 0, "compute queue allocation failed"); - DecoderConfigInfo config{sizeof(DecoderConfigInfo), 1, CodecVp9, 0, 0, static_cast(Width), static_cast(Height), 4, 3, queue, 0x3f, 0, true, {}}; + SceVdecsw::DecoderConfigInfo config{{sizeof(SceVdecsw::DecoderConfigInfo), 1, CodecVp9, 0, 0, static_cast(Width), static_cast(Height), 4, 3}, queue, 0x3f, 0, true, {}}; check(sceVdecswQueryDecoderMemoryInfo(&config, &memory) == 0 && memory.maxFrameBufferSize != 0, "VP9 decoder memory query failed"); check(sceVdecswCreateDecoder(&config, &memory, &decoder) == 0, "VP9 decoder creation failed"); } @@ -426,6 +249,7 @@ struct Vp9Session { ~Vp9Session() { sceVdecswDeleteDecoder(decoder); sceVdecswReleaseComputeQueue(queue); + } }; @@ -439,20 +263,20 @@ bool throws(TAction action) { return false; } -Vp9PictureInfo sentinelVp9Info(std::uint64_t size = sizeof(Vp9PictureInfo)) { - Vp9PictureInfo info; +SceVideodec2::Vp9PictureInfo sentinelVp9Info(std::uint64_t size = sizeof(SceVideodec2::Vp9PictureInfo)) { + SceVideodec2::Vp9PictureInfo info; std::memset(&info, 0xcc, sizeof(info)); info.thisSize = size; return info; } -bool sameBytes(const Vp9PictureInfo& left, const Vp9PictureInfo& right) { - return std::memcmp(&left, &right, sizeof(Vp9PictureInfo)) == 0; +bool sameBytes(const SceVideodec2::Vp9PictureInfo& left, const SceVideodec2::Vp9PictureInfo& right) { + return std::memcmp(&left, &right, sizeof(SceVideodec2::Vp9PictureInfo)) == 0; } -void checkVp9Info(const Vp9PictureInfo& info, std::size_t picture) { +void checkVp9Info(const SceVideodec2::Vp9PictureInfo& info, std::size_t picture) { const std::string name = "VP9 picture " + std::to_string(picture); - check(info.thisSize == sizeof(Vp9PictureInfo) && info.isValid, name + " has no picture info"); + check(info.thisSize == sizeof(SceVideodec2::Vp9PictureInfo) && info.isValid, name + " has no picture info"); check(info.ptsData == 1000 + picture && info.dtsData == picture && info.attachedData == 0xa0 + picture, name + " timestamps differ"); check(info.profile == 0 && info.bitDepth == 8 && info.colorRange == 0 && info.colorSpace == 0 && info.numFrames == 1 && info.intraOnly == 0, name + " coded header fields differ"); check(info.keyFrameFlag == (picture == 0 ? 1u : 0u), name + " key frame flag differs"); @@ -497,7 +321,7 @@ void testVp9PictureInfo() { } }; for (std::size_t unit = 0; unit < units.size(); ++unit) { - const InputData input{sizeof(InputData), units[unit].data(), units[unit].size(), 1000 + unit, unit, 0xa0 + unit}; + const SceVideodec2::InputData input{sizeof(SceVideodec2::InputData), units[unit].data(), units[unit].size(), 1000 + unit, unit, 0xa0 + unit}; check(sceVdecswSetDecodeInput(session.decoder, &input) == 0, "VP9 decode input was rejected"); InputResult consumed{sizeof(InputResult)}; check(sceVdecswTrySyncDecodeInput(session.decoder, &consumed) == 0 && consumed.decodedAu == units[unit].data(), "a VP9 access unit was not consumed"); @@ -533,21 +357,21 @@ void testVp9PictureInfo() { unknown.frameBuffer = nullptr; check(throws([&] { sceVdecswGetVp9PictureInfo(&unknown, &info); }) && sameBytes(info, unchanged), "a null frame buffer was accepted"); - const auto head = offsetof(Vp9PictureInfo, profile); + const auto head = offsetof(SceVideodec2::Vp9PictureInfo, profile); auto partial = sentinelVp9Info(head); check(sceVdecswGetVp9PictureInfo(&outputs[2], &partial) == 0, "a VP9 picture info with a short size field was rejected"); check(partial.thisSize == head && partial.isValid && partial.ptsData == 1002 && partial.dtsData == 2 && partial.attachedData == 0xa2, "the leading VP9 picture info fields were not written"); check(partial.profile == unchanged.profile && partial.frameWidth == unchanged.frameWidth && partial.renderHeight == unchanged.renderHeight, "a VP9 picture info with a short size field was written beyond it"); struct Oversized { - Vp9PictureInfo info; + SceVideodec2::Vp9PictureInfo info; std::uint8_t tail[64]; } oversized; std::memset(&oversized, 0xcc, sizeof(oversized)); oversized.info.thisSize = sizeof(Oversized); check(sceVdecswGetVp9PictureInfo(&outputs[3], &oversized.info) == 0, "a VP9 picture info with a long size field was rejected"); check(oversized.info.thisSize == sizeof(Oversized), "a long VP9 picture info size field was changed"); - oversized.info.thisSize = sizeof(Vp9PictureInfo); + oversized.info.thisSize = sizeof(SceVideodec2::Vp9PictureInfo); checkVp9Info(oversized.info, 3); for (const auto byte : oversized.tail) check(byte == 0xcc, "a VP9 picture info with a long size field was written beyond the structure"); @@ -561,7 +385,7 @@ void testVp9PictureInfo() { void testVp9PictureInfoOfAvcPicture() { Session session; const auto units = accessUnits(false); - const InputData input{sizeof(InputData), units[0].data(), units[0].size(), 1000, 0, 0xa0}; + const SceVideodec2::InputData input{sizeof(SceVideodec2::InputData), units[0].data(), units[0].size(), 1000, 0, 0xa0}; check(sceVdecswSetDecodeInput(session.decoder, &input) == 0, "decode input was rejected"); InputResult result{sizeof(InputResult)}; check(sceVdecswSyncDecodeInput(session.decoder, &result) == 0, "the access unit was not consumed"); @@ -583,7 +407,7 @@ void testHevcMain10() { std::vector buffer(session.memory.maxFrameBufferSize); const FrameBuffer frame{sizeof(FrameBuffer), buffer.data(), buffer.size()}; check(sceVdecswSetDecodeOutput(session.decoder, &frame) == 0, "Main 10 HEVC output buffer was rejected"); - const InputData input{sizeof(InputData), HevcMain10Stream.data(), HevcMain10Stream.size(), 1000, 0, 0xa0}; + const SceVideodec2::InputData input{sizeof(SceVideodec2::InputData), HevcMain10Stream.data(), HevcMain10Stream.size(), 1000, 0, 0xa0}; check(sceVdecswSetDecodeInput(session.decoder, &input) == 0, "Main 10 HEVC decode input was rejected"); InputResult consumed{sizeof(InputResult)}; check(sceVdecswSyncDecodeInput(session.decoder, &consumed) == 0, "the Main 10 HEVC access unit was not consumed"); diff --git a/core/libs/tests/GuestVectorAlgorithms.cpp b/core/libs/tests/GuestVectorAlgorithms.cpp index 8fd443df2e..99eaebf937 100644 --- a/core/libs/tests/GuestVectorAlgorithms.cpp +++ b/core/libs/tests/GuestVectorAlgorithms.cpp @@ -1,32 +1,47 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include #include #include -struct MinMaxPointers { - const void* minimum; - const void* maximum; -}; - -extern "C" { -const void* APS5_VABI __std_find_trivial_2_nid_postfix(const void*, const void*, std::uint16_t); -const void* APS5_VABI __std_find_trivial_unsized_1_nid_postfix(const void*, std::uint8_t); -const void* APS5_VABI __std_find_trivial_unsized_2_nid_postfix(const void*, std::uint16_t); -const void* APS5_VABI __std_find_trivial_unsized_4_nid_postfix(const void*, std::uint32_t); -const void* APS5_VABI __std_find_trivial_unsized_8_nid_postfix(const void*, std::uint64_t); -std::size_t APS5_VABI __std_count_trivial_8_nid_postfix(const void*, const void*, std::uint64_t); -const void* APS5_VABI __std_min_element_1_nid_postfix(const void*, const void*, bool); -const void* APS5_VABI __std_max_element_4_nid_postfix(const void*, const void*, bool); -MinMaxPointers APS5_VABI __std_minmax_element_2_nid_postfix(const void*, const void*, bool); -MinMaxPointers APS5_VABI __std_minmax_element_8_nid_postfix(const void*, const void*, bool); -void APS5_VABI __std_reverse_trivially_swappable_2_nid_postfix(void*, void*); -void APS5_VABI __std_reverse_copy_trivially_copyable_8_nid_postfix(const void*, const void*, void*); -void APS5_VABI __std_swap_ranges_trivially_swappable_noalias_nid_postfix(void*, void*, void*); -} static void Require(bool value) { if (!value) std::abort(); } +static void CheckSizedHelpers() { + const std::uint8_t bytes[] = {3, 0xff, 3, 9, 0xff}; + Require(__std_find_trivial_1_nid_postfix(bytes, bytes + 5, 0xff) == bytes + 1); + Require(__std_find_trivial_1_nid_postfix(bytes, bytes + 5, 4) == bytes + 5); + Require(__std_find_trivial_1_nid_postfix(bytes, bytes, 3) == bytes); + Require(__std_count_trivial_1_nid_postfix(bytes, bytes + 5, 3) == 2 && __std_count_trivial_1_nid_postfix(bytes, bytes + 5, 7) == 0); + Require(__std_max_element_1_nid_postfix(bytes, bytes + 5, false) == bytes + 1); + Require(__std_max_element_1_nid_postfix(bytes, bytes + 5, true) == bytes + 3); + + const std::uint16_t halves[] = {0x8000, 5, 0x7fff, 5, 0x8000}; + Require(__std_count_trivial_2_nid_postfix(halves, halves + 5, 5) == 2 && __std_count_trivial_2_nid_postfix(halves, halves, 5) == 0); + Require(__std_min_element_2_nid_postfix(halves, halves + 5, false) == halves + 1); + Require(__std_min_element_2_nid_postfix(halves, halves + 5, true) == halves); + Require(__std_max_element_2_nid_postfix(halves, halves + 5, false) == halves); + Require(__std_max_element_2_nid_postfix(halves, halves + 5, true) == halves + 2); + + const std::uint32_t words[] = {7, 0xfffffff0u, 1, 1, 0xfffffff0u}; + Require(__std_find_trivial_4_nid_postfix(words, words + 5, 1) == words + 2); + Require(__std_find_trivial_4_nid_postfix(words, words + 5, 2) == words + 5); + Require(__std_count_trivial_4_nid_postfix(words, words + 5, 0xfffffff0u) == 2); + Require(__std_min_element_4_nid_postfix(words, words + 5, false) == words + 2); + Require(__std_min_element_4_nid_postfix(words, words + 5, true) == words + 1); + Require(__std_min_element_4_nid_postfix(words, words, true) == words); + + const std::uint64_t wides[] = {0x8000000000000000ull, 2, 0x7fffffffffffffffull, 0x8000000000000000ull}; + Require(__std_find_trivial_8_nid_postfix(wides, wides + 4, 0x8000000000000000ull) == wides); + Require(__std_find_trivial_8_nid_postfix(wides + 1, wides + 4, 0x8000000000000000ull) == wides + 3); + Require(__std_min_element_8_nid_postfix(wides, wides + 4, true) == wides); + Require(__std_min_element_8_nid_postfix(wides, wides + 4, false) == wides + 1); + Require(__std_max_element_8_nid_postfix(wides, wides + 4, false) == wides); + Require(__std_max_element_8_nid_postfix(wides, wides + 4, true) == wides + 2); + Require(__std_max_element_8_nid_postfix(wides, wides, false) == wides); +} + static void CheckFindAndCount() { const std::uint16_t halves[] = {5, 7, 9, 7}; Require(__std_find_trivial_2_nid_postfix(halves, halves + 4, 7) == halves + 1); @@ -105,10 +120,12 @@ static void CheckMinMax() { static void CheckReverseAndSwap() { std::uint16_t halves[] = {1, 2, 3, 4, 5}; __std_reverse_trivially_swappable_2_nid_postfix(halves, halves + 5); + Require(halves[0] == 5 && halves[1] == 4 && halves[2] == 3 && halves[3] == 2 && halves[4] == 1); const std::uint64_t wides[] = {1, 2, 3}; std::uint64_t reversed[4] = {9, 9, 9, 9}; __std_reverse_copy_trivially_copyable_8_nid_postfix(wides, wides + 3, reversed); + Require(reversed[0] == 3 && reversed[1] == 2 && reversed[2] == 1 && reversed[3] == 9); unsigned char left[37], right[37]; for (int i = 0; i < 37; ++i) { @@ -116,10 +133,12 @@ static void CheckReverseAndSwap() { right[i] = static_cast(100 + i); } __std_swap_ranges_trivially_swappable_noalias_nid_postfix(left, left + 37, right); + for (int i = 0; i < 37; ++i) Require(left[i] == 100 + i && right[i] == i); } int main() { + CheckSizedHelpers(); CheckFindAndCount(); CheckUnsizedRescan(); CheckMinMax(); diff --git a/core/libs/tests/GuestVideoOutColorSpace.cpp b/core/libs/tests/GuestVideoOutColorSpace.cpp index 1c081f65f9..d794feff72 100644 --- a/core/libs/tests/GuestVideoOutColorSpace.cpp +++ b/core/libs/tests/GuestVideoOutColorSpace.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceVideoOut/include/Output.hpp" #include "SceTypes.hpp" #include "prx/libc/include/Shutdown.hpp" #include "tests/VideoOutTestEnvironment.hpp" @@ -8,18 +9,6 @@ #include #include -extern "C" { -int APS5_VABI sceVideoOutOpen(int userId, int busType, int index, const void* param); -int APS5_VABI sceVideoOutClose(int handle); -int APS5_VABI sceVideoOutColorSpaceConversionSettingsSetDefaultSdrToHdrConversion(VideoOutColorSpaceConversionSettings* settings); -int APS5_VABI sceVideoOutColorSpaceConversionSettingsSetSdrToHdrConversion(VideoOutColorSpaceConversionSettings* settings, float lumaScale, uint32_t option); -int APS5_VABI sceVideoOutAdjustColorSpaceConversion(int handle, const VideoOutColorSpaceConversionSettings* settings); -int APS5_VABI sceVideoOutColorSpaceConversionSettingsSetDefaultSdrToHdrConversion_(VideoOutColorSpaceConversionSettings* settings, uint32_t settings_size); -int APS5_VABI sceVideoOutColorSpaceConversionSettingsSetSdrToHdrConversion_(VideoOutColorSpaceConversionSettings* settings, float lumaScale, uint32_t option, uint32_t settings_size); -int APS5_VABI sceVideoOutAdjustColorSpaceConversion_(int handle, const VideoOutColorSpaceConversionSettings* settings, uint32_t settings_size); -int APS5_VABI sceVideoOutSetGlobalBlendSpace(int handle, uint32_t space, uint32_t option); -} - static constexpr int SYSTEM_USER = 255; static constexpr int MAIN_BUS = 0; diff --git a/core/libs/tests/GuestVideoOutCursor.cpp b/core/libs/tests/GuestVideoOutCursor.cpp index 214293bdd2..283d91bccf 100644 --- a/core/libs/tests/GuestVideoOutCursor.cpp +++ b/core/libs/tests/GuestVideoOutCursor.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceVideoOut/include/VideoOut.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -6,13 +7,6 @@ #include #include -extern "C" { -int APS5_VABI sceVideoOutCursorEnable(std::int32_t handle, std::int32_t index, const void* address); -int APS5_VABI sceVideoOutCursorDisable(std::int32_t handle, std::int32_t index); -int APS5_VABI sceVideoOutCursorSetImageAddress(std::int32_t handle, std::int32_t index, const void* address); -int APS5_VABI sceVideoOutCursorSetPosition(std::int32_t handle, std::int32_t index, std::uint32_t x, std::uint32_t y); -} - static bool ReportsNotImplemented(const std::string& name, const std::function& call) { try { call(); diff --git a/core/libs/tests/GuestVideoOutHdr.cpp b/core/libs/tests/GuestVideoOutHdr.cpp index a6e78ed34d..08fc189878 100644 --- a/core/libs/tests/GuestVideoOutHdr.cpp +++ b/core/libs/tests/GuestVideoOutHdr.cpp @@ -1,3 +1,7 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libSceVideoOut/include/Output.hpp" +#include "prx/libSceVideoOut/include/Event.hpp" +#include "prx/libSceSystemService/include/SystemService.hpp" #include "SceTypes.hpp" #include "prx/libc/include/Shutdown.hpp" #include "prx/libkernel/Equeue/Equeue.hpp" @@ -14,19 +18,6 @@ #include #include -extern "C" { -int APS5_VABI sceVideoOutOpen(int userId, int busType, int index, const void* param); -int APS5_VABI sceVideoOutClose(int handle); -int APS5_VABI sceVideoOutGetOutputStatus(int handle, VideoOutOutputStatus* status); -int APS5_VABI sceVideoOutGetOutputStatusWithVrr(int handle, void* status); -int APS5_VABI sceVideoOutAddOutputModeEvent(KernelEqueue eq, int handle, void* udata); -int APS5_VABI sceVideoOutGetEventId(const KernelEvent* ev); -int APS5_VABI sceKernelCreateEqueue(KernelEqueue* eq, const char* name); -int APS5_VABI sceKernelDeleteEqueue(KernelEqueue eq); -int APS5_VABI sceKernelWaitEqueue(KernelEqueue eq, KernelEvent* ev, int num, int* out, const KernelUseconds* timo); -int APS5_VABI sceSystemServiceGetHdrToneMapLuminance(SystemServiceHdrToneMapLuminance* luminance); -} - namespace { constexpr int SystemUser = 255; diff --git a/core/libs/tests/GuestVideoOutHighFrameRate.cpp b/core/libs/tests/GuestVideoOutHighFrameRate.cpp index 3e4f4c4437..541436b236 100644 --- a/core/libs/tests/GuestVideoOutHighFrameRate.cpp +++ b/core/libs/tests/GuestVideoOutHighFrameRate.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceVideoOut/include/Output.hpp" #include "SceTypes.hpp" #include "prx/libc/include/Shutdown.hpp" #include "tests/VideoOutTestEnvironment.hpp" @@ -7,16 +8,6 @@ #include #include -extern "C" { -int APS5_VABI sceVideoOutOpen(int, int, int, const void*); -int APS5_VABI sceVideoOutClose(int); -int APS5_VABI sceVideoOutIsOutputSupported(int, std::uint64_t, const VideoOutOutputOptions*, void*, std::uint64_t); -int APS5_VABI sceVideoOutConfigureOutput(int, std::uint64_t, const VideoOutOutputOptions*, void*, std::uint64_t); -int APS5_VABI sceVideoOutWaitVblank(int); -int APS5_VABI sceVideoOutGetOutputStatus(int, VideoOutOutputStatus*); -int APS5_VABI sceVideoOutGetResolutionStatus(int, VideoOutResolutionStatus*); -} - static constexpr int Unsupported = static_cast(0x80290016u); static void Require(bool value, const char* message) { diff --git a/core/libs/tests/GuestVideoOutOutputMode.cpp b/core/libs/tests/GuestVideoOutOutputMode.cpp index 82ce4bc2fa..7c86474ea9 100644 --- a/core/libs/tests/GuestVideoOutOutputMode.cpp +++ b/core/libs/tests/GuestVideoOutOutputMode.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceVideoOut/include/Output.hpp" #include "SceTypes.hpp" #include "prx/libc/include/Shutdown.hpp" #include "tests/VideoOutTestEnvironment.hpp" @@ -8,14 +9,6 @@ #include #include -extern "C" { -int APS5_VABI sceVideoOutOpen(int userId, int busType, int index, const void* param); -int APS5_VABI sceVideoOutClose(int handle); -int APS5_VABI sceVideoOutInitializeOutputOptions(VideoOutOutputOptions* options); -int APS5_VABI sceVideoOutIsOutputSupported(int handle, std::uint64_t mode, const VideoOutOutputOptions* options, void* reservedPtr, std::uint64_t reserved); -int APS5_VABI sceVideoOutConfigureOutput(int handle, std::uint64_t mode, const VideoOutOutputOptions* options, void* reservedPtr, std::uint64_t reserved); -} - static constexpr int SYSTEM_USER = 255; static constexpr int MAIN_BUS = 0; static constexpr int HMD2_MAIN_BUS = 0x20; diff --git a/core/libs/tests/GuestVideoOutResolutionStatus.cpp b/core/libs/tests/GuestVideoOutResolutionStatus.cpp index e401ad3023..338783ec96 100644 --- a/core/libs/tests/GuestVideoOutResolutionStatus.cpp +++ b/core/libs/tests/GuestVideoOutResolutionStatus.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceVideoOut/include/Output.hpp" #include "SceTypes.hpp" #include "prx/libc/include/Shutdown.hpp" #include "tests/VideoOutTestEnvironment.hpp" @@ -8,14 +9,6 @@ #include #include -extern "C" { -int APS5_VABI sceVideoOutOpen(int userId, int busType, int index, const void* param); -int APS5_VABI sceVideoOutClose(int handle); -int APS5_VABI sceVideoOutGetOutputStatus(int handle, VideoOutOutputStatus* status); -int APS5_VABI sceVideoOutGetOutputStatusWithVrr(int handle, void* status); -int APS5_VABI sceVideoOutGetResolutionStatus(int handle, VideoOutResolutionStatus* status); -} - static constexpr int SYSTEM_USER = 255; static constexpr int MAIN_BUS = 0; static constexpr int NEVER_OPENED_HANDLE = 2; diff --git a/core/libs/tests/GuestVideoOutWqhdDetection.cpp b/core/libs/tests/GuestVideoOutWqhdDetection.cpp index c0e68b0c49..0e543eaade 100644 --- a/core/libs/tests/GuestVideoOutWqhdDetection.cpp +++ b/core/libs/tests/GuestVideoOutWqhdDetection.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceVideoOut/include/Output.hpp" #include "SceTypes.hpp" #include "prx/libc/include/Shutdown.hpp" #include "tests/VideoOutTestEnvironment.hpp" @@ -6,13 +7,6 @@ #include #include -extern "C" { -int APS5_VABI sceVideoOutOpen(int userId, int busType, int index, const void* param); -int APS5_VABI sceVideoOutClose(int handle); -int APS5_VABI sceVideoOutGetOutputStatus(int handle, VideoOutOutputStatus* status); -int APS5_VABI sceVideoOutAllowOutputResolutionWqhdDetection(int handle); -} - static constexpr int SYSTEM_USER = 255; static constexpr int MAIN_BUS = 0; static constexpr int NEVER_OPENED_HANDLE = 2; diff --git a/core/libs/tests/GuestVideoRecording.cpp b/core/libs/tests/GuestVideoRecording.cpp index 537811d685..ff7b12233e 100644 --- a/core/libs/tests/GuestVideoRecording.cpp +++ b/core/libs/tests/GuestVideoRecording.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceVideoRecordingP/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -6,17 +7,6 @@ #include #include -extern "C" { -void APS5_VABI _sceVideoRecordingQueryParam_nid_postfix(void* param); -int APS5_VABI sceVideoRecordingGetStatus(void); -int APS5_VABI sceVideoRecordingQueryMemSize(const void* param); -int APS5_VABI sceVideoRecordingOpen(const char* path, const void* param, void* heap, int heapSize); -int APS5_VABI sceVideoRecordingStart(void); -int APS5_VABI sceVideoRecordingStop(void); -int APS5_VABI sceVideoRecordingClose(int discard); -int APS5_VABI sceVideoRecordingGetInfo(std::int32_t info, void* data, std::size_t size); -} - namespace { constexpr int StatusNone = 0; @@ -50,10 +40,10 @@ int main() { std::array heap{}; heap.fill(Sentinel); - Require(Throws([&] { _sceVideoRecordingQueryParam_nid_postfix(param.data()); }), "the default parameters were produced"); - Require(Throws([&] { sceVideoRecordingQueryMemSize(param.data()); }), "a heap size was reported"); + Require(Throws([&] { _sceVideoRecordingQueryParam_nid_postfix(reinterpret_cast(param.data())); }), "the default parameters were produced"); + Require(Throws([&] { sceVideoRecordingQueryMemSize(reinterpret_cast(param.data())); }), "a heap size was reported"); Require(Throws([&] { sceVideoRecordingQueryMemSize(nullptr); }), "a heap size was reported for no parameters"); - Require(Throws([&] { sceVideoRecordingOpen("clip.mp4", param.data(), heap.data(), static_cast(heap.size())); }), "the recorder opened"); + Require(Throws([&] { sceVideoRecordingOpen("clip.mp4", reinterpret_cast(param.data()), heap.data(), static_cast(heap.size())); }), "the recorder opened"); Require(Throws([&] { sceVideoRecordingStart(); }), "the encoder started"); Require(Throws([&] { sceVideoRecordingStop(); }), "the encoder stopped"); Require(Throws([&] { sceVideoRecordingClose(0); }), "the recorder closed"); diff --git a/core/libs/tests/GuestVideodec.cpp b/core/libs/tests/GuestVideodec.cpp index 894d6f96ee..236336d978 100644 --- a/core/libs/tests/GuestVideodec.cpp +++ b/core/libs/tests/GuestVideodec.cpp @@ -1,3 +1,5 @@ +#include "prx/libSceVideodec2/include/Api.hpp" +#include "prx/libSceVideodec/include/Api.hpp" #include #include #include @@ -6,123 +8,16 @@ #include "prx/libc/include/General.hpp" #include "H264Fixture.hpp" -struct ConfigInfo { - std::uint64_t thisSize; - std::uint32_t codecType; - std::uint32_t profile; - std::uint32_t maxLevel; - std::int32_t maxFrameWidth; - std::int32_t maxFrameHeight; - std::int32_t maxDpbFrameCount; - std::uint64_t videodecFlags; -}; - -struct ResourceInfo { - std::uint64_t thisSize; - std::uint64_t cpuMemorySize; - void* cpuMemory; - std::uint64_t cpuGpuMemorySize; - void* cpuGpuMemory; - std::uint64_t maxFrameBufferSize; - std::uint32_t frameBufferAlignment; -}; - -struct Ctrl { - std::uint64_t thisSize; - void* handle; - std::uint64_t version; -}; - -struct FrameBuffer { - std::uint64_t thisSize; - void* frameBuffer; - std::uint64_t frameBufferSize; -}; - -struct AvcInfo { - std::uint32_t numUnitsInTick; - std::uint32_t timeScale; - std::uint8_t fixedFrameRateFlag; - std::uint8_t aspectRatioIdc; - std::uint16_t sarWidth; - std::uint16_t sarHeight; - std::uint8_t colourPrimaries; - std::uint8_t transferCharacteristics; - std::uint8_t matrixCoefficients; - std::uint8_t videoFullRangeFlag; - std::uint32_t frameCropLeftOffset; - std::uint32_t frameCropRightOffset; - std::uint32_t frameCropTopOffset; - std::uint32_t frameCropBottomOffset; -}; - -union CodecInfo { - std::uint8_t reserved[64]; - AvcInfo avc; -}; - -struct PictureInfo { - std::uint64_t thisSize; - std::uint32_t isValid; - std::uint32_t codecType; - std::uint32_t frameWidth; - std::uint32_t framePitch; - std::uint32_t frameHeight; - std::uint32_t isErrorPic; - std::uint64_t ptsData; - std::uint64_t attachedData; - CodecInfo codec; -}; - -struct InputData { - std::uint64_t thisSize; - const std::uint8_t* auData; - std::uint64_t auSize; - std::uint64_t ptsData; - std::uint64_t dtsData; - std::uint64_t attachedData; -}; - -struct Decoder2ConfigInfo { - std::uint64_t thisSize; - std::uint32_t resourceType; - std::uint32_t codecType; - std::uint32_t profile; - std::uint32_t maxLevel; - std::int32_t maxFrameWidth; - std::int32_t maxFrameHeight; - std::int32_t maxDpbFrameCount; - std::uint32_t decodePipelineDepth; -}; - -struct Decoder2MemoryInfo { - std::uint64_t thisSize; - std::uint64_t cpuMemorySize; - void* cpuMemory; - std::uint64_t gpuMemorySize; - void* gpuMemory; - std::uint64_t cpuGpuMemorySize; - void* cpuGpuMemory; - std::uint64_t maxFrameBufferSize; - std::uint32_t frameBufferAlignment; -}; +using namespace SceVideodec; static_assert(sizeof(PictureInfo) == 112 && sizeof(AvcInfo) == 36); static_assert(sizeof(ConfigInfo) == 40 && sizeof(ResourceInfo) == 56 && sizeof(Ctrl) == 24); -static_assert(sizeof(Decoder2ConfigInfo) == 40 && sizeof(Decoder2MemoryInfo) == 72); - -extern "C" { -int APS5_VABI sceVideodecCreateDecoder(const ConfigInfo*, const ResourceInfo*, Ctrl*); -int APS5_VABI sceVideodecDecode(Ctrl*, const InputData*, FrameBuffer*, PictureInfo*); -int APS5_VABI sceVideodecDeleteDecoder(Ctrl*); -int APS5_VABI sceVideodecFlush(Ctrl*, FrameBuffer*, PictureInfo*); -int APS5_VABI sceVideodecReset(Ctrl*); -int APS5_VABI sceVideodecQueryResourceInfo(const ConfigInfo*, ResourceInfo*); -int APS5_VABI sceVideodec2QueryDecoderMemoryInfo_nid_postfix(const Decoder2ConfigInfo*, Decoder2MemoryInfo*); -} +static_assert(sizeof(SceVideodec2::DecoderConfigInfo) == 40 && sizeof(SceVideodec2::DecoderMemoryInfo) == 72); namespace { +using namespace SceVideodec; + using namespace H264Fixture; constexpr int ErrorApiFail = static_cast(0x80C10000); @@ -176,7 +71,7 @@ void testDecode(const std::vector>& units, std::uint32 timestamps.push_back(picture.ptsData); }; for (std::size_t unit = 0; unit < units.size(); ++unit) { - const InputData input{sizeof(InputData), units[unit].data(), units[unit].size(), 1000 + unit, unit, 0xa0 + unit}; + const SceVideodec2::InputData input{sizeof(SceVideodec2::InputData), units[unit].data(), units[unit].size(), 1000 + unit, unit, 0xa0 + unit}; auto target = session.MakeTarget(); PictureInfo picture{sizeof(PictureInfo)}; const auto status = sceVideodecDecode(&session.ctrl, &input, &target, &picture); @@ -221,22 +116,22 @@ void testErrors() { foreign.handle = reinterpret_cast(static_cast(0x1234)); check(sceVideodecDeleteDecoder(&foreign) == ErrorHandle, "an unknown decoder was deleted"); check(sceVideodecReset(&foreign) == ErrorHandle, "an unknown decoder was reset"); - const InputData empty{sizeof(InputData), nullptr, 0, 0, 0, 0}; + const SceVideodec2::InputData empty{sizeof(SceVideodec2::InputData), nullptr, 0, 0, 0, 0}; FrameBuffer frame{sizeof(FrameBuffer), nullptr, 0}; PictureInfo picture{sizeof(PictureInfo)}; check(sceVideodecDecode(nullptr, &empty, &frame, &picture) == ErrorArgumentPointer, "a null control block was accepted"); check(sceVideodecDecode(&ctrl, &empty, &frame, &picture) == ErrorAuPointer, "a null access unit was accepted"); - const InputData sized{sizeof(InputData), reinterpret_cast(&config), 0, 0, 0, 0}; + const SceVideodec2::InputData sized{sizeof(SceVideodec2::InputData), reinterpret_cast(&config), 0, 0, 0, 0}; check(sceVideodecDecode(&ctrl, &sized, &frame, &picture) == ErrorAuSize, "an empty access unit was accepted"); FrameBuffer missing{sizeof(FrameBuffer), nullptr, FrameBytes}; const auto units = accessUnits(false); - const InputData input{sizeof(InputData), units[0].data(), units[0].size(), 0, 0, 0}; + const SceVideodec2::InputData input{sizeof(SceVideodec2::InputData), units[0].data(), units[0].size(), 0, 0, 0}; check(sceVideodecDecode(&ctrl, &input, &missing, &picture) == ErrorFrameBufferPointer, "a null frame buffer was accepted"); std::vector storage(static_cast(FrameBytes)); FrameBuffer shortBuffer{sizeof(FrameBuffer), storage.data(), FrameBytes - 1}; int refusals = 0; for (std::size_t unit = 0; unit < units.size(); ++unit) { - const InputData unit0{sizeof(InputData), units[unit].data(), units[unit].size(), 1000 + unit, unit, 0xa0 + unit}; + const SceVideodec2::InputData unit0{sizeof(SceVideodec2::InputData), units[unit].data(), units[unit].size(), 1000 + unit, unit, 0xa0 + unit}; const auto status = sceVideodecDecode(&ctrl, &unit0, &shortBuffer, &picture); check(status == 0 || status == ErrorFrameBufferSize, "a decode failed"); if (status == ErrorFrameBufferSize) ++refusals; @@ -249,7 +144,7 @@ void testErrors() { void testReset() { Session session; const auto units = accessUnits(false); - const InputData input{sizeof(InputData), units[0].data(), units[0].size(), 1000, 0, 0xa0}; + const SceVideodec2::InputData input{sizeof(SceVideodec2::InputData), units[0].data(), units[0].size(), 1000, 0, 0xa0}; auto target = session.MakeTarget(); PictureInfo picture{sizeof(PictureInfo)}; check(sceVideodecDecode(&session.ctrl, &input, &target, &picture) == 0, "decode failed"); @@ -262,8 +157,8 @@ void testQueryResourceInfo(std::int32_t width, std::int32_t height, std::uint32_ const ConfigInfo config{sizeof(ConfigInfo), 1, profile, level, width, height, 4, 0}; ResourceInfo resource{sizeof(ResourceInfo)}; check(sceVideodecQueryResourceInfo(&config, &resource) == 0, "the resource query failed"); - const Decoder2ConfigInfo mapped{sizeof(Decoder2ConfigInfo), 1, 1, profile, level, width, height, 4, 1}; - Decoder2MemoryInfo memory{sizeof(Decoder2MemoryInfo)}; + const SceVideodec2::DecoderConfigInfo mapped{sizeof(SceVideodec2::DecoderConfigInfo), 1, 1, profile, level, width, height, 4, 1}; + SceVideodec2::DecoderMemoryInfo memory{sizeof(SceVideodec2::DecoderMemoryInfo)}; check(sceVideodec2QueryDecoderMemoryInfo_nid_postfix(&mapped, &memory) == 0, "the Videodec2 memory query failed"); check(resource.thisSize == sizeof(ResourceInfo), "the resource information size was changed"); check(resource.cpuMemorySize == memory.cpuMemorySize, "the CPU memory size differs from libSceVideodec2"); diff --git a/core/libs/tests/GuestVideodec2.cpp b/core/libs/tests/GuestVideodec2.cpp index 565f4454b4..f6caa14b4b 100644 --- a/core/libs/tests/GuestVideodec2.cpp +++ b/core/libs/tests/GuestVideodec2.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceVideodec2/include/Api.hpp" #include #include #include @@ -14,111 +15,15 @@ #include "HevcFixture.hpp" #include "Vp9Fixture.hpp" -struct DecoderConfigInfo { - std::uint64_t thisSize; - std::uint32_t resourceType; - std::uint32_t codecType; - std::uint32_t profile; - std::uint32_t maxLevel; - std::int32_t maxFrameWidth; - std::int32_t maxFrameHeight; - std::int32_t maxDpbFrameCount; - std::uint32_t decodePipelineDepth; -}; - -struct DecoderMemoryInfo { - std::uint64_t thisSize; - std::uint64_t cpuMemorySize; - void* cpuMemory; - std::uint64_t gpuMemorySize; - void* gpuMemory; - std::uint64_t cpuGpuMemorySize; - void* cpuGpuMemory; - std::uint64_t maxFrameBufferSize; - std::uint32_t frameBufferAlignment; -}; - -struct InputData { - std::uint64_t thisSize; - const std::uint8_t* auData; - std::uint64_t auSize; - std::uint64_t ptsData; - std::uint64_t dtsData; - std::uint64_t attachedData; -}; - -struct FrameBuffer { - std::uint64_t thisSize; - void* frameBuffer; - std::uint64_t frameBufferSize; - bool isAccepted; -}; - -struct OutputInfo { - std::uint64_t thisSize; - bool isValid; - bool isErrorFrame; - std::uint8_t pictureCount; - std::uint32_t codecType; - std::uint32_t frameWidth; - std::uint32_t framePitch; - std::uint32_t frameHeight; - void* frameBuffer; - std::uint64_t frameBufferSize; - std::uint32_t frameFormat; - std::uint32_t framePitchInBytes; -}; - -struct AvcPictureInfo { - std::uint64_t thisSize; - bool isValid; - std::uint64_t ptsData; - std::uint64_t dtsData; - std::uint64_t attachedData; - std::uint8_t idrPictureFlag; - std::uint8_t profileIdc; - std::uint8_t levelIdc; - std::uint32_t picWidthInLumaSamples; - std::uint32_t picHeightInLumaSamples; -}; - -struct Vp9PictureInfo { - std::uint64_t thisSize; - bool isValid; - std::uint64_t ptsData; - std::uint64_t dtsData; - std::uint64_t attachedData; - std::uint32_t profile; - std::uint32_t level; - std::uint32_t keyFrameFlag; - std::uint32_t intraOnly; - std::uint8_t bitDepth; - std::uint8_t colorRange; - std::uint32_t colorSpace; - std::uint32_t numFrames; - std::uint32_t frameWidth; - std::uint32_t frameHeight; - std::uint32_t renderWidth; - std::uint32_t renderHeight; -}; +using namespace SceVideodec2; static_assert(sizeof(Vp9PictureInfo) == 88); static_assert(offsetof(Vp9PictureInfo, colorSpace) == 60); -extern "C" { -int APS5_VABI sceVideodec2QueryDecoderMemoryInfo_nid_postfix(const DecoderConfigInfo*, DecoderMemoryInfo*); -int APS5_VABI sceVideodec2CreateDecoder_nid_postfix(const DecoderConfigInfo*, const DecoderMemoryInfo*, std::uint64_t*); -int APS5_VABI sceVideodec2DeleteDecoder_nid_postfix(std::uint64_t); -int APS5_VABI sceVideodec2Decode_nid_postfix(std::uint64_t, const InputData*, FrameBuffer*, OutputInfo*); -int APS5_VABI sceVideodec2Flush_nid_postfix(std::uint64_t, FrameBuffer*, OutputInfo*); -int APS5_VABI sceVideodec2Reset_nid_postfix(std::uint64_t); -int APS5_VABI sceVideodec2GetPictureInfo_nid_postfix(const OutputInfo*, AvcPictureInfo*, void*); -int APS5_VABI sceVideodec2GetVp9PictureInfo_nid_postfix(const OutputInfo*, Vp9PictureInfo*); -int APS5_VABI sceVideodec2GetAvcPictureInfo_nid_postfix(const OutputInfo*, AvcPictureInfo*, AvcPictureInfo*); -} - namespace { +using namespace SceVideodec2; + using namespace H264Fixture; using namespace HevcFixture; @@ -173,7 +78,6 @@ void check(bool condition, const std::string& message) { if (!condition) throw std::runtime_error(message); } - template void checkThrows(TAction action) { bool threw = false; @@ -217,8 +121,10 @@ void testFailures() { input.auData = unit.data(); input.auSize = unit.size(); sceVideodec2Decode_nid_postfix(handle, &input, &frame, &output); + } sceVideodec2Flush_nid_postfix(handle, &frame, &output); + }); check(sceVideodec2DeleteDecoder_nid_postfix(handle) == 0, "delete failed"); } diff --git a/core/libs/tests/GuestVideodec2Unimplemented.cpp b/core/libs/tests/GuestVideodec2Unimplemented.cpp index 6f2fc0ef0a..25eb1d8a77 100644 --- a/core/libs/tests/GuestVideodec2Unimplemented.cpp +++ b/core/libs/tests/GuestVideodec2Unimplemented.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceVideodec2/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -5,22 +6,6 @@ #include #include -extern "C" { -int APS5_VABI sceVideodec2TermLibrary(); -int APS5_VABI sceVideodec2QueryLibraryInfo(); -int APS5_VABI sceVideodec2QueryDecoderInfo(); -int APS5_VABI sceVideodec2MapMemory(); -int APS5_VABI sceVideodec2MapDirectMemory(void* decoder, const void* memory); -int APS5_VABI sceVideodec2PresetDecoderConfigInfo(); -int APS5_VABI sceVideodec2PresetDecoderConfigInfoAvc(); -int APS5_VABI sceVideodec2PresetDecoderConfigInfoHevc(); -int APS5_VABI sceVideodec2PresetDecoderConfigInfoVp9(); -int APS5_VABI sceVideodec2CreateDecoderBid(); -int APS5_VABI sceVideodec2CreateHevcDecoder(); -int APS5_VABI sceVideodec2QueryHevcDecoderMemoryInfo(); -int APS5_VABI sceVideodec2GetHevcPictureInfo(); -} - static bool ReportsNotImplemented(const std::string& name, const std::function& call) { try { call(); diff --git a/core/libs/tests/GuestVoice.cpp b/core/libs/tests/GuestVoice.cpp index 2b9e024dcc..112adf8c4d 100644 --- a/core/libs/tests/GuestVoice.cpp +++ b/core/libs/tests/GuestVoice.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceVoice/include/Api.hpp" #include "SceTypes.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -9,38 +10,6 @@ #include #include -extern "C" { -int APS5_VABI sceVoiceInit(const VoiceInitParam*, std::int32_t); -int APS5_VABI sceVoiceSetThreadsParams(const VoiceThreadsParams*); -int APS5_VABI sceVoiceStart(const VoiceStartParam*); -int APS5_VABI sceVoiceStop(); -int APS5_VABI sceVoiceEnd_nid_postfix(); -int APS5_VABI sceVoiceCreatePort(std::uint32_t*, const VoicePortParam*); -int APS5_VABI sceVoiceDeletePort(std::uint32_t); -int APS5_VABI sceVoiceConnectIPortToOPort(std::uint32_t, std::uint32_t); -int APS5_VABI sceVoiceDisconnectIPortFromOPort(std::uint32_t, std::uint32_t); -int APS5_VABI sceVoiceGetVolume(std::uint32_t, float*); -int APS5_VABI sceVoiceSetMuteFlag(std::uint32_t, std::uint8_t); -int APS5_VABI sceVoiceSetVolume(std::uint32_t, float); -int APS5_VABI sceVoiceGetBitRate(std::uint32_t, std::uint32_t*); -int APS5_VABI sceVoiceGetMuteFlag(std::uint32_t, bool*); -int APS5_VABI sceVoiceGetPortInfo(std::uint32_t, VoicePortInfo*); -int APS5_VABI sceVoiceReadFromOPort(std::uint32_t, void*, std::uint32_t*); -int APS5_VABI sceVoiceResetPort(std::uint32_t); -int APS5_VABI sceVoicePausePort(std::uint32_t); -int APS5_VABI sceVoiceResumePort(std::uint32_t); -int APS5_VABI sceVoicePausePortAll(void); -int APS5_VABI sceVoiceResumePortAll(void); -int APS5_VABI sceVoiceGetResourceInfo(VoiceResourceInfo*); -int APS5_VABI sceVoiceEnableChat(void); -int APS5_VABI sceVoiceDisableChat(void); -int APS5_VABI sceVoiceInitHQ(const VoiceInitParam*, std::int32_t); -int APS5_VABI sceVoiceVADSetVersion(std::int32_t); -int APS5_VABI sceVoiceSetMuteFlagAll(bool); -int APS5_VABI sceVoiceSetBitRate(std::uint32_t, std::uint32_t); -int APS5_VABI sceVoiceUpdatePort(std::uint32_t, const VoicePortParam*); -} - namespace { constexpr int NotInitialized = static_cast(0x804E0801u); diff --git a/core/libs/tests/GuestVoiceChat.cpp b/core/libs/tests/GuestVoiceChat.cpp index 0a94bcefa8..0b80ea67e8 100644 --- a/core/libs/tests/GuestVoiceChat.cpp +++ b/core/libs/tests/GuestVoiceChat.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceVoiceChat/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -5,22 +6,9 @@ #include extern "C" { -int APS5_VABI sceVoiceChatInitialize(void* param); -int APS5_VABI sceVoiceChatTerminate(void); -int APS5_VABI sceVoiceChatRegisterHandlers(void* a); -int APS5_VABI sceVoiceChatRegisterMicEventHandler(void* a, void* b); -int APS5_VABI sceVoiceChatRegisterChannelEventHandler(void* a, void* b); -int APS5_VABI sceVoiceChatUnregisterMicEventHandler(void* a); -int APS5_VABI sceVoiceChatProcessEvent(void); -int APS5_VABI sceVoiceChatStartChannelEvent(void* a); -int APS5_VABI sceVoiceChatStopChannelEvent(void* a); -int APS5_VABI sceVoiceChatGetMicState(int32_t* state); -int APS5_VABI sceVoiceChatGetUserVoiceVolumeGain(void* a, int32_t* gain); -int APS5_VABI sceVoiceChatSetUserVoiceVolumeGain(void* a, int32_t gain); -int APS5_VABI sceVoiceChatGetActiveChannel(void* channel); -int APS5_VABI sceVoiceChatCreateRequest(void* a, void* b); + int APS5_VABI sceVoiceChatRequestAcsTts(int requestId, void* a, void* b); -int APS5_VABI sceVoiceChatAbortRequest(int requestId); + } static void Require(bool value, const char* what) { diff --git a/core/libs/tests/GuestVoicePortAttr.cpp b/core/libs/tests/GuestVoicePortAttr.cpp index ceaa036b65..3bdcc5e6de 100644 --- a/core/libs/tests/GuestVoicePortAttr.cpp +++ b/core/libs/tests/GuestVoicePortAttr.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceVoice/include/Api.hpp" #include "SceTypes.hpp" #include @@ -8,14 +9,6 @@ #include #include -extern "C" { -int APS5_VABI sceVoiceInit(const VoiceInitParam*, int32_t); -int APS5_VABI sceVoiceEnd_nid_postfix(void); -int APS5_VABI sceVoiceCreatePort(uint32_t*, const VoicePortParam*); -int APS5_VABI sceVoiceDeletePort(uint32_t); -int APS5_VABI sceVoiceGetPortAttr(uint32_t, int32_t, void*, int32_t); -} - static void Require(bool value) { if (!value) std::abort(); } template diff --git a/core/libs/tests/GuestVoiceQoS.cpp b/core/libs/tests/GuestVoiceQoS.cpp index b4d318548e..ebd15d8af0 100644 --- a/core/libs/tests/GuestVoiceQoS.cpp +++ b/core/libs/tests/GuestVoiceQoS.cpp @@ -1,36 +1,10 @@ +#include "prx/libSceVoiceQoS/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include #include #include -extern "C" { -int APS5_VABI sceVoiceQoSInit(void*, std::uint32_t, std::int32_t); -int APS5_VABI sceVoiceQoSEnd(); -int APS5_VABI sceVoiceQoSCreateLocalEndpoint(std::int32_t*, std::int32_t, std::int32_t, std::int32_t); -int APS5_VABI sceVoiceQoSDeleteLocalEndpoint(std::int32_t); -int APS5_VABI sceVoiceQoSCreateRemoteEndpoint(std::int32_t*); -int APS5_VABI sceVoiceQoSDeleteRemoteEndpoint(std::int32_t); -int APS5_VABI sceVoiceQoSConnect(std::int32_t*, std::int32_t, std::int32_t); -int APS5_VABI sceVoiceQoSDisconnect(std::int32_t); -int APS5_VABI sceVoiceQoSSetLocalEndpointAttribute(std::int32_t, std::int32_t, const void*, std::int32_t); -int APS5_VABI sceVoiceQoSSetRemoteEndpointAttribute(std::int32_t, std::int32_t, const void*, std::int32_t); -int APS5_VABI sceVoiceQoSGetLocalEndpointAttribute(std::int32_t, std::int32_t, void*, std::int32_t); -int APS5_VABI sceVoiceQoSGetRemoteEndpointAttribute(std::int32_t, std::int32_t, void*, std::int32_t); -int APS5_VABI sceVoiceQoSGetConnectionAttribute(std::int32_t, std::int32_t, void*, std::int32_t); -int APS5_VABI sceVoiceQoSGetLocalEndpoint(std::int32_t, std::int32_t*); -int APS5_VABI sceVoiceQoSGetRemoteEndpoint(std::int32_t, std::int32_t*); -int APS5_VABI sceVoiceQoSEnableChat(); -int APS5_VABI sceVoiceQoSDisableChat(); -int APS5_VABI sceVoiceQoSGetStatus(std::int32_t, std::int32_t, void*, std::int32_t); -int APS5_VABI sceVoiceQoSDebugGetStatus(std::int32_t, std::int32_t, void*, std::int32_t); -int APS5_VABI sceVoiceQoSInitHQ(void*, std::uint32_t, std::int32_t); -int APS5_VABI sceVoiceQoSSetMode(); -int APS5_VABI sceVoiceQoSTerminate(); -int APS5_VABI sceVoiceQoSReadPacket(std::int32_t, void*, std::uint32_t*); -int APS5_VABI sceVoiceQoSWritePacket(std::int32_t, const void*, std::uint32_t*); -} - static void Require(bool value) { if (!value) std::abort(); } template diff --git a/core/libs/tests/GuestVorbisDec.cpp b/core/libs/tests/GuestVorbisDec.cpp index d34eb5d9ad..9b44ce165b 100644 --- a/core/libs/tests/GuestVorbisDec.cpp +++ b/core/libs/tests/GuestVorbisDec.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceVorbisDec/include/Api.hpp" #include "prx/libSceVorbisDec/include/GuestVorbisFile.hpp" #include "prx/libc/include/general/VabiMacros.hpp" @@ -17,43 +18,6 @@ using namespace VorbisDec; -extern "C" { -int APS5_VABI sceVorbisDecOpenCallbacks(void* datasource, void* vf, const char* initial, std::int64_t ibytes, GuestCallbacks callbacks); -int APS5_VABI sceVorbisDecClear(void* vf); -std::int64_t APS5_VABI sceVorbisDecBitrate(void* vf, int link); -std::int64_t APS5_VABI sceVorbisDecBitrateInstant(void* vf); -std::int64_t APS5_VABI sceVorbisDecStreams(void* vf); -std::int64_t APS5_VABI sceVorbisDecSeekable(void* vf); -std::int64_t APS5_VABI sceVorbisDecSerialNumber(void* vf, int link); -std::int64_t APS5_VABI sceVorbisDecRawTotal(void* vf, int link); -std::int64_t APS5_VABI sceVorbisDecPcmTotal(void* vf, int link); -double APS5_VABI sceVorbisDecTimeTotal(void* vf, int link); -int APS5_VABI sceVorbisDecRawSeek(void* vf, std::int64_t position); -int APS5_VABI sceVorbisDecPcmSeek(void* vf, std::int64_t position); -int APS5_VABI sceVorbisDecPcmSeekPage(void* vf, std::int64_t position); -int APS5_VABI sceVorbisDecTimeSeek(void* vf, double position); -int APS5_VABI sceVorbisDecTimeSeekPage(void* vf, double position); -int APS5_VABI sceVorbisDecRawSeekLap(void* vf, std::int64_t position); -int APS5_VABI sceVorbisDecPcmSeekLap(void* vf, std::int64_t position); -int APS5_VABI sceVorbisDecPcmSeekPageLap(void* vf, std::int64_t position); -int APS5_VABI sceVorbisDecTimeSeekLap(void* vf, double position); -int APS5_VABI sceVorbisDecTimeSeekPageLap(void* vf, double position); -std::int64_t APS5_VABI sceVorbisDecRawTell(void* vf); -std::int64_t APS5_VABI sceVorbisDecPcmTell(void* vf); -double APS5_VABI sceVorbisDecTimeTell(void* vf); -GuestInfo* APS5_VABI sceVorbisDecInfo(void* vf, int link); -GuestComment* APS5_VABI sceVorbisDecComment(void* vf, int link); -std::int64_t APS5_VABI sceVorbisDecRead(void* vf, char* buffer, int length, int bigEndian, int word, int isSigned, int* bitstream); -std::int64_t APS5_VABI sceVorbisDecReadFloat(void* vf, float*** pcmChannels, int samples, int* bitstream); -std::int64_t APS5_VABI sceVorbisDecReadFilter(void* vf, char* buffer, int length, int bigEndian, int word, int isSigned, int* bitstream, GuestFilter filter, void* filterParam); -int APS5_VABI sceVorbisDecCrossLap(void* first, void* second); -int APS5_VABI sceVorbisDecHalfrate(void* vf, int flag); -int APS5_VABI sceVorbisDecHalfrateP(void* vf); -int APS5_VABI sceVorbisDecGetDecodePriority(void); -int APS5_VABI sceVorbisDecSetDecodePriority(void); -int APS5_VABI sceVorbisDecGetLastDecodeError(void); -} - namespace { constexpr int FirstSerial = 0x1234abcd; diff --git a/core/libs/tests/GuestVrServiceDialog.cpp b/core/libs/tests/GuestVrServiceDialog.cpp index 8d72100186..95f074d84c 100644 --- a/core/libs/tests/GuestVrServiceDialog.cpp +++ b/core/libs/tests/GuestVrServiceDialog.cpp @@ -1,17 +1,8 @@ +#include "prx/libSceVrServiceDialog/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include -extern "C" { -int APS5_VABI sceVrServiceDialogInitialize(void); -int APS5_VABI sceVrServiceDialogOpen(const void* param); -int APS5_VABI sceVrServiceDialogUpdateStatus(void); -int APS5_VABI sceVrServiceDialogGetStatus(void); -int APS5_VABI sceVrServiceDialogGetResult(void* result); -int APS5_VABI sceVrServiceDialogClose(void); -int APS5_VABI sceVrServiceDialogTerminate(void); -} - namespace { void Require(bool value) { if (!value) std::abort(); } diff --git a/core/libs/tests/GuestVrSetupDialog.cpp b/core/libs/tests/GuestVrSetupDialog.cpp index decf0c81e2..3297365257 100644 --- a/core/libs/tests/GuestVrSetupDialog.cpp +++ b/core/libs/tests/GuestVrSetupDialog.cpp @@ -1,18 +1,9 @@ +#include "prx/libSceVrSetupDialog/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include #include "prx/libSceCommonDialog/CommonDialog.hpp" -extern "C" { -int APS5_VABI sceVrSetupDialogInitialize(void); -int APS5_VABI sceVrSetupDialogOpen(const VrSetupDialogParam* param); -int APS5_VABI sceVrSetupDialogUpdateStatus(void); -int APS5_VABI sceVrSetupDialogGetStatus(void); -int APS5_VABI sceVrSetupDialogGetResult(std::int32_t* result); -int APS5_VABI sceVrSetupDialogClose(void); -int APS5_VABI sceVrSetupDialogTerminate(void); -} - namespace { void Require(bool value) { if (!value) std::abort(); } diff --git a/core/libs/tests/GuestVrTracker2.cpp b/core/libs/tests/GuestVrTracker2.cpp index 0bbe3a869e..a1e4b0693a 100644 --- a/core/libs/tests/GuestVrTracker2.cpp +++ b/core/libs/tests/GuestVrTracker2.cpp @@ -1,26 +1,21 @@ -#include "prx/libc/include/general/VabiMacros.hpp" +#include "prx/libSceVrTracker2/include/Api.hpp" +#include "prx/libkernel/libkernel.hpp" #include "ProcessParametersFixture.hpp" +#include #include #include #include #include #include +#include +#include +#include #include +#include +#include -extern "C" { -std::int32_t APS5_VABI VrTracker2NotInitialized(); -std::int32_t APS5_VABI sceVrTracker2Finalize(); -std::int32_t APS5_VABI VrTracker2ClearWideResult(void* result); -std::int32_t APS5_VABI VrTracker2ClearNarrowResult(void* result); -std::int32_t APS5_VABI VrTracker2CheckSecondThenReportNotInitialized(const void* first, const void* second); -std::int32_t APS5_VABI VrTracker2Accept(); -std::int32_t APS5_VABI VrTracker2FillDefaults(void* output); -std::int32_t APS5_VABI VrTracker2ClearWord(void* output); -std::int32_t APS5_VABI sceVrTracker2QueryMemory(const void* parameter, void* requirement); -struct VrTracker2InitializeParameter; -std::int32_t APS5_VABI sceVrTracker2Initialize(const VrTracker2InitializeParameter* parameter); -} +static_assert(sizeof(VrTracker2InitializeParameter) == 72); namespace { @@ -28,6 +23,8 @@ alignas(16) std::array process{}; constexpr std::int32_t NotInitialized = static_cast(0x8A740001u); constexpr std::int32_t InvalidArgument = static_cast(0x8A740006u); +constexpr std::uint32_t TrackerMemory = 32u << 20; +constexpr std::size_t WorkMemoryTail = 64u << 10; void Require(bool condition, const char* message) { if (!condition) { @@ -58,6 +55,118 @@ bool Throws(TCall call) { return false; } +VrTracker2InitializeParameter TrackerParameter(std::vector& memory) { + VrTracker2InitializeParameter parameter{}; + parameter.size = sizeof(parameter); + parameter.threadPriorities[0] = 256; + parameter.threadPriorities[1] = 767; + parameter.threadAffinityMasks[0] = 0x1fff; + parameter.workMemory = memory.data(); + parameter.workMemorySize = static_cast(memory.size()); + parameter.workMemoryAlignment = 0x10000; + return parameter; +} + +bool WorkMemoryCleared(const std::vector& memory) { + return AllEqual(memory.data(), memory.data() + TrackerMemory, 0) && AllEqual(memory.data() + TrackerMemory, memory.data() + memory.size(), 0xAA); +} + +bool WorkMemoryUntouched(const std::vector& memory) { + return AllEqual(memory.data(), memory.data() + memory.size(), 0xAA); +} + +std::int32_t InitializeFresh(std::vector& memory, const VrTracker2InitializeParameter& parameter) { + std::fill(memory.begin(), memory.end(), 0xAA); + return sceVrTracker2Initialize(¶meter); +} + +void CheckInitializeValidation(std::vector& memory) { + const auto valid = TrackerParameter(memory); + Require(sceVrTracker2Initialize(nullptr) == InvalidArgument, "initialize null"); + for (const std::uint32_t size : {0u, 71u, 73u}) { + auto parameter = valid; + parameter.size = size; + parameter.mode = 1000; + Require(InitializeFresh(memory, parameter) == InvalidArgument, "initialize size before mode"); + } + for (const std::uint32_t mode : {1u, 999u, 1002u, 0xffffffffu}) { + auto parameter = valid; + parameter.mode = mode; + Require(InitializeFresh(memory, parameter) == InvalidArgument, "initialize mode"); + } + auto parameter = valid; + parameter.workMemory = nullptr; + Require(InitializeFresh(memory, parameter) == InvalidArgument, "initialize work memory null"); + parameter = valid; + parameter.workMemorySize = TrackerMemory - 1; + Require(InitializeFresh(memory, parameter) == InvalidArgument, "initialize work memory size"); + parameter = valid; + parameter.workMemoryAlignment = 0xffff; + Require(InitializeFresh(memory, parameter) == InvalidArgument, "initialize alignment"); + for (std::size_t index = 0; index < sizeof(parameter.reserved); ++index) { + parameter = valid; + parameter.reserved[index] = 1; + Require(InitializeFresh(memory, parameter) == InvalidArgument, "initialize reserved byte"); + } + for (std::size_t index = 0; index < 2; ++index) { + for (const std::int32_t priority : {255, 768, -1}) { + parameter = valid; + parameter.threadPriorities[index] = priority; + Require(InitializeFresh(memory, parameter) == InvalidArgument, "initialize thread priority"); + } + for (const std::uint64_t mask : {std::uint64_t{0x2000}, std::uint64_t{0x3fff}, std::uint64_t{1} << 63}) { + parameter = valid; + parameter.threadAffinityMasks[index] = mask; + Require(InitializeFresh(memory, parameter) == InvalidArgument, "initialize affinity mask"); + } + } + Require(WorkMemoryUntouched(memory), "initialize validation leaves work memory"); +} + +void CheckInitializeTracking(std::vector& memory, std::uint32_t sdkVersion) { + const auto valid = TrackerParameter(memory); + Require(InitializeFresh(memory, valid) == -1, "initialize tracking start result"); + Require(WorkMemoryCleared(memory), "initialize clears tracker memory"); + Require(sceVrTracker2Finalize() == NotInitialized, "initialize failure leaves module uninitialized"); + Require(VrTracker2NotInitialized() == NotInitialized, "initialize failure keeps uninitialized answers"); + Require(InitializeFresh(memory, valid) == -1, "initialize retry after failure"); + auto parameter = valid; + parameter.workMemoryAlignment = 0x10001; + parameter.option = 0xffffffffu; + parameter.coordinateSystem = 2; + parameter.disableOption = 1; + parameter.threadAffinityMasks[1] = 0x1fff; + Require(InitializeFresh(memory, parameter) == -1, "initialize late checks follow tracking"); + for (const std::int8_t optionMode : {std::int8_t{-1}, std::int8_t{0}}) { + parameter = valid; + parameter.optionMode = optionMode; + Require(InitializeFresh(memory, parameter) == -1, "initialize accepted option mode"); + } + for (const std::int8_t optionMode : {std::int8_t{2}, std::int8_t{-2}, std::int8_t{127}}) { + parameter = valid; + parameter.optionMode = optionMode; + Require(InitializeFresh(memory, parameter) == InvalidArgument, "initialize option mode"); + Require(WorkMemoryCleared(memory), "initialize option mode follows clearing"); + } + parameter = valid; + parameter.optionMode = 1; + Require(InitializeFresh(memory, parameter) == (sdkVersion >= 0x7000000 ? -1 : InvalidArgument), "initialize SDK option mode"); + Require(sceVrTracker2Finalize() == NotInitialized, "initialize leaves module uninitialized"); +} + +std::filesystem::path EnterApplicationRoot() { + std::random_device device; + std::filesystem::path root; + do { + root = std::filesystem::temp_directory_path() / + ("guest_vr_tracker2_" + std::to_string(getpid_nid_postfix()) + "_" + std::to_string(device())); + } while (!std::filesystem::create_directory(root)); + std::filesystem::create_directories(root / "app0" / "sce_sys"); + std::ofstream(root / "app0" / "sce_sys" / "param.json") << "{\n \"contentId\": \"IV0000-ABCD00000_00-VRTRACKER2000000\",\n \"localizedParameters\": {\"defaultLanguage\": \"en-US\", \"en-US\": {\"titleName\": \"VrTracker2\"}},\n \"titleId\": \"ABCD00000\"\n}\n"; + std::filesystem::current_path(root); + return root; +} + } int main() { @@ -98,17 +207,17 @@ int main() { parameter.back() = 0xAA; std::array requirement{}; requirement.fill(0xAA); - Require(sceVrTracker2QueryMemory(parameter.data(), requirement.data()) == 0, "query return"); + Require(sceVrTracker2QueryMemory(reinterpret_cast(parameter.data()), reinterpret_cast(requirement.data())) == 0, "query return"); const std::array fields{0x20, 0, 0, 0, 0, 0, 0, 0x02, 0, 0, 0x01, 0}; Require(std::memcmp(requirement.data(), fields.data(), fields.size()) == 0, "query fields"); Require(AllEqual(requirement.data() + 12, requirement.data() + 32, 0) && AllEqual(requirement.data() + 32, requirement.data() + 40, 0xAA), "query writes 32 bytes"); - Require(sceVrTracker2QueryMemory(nullptr, requirement.data()) == InvalidArgument, "query null parameter"); - Require(sceVrTracker2QueryMemory(parameter.data(), nullptr) == InvalidArgument, "query null requirement"); + Require(sceVrTracker2QueryMemory(nullptr, reinterpret_cast(requirement.data())) == InvalidArgument, "query null parameter"); + Require(sceVrTracker2QueryMemory(reinterpret_cast(parameter.data()), nullptr) == InvalidArgument, "query null requirement"); for (std::size_t offset = 4; offset < 32; ++offset) { auto rejected = parameter; rejected[offset] = 1; requirement.fill(0xAA); - Require(sceVrTracker2QueryMemory(rejected.data(), requirement.data()) == InvalidArgument, "query reserved byte"); + Require(sceVrTracker2QueryMemory(reinterpret_cast(rejected.data()), reinterpret_cast(requirement.data())) == InvalidArgument, "query reserved byte"); Require(AllEqual(requirement.data(), requirement.data() + 40, 0xAA), "query rejection leaves output"); } const std::uint64_t processSize = process.size(); @@ -121,7 +230,7 @@ int main() { for (const std::uint32_t mode : {1000u, 1001u}) { std::memcpy(parameter.data() + 4, &mode, sizeof(mode)); requirement.fill(0xAA); - const auto result = sceVrTracker2QueryMemory(parameter.data(), requirement.data()); + const auto result = sceVrTracker2QueryMemory(reinterpret_cast(parameter.data()), reinterpret_cast(requirement.data())); if (version < 0x1000000) { Require(result == InvalidArgument, "query SDK restriction"); Require(AllEqual(requirement.data(), requirement.data() + requirement.size(), 0xAA), "SDK rejection preserves output"); @@ -136,8 +245,17 @@ int main() { } } parameter[0] = 0x21; - Require(sceVrTracker2QueryMemory(parameter.data(), requirement.data()) == InvalidArgument, "query size"); + Require(sceVrTracker2QueryMemory(reinterpret_cast(parameter.data()), reinterpret_cast(requirement.data())) == InvalidArgument, "query size"); - Require(Throws([] { sceVrTracker2Initialize(nullptr); }), "unknown export"); + std::vector memory(TrackerMemory + WorkMemoryTail); + CheckInitializeValidation(memory); + const auto previous = std::filesystem::current_path(); + const auto root = EnterApplicationRoot(); + for (const std::uint32_t version : {0x6ffffffu, 0x7000000u}) { + std::memcpy(process.data() + 0x10, &version, sizeof(version)); + CheckInitializeTracking(memory, version); + } + std::filesystem::current_path(previous); + std::filesystem::remove_all(root); return 0; } diff --git a/core/libs/tests/GuestVrTrackerDevices.cpp b/core/libs/tests/GuestVrTrackerDevices.cpp index bfffa872c9..d34384fa7a 100644 --- a/core/libs/tests/GuestVrTrackerDevices.cpp +++ b/core/libs/tests/GuestVrTrackerDevices.cpp @@ -1,21 +1,9 @@ +#include "prx/libSceVrTracker/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include #include -extern "C" { -int APS5_VABI sceVrTrackerQueryMemory(const void*, void*); -int APS5_VABI sceVrTrackerInit(const void*); -int APS5_VABI sceVrTrackerTerm(); -int APS5_VABI sceVrTrackerRegisterDevice(int, int); -int APS5_VABI sceVrTrackerRegisterDevice2(int, int); -int APS5_VABI sceVrTrackerRegisterDeviceInternal(int, int, int, int); -int APS5_VABI sceVrTrackerUnregisterDevice(int); -int APS5_VABI sceVrTrackerRecalibrate(const void*); -int APS5_VABI sceVrTrackerSetDurationUntilStatusNotTracking(int, std::uint32_t); -int APS5_VABI sceVrTrackerGpuWaitAndCpuProcess(); -} - namespace { constexpr int NotInit = static_cast(0x81260801u); @@ -30,50 +18,10 @@ constexpr int Pad = 1; constexpr int Move = 2; constexpr int Gun = 3; -struct Calibration { - std::uint32_t hmd, pad, move, gun; - std::uint32_t reserved[4]; -}; - -struct QueryParam { - std::uint32_t size = sizeof(QueryParam); - std::uint32_t profile = 0; - std::uint32_t reserved[6]{}; - Calibration calibration{}; -}; - struct QueryResult { std::uint32_t words[16]; }; -struct InitParam { - std::uint32_t size = sizeof(InitParam); - std::uint32_t profile = 0; - std::uint32_t executionMode = 0; - std::int32_t priorities[4]{}; - std::int32_t reserved = 0; - std::uint64_t cpuMask = 0; - Calibration calibration{}; - void* onion = nullptr; - std::uint32_t onionSize = 0x400000; - std::uint32_t onionAlignment = 0x10000; - void* garlic = nullptr; - std::uint32_t garlicSize = 0x3000000; - std::uint32_t garlicAlignment = 0x10000; - void* work = nullptr; - std::uint32_t workSize = 0x1000000; - std::uint32_t workAlignment = 0x10000; - std::int32_t pipe = 0; - std::int32_t queue = 0; -}; - -struct RecalibrateParam { - std::uint32_t size = sizeof(RecalibrateParam); - std::uint32_t deviceType = 0; - std::uint32_t calibrationType = 0; - std::uint32_t reserved[5]{}; -}; - std::uint8_t g_onion[16]; std::uint8_t g_garlic[16]; std::uint8_t g_work[16]; @@ -92,23 +40,30 @@ QueryResult FreshResult() { return result; } -InitParam ValidInit() { - InitParam init; - init.onion = g_onion; - init.garlic = g_garlic; - init.work = g_work; +VrTrackerLegacy::InitParam ValidInit() { + VrTrackerLegacy::InitParam init{}; + init.size = sizeof(init); + init.direct_memory_onion_size = 0x400000; + init.direct_memory_onion_alignment = 0x10000; + init.direct_memory_garlic_size = 0x3000000; + init.direct_memory_garlic_alignment = 0x10000; + init.work_memory_size = 0x1000000; + init.work_memory_alignment = 0x10000; + init.direct_memory_onion = g_onion; + init.direct_memory_garlic = g_garlic; + init.work_memory = g_work; return init; } -int Recalibrate(std::uint32_t deviceType, std::uint32_t size = sizeof(RecalibrateParam)) { - RecalibrateParam param; +int Recalibrate(std::uint32_t deviceType, std::uint32_t size = sizeof(VrTrackerLegacy::RecalibrateParam)) { + VrTrackerLegacy::RecalibrateParam param{}; param.size = size; - param.deviceType = deviceType; + param.device_type = deviceType; return sceVrTrackerRecalibrate(¶m); } void CheckQueryMemory() { - QueryParam query; + VrTrackerLegacy::QueryMemoryParam query{sizeof(VrTrackerLegacy::QueryMemoryParam)}; auto result = FreshResult(); Require(sceVrTrackerQueryMemory(&query, &result) == 0); Require(result.words[0] == Untouched); @@ -117,22 +72,22 @@ void CheckQueryMemory() { Require(result.words[5] == 0x1000000 && result.words[6] == 0x10000); Require(result.words[7] == Untouched); - query.calibration.move = 1; + query.calibration_settings.move_position = 1; query.profile = 100; Require(sceVrTrackerQueryMemory(&query, &result) == 0 && result.words[1] == 0x800000); auto rejected = FreshResult(); - QueryParam bad = query; + VrTrackerLegacy::QueryMemoryParam bad = query; bad.profile = 1; Require(sceVrTrackerQueryMemory(&bad, &rejected) == ArgumentInvalid); bad = query; - bad.calibration.hmd = 1; + bad.calibration_settings.hmd_position = 1; Require(sceVrTrackerQueryMemory(&bad, &rejected) == ArgumentInvalid); bad = query; - bad.calibration.pad = 2; + bad.calibration_settings.pad_position = 2; Require(sceVrTrackerQueryMemory(&bad, &rejected) == ArgumentInvalid); bad = query; - bad.size = sizeof(QueryParam) - 1; + bad.size = sizeof(VrTrackerLegacy::QueryMemoryParam) - 1; Require(sceVrTrackerQueryMemory(&bad, &rejected) == ArgumentInvalid); Require(sceVrTrackerQueryMemory(nullptr, &rejected) == ArgumentInvalid); Require(sceVrTrackerQueryMemory(&query, nullptr) == ArgumentInvalid); @@ -150,31 +105,31 @@ void CheckBeforeInit() { void CheckInit() { auto bad = ValidInit(); - bad.size = sizeof(InitParam) - 8; - Require(sceVrTrackerInit(&bad) == ArgumentInvalid); + bad.size = sizeof(VrTrackerLegacy::InitParam) - 8; + Require(sceVrTrackerInit(reinterpret_cast(&bad)) == ArgumentInvalid); bad.size = 144; - RequireThrows([&] { sceVrTrackerInit(&bad); }); + RequireThrows([&] { sceVrTrackerInit(reinterpret_cast(&bad)); }); bad = ValidInit(); - bad.calibration.move = 1; - Require(sceVrTrackerInit(&bad) == ArgumentInvalid); - bad.onionSize = 0x800000; - bad.pipe = 7; - Require(sceVrTrackerInit(&bad) == ArgumentInvalid); - bad.pipe = 0; - bad.queue = 8; - Require(sceVrTrackerInit(&bad) == ArgumentInvalid); - bad.queue = 0; - bad.work = nullptr; - Require(sceVrTrackerInit(&bad) == ArgumentInvalid); - bad.work = g_work; - bad.garlicAlignment = 0x1000; - Require(sceVrTrackerInit(&bad) == ArgumentInvalid); + bad.calibration_settings.move_position = 1; + Require(sceVrTrackerInit(reinterpret_cast(&bad)) == ArgumentInvalid); + bad.direct_memory_onion_size = 0x800000; + bad.gpu_pipe_id = 7; + Require(sceVrTrackerInit(reinterpret_cast(&bad)) == ArgumentInvalid); + bad.gpu_pipe_id = 0; + bad.gpu_queue_id = 8; + Require(sceVrTrackerInit(reinterpret_cast(&bad)) == ArgumentInvalid); + bad.gpu_queue_id = 0; + bad.work_memory = nullptr; + Require(sceVrTrackerInit(reinterpret_cast(&bad)) == ArgumentInvalid); + bad.work_memory = g_work; + bad.direct_memory_garlic_alignment = 0x1000; + Require(sceVrTrackerInit(reinterpret_cast(&bad)) == ArgumentInvalid); Require(sceVrTrackerInit(nullptr) == ArgumentInvalid); Require(sceVrTrackerTerm() == NotInit); const auto init = ValidInit(); - Require(sceVrTrackerInit(&init) == 0); - Require(sceVrTrackerInit(&init) == AlreadyInitialized); + Require(sceVrTrackerInit(reinterpret_cast(&init)) == 0); + Require(sceVrTrackerInit(reinterpret_cast(&init)) == AlreadyInitialized); Require(sceVrTrackerInit(nullptr) == AlreadyInitialized); Require(sceVrTrackerGpuWaitAndCpuProcess() == NotExecuteGpuSubmit); } @@ -193,7 +148,7 @@ void CheckDevices() { Require(Recalibrate(Hmd) == DeviceNotRegistered); Require(Recalibrate(Gun) == DeviceNotRegistered); Require(Recalibrate(4) == ArgumentInvalid); - Require(Recalibrate(Pad, sizeof(RecalibrateParam) + 4) == ArgumentInvalid); + Require(Recalibrate(Pad, sizeof(VrTrackerLegacy::RecalibrateParam) + 4) == ArgumentInvalid); Require(sceVrTrackerRecalibrate(nullptr) == ArgumentInvalid); Require(sceVrTrackerSetDurationUntilStatusNotTracking(Gun, 10) == 0); @@ -212,7 +167,7 @@ void CheckTerm() { Require(sceVrTrackerTerm() == NotInit); Require(sceVrTrackerRegisterDevice(Gun, 8) == NotInit); const auto init = ValidInit(); - Require(sceVrTrackerInit(&init) == 0); + Require(sceVrTrackerInit(reinterpret_cast(&init)) == 0); Require(sceVrTrackerRegisterDevice(Move, 11) == DeviceAlreadyRegistered); Require(sceVrTrackerTerm() == 0); } diff --git a/core/libs/tests/GuestWaitpid.cpp b/core/libs/tests/GuestWaitpid.cpp index 8ef90e7b19..9b958641cb 100644 --- a/core/libs/tests/GuestWaitpid.cpp +++ b/core/libs/tests/GuestWaitpid.cpp @@ -1,12 +1,9 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include -extern "C" { -int APS5_VABI wait_nid_postfix(int*); -int APS5_VABI waitpid_nid_postfix(int, int*, int); -int APS5_VABI getpid_nid_postfix(void); -int* APS5_VABI __error_nid_postfix(); -} + constexpr int noChild = 10; constexpr int invalidArgument = 22; constexpr int untouched = 0x5a5a5a5a; diff --git a/core/libs/tests/GuestWcsrtombs.cpp b/core/libs/tests/GuestWcsrtombs.cpp index 794748e08b..b9139ceaa8 100644 --- a/core/libs/tests/GuestWcsrtombs.cpp +++ b/core/libs/tests/GuestWcsrtombs.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -5,9 +6,6 @@ #include #include -extern "C" std::size_t APS5_VABI wcsrtombs_nid_postfix(char*, const std::uint16_t**, std::size_t, void*); -extern "C" int* APS5_VABI __error_nid_postfix(); - static void Require(bool value, const char* message) { if (!value) { std::fprintf(stderr, "%s\n", message); diff --git a/core/libs/tests/GuestWcsrtombsS.cpp b/core/libs/tests/GuestWcsrtombsS.cpp index 41095b7dde..2169489807 100644 --- a/core/libs/tests/GuestWcsrtombsS.cpp +++ b/core/libs/tests/GuestWcsrtombsS.cpp @@ -1,11 +1,9 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include #include -extern "C" int APS5_VABI wcsrtombs_s_nid_postfix( - std::size_t*, char*, std::size_t, const std::uint16_t**, std::size_t, void*); -extern "C" int APS5_VABI wcstombs_s_nid_postfix(std::size_t*, char*, std::size_t, const std::uint16_t*, std::size_t); static void Require(bool value) { if (!value) std::abort(); } constexpr auto Failed = static_cast(-1); diff --git a/core/libs/tests/GuestWebBrowserDialog.cpp b/core/libs/tests/GuestWebBrowserDialog.cpp index 6289900e72..01fdca210e 100644 --- a/core/libs/tests/GuestWebBrowserDialog.cpp +++ b/core/libs/tests/GuestWebBrowserDialog.cpp @@ -1,21 +1,9 @@ +#include "prx/libSceWebBrowserDialog/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libSceCommonDialog/CommonDialog.hpp" #include #include -extern "C" { -int APS5_VABI sceWebBrowserDialogInitialize(void); -int APS5_VABI sceWebBrowserDialogTerminate(void); -int APS5_VABI sceWebBrowserDialogSetCookie(const void* param); -int APS5_VABI sceWebBrowserDialogResetCookie(const void* param); -int APS5_VABI sceWebBrowserDialogOpen(const void* param); -int APS5_VABI sceWebBrowserDialogOpenForPredeterminedContent(const void* param, const WebBrowserDialogAllowList* allowList); -int APS5_VABI sceWebBrowserDialogClose(void); -int APS5_VABI sceWebBrowserDialogGetStatus(void); -int APS5_VABI sceWebBrowserDialogUpdateStatus(void); -int APS5_VABI sceWebBrowserDialogGetResult(WebBrowserDialogResult* result); -} - namespace { constexpr int COMMON_DIALOG_STATUS_NONE = 0; diff --git a/core/libs/tests/GuestWebBrowserDialogCookies.cpp b/core/libs/tests/GuestWebBrowserDialogCookies.cpp index 723bada25d..32deb3db57 100644 --- a/core/libs/tests/GuestWebBrowserDialogCookies.cpp +++ b/core/libs/tests/GuestWebBrowserDialogCookies.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceWebBrowserDialog/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -5,28 +6,6 @@ #include #include -struct ResetCookieParam { - std::uint64_t size; - std::uint8_t reserved[256]; -}; - -struct SetCookieParam { - std::uint64_t size; - const char* url; - const char* cookie; - std::uint8_t reserved[256]; -}; - -extern "C" { -int APS5_VABI sceWebBrowserDialogInitialize(void); -int APS5_VABI sceWebBrowserDialogTerminate(void); -int APS5_VABI sceWebBrowserDialogOpen(const void* param); -int APS5_VABI sceWebBrowserDialogClose(void); -int APS5_VABI sceWebBrowserDialogUpdateStatus(void); -int APS5_VABI sceWebBrowserDialogSetCookie(const SetCookieParam* param); -int APS5_VABI sceWebBrowserDialogResetCookie(const ResetCookieParam* param); -} - namespace { constexpr int NOT_INITIALIZED = static_cast(0x80B80003u); @@ -41,16 +20,16 @@ void Require(bool value, const char* what) { std::abort(); } -SetCookieParam Cookie(const char* url, const char* cookie) { - SetCookieParam param {}; +WebBrowserDialogCookieParam Cookie(const char* url, const char* cookie) { + WebBrowserDialogCookieParam param {}; param.size = sizeof(param); - param.url = url; + param.address = url; param.cookie = cookie; return param; } -ResetCookieParam Reset() { - ResetCookieParam param {}; +WebBrowserDialogResetCookieParam Reset() { + WebBrowserDialogResetCookieParam param {}; param.size = sizeof(param); return param; } @@ -61,7 +40,7 @@ void CheckSetCookieParameters() { Require(sceWebBrowserDialogSetCookie(nullptr) == ARG_NULL, "SetCookie null"); auto wrongSize = valid; - wrongSize.size = sizeof(ResetCookieParam); + wrongSize.size = sizeof(WebBrowserDialogResetCookieParam); Require(sceWebBrowserDialogSetCookie(&wrongSize) == PARAM_INVALID, "SetCookie size"); auto noUrl = Cookie(nullptr, "a=b"); Require(sceWebBrowserDialogSetCookie(&noUrl) == PARAM_INVALID, "SetCookie null url"); @@ -96,7 +75,7 @@ void CheckResetCookieParameters() { Require(sceWebBrowserDialogResetCookie(&valid) == 0, "valid ResetCookie"); Require(sceWebBrowserDialogResetCookie(nullptr) == ARG_NULL, "ResetCookie null"); auto wrongSize = valid; - wrongSize.size = sizeof(SetCookieParam); + wrongSize.size = sizeof(WebBrowserDialogCookieParam); Require(sceWebBrowserDialogResetCookie(&wrongSize) == PARAM_INVALID, "ResetCookie size"); auto reserved = valid; reserved.reserved[0] = 1; diff --git a/core/libs/tests/GuestWideConversion.cpp b/core/libs/tests/GuestWideConversion.cpp index 808a23b90f..5590c6124a 100644 --- a/core/libs/tests/GuestWideConversion.cpp +++ b/core/libs/tests/GuestWideConversion.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -8,25 +9,6 @@ #include #include -extern "C" { -std::uint64_t APS5_VABI _WStoul_nid_postfix(const char16_t*, char16_t**, int); -int APS5_VABI _Iswctype_nid_postfix(std::uint32_t, std::uint64_t); -int APS5_VABI swscanf_nid_postfix(const char16_t*, const char16_t*, ...); -int APS5_VABI swscanf_s_nid_postfix(const char16_t*, const char16_t*, ...); -int APS5_VABI iswalnum_nid_postfix(std::uint32_t); -int APS5_VABI iswalpha_nid_postfix(std::uint32_t); -int APS5_VABI iswcntrl_nid_postfix(std::uint32_t); -int APS5_VABI iswdigit_nid_postfix(std::uint32_t); -int APS5_VABI iswgraph_nid_postfix(std::uint32_t); -int APS5_VABI iswlower_nid_postfix(std::uint32_t); -int APS5_VABI iswprint_nid_postfix(std::uint32_t); -int APS5_VABI iswpunct_nid_postfix(std::uint32_t); -int APS5_VABI iswspace_nid_postfix(std::uint32_t); -int APS5_VABI iswupper_nid_postfix(std::uint32_t); -int APS5_VABI iswxdigit_nid_postfix(std::uint32_t); -int APS5_VABI iswblank_nid_postfix(std::uint32_t); -} - static int failures = 0; static void Require(bool condition, const char* message) { diff --git a/core/libs/tests/GuestWideFormatting.cpp b/core/libs/tests/GuestWideFormatting.cpp index 30f62dc841..56b278d8ae 100644 --- a/core/libs/tests/GuestWideFormatting.cpp +++ b/core/libs/tests/GuestWideFormatting.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "SceTypes.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libc/include/GuestTime.hpp" @@ -8,16 +9,6 @@ #include #include -extern "C" int APS5_VABI vswprintf_nid_postfix(char16_t*, std::size_t, const char16_t*, VaList*); -extern "C" int APS5_VABI snwprintf_s_nid_postfix(char16_t*, std::size_t, const char16_t*, ...); -extern "C" int APS5_VABI vswprintf_s_nid_postfix(char16_t*, std::size_t, const char16_t*, VaList*); -extern "C" int APS5_VABI swprintf_s_nid_postfix(char16_t*, std::size_t, const char16_t*, ...); -extern "C" int APS5_VABI vsnwprintf_s_nid_postfix(char16_t*, std::size_t, const char16_t*, VaList*); -extern "C" int APS5_VABI swprintf_nid_postfix(char16_t*, std::size_t, const char16_t*, ...); -extern "C" std::size_t APS5_VABI strftime_nid_postfix(char*, std::size_t, const char*, const GuestTm*); -extern "C" std::size_t APS5_VABI wcsftime_nid_postfix(char16_t*, std::size_t, const char16_t*, const GuestTm*); -extern "C" int* APS5_VABI __error_nid_postfix(); - static int APS5_VABI Format(char16_t* buffer, std::size_t size, const char16_t* format, ...) { #ifdef _WIN32 __builtin_sysv_va_list args; @@ -212,7 +203,8 @@ static void CheckSwprintf() { static bool WcsftimeThrows(char16_t* buffer, const char16_t* format, const GuestTm* time) { try { - wcsftime_nid_postfix(buffer, 16, format, time); + wcsftime_nid_postfix(reinterpret_cast(buffer), 16, reinterpret_cast(format), time); + } catch (const std::invalid_argument&) { return true; } @@ -246,33 +238,33 @@ static void CheckWcsftime() { char16_t wide[128]; const std::size_t length = strftime_nid_postfix(narrow, sizeof(narrow), item.narrow, &time); Require(length != 0, "wcsftime reference strftime"); - Require(wcsftime_nid_postfix(wide, 128, item.wide, &time) == length, "wcsftime length matches strftime"); + Require(wcsftime_nid_postfix(reinterpret_cast(wide), 128, reinterpret_cast(item.wide), &time) == length, "wcsftime length matches strftime"); for (std::size_t index = 0; index <= length; ++index) Require(wide[index] == static_cast(narrow[index]), "wcsftime output matches strftime"); } char16_t buffer[32]; - Require(wcsftime_nid_postfix(buffer, 32, u"%Y-%m-%d %H:%M:%S", &time) == 19 + Require(wcsftime_nid_postfix(reinterpret_cast(buffer), 32, reinterpret_cast(u"%Y-%m-%d %H:%M:%S"), &time) == 19 && buffer == std::u16string(u"2024-02-29 13:05:09"), "wcsftime date and time"); - Require(wcsftime_nid_postfix(buffer, 32, u"%a %b %j %p", &time) == 14 + Require(wcsftime_nid_postfix(reinterpret_cast(buffer), 32, reinterpret_cast(u"%a %b %j %p"), &time) == 14 && buffer == std::u16string(u"Thu Feb 060 PM"), "wcsftime names"); - Require(wcsftime_nid_postfix(buffer, 32, u"%%", &time) == 1 && buffer == std::u16string(u"%"), "wcsftime percent"); - Require(wcsftime_nid_postfix(buffer, 20, u"%Y-%m-%d %H:%M:%S", &time) == 19, "wcsftime exact fit"); + Require(wcsftime_nid_postfix(reinterpret_cast(buffer), 32, reinterpret_cast(u"%%"), &time) == 1 && buffer == std::u16string(u"%"), "wcsftime percent"); + Require(wcsftime_nid_postfix(reinterpret_cast(buffer), 20, reinterpret_cast(u"%Y-%m-%d %H:%M:%S"), &time) == 19, "wcsftime exact fit"); int& error = *__error_nid_postfix(); for (auto& unit : buffer) unit = u'x'; error = 5; - Require(wcsftime_nid_postfix(buffer, 19, u"%Y-%m-%d %H:%M:%S", &time) == 0 && error == 5 && buffer[0] == u'x', + Require(wcsftime_nid_postfix(reinterpret_cast(buffer), 19, reinterpret_cast(u"%Y-%m-%d %H:%M:%S"), &time) == 0 && error == 5 && buffer[0] == u'x', "wcsftime overflow"); - Require(wcsftime_nid_postfix(buffer, 1, u"%Y", &time) == 0 && error == 5 && buffer[0] == u'x', "wcsftime one unit"); - Require(wcsftime_nid_postfix(buffer, 0, u"%Y", &time) == 0 && error == 5 && buffer[0] == u'x', "wcsftime zero size"); - Require(wcsftime_nid_postfix(buffer, 32, u"", &time) == 0 && error == 5 && buffer[0] == u'x', "wcsftime empty format"); - Require(wcsftime_nid_postfix(nullptr, 32, u"%Y", &time) == 0 && error == 5, "wcsftime null buffer"); - Require(wcsftime_nid_postfix(buffer, 32, u"%Y \u20ac", &time) == 6 && buffer == std::u16string(u"2024 \u20ac"), + Require(wcsftime_nid_postfix(reinterpret_cast(buffer), 1, reinterpret_cast(u"%Y"), &time) == 0 && error == 5 && buffer[0] == u'x', "wcsftime one unit"); + Require(wcsftime_nid_postfix(reinterpret_cast(buffer), 0, reinterpret_cast(u"%Y"), &time) == 0 && error == 5 && buffer[0] == u'x', "wcsftime zero size"); + Require(wcsftime_nid_postfix(reinterpret_cast(buffer), 32, reinterpret_cast(u""), &time) == 0 && error == 5 && buffer[0] == u'x', "wcsftime empty format"); + Require(wcsftime_nid_postfix(nullptr, 32, reinterpret_cast(u"%Y"), &time) == 0 && error == 5, "wcsftime null buffer"); + Require(wcsftime_nid_postfix(reinterpret_cast(buffer), 32, reinterpret_cast(u"%Y \u20ac"), &time) == 6 && buffer == std::u16string(u"2024 \u20ac"), "wcsftime passes a character above 0xff through UTF-8"); - Require(wcsftime_nid_postfix(buffer, 7, u"%Y \u20ac", &time) == 6, "wcsftime sizes the narrow buffer for three-byte characters"); + Require(wcsftime_nid_postfix(reinterpret_cast(buffer), 7, reinterpret_cast(u"%Y \u20ac"), &time) == 6, "wcsftime sizes the narrow buffer for three-byte characters"); for (auto& unit : buffer) unit = u'x'; error = 5; - Require(wcsftime_nid_postfix(buffer, SIZE_MAX, u"%Y", &time) == 0 && error == 22 && buffer[0] == u'x', + Require(wcsftime_nid_postfix(reinterpret_cast(buffer), SIZE_MAX, reinterpret_cast(u"%Y"), &time) == 0 && error == 22 && buffer[0] == u'x', "wcsftime oversized buffer"); Require(WcsftimeThrows(buffer, nullptr, &time), "wcsftime null format"); Require(WcsftimeThrows(buffer, u"%Y", nullptr), "wcsftime null time"); diff --git a/core/libs/tests/GuestWideStreamScan.cpp b/core/libs/tests/GuestWideStreamScan.cpp index 632a989759..857a72001f 100644 --- a/core/libs/tests/GuestWideStreamScan.cpp +++ b/core/libs/tests/GuestWideStreamScan.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/FileStream.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -8,15 +9,7 @@ extern "C" { extern FileStream* __stdinp_nid_postfix; -int APS5_VABI vfwscanf_nid_postfix(FileStream*, const char16_t*, void*); -int APS5_VABI vfwscanf_s_nid_postfix(FileStream*, const char16_t*, void*); -int APS5_VABI vwscanf_nid_postfix(const char16_t*, void*); -int APS5_VABI vwscanf_s_nid_postfix(const char16_t*, void*); -int APS5_VABI fwscanf_nid_postfix(FileStream*, const char16_t*, ...); -int APS5_VABI fwscanf_s_nid_postfix(FileStream*, const char16_t*, ...); -int APS5_VABI wscanf_nid_postfix(const char16_t*, ...); -int APS5_VABI wscanf_s_nid_postfix(const char16_t*, ...); -std::int32_t APS5_VABI fgetwc_nid_postfix(FileStream*); + } #ifdef _WIN32 @@ -35,28 +28,28 @@ static void Require(bool value, const char* what) { static int APS5_VABI ScanStream(FileStream* stream, const char16_t* format, ...) { APS5_VA_BEGIN(format); - const int result = vfwscanf_nid_postfix(stream, format, args); + const int result = vfwscanf_nid_postfix(stream, format, reinterpret_cast(args)); APS5_VA_END(); return result; } static int APS5_VABI ScanStreamSized(FileStream* stream, const char16_t* format, ...) { APS5_VA_BEGIN(format); - const int result = vfwscanf_s_nid_postfix(stream, format, args); + const int result = vfwscanf_s_nid_postfix(stream, format, reinterpret_cast(args)); APS5_VA_END(); return result; } static int APS5_VABI ScanInput(const char16_t* format, ...) { APS5_VA_BEGIN(format); - const int result = vwscanf_nid_postfix(format, args); + const int result = vwscanf_nid_postfix(format, reinterpret_cast(args)); APS5_VA_END(); return result; } static int APS5_VABI ScanInputSized(const char16_t* format, ...) { APS5_VA_BEGIN(format); - const int result = vwscanf_s_nid_postfix(format, args); + const int result = vwscanf_s_nid_postfix(format, reinterpret_cast(args)); APS5_VA_END(); return result; } diff --git a/core/libs/tests/GuestWideStrings.cpp b/core/libs/tests/GuestWideStrings.cpp index 406637d7f0..db3553fee9 100644 --- a/core/libs/tests/GuestWideStrings.cpp +++ b/core/libs/tests/GuestWideStrings.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -10,58 +11,6 @@ #include #include -extern "C" { -std::size_t APS5_VABI c32rtomb_nid_postfix(char* destination, std::uint32_t value, void* state); -std::size_t APS5_VABI c16rtomb_nid_postfix(char* destination, std::uint16_t unit, void* state); -std::size_t APS5_VABI mbrtoc32_nid_postfix(std::uint32_t* destination, const char* source, std::size_t count, void* state); -std::size_t APS5_VABI mbrtoc16_nid_postfix(std::uint16_t* destination, const char* source, std::size_t count, void* state); -int APS5_VABI mblen_nid_postfix(const char* source, std::size_t count); -int APS5_VABI wctomb_nid_postfix(char* destination, std::uint16_t value); -int* APS5_VABI __error_nid_postfix(); -const char16_t* APS5_VABI wmemchr_nid_postfix(const char16_t* s, char16_t c, std::size_t n); -int APS5_VABI wmemcmp_nid_postfix(const char16_t* s1, const char16_t* s2, std::size_t n); -char16_t* APS5_VABI wmemcpy_nid_postfix(char16_t* dest, const char16_t* src, std::size_t n); -char16_t* APS5_VABI wmemmove_nid_postfix(char16_t* dest, const char16_t* src, std::size_t n); -std::size_t APS5_VABI wcslen_nid_postfix(const char16_t* s); -std::size_t APS5_VABI wcsnlen_s_nid_postfix(const char16_t* s, std::size_t maxlen); -int APS5_VABI wcscmp_nid_postfix(const char16_t* s1, const char16_t* s2); -int APS5_VABI wcsncmp_nid_postfix(const char16_t* s1, const char16_t* s2, std::size_t n); -char16_t* APS5_VABI wcscpy_nid_postfix(char16_t* dest, const char16_t* src); -char16_t* APS5_VABI wcscat_nid_postfix(char16_t* dest, const char16_t* src); -char16_t* APS5_VABI wcsncpy_nid_postfix(char16_t* dest, const char16_t* src, std::size_t n); -int APS5_VABI wmemcpy_s_nid_postfix(char16_t* dest, std::size_t destsz, const char16_t* src, std::size_t count); -int APS5_VABI wmemmove_s_nid_postfix(char16_t* dest, std::size_t destsz, const char16_t* src, std::size_t count); -int APS5_VABI wcsncpy_s_nid_postfix(char16_t* dest, std::size_t destsz, const char16_t* src, std::size_t count); -int APS5_VABI wcscpy_s_nid_postfix(char16_t* dest, std::size_t destsz, const char16_t* src); -void* APS5_VABI set_constraint_handler_s_nid_postfix(void* handler); -void APS5_VABI ignore_handler_s_nid_postfix(const char* message, void* pointer, int error); -char16_t* APS5_VABI wcsncat_nid_postfix(char16_t* dest, const char16_t* src, std::size_t n); -int APS5_VABI wcsncat_s_nid_postfix(char16_t* dest, std::size_t destsz, const char16_t* src, std::size_t count); -int APS5_VABI wcscat_s_nid_postfix(char16_t* dest, std::size_t destsz, const char16_t* src); -const char16_t* APS5_VABI wcschr_nid_postfix(const char16_t* s, char16_t c); -const char16_t* APS5_VABI wcsrchr_nid_postfix(const char16_t* s, char16_t c); -const char16_t* APS5_VABI wcsstr_nid_postfix(const char16_t* haystack, const char16_t* needle); -const char16_t* APS5_VABI wcspbrk_nid_postfix(const char16_t* s, const char16_t* accept); -std::size_t APS5_VABI wcsspn_nid_postfix(const char16_t* s, const char16_t* accept); -std::size_t APS5_VABI wcscspn_nid_postfix(const char16_t* s, const char16_t* reject); -char16_t* APS5_VABI wcstok_nid_postfix(char16_t* text, const char16_t* delimiters, char16_t** last); -char16_t* APS5_VABI wmemset_nid_postfix(char16_t* s, char16_t c, std::size_t n); -double APS5_VABI wcstod_nid_postfix(const char16_t* str, char16_t** endptr); -float APS5_VABI wcstof_nid_postfix(const char16_t* str, char16_t** endptr); -long double APS5_VABI wcstold_nid_postfix(const char16_t* str, char16_t** endptr); -long long APS5_VABI wcstol_nid_postfix(const char16_t* str, char16_t** endptr, int base); -long long APS5_VABI wcstoll_nid_postfix(const char16_t* str, char16_t** endptr, int base); -long long APS5_VABI wcstoimax_nid_postfix(const char16_t* str, char16_t** endptr, int base); -unsigned long long APS5_VABI wcstoumax_nid_postfix(const char16_t* str, char16_t** endptr, int base); -unsigned long long APS5_VABI strtouq_nid_postfix(const char* str, char** endptr, int base); -char* APS5_VABI rindex_nid_postfix(const char* s, int c); -int APS5_VABI flsl_nid_postfix(std::int64_t mask); -unsigned long long APS5_VABI wcstoul_nid_postfix(const char16_t* str, char16_t** endptr, int base); -unsigned long long APS5_VABI wcstoull_nid_postfix(const char16_t* str, char16_t** endptr, int base); -int APS5_VABI wcscoll_nid_postfix(const char16_t* first, const char16_t* second); -std::size_t APS5_VABI wcsxfrm_nid_postfix(char16_t* destination, const char16_t* source, std::size_t count); -} - namespace { void require(bool condition) { @@ -151,11 +100,13 @@ int main() { char16_t buffer[8]; wmemset_nid_postfix(buffer, 0xaaaa, 8); + require(wcscpy_nid_postfix(buffer, u"wide") == buffer); require(same(buffer, u"wide", 5) && buffer[5] == 0xaaaa); char16_t concatenated[8]; wmemset_nid_postfix(concatenated, 0xaaaa, 8); + concatenated[0] = 0; require(wcscat_nid_postfix(concatenated, u"ab") == concatenated); require(wcscat_nid_postfix(concatenated, u"世") == concatenated); @@ -168,6 +119,7 @@ int main() { require(same(buffer, padded, 6)); wmemset_nid_postfix(buffer, 0xaaaa, 8); wcsncpy_nid_postfix(buffer, u"abcdef", 3); + const char16_t truncated[] = {u'a', u'b', u'c', 0xaaaa}; require(same(buffer, truncated, 4)); @@ -177,9 +129,11 @@ int main() { require(wmemcpy_s_nid_postfix(nullptr, 16, u"abc", 3) == 22); require(wmemcpy_s_nid_postfix(memBuf, 16, nullptr, 3) == 22 && memBuf[0] == 0); wmemset_nid_postfix(memBuf, u'Z', 16); + require(wmemcpy_s_nid_postfix(memBuf, 4, u"12345", 5) == 34 && memBuf[0] == 0 && memBuf[3] == 0); require(wmemcpy_s_nid_postfix(memBuf, ((SIZE_MAX >> 1) / sizeof(char16_t)) + 1, u"a", 1) == 34); wmemcpy_s_nid_postfix(memBuf, 16, u"abcdefgh", 8); + require(wmemcpy_s_nid_postfix(memBuf + 2, 8, memBuf, 4) == 22 && memBuf[2] == 0); wmemcpy_s_nid_postfix(memBuf, 16, u"0123456789", 10); @@ -206,23 +160,26 @@ int main() { require(wcsncpy_s_nid_postfix(strBuf, 5, u"hello", 5) == 34 && strBuf[0] == 0); require(wcsncpy_s_nid_postfix(strBuf, ((SIZE_MAX >> 1) / sizeof(char16_t)) + 1, u"a", 1) == 34); wcsncpy_s_nid_postfix(strBuf, 16, u"abcdef", 6); + require(wcsncpy_s_nid_postfix(strBuf + 1, 10, strBuf, 3) == 22 && strBuf[1] == 0); char16_t cpyBuf[16]; - require(wcscpy_s_nid_postfix(cpyBuf, 16, u"wide") == 0 && same(cpyBuf, u"wide", 5)); + require(wcscpy_s_nid_postfix(reinterpret_cast(cpyBuf), 16, reinterpret_cast(u"wide")) == 0 && same(cpyBuf, u"wide", 5)); void* previousHandler = set_constraint_handler_s_nid_postfix(reinterpret_cast(&ignore_handler_s_nid_postfix)); - require(wcscpy_s_nid_postfix(nullptr, 16, u"wide") == 22); - require(wcscpy_s_nid_postfix(cpyBuf, 0, u"wide") == 22); - require(wcscpy_s_nid_postfix(cpyBuf, 16, nullptr) == 22 && cpyBuf[0] == 0); - require(wcscpy_s_nid_postfix(cpyBuf, 4, u"wide") == 34 && cpyBuf[0] == 0); + require(wcscpy_s_nid_postfix(nullptr, 16, reinterpret_cast(u"wide")) == 22); + require(wcscpy_s_nid_postfix(reinterpret_cast(cpyBuf), 0, reinterpret_cast(u"wide")) == 22); + require(wcscpy_s_nid_postfix(reinterpret_cast(cpyBuf), 16, nullptr) == 22 && cpyBuf[0] == 0); + require(wcscpy_s_nid_postfix(reinterpret_cast(cpyBuf), 4, reinterpret_cast(u"wide")) == 34 && cpyBuf[0] == 0); cpyBuf[0] = 0x1234; - require(wcscpy_s_nid_postfix(cpyBuf, ((SIZE_MAX >> 1) / sizeof(char16_t)) + 1, u"a") == 34 && cpyBuf[0] == 0x1234); - wcscpy_s_nid_postfix(cpyBuf, 16, u"abcdef"); - require(wcscpy_s_nid_postfix(cpyBuf + 1, 10, cpyBuf) == 22 && cpyBuf[1] == 0); + require(wcscpy_s_nid_postfix(reinterpret_cast(cpyBuf), ((SIZE_MAX >> 1) / sizeof(char16_t)) + 1, reinterpret_cast(u"a")) == 34 && cpyBuf[0] == 0x1234); + wcscpy_s_nid_postfix(reinterpret_cast(cpyBuf), 16, reinterpret_cast(u"abcdef")); + + require(wcscpy_s_nid_postfix(reinterpret_cast(cpyBuf + 1), 10, reinterpret_cast(cpyBuf)) == 22 && cpyBuf[1] == 0); set_constraint_handler_s_nid_postfix(previousHandler); char16_t ncatBuf[16]; wmemset_nid_postfix(ncatBuf, 0xaaaa, 16); + ncatBuf[0] = 0; require(wcsncat_nid_postfix(ncatBuf, u"hello", 3) == ncatBuf); require(same(ncatBuf, u"hel", 4) && ncatBuf[4] == 0xaaaa); @@ -232,24 +189,32 @@ int main() { wcsncpy_s_nid_postfix(strBuf, 16, u"hello", 5); require(wcsncat_s_nid_postfix(strBuf, 16, u" world", 6) == 0 && same(strBuf, u"hello world", 12)); wcsncpy_s_nid_postfix(strBuf, 16, u"foo", 3); + require(wcsncat_s_nid_postfix(strBuf, 16, u"barbaz", 3) == 0 && same(strBuf, u"foobar", 7)); wcsncpy_s_nid_postfix(strBuf, 8, u"abc", 3); + require(wcsncat_s_nid_postfix(strBuf, 8, u"1234", 4) == 0 && same(strBuf, u"abc1234", 8)); wcsncpy_s_nid_postfix(strBuf, 8, u"abc", 3); + require(wcsncat_s_nid_postfix(strBuf, 8, u"12345", 5) == 34 && strBuf[0] == 0); wmemset_nid_postfix(strBuf, u'x', 4); + require(wcsncat_s_nid_postfix(strBuf, 4, u"a", 1) == 34 && strBuf[0] == 0); wcsncpy_s_nid_postfix(strBuf, 16, u"abc", 3); + require(wcsncat_s_nid_postfix(strBuf, 16, strBuf + 1, 2) == 0 && same(strBuf, u"abcbc", 6)); const char16_t splitSource[] = u"abc\0xyz"; std::memcpy(strBuf, splitSource, sizeof(splitSource)); require(wcsncat_s_nid_postfix(strBuf, 16, strBuf + 4, 3) == 22 && strBuf[0] == 0); wcsncpy_s_nid_postfix(strBuf, 16, u"abc", 3); + require(wcscat_s_nid_postfix(strBuf, 16, u"def") == 0 && same(strBuf, u"abcdef", 7)); wcsncpy_s_nid_postfix(strBuf, 8, u"12345", 5); + require(wcscat_s_nid_postfix(strBuf, 8, u"6789") == 34 && strBuf[0] == 0); require(wcscat_s_nid_postfix(nullptr, 8, u"a") == 22); wcsncpy_s_nid_postfix(strBuf, 8, u"123", 3); + require(wcscat_s_nid_postfix(strBuf, 8, nullptr) == 22 && strBuf[0] == 0); const char16_t* text = u"a世b世c"; @@ -390,8 +355,10 @@ int main() { char16_t transformed[8]; wmemset_nid_postfix(transformed, 0xaaaa, 8); + require(wcsxfrm_nid_postfix(transformed, u"wide", 8) == 4 && same(transformed, u"wide", 5) && transformed[5] == 0xaaaa); wmemset_nid_postfix(transformed, 0xaaaa, 8); + require(wcsxfrm_nid_postfix(transformed, u"much too long", 4) == 13); if (!same(transformed, u"muc", 4)) std::fputs("wcsxfrm did not copy and terminate its truncated result\n", stderr); require(same(transformed, u"muc", 4) && transformed[4] == 0xaaaa); @@ -415,6 +382,7 @@ int main() { TransformCase{u"\x7fff\x8000\xffff\xd83d\xde00", 6, 5, u"\x7fff\x8000\xffff\xd83d\xde00", 6} }) { wmemset_nid_postfix(transformed, 0xaaaa, 8); + require(wcsxfrm_nid_postfix(transformed, test.source, test.count) == test.length); require(same(transformed, test.expected, test.written)); for (std::size_t index = test.written; index < 8; ++index) require(transformed[index] == 0xaaaa); diff --git a/core/libs/tests/GuestWorkingDirectory.cpp b/core/libs/tests/GuestWorkingDirectory.cpp index de3ea75fc1..f14f721431 100644 --- a/core/libs/tests/GuestWorkingDirectory.cpp +++ b/core/libs/tests/GuestWorkingDirectory.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/ApplicationHeap.hpp" #include "prx/libc/include/General.hpp" #include "prx/libc/include/GuestHeap.hpp" @@ -8,11 +9,7 @@ #include #include #include -extern "C" { -int APS5_VABI chdir_nid_postfix(const char*); -char* APS5_VABI getcwd_nid_postfix(char*, std::size_t); -int* APS5_VABI __error_nid_postfix(); -} + static void Require(bool value) { if (!value) std::abort(); } static int allocations = 0; static int releases = 0; diff --git a/core/libs/tests/GuestZlib.cpp b/core/libs/tests/GuestZlib.cpp index 86bdc65e8d..9f8a857137 100644 --- a/core/libs/tests/GuestZlib.cpp +++ b/core/libs/tests/GuestZlib.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceZlib/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -10,14 +11,6 @@ #include #include -extern "C" { -std::int32_t APS5_VABI sceZlibInitialize(const void*, std::uint64_t); -std::int32_t APS5_VABI sceZlibFinalize(); -std::int32_t APS5_VABI sceZlibInflate(const void*, std::uint32_t, void*, std::uint32_t, std::uint64_t*); -std::int32_t APS5_VABI sceZlibWaitForDone(std::uint64_t*, std::uint32_t*); -std::int32_t APS5_VABI sceZlibGetResult(std::uint64_t, std::uint32_t*, std::int32_t*); -} - static void Require(bool value, const std::source_location& location = std::source_location::current()) { if (value) return; std::fprintf(stderr, "Zlib assertion failed at line %u\n", location.line()); diff --git a/core/libs/tests/JobManagerFailures.cpp b/core/libs/tests/JobManagerFailures.cpp new file mode 100644 index 0000000000..d6586fcb9b --- /dev/null +++ b/core/libs/tests/JobManagerFailures.cpp @@ -0,0 +1,156 @@ +#include "prx/libSceJobManager/libSceJobManager.hpp" +#include "SceTypes.hpp" +#include +#include +#include +#include +#include +#include +#include +#include + +namespace { + +int failure = 0; +int calls = 0; +int attributes = 0; +int threads = 0; +int queues = 0; +int registrations = 0; + +bool Fail() { return ++calls == failure; } + +void Check(bool condition) { + if (!condition) std::abort(); +} + +struct EventQueue { + std::mutex lock; + std::condition_variable ready; + bool triggered = false; +}; + +} + +extern "C" { + +int APS5_VABI scePthreadAttrInit(PthreadAttr* value) { + if (Fail()) return 12; + *value = reinterpret_cast(new int); + ++attributes; + return 0; +} + +int APS5_VABI scePthreadAttrDestroy(PthreadAttr* value) { + delete reinterpret_cast(*value); + *value = nullptr; + --attributes; + return 0; +} + +int APS5_VABI scePthreadAttrSetinheritsched(PthreadAttr*, int) { return Fail() ? 22 : 0; } +int APS5_VABI scePthreadAttrSetschedparam(PthreadAttr*, const KernelSchedParam*) { return Fail() ? 22 : 0; } +int APS5_VABI scePthreadAttrSetstacksize(PthreadAttr*, std::size_t) { return Fail() ? 22 : 0; } +int APS5_VABI scePthreadAttrSetaffinity(PthreadAttr*, KernelCpumask) { return Fail() ? 22 : 0; } + +int APS5_VABI scePthreadCreate(Pthread* value, const PthreadAttr*, PthreadEntry entry, void* argument, const char*) { + if (Fail()) return 11; + *value = reinterpret_cast(new std::thread([=] { entry(argument); })); + ++threads; + return 0; +} + +int APS5_VABI scePthreadJoin(Pthread value, void**) { + auto* thread = reinterpret_cast(value); + thread->join(); + delete thread; + --threads; + return 0; +} + +int APS5_VABI sceKernelCreateEqueue(KernelEqueue* value, const char*) { + if (Fail()) return 12; + *value = reinterpret_cast(new EventQueue); + ++queues; + return 0; +} + +int APS5_VABI sceKernelDeleteEqueue(KernelEqueue value) { + delete reinterpret_cast(value); + --queues; + return 0; +} + +int APS5_VABI sceKernelWaitEqueue(KernelEqueue value, KernelEvent* event, int, int* count, const KernelUseconds*) { + auto& queue = *reinterpret_cast(value); + std::unique_lock guard(queue.lock); + queue.ready.wait(guard, [&queue] { return queue.triggered; }); + event->filter = -11; + event->ident = 0; + *count = 1; + return 0; +} + +int APS5_VABI sceKernelAddUserEventEdge(KernelEqueue, int) { return 0; } + +int APS5_VABI sceKernelTriggerUserEvent(KernelEqueue value, int, void*) { + auto& queue = *reinterpret_cast(value); + const std::lock_guard guard(queue.lock); + queue.triggered = true; + queue.ready.notify_all(); + return 0; +} + +int APS5_VABI sceKernelGetEventFilter(const KernelEvent* event) { return event->filter; } +std::uintptr_t APS5_VABI sceKernelGetEventId(const KernelEvent* event) { return event->ident; } + +int APS5_VABI sceAgcDriverAddEqEvent(KernelEqueue, int, void*) { + if (Fail()) return 22; + ++registrations; + return 0; +} + +int APS5_VABI sceAgcDriverDeleteEqEvent(KernelEqueue, int) { + --registrations; + return 0; +} + + +} + +int main() { + constexpr std::size_t size = 1024 * 1024; + void* memory = ::operator new(size, std::align_val_t{256}); + for (const std::uint32_t computeSequences : {0u, 2u}) { + int failures = 0; + for (failure = 1; failure < 40; ++failure) { + alignas(64) unsigned char manager[0x100]{}; + _ZN3sce3Job10JobManagerC1Ev(manager); + calls = 0; + bool threw = false; + try { + Check(_ZN3sce3Job10JobManager10initializeEPvmjjjmPKNS1_12ConfigParamsE(manager, memory, size, 3, 2, computeSequences, computeSequences ? 5 : 0, nullptr) == 0); + } catch (const std::runtime_error&) { + threw = true; + ++failures; + } + if (threw) { + Check(_ZN3sce3Job10JobManager27getSequenceFactoryInterfaceENS1_8PriorityE(manager, 0) == nullptr); + Check(_ZN3sce3Job10JobManager8shutdownEv(manager) == static_cast(0x81581010u)); + } else { + Check(_ZN3sce3Job10JobManager8shutdownEv(manager) == 0); + } + Check(attributes == 0 && threads == 0 && queues == 0 && registrations == 0); + if (!threw) break; + const int injected = failure; + failure = 0; + Check(_ZN3sce3Job10JobManager10initializeEPvmjjjmPKNS1_12ConfigParamsE(manager, memory, size, 3, 2, computeSequences, computeSequences ? 5 : 0, nullptr) == 0); + Check(_ZN3sce3Job10JobManager8shutdownEv(manager) == 0); + Check(attributes == 0 && threads == 0 && queues == 0 && registrations == 0); + failure = injected; + } + Check(failures == (computeSequences ? 27 : 18)); + std::printf("initialization failures recovered: %d\n", failures); + } + ::operator delete(memory, std::align_val_t{256}); +} diff --git a/core/libs/tests/JobManagerProfiler.cpp b/core/libs/tests/JobManagerProfiler.cpp new file mode 100644 index 0000000000..a2a4bebb5e --- /dev/null +++ b/core/libs/tests/JobManagerProfiler.cpp @@ -0,0 +1,394 @@ +#include "prx/libSceAgcDriver/Execution/include/Driver.hpp" +#include "prx/libSceJobManager/libSceJobManager.hpp" +#include "prx/libSceAgcDriver/libSceAgcDriver.hpp" +#include "prx/libSceAgc/libSceAgc.hpp" +#include "SceTypes.hpp" +#include "prx/libSceAgcDriver/tests/execution/VulkanTestDevice.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace { + +enum class Kind { Sequence, Job, Dispatch, Body }; + +struct Event { + Kind kind; + const char* name; + std::uint16_t manager; + std::uint16_t sequence; + std::uint16_t dispatch; + std::uint16_t value; + std::uint16_t event; + std::uint64_t entry; + std::uint64_t argument; +}; + +std::mutex eventLock; +std::vector events; + +void Check(bool condition, int line) { + if (!condition) { + std::fprintf(stderr, "job manager profiler check failed at line %d\n", line); + std::abort(); + } +} + +#define Require(value) Check((value), __LINE__) + +void Record(Event event) { + const std::lock_guard guard(eventLock); + events.push_back(event); +} + +std::vector Snapshot() { + const std::lock_guard guard(eventLock); + return events; +} + +void Clear() { + const std::lock_guard guard(eventLock); + events.clear(); +} + +struct Fixture { + alignas(256) std::array memory{}; + alignas(64) std::array object{}; + ISequenceFactory* factory = nullptr; + std::uint16_t id = 0; + + explicit Fixture(std::uint32_t workers = 1) { + _ZN3sce3Job10JobManagerC1Ev(object.data()); + Require(_ZN3sce3Job10JobManager10initializeEPvmjjjmPKNS1_12ConfigParamsE(object.data(), memory.data(), memory.size(), workers, 2, 2, 0x122, nullptr) == 0); + factory = _ZN3sce3Job10JobManager34getUnifiedSequenceFactoryInterfaceENS1_8PriorityE(object.data(), 0); + id = static_cast(_mm_crc32_u64(0, reinterpret_cast(memory.data())) >> 16); + Clear(); + } + + void Stop() { + Require(_ZN3sce3Job10JobManager8shutdownEv(object.data()) == 0); + } + + ISequence* Create(const char* name, bool compute = false) { + ISequence* sequence = nullptr; + if (compute) Require(factory->CreateCompute(&sequence, 16, 8, 8, 4, name) == 0); + else Require(factory->Create(&sequence, 16, 8, 8, 4, name) == 0); + return sequence; + } +}; + +struct Context { + std::atomic entered{false}; + std::atomic calls{0}; + std::atomic released{true}; +}; + +void APS5_VABI Job(void* argument, std::uint32_t index) { + Record({Kind::Body, nullptr, 0, 0, 0, static_cast(index), 0, 0, reinterpret_cast(argument)}); + auto& context = *static_cast(argument); + ++context.calls; + context.entered.store(true); + while (!context.released.load()) std::this_thread::yield(); +} + +void Await(const std::atomic& flag) { + const auto deadline = std::chrono::steady_clock::now() + std::chrono::seconds(3); + while (!flag.load() && std::chrono::steady_clock::now() < deadline) std::this_thread::yield(); + Require(flag.load()); +} + +struct Reader { + std::vector records = Snapshot(); + std::size_t next = 0; + std::uint16_t manager; + + explicit Reader(std::uint16_t id) : manager(id) {} + + Event Take(Kind kind) { + Require(next < records.size()); + const Event result = records[next++]; + Require(result.kind == kind); + if (kind != Kind::Body) Require(result.manager == manager); + return result; + } + + void Sequence(const char* name, std::uint16_t id, std::uint16_t event) { + const Event result = Take(Kind::Sequence); + Require(result.name == name && result.sequence == id && result.event == event); + } + + std::uint16_t Dispatch(const char* name, Context& context, std::uint16_t count, std::uint16_t sequence = 0) { + std::uint16_t dispatch = 0; + for (std::uint16_t index = 0; index < count; ++index) { + const Event begin = Take(Kind::Job); + if (index == 0) dispatch = begin.dispatch; + Require(begin.dispatch == dispatch && begin.value == index && begin.event == 16); + const Event body = Take(Kind::Body); + Require(body.value == index && body.argument == reinterpret_cast(&context)); + const Event end = Take(Kind::Job); + Require(end.dispatch == dispatch && end.value == index && end.event == 32); + } + const Event result = Take(Kind::Dispatch); + Require(result.name == name && result.sequence == sequence && result.dispatch == dispatch && result.value == count); + Require(result.entry == reinterpret_cast(&Job) && result.argument == reinterpret_cast(&context)); + return dispatch; + } + + void Done() const { Require(next == records.size()); } +}; + +void EmptyAndIdentityCase() { + Fixture fixture; + const char* cpuName = "cpu"; + const char* gpuName = "compute"; + ISequence* cpu0 = fixture.Create(cpuName); + ISequence* cpu1 = fixture.Create(nullptr); + ISequence* gpu0 = fixture.Create(gpuName, true); + ISequence* gpu1 = fixture.Create(nullptr, true); + ISequence* unused = nullptr; + Require(fixture.factory->Create(&unused, 1, 1, 0, 1, "overflow") == static_cast(0x81580006u)); + Require(fixture.factory->Create(nullptr, 1, 1, 0, 1, "null") == static_cast(0x81580001u)); + for (ISequence* sequence : {cpu0, cpu1, gpu0, gpu1}) { + Require(sequence->SyncPoint() == 0); + Require(sequence->Wait() == 0); + } + Require(fixture.factory->Destroy(cpu0) == 0); + Require(fixture.factory->Destroy(cpu1) == 0); + Require(fixture.factory->DestroyCompute(gpu0) == 0); + Require(fixture.factory->DestroyCompute(gpu1) == 0); + ISequence* reused = fixture.Create(nullptr); + Require(fixture.factory->Destroy(reused) == 0); + fixture.Stop(); + Reader reader(fixture.id); + reader.Sequence(cpuName, 0, 1); + reader.Sequence(nullptr, 1, 1); + reader.Sequence(gpuName, 0, 1); + reader.Sequence(nullptr, 1, 1); + reader.Sequence(cpuName, 0, 2); + reader.Sequence(nullptr, 1, 2); + reader.Sequence(gpuName, 0, 2); + reader.Sequence(nullptr, 1, 2); + reader.Sequence(nullptr, 0, 1); + reader.Sequence(nullptr, 0, 2); + reader.Done(); +} + +void BatchCase(bool sync, bool wait, bool compute = false) { + Fixture fixture; + const char* name = "sequence"; + const char* firstName = "first"; + const char* secondName = "second"; + ISequence* sequence = fixture.Create(name, compute); + const std::uint16_t id = compute ? 2 : 0; + Context first; + Context second; + first.released.store(false); + Require(sequence->Dispatch(Job, &first, 1, firstName) == 0); + Await(first.entered); + if (sync) Require(sequence->SyncPoint() == 0); + if (wait) { + first.released.store(true); + Require(sequence->Wait() == 0); + } + Require(sequence->Dispatch(Job, &second, 4, secondName) == 0); + first.released.store(true); + Require(sequence->Wait() == 0); + if (compute) Require(fixture.factory->DestroyCompute(sequence) == 0); + else Require(fixture.factory->Destroy(sequence) == 0); + fixture.Stop(); + Reader reader(fixture.id); + reader.Sequence(name, 0, 1); + reader.Sequence(name, id, 3); + const auto firstId = reader.Dispatch(firstName, first, 1, id); + if (sync || wait) { + reader.Sequence(name, id, 4); + reader.Sequence(name, id, 3); + } + const auto secondId = reader.Dispatch(secondName, second, 4, id); + if (!wait) Require(firstId != secondId); + reader.Sequence(name, id, 4); + reader.Sequence(name, 0, 2); + reader.Done(); +} + +void ConcurrentCase() { + Fixture fixture(4); + ISequence* sequence = fixture.Create(nullptr); + Context context; + context.released.store(false); + Require(sequence->Dispatch(Job, &context, 8, nullptr) == 0); + const auto deadline = std::chrono::steady_clock::now() + std::chrono::seconds(3); + while (context.calls.load() < 4 && std::chrono::steady_clock::now() < deadline) std::this_thread::yield(); + Require(context.calls.load() == 4); + context.released.store(true); + Require(sequence->Wait() == 0); + Require(fixture.factory->Destroy(sequence) == 0); + fixture.Stop(); + Reader reader(fixture.id); + reader.Sequence(nullptr, 0, 1); + reader.Sequence(nullptr, 0, 3); + std::array states{}; + std::uint16_t dispatch = 0; + for (std::size_t index = 0; index < states.size() * 3; ++index) { + Require(reader.next < reader.records.size()); + const Event event = reader.records[reader.next++]; + Require(event.value < states.size()); + auto& state = states[event.value]; + if (event.kind == Kind::Job) { + if (index == 0) dispatch = event.dispatch; + Require(event.manager == fixture.id && event.dispatch == dispatch); + Require((state == 0 && event.event == 16) || (state == 2 && event.event == 32)); + } else { + Require(event.kind == Kind::Body && state == 1 && event.argument == reinterpret_cast(&context)); + } + ++state; + } + for (const auto state : states) Require(state == 3); + const Event metadata = reader.Take(Kind::Dispatch); + Require(metadata.dispatch == dispatch && metadata.value == 8 && metadata.sequence == 0 && metadata.name == nullptr); + Require(metadata.entry == reinterpret_cast(&Job) && metadata.argument == reinterpret_cast(&context)); + reader.Sequence(nullptr, 0, 4); + reader.Sequence(nullptr, 0, 2); + reader.Done(); +} + +void GpuBarrierCase(bool mixed, bool cpuAfter) { + Fixture fixture; + ISequence* sequence = fixture.Create(nullptr, true); + alignas(256) static const std::array code{0xbf810000u}; + const auto address = reinterpret_cast(code.data()); + const std::array registers{{{0x20c, static_cast(address >> 8)}, {0x20d, static_cast(address >> 40) & 0xff}, {0x207, 1}, {0x208, 1}, {0x209, 1}, {0x212, 0}, {0x213, 0}}}; + const std::array specials{0, 0, 0, 0, 1, 0, 0, 0}; + const ShaderRegister* registerPointer = registers.data(); + const std::uint32_t* specialPointer = specials.data(); + std::array shader{}; + std::memcpy(shader.data() + 0x20, ®isterPointer, sizeof(registerPointer)); + std::memcpy(shader.data() + 0x28, &specialPointer, sizeof(specialPointer)); + shader[0x5c] = static_cast(registers.size()); + alignas(64) std::uint32_t gate = 0; + alignas(256) std::array commands{}; + CommandBuffer buffer{commands.data(), commands.data() + commands.size(), commands.data(), commands.data() + commands.size(), nullptr, nullptr, 0}; + Require(sceAgcAcbWaitRegMem(&buffer, 0, 3, 3, &gate, 1, 0xffffffffu, 0x190) != nullptr); + const Packet packet{commands.data(), static_cast(buffer.cursor_up - commands.data()), 0, {}}; + Require(sceAgcDriverSubmitAcb(0x21, &packet) == 0); + Context context; + if (mixed) { + context.released.store(false); + Require(sequence->Dispatch(Job, &context, 1, nullptr) == 0); + Await(context.entered); + } + Require(sequence->DispatchCompute(shader.data(), nullptr, 1, 1, 1, nullptr) == 0); + Require(sequence->SyncPoint() == 0); + if (cpuAfter) { + Require(sequence->Dispatch(Job, &context, 1, nullptr) == 0); + Require(sequence->SyncPoint() == 0); + } + Require(sequence->DispatchCompute(shader.data(), nullptr, 1, 1, 1, nullptr) == 0); + context.released.store(true); + std::atomic_ref(gate).store(1); + Require(sequence->Wait() == 0); + Require(fixture.factory->DestroyCompute(sequence) == 0); + fixture.Stop(); + Reader reader(fixture.id); + reader.Sequence(nullptr, 0, 1); + reader.Sequence(nullptr, 2, 3); + if (cpuAfter) { + reader.Sequence(nullptr, 2, 4); + reader.Sequence(nullptr, 2, 3); + } + if (mixed || cpuAfter) { + reader.Dispatch(nullptr, context, 1, 2); + reader.Sequence(nullptr, 2, 4); + reader.Sequence(nullptr, 2, 3); + } + reader.Sequence(nullptr, 2, 4); + reader.Sequence(nullptr, 0, 2); + reader.Done(); +} + +void ShutdownCase(bool queued) { + Fixture fixture; + ISequence* sequence = fixture.Create(nullptr); + Context first; + Context canceled; + first.released.store(false); + Require(sequence->Dispatch(Job, &first, 1, nullptr) == 0); + Await(first.entered); + if (queued) { + Require(sequence->SyncPoint() == 0); + Require(sequence->Dispatch(Job, &canceled, 1, "canceled") == 0); + } + std::atomic stopping{false}; + std::thread stopper([&] { + stopping.store(true); + fixture.Stop(); + }); + Await(stopping); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + first.released.store(true); + stopper.join(); + Require(!canceled.entered.load()); + Reader reader(fixture.id); + reader.Sequence(nullptr, 0, 1); + reader.Sequence(nullptr, 0, 3); + reader.Dispatch(nullptr, first, 1); + if (queued) { + reader.Sequence(nullptr, 0, 4); + reader.Sequence(nullptr, 0, 3); + } + reader.Done(); +} + +} + +extern "C" { + +int APS5_VABI sceRazorCpuJobManagerSequence(const char* name, std::uint16_t manager, std::uint16_t sequence, std::uint16_t event) { + Record({Kind::Sequence, name, manager, sequence, 0, 0, event, 0, 0}); + return -1; +} + +int APS5_VABI sceRazorCpuJobManagerJob(std::uint16_t manager, std::uint16_t dispatch, std::uint16_t index, std::uint16_t event) { + Record({Kind::Job, nullptr, manager, 0, dispatch, index, event, 0, 0}); + return -1; +} + +int APS5_VABI sceRazorCpuJobManagerDispatch(const char* name, std::uint16_t manager, std::uint16_t sequence, std::uint16_t dispatch, std::uint16_t count, std::uint64_t entry, std::uint64_t argument) { + Record({Kind::Dispatch, name, manager, sequence, dispatch, count, 0, entry, argument}); + return -1; +} + +} + +int main(int argc, char** argv) { + if (argc == 2 && std::strcmp(argv[1], "gpu") == 0) { + auto device = OpenVulkanTestDevice(); + if (!device) return VulkanTestSkipped; + device.reset(); + GpuBarrierCase(false, false); + GpuBarrierCase(false, true); + GpuBarrierCase(true, false); + AgcDriverShutdown_nid_postfix(); + std::puts("job manager GPU profiler tests passed"); + return 0; + } + if (argc != 1) return 2; + EmptyAndIdentityCase(); + BatchCase(false, false); + BatchCase(true, false); + BatchCase(false, true); + BatchCase(true, false, true); + ConcurrentCase(); + ShutdownCase(false); + ShutdownCase(true); + std::puts("job manager profiler tests passed"); +} diff --git a/core/libs/tests/JobManagerReference.cpp b/core/libs/tests/JobManagerReference.cpp index b808c60f2f..f3934c5cf6 100644 --- a/core/libs/tests/JobManagerReference.cpp +++ b/core/libs/tests/JobManagerReference.cpp @@ -1,12 +1,15 @@ +#include "prx/libSceJobManager/libSceJobManager.hpp" #include "SceTypes.hpp" #include #include #include +#ifdef _WIN32 #include +#else +#include +#include +#endif -struct MemorySizeQueryParams; -struct ConfigParams; -struct SequenceFactory; int RunJobManagerCase(const char* name); @@ -14,6 +17,7 @@ template static T Resolve(const char* nid) { const bool host = std::getenv("ANYPS5_JOB_MANAGER_HOST") != nullptr; const char* library = host ? "libSceJobManager.prx" : "libSceJobManager.prx.guest.prx"; +#ifdef _WIN32 HMODULE module = GetModuleHandleA(library); if (module == nullptr && host) module = LoadLibraryA("libs\\libSceJobManager.prx"); const FARPROC symbol = module != nullptr ? GetProcAddress(module, nid) : nullptr; @@ -21,6 +25,15 @@ static T Resolve(const char* nid) { std::fprintf(stderr, "JobManager reference: missing %s in %s (Windows error %lu)\n", nid, library, GetLastError()); std::exit(3); } +#else + static void* module = dlopen(host ? "libs/libSceJobManager.prx" : "app0/sce_module/libSceJobManager.prx.guest.prx", RTLD_NOW | RTLD_LOCAL); + const std::string name = host ? nid : std::string(nid) + "#guest"; + void* symbol = module != nullptr ? dlsym(module, name.c_str()) : nullptr; + if (symbol == nullptr) { + std::fprintf(stderr, "JobManager reference: missing %s in %s (%s)\n", name.c_str(), library, dlerror()); + std::exit(3); + } +#endif return reinterpret_cast(symbol); } @@ -56,12 +69,12 @@ int APS5_VABI _ZN3sce3Job10JobManager8shutdownEv(void* self) { return call(self); } -SequenceFactory* APS5_VABI _ZN3sce3Job10JobManager27getSequenceFactoryInterfaceENS1_8PriorityE(void* self, std::uint32_t priority) { +ISequenceFactory* APS5_VABI _ZN3sce3Job10JobManager27getSequenceFactoryInterfaceENS1_8PriorityE(void* self, std::uint32_t priority) { static const auto call = Resolve("W-yXgQmaozU"); return call(self, priority); } -SequenceFactory* APS5_VABI _ZN3sce3Job10JobManager34getUnifiedSequenceFactoryInterfaceENS1_8PriorityE(void* self, std::uint32_t priority) { +ISequenceFactory* APS5_VABI _ZN3sce3Job10JobManager34getUnifiedSequenceFactoryInterfaceENS1_8PriorityE(void* self, std::uint32_t priority) { static const auto call = Resolve("L5jTAtk3HKA"); return call(self, priority); } @@ -73,7 +86,12 @@ int APS5_VABI _ZN3sce3Job10JobManager24setPersistentThreadCountEj(void* self, st int APS5_VABI Run_nid_no_patch() { const char* name = std::getenv("ANYPS5_JOB_MANAGER_CASE"); - return name != nullptr ? RunJobManagerCase(name) : 2; + const int result = name != nullptr ? RunJobManagerCase(name) : 2; +#ifdef _WIN32 + return result; +#else + std::exit(result); +#endif } } diff --git a/core/libs/tests/JobManagerRegistration.cpp b/core/libs/tests/JobManagerRegistration.cpp new file mode 100644 index 0000000000..056b51a6b3 --- /dev/null +++ b/core/libs/tests/JobManagerRegistration.cpp @@ -0,0 +1,86 @@ +#include "prx/libSceJobManager/libSceJobManager.hpp" +#include "SceTypes.hpp" +#include +#include +#include +#include +#include + +namespace { + +alignas(256) std::array workArea{}; +alignas(64) std::array manager{}; +std::uint32_t registrationCalls = 0; +std::uint32_t unregistrationCalls = 0; +std::uint32_t assignedId = 0; +bool writeId = true; +int registrationResult = 0; +std::atomic jobs{0}; + +void Require(bool condition) { + if (!condition) std::abort(); +} + +int Initialize(bool unified, void* memory) { + if (unified) return _ZN3sce3Job10JobManager10initializeEPvmjjjmPKNS1_12ConfigParamsE(manager.data(), memory, workArea.size(), 1, 1, 0, 0, nullptr); + return _ZN3sce3Job10JobManager10initializeEPvmjjPKNS1_12ConfigParamsE(manager.data(), memory, workArea.size(), 1, 1, nullptr); +} + +void APS5_VABI Count(void*, std::uint32_t) { + ++jobs; +} + +} + +extern "C" { + +int APS5_VABI _sceUlobjmgrRegisterObject_nid_postfix(std::uint64_t object, std::int32_t kind, std::uint32_t* id) { + Require(object == reinterpret_cast(workArea.data()) && kind == 0x21 && id != nullptr); + Require(workArea[0] == 0x4a && workArea[1] == 0x4d); + Require(_ZN3sce3Job10JobManager27getSequenceFactoryInterfaceENS1_8PriorityE(manager.data(), 0) != nullptr); + ++registrationCalls; + if (writeId) *id = assignedId; + return registrationResult; +} + +int APS5_VABI _sceUlobjmgrUnregisterObject_nid_postfix(std::uint32_t id) { + Require(id == (writeId ? assignedId : 0)); + Require(_ZN3sce3Job10JobManager27getSequenceFactoryInterfaceENS1_8PriorityE(manager.data(), 0) != nullptr); + ++unregistrationCalls; + return 37; +} + +} + +int main() { + for (const bool unified : {false, true}) { + for (const auto [result, assignsId] : std::array, 5>{{{0, true}, {22, true}, {static_cast(0x8002000cu), true}, {22, false}, {static_cast(0x8002000cu), false}}}) { + for (const bool destructor : {false, true}) { + _ZN3sce3Job10JobManagerC1Ev(manager.data()); + const auto before = registrationCalls; + Require(Initialize(unified, nullptr) == static_cast(0x81581001u)); + Require(registrationCalls == before); + registrationResult = result; + writeId = assignsId; + assignedId = 101 + before; + Require(Initialize(unified, workArea.data()) == result); + Require(registrationCalls == before + 1 && unregistrationCalls == before); + Require(Initialize(unified, workArea.data()) == static_cast(0x81581020u)); + Require(registrationCalls == before + 1); + auto* factory = _ZN3sce3Job10JobManager27getSequenceFactoryInterfaceENS1_8PriorityE(manager.data(), 0); + ISequence* sequence = nullptr; + Require(factory->Create(&sequence, 3, 1, 0, 1, nullptr) == 0); + jobs = 0; + Require(sequence->Dispatch(Count, nullptr, 3, nullptr) == 0); + Require(factory->Destroy(sequence) == 0 && jobs == 3); + if (destructor) _ZN3sce3Job10JobManagerD1Ev(manager.data()); + else Require(_ZN3sce3Job10JobManager8shutdownEv(manager.data()) == 0); + Require(unregistrationCalls == before + 1); + Require(_ZN3sce3Job10JobManager8shutdownEv(manager.data()) == static_cast(0x81581010u)); + _ZN3sce3Job10JobManagerD1Ev(manager.data()); + Require(unregistrationCalls == before + 1); + } + } + } + std::puts("job manager registration tests passed"); +} diff --git a/core/libs/tests/JsonCopyFailure.cpp b/core/libs/tests/JsonCopyFailure.cpp index 6f95b142e3..b8e2562656 100644 --- a/core/libs/tests/JsonCopyFailure.cpp +++ b/core/libs/tests/JsonCopyFailure.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceJson2/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -5,58 +6,10 @@ #include #include #include +#include #include -struct Value { void* node; }; -struct String { void* text; }; -struct Array { void* items; }; -struct Object { void* items; }; -struct Iterator { void* state; }; -struct Pair { String key; std::uint64_t reserved; Value value; }; - -extern "C" { -Iterator* APS5_VABI _ZNK3sce4Json5Array5beginEv(Iterator*, const Array*); -Iterator* APS5_VABI _ZNK3sce4Json6Object5beginEv(Iterator*, const Object*); -void APS5_VABI _ZN3sce4Json5Array8iteratorC1ERKS2_(Iterator*, const Iterator*); -void APS5_VABI _ZN3sce4Json6Object8iteratorC1ERKS2_(Iterator*, const Iterator*); -void APS5_VABI _ZN3sce4Json5Array8iteratorD1Ev(Iterator*); -void APS5_VABI _ZN3sce4Json6Object8iteratorD1Ev(Iterator*); -void APS5_VABI _ZN3sce4Json5Value4swapERS1_(Value*, Value*); -void APS5_VABI _ZN3sce4Json5ValueC1Ev(Value*); -void APS5_VABI _ZN3sce4Json5ValueC1EPKc(Value*, const char*); -void APS5_VABI _ZN3sce4Json5ValueC1ERKNS0_6StringE(Value*, const String*); -void APS5_VABI _ZN3sce4Json5ValueC1ERKNS0_5ArrayE(Value*, const Array*); -void APS5_VABI _ZN3sce4Json5ValueC1ERKNS0_6ObjectE(Value*, const Object*); -void APS5_VABI _ZN3sce4Json5ValueC1ENS0_9ValueTypeE(Value*, std::int32_t); -void APS5_VABI _ZN3sce4Json5ValueC1ERKS1_(Value*, const Value*); -void APS5_VABI _ZN3sce4Json5ValueD1Ev(Value*); -Value* APS5_VABI _ZN3sce4Json5ValueaSERKS1_(Value*, const Value*); -int APS5_VABI _ZN3sce4Json5Value3setERKNS0_5ArrayE(Value*, const Array*); -int APS5_VABI _ZN3sce4Json5Value3setERKNS0_6ObjectE(Value*, const Object*); -int APS5_VABI _ZN3sce4Json5Value3setENS0_9ValueTypeE(Value*, std::int32_t); -std::int32_t APS5_VABI _ZNK3sce4Json5Value7getTypeEv(const Value*); -const Array* APS5_VABI _ZNK3sce4Json5Value8getArrayEv(const Value*); -const Object* APS5_VABI _ZNK3sce4Json5Value9getObjectEv(const Value*); -int APS5_VABI _ZN3sce4Json5Value9serializeERNS0_6StringE(Value*, String*); -int APS5_VABI _ZN3sce4Json6Parser5parseERNS0_5ValueEPKcm(Value*, const char*, std::size_t); -void APS5_VABI _ZN3sce4Json6StringC1Ev(String*); -void APS5_VABI _ZN3sce4Json6StringC1EPKc(String*, const char*); -void APS5_VABI _ZN3sce4Json6StringD1Ev(String*); -const char* APS5_VABI _ZNK3sce4Json6String5c_strEv(const String*); -void APS5_VABI _ZN3sce4Json5ArrayC1Ev(Array*); -void APS5_VABI _ZN3sce4Json5ArrayC1ERKS1_(Array*, const Array*); -void APS5_VABI _ZN3sce4Json5ArrayD1Ev(Array*); -void APS5_VABI _ZN3sce4Json5Array9push_backERKNS0_5ValueE(Array*, const Value*); -std::size_t APS5_VABI _ZNK3sce4Json5Array4sizeEv(const Array*); -const Value* APS5_VABI _ZNK3sce4Json5Array5frontEv(const Array*); -void APS5_VABI _ZN3sce4Json6ObjectC1Ev(Object*); -void APS5_VABI _ZN3sce4Json6ObjectC1ERKS1_(Object*, const Object*); -void APS5_VABI _ZN3sce4Json6ObjectD1Ev(Object*); -Object* APS5_VABI _ZN3sce4Json6ObjectaSERKS1_(Object*, const Object*); -std::size_t APS5_VABI _ZNK3sce4Json6Object4sizeEv(const Object*); -void APS5_VABI _ZN3sce4Json6Object4PairC1ERKNS0_6StringERKNS0_5ValueE(Pair*, const String*, const Value*); -void APS5_VABI _ZN3sce4Json6Object4PairD1Ev(Pair*); -} +using namespace SceJson2; static std::ptrdiff_t allocationBudget = -1; static std::size_t liveAllocations = 0; @@ -95,9 +48,112 @@ static void Require(bool condition, const char* message) { static void CheckValue(const Value& value, const char* expected) { String output{}; _ZN3sce4Json6StringC1Ev(&output); + Require(_ZN3sce4Json5Value9serializeERNS0_6StringE(const_cast(&value), &output) == 0, "serialization failed"); Require(std::strcmp(_ZNK3sce4Json6String5c_strEv(&output), expected) == 0, "value changed"); _ZN3sce4Json6StringD1Ev(&output); + +} + +struct HandlerContext { + Value fallback{}; + const Value* parent = nullptr; + unsigned calls = 0; +}; + +static const Value& APS5_VABI OnTypeMismatch(ValueType requested, const Value* value, const Value* second, void* context) { + auto& handler = *static_cast(context); + Require(requested == 2 && value == handler.parent && second == nullptr, "handler arguments changed"); + ++handler.calls; + return handler.fallback; +} + +static void CheckHandler(HandlerContext& handler) { + Require(*_ZNK3sce4Json5Value10getIntegerEv(handler.parent) == 77 && handler.calls == 1, "handler was lost"); +} + +static int APS5_VABI ReadNext(char& character, void* context) { + auto& cursor = *static_cast(context); + character = *cursor; + if (!character) return -1; + ++cursor; + return 0; +} + +static bool Parse(const char* document, bool valid, bool callback, const char* expected = nullptr) { + Value result{}; + HandlerContext handler{}; + _ZN3sce4Json5ValueC1EPKc(&result, "previous"); + _ZN3sce4Json5ValueC1El(&handler.fallback, 77); + handler.parent = &result; + Require(_ZN3sce4Json5Value22setTypeMismatchHandlerEPFRKS1_NS0_9ValueTypeEPS2_S5_PvES6_(&result, OnTypeMismatch, &handler) == 0, "set handler failed"); + bool completed = false; + allocationBudget = activeBudget; + try { + const char* cursor = document; + const int status = callback ? _ZN3sce4Json6Parser5parseERNS0_5ValueEPFiRcPvES5_(&result, ReadNext, &cursor) + : _ZN3sce4Json6Parser5parseERNS0_5ValueEPKcm(&result, document, std::strlen(document)); + Require(status == (valid ? 0 : (callback ? -1 : static_cast(0x80848101))), "unexpected parse result"); + completed = true; + } catch (const std::bad_alloc&) { + } + allocationBudget = -1; + CheckValue(result, completed && valid ? (expected ? expected : document) : "\"previous\""); + CheckHandler(handler); + _ZN3sce4Json5ValueD1Ev(&result); + _ZN3sce4Json5ValueD1Ev(&handler.fallback); + return completed; +} + +static bool ObjectEntry(const char* keyText) { + Object object{}; + String oldKey{}, newKey{}; + HandlerContext handler{}; + _ZN3sce4Json6ObjectC1Ev(&object); + _ZN3sce4Json6StringC1EPKc(&oldKey, "kept"); + _ZN3sce4Json6StringC1EPKc(&newKey, keyText); + Value* kept = _ZN3sce4Json6ObjectixERKNS0_6StringE(&object, &oldKey); + Require(_ZN3sce4Json5Value3setEPKc(kept, "previous") == 0, "prepare entry failed"); + _ZN3sce4Json5ValueC1El(&handler.fallback, 77); + handler.parent = kept; + Require(_ZN3sce4Json5Value22setTypeMismatchHandlerEPFRKS1_NS0_9ValueTypeEPS2_S5_PvES6_(kept, OnTypeMismatch, &handler) == 0, "set handler failed"); + bool completed = false; + Value* inserted = nullptr; + allocationBudget = activeBudget; + try { + inserted = _ZN3sce4Json6ObjectixERKNS0_6StringE(&object, &newKey); + completed = true; + } catch (const std::bad_alloc&) { + } + allocationBudget = 0; + Require(_ZN3sce4Json6ObjectixERKNS0_6StringE(&object, &oldKey) == kept, "existing entry changed"); + allocationBudget = -1; + Require(_ZNK3sce4Json6Object4sizeEv(&object) == (completed ? 2 : 1), "failed insertion changed object size"); + if (completed) Require(inserted && _ZNK3sce4Json5Value7getTypeEv(inserted) == 0, "new entry is not null"); + CheckValue(*kept, "\"previous\""); + CheckHandler(handler); + _ZN3sce4Json6ObjectD1Ev(&object); + _ZN3sce4Json6StringD1Ev(&newKey); + _ZN3sce4Json6StringD1Ev(&oldKey); + _ZN3sce4Json5ValueD1Ev(&handler.fallback); + return completed; +} + +template +static unsigned CheckFailures(const char* name, TOperation operation) { + activeCase = name; + bool succeeded = false; + unsigned failures = 0; + for (activeBudget = 0; activeBudget < 256 && !succeeded; ++activeBudget) { + const auto before = liveAllocations; + succeeded = operation(); + if (liveAllocations != before) std::fprintf(stderr, "expected %zu live allocations, got %zu\n", before, liveAllocations); + Require(liveAllocations == before, "operation leaked allocations"); + failures += !succeeded; + } + Require(succeeded, "operation never succeeded"); + std::printf("%s: %u allocation failures, no leaks\n", name, failures); + return failures; } enum class Operation { @@ -115,6 +171,7 @@ static bool Run(Operation operation, const Value& source, const char* expected, const bool typeSetter = operation == Operation::SetTypeArray || operation == Operation::SetTypeObject || operation == Operation::SetTypeString; if (operation == Operation::ValueAssign || operation == Operation::SetArray || operation == Operation::SetObject || typeSetter) { _ZN3sce4Json5ValueC1EPKc(&result, "previous"); + valueReady = true; } if (operation == Operation::ArrayAppend) { _ZN3sce4Json5ArrayC1Ev(&arrayResult); arrayReady = true; } @@ -133,14 +190,14 @@ static bool Run(Operation operation, const Value& source, const char* expected, case Operation::ValueObject: _ZN3sce4Json5ValueC1ERKNS0_6ObjectE(&result, &object); valueReady = true; break; case Operation::ValueString: _ZN3sce4Json5ValueC1ERKNS0_6StringE(&result, &text); valueReady = true; break; case Operation::ValueText: _ZN3sce4Json5ValueC1EPKc(&result, _ZNK3sce4Json6String5c_strEv(&text)); valueReady = true; break; - case Operation::ValueTypeString: _ZN3sce4Json5ValueC1ENS0_9ValueTypeE(&result, 5); valueReady = true; break; - case Operation::ValueTypeArray: _ZN3sce4Json5ValueC1ENS0_9ValueTypeE(&result, 6); valueReady = true; break; - case Operation::ValueTypeObject: _ZN3sce4Json5ValueC1ENS0_9ValueTypeE(&result, 7); valueReady = true; break; + case Operation::ValueTypeString: _ZN3sce4Json5ValueC1ENS0_9ValueTypeE(&result, static_cast(5)); valueReady = true; break; + case Operation::ValueTypeArray: _ZN3sce4Json5ValueC1ENS0_9ValueTypeE(&result, static_cast(6)); valueReady = true; break; + case Operation::ValueTypeObject: _ZN3sce4Json5ValueC1ENS0_9ValueTypeE(&result, static_cast(7)); valueReady = true; break; case Operation::SetArray: _ZN3sce4Json5Value3setERKNS0_5ArrayE(&result, &array); break; case Operation::SetObject: _ZN3sce4Json5Value3setERKNS0_6ObjectE(&result, &object); break; - case Operation::SetTypeArray: _ZN3sce4Json5Value3setENS0_9ValueTypeE(&result, 6); break; - case Operation::SetTypeObject: _ZN3sce4Json5Value3setENS0_9ValueTypeE(&result, 7); break; - case Operation::SetTypeString: _ZN3sce4Json5Value3setENS0_9ValueTypeE(&result, 5); break; + case Operation::SetTypeArray: _ZN3sce4Json5Value3setENS0_9ValueTypeE(&result, static_cast(6)); break; + case Operation::SetTypeObject: _ZN3sce4Json5Value3setENS0_9ValueTypeE(&result, static_cast(7)); break; + case Operation::SetTypeString: _ZN3sce4Json5Value3setENS0_9ValueTypeE(&result, static_cast(5)); break; case Operation::PairCopy: _ZN3sce4Json6Object4PairC1ERKNS0_6StringERKNS0_5ValueE(&pair, &text, &source); pairReady = true; break; } succeeded = true; @@ -154,16 +211,19 @@ static bool Run(Operation operation, const Value& source, const char* expected, CheckValue(result, "\"previous\""); } _ZN3sce4Json5ValueD1Ev(&result); + } if (arrayReady) { const auto count = _ZNK3sce4Json5Array4sizeEv(&arrayResult); Require(count == (succeeded ? (operation == Operation::ArrayAppend ? 1 : 3) : 0), "array contents changed"); if (succeeded && operation == Operation::ArrayAppend) CheckValue(*_ZNK3sce4Json5Array5frontEv(&arrayResult), expected); _ZN3sce4Json5ArrayD1Ev(&arrayResult); + } if (objectReady) { Require(_ZNK3sce4Json6Object4sizeEv(&objectResult) == (succeeded ? 2 : 0), "object contents changed"); _ZN3sce4Json6ObjectD1Ev(&objectResult); + } if (pairReady) { CheckValue(pair.value, expected); _ZN3sce4Json6Object4PairD1Ev(&pair); } return succeeded; @@ -178,9 +238,11 @@ int main() { String text{}; _ZN3sce4Json5ValueC1Ev(&objectValue); _ZN3sce4Json5ValueC1Ev(&arrayValue); + Require(_ZN3sce4Json6Parser5parseERNS0_5ValueEPKcm(&objectValue, objectJson, std::strlen(objectJson)) == 0, "prepare object"); Require(_ZN3sce4Json6Parser5parseERNS0_5ValueEPKcm(&arrayValue, arrayJson, std::strlen(arrayJson)) == 0, "prepare array"); _ZN3sce4Json6StringC1EPKc(&text, "a sufficiently long string to require its own allocation"); + const auto* array = _ZNK3sce4Json5Value8getArrayEv(&arrayValue); const auto* object = _ZNK3sce4Json5Value9getObjectEv(&objectValue); struct Case { const char* name; Operation operation; const Value* source; const char* expected; }; @@ -208,31 +270,27 @@ int main() { }; unsigned failures = 0; for (const auto& test : cases) { - activeCase = test.name; - bool succeeded = false; - for (activeBudget = 0; activeBudget < 256 && !succeeded; ++activeBudget) { - const auto before = liveAllocations; - succeeded = Run(test.operation, *test.source, test.expected, *array, *object, text); - if (liveAllocations != before) std::fprintf(stderr, "expected %zu live allocations, got %zu\n", before, liveAllocations); - Require(liveAllocations == before, "copy leaked allocations"); - failures += !succeeded; + failures += CheckFailures(test.name, [&] { + const bool succeeded = Run(test.operation, *test.source, test.expected, *array, *object, text); CheckValue(objectValue, objectJson); CheckValue(arrayValue, arrayJson); - } - Require(succeeded, "copy never succeeded"); + return succeeded; + }); } - for (bool objectIterator : {false, true}) { + const auto checkIterator = [&]() { + constexpr bool objectIterator = TObject; + using TIterator = std::conditional_t; activeCase = objectIterator ? "object iterator copy" : "array iterator copy"; const auto before = liveAllocations; - Iterator source{}; - if (objectIterator) _ZNK3sce4Json6Object5beginEv(&source, object); + TIterator source{}; + if constexpr (objectIterator) _ZNK3sce4Json6Object5beginEv(&source, object); else _ZNK3sce4Json5Array5beginEv(&source, array); for (activeBudget = 0; activeBudget <= 1; ++activeBudget) { - Iterator copy{}; + TIterator copy{}; bool succeeded = false; allocationBudget = activeBudget; try { - if (objectIterator) _ZN3sce4Json6Object8iteratorC1ERKS2_(©, &source); + if constexpr (objectIterator) _ZN3sce4Json6Object8iteratorC1ERKS2_(©, &source); else _ZN3sce4Json5Array8iteratorC1ERKS2_(©, &source); succeeded = true; } catch (const std::bad_alloc&) { @@ -241,13 +299,15 @@ int main() { allocationBudget = -1; Require(succeeded == (activeBudget == 1), "iterator allocation failure ignored"); if (succeeded) Require(copy.state != source.state, "iterator copy shares owned storage"); - if (objectIterator) _ZN3sce4Json6Object8iteratorD1Ev(©); + if constexpr (objectIterator) _ZN3sce4Json6Object8iteratorD1Ev(©); else _ZN3sce4Json5Array8iteratorD1Ev(©); } - if (objectIterator) _ZN3sce4Json6Object8iteratorD1Ev(&source); + if constexpr (objectIterator) _ZN3sce4Json6Object8iteratorD1Ev(&source); else _ZN3sce4Json5Array8iteratorD1Ev(&source); Require(liveAllocations == before, "iterator copy leaked allocations"); - } + }; + checkIterator.operator()(); + checkIterator.operator()(); activeCase = "value swap"; bool swapSucceeded = false; for (activeBudget = 0; activeBudget < 256 && !swapSucceeded; ++activeBudget) { @@ -255,9 +315,11 @@ int main() { Value first{}, second{}; _ZN3sce4Json5ValueC1ERKS1_(&first, &objectValue); _ZN3sce4Json5ValueC1ERKS1_(&second, &arrayValue); + allocationBudget = activeBudget; try { _ZN3sce4Json5Value4swapERS1_(&first, &second); + swapSucceeded = true; } catch (const std::bad_alloc&) { ++failures; @@ -269,14 +331,36 @@ int main() { } _ZN3sce4Json5ValueD1Ev(&first); _ZN3sce4Json5ValueD1Ev(&second); + Require(liveAllocations == before, "swap leaked allocations"); CheckValue(objectValue, objectJson); CheckValue(arrayValue, arrayJson); } Require(swapSucceeded, "swap never succeeded"); + struct ParseCase { const char* name; const char* document; bool valid; bool callback; const char* expected = nullptr; }; + const ParseCase parseCases[] = { + {"parse empty array", "[]", true, false}, + {"parse empty object", "{}", true, false}, + {"parse array", "[1]", true, false}, + {"parse object", "{\"a\":1}", true, false}, + {"parse nested array", arrayJson, true, false}, + {"parse nested object", objectJson, true, false}, + {"parse long key", "{\"a sufficiently long key to require its own allocation\":{\"child\":[1,2]}}", true, false}, + {"parse invalid array", "[1,{\"a\":[true,null]}", false, false}, + {"parse invalid object", "{\"a\":[{\"b\":\"a sufficiently long string allocation\"},[true,null,17]]", false, false}, + {"parse trailing input", "{\"a\":[1]}x", true, false, "{\"a\":[1]}"}, + {"parse callback", objectJson, true, true}, + {"parse invalid callback", "[{\"a\":[1]}", false, true}, + }; + for (const auto& test : parseCases) + failures += CheckFailures(test.name, [&] { return Parse(test.document, test.valid, test.callback, test.expected); }); + failures += CheckFailures("insert short key", [] { return ObjectEntry("missing"); }); + failures += CheckFailures("insert long key", [&] { return ObjectEntry(_ZNK3sce4Json6String5c_strEv(&text)); }); _ZN3sce4Json6StringD1Ev(&text); _ZN3sce4Json5ValueD1Ev(&arrayValue); _ZN3sce4Json5ValueD1Ev(&objectValue); + Require(liveAllocations == initial, "source cleanup leaked allocations"); - std::printf("JSON copy cleanup: %zu operations, %u allocation failures, no leaks\n", sizeof(cases) / sizeof(cases[0]) + 3, failures); + std::printf("JSON allocation cleanup: %zu operations, %u allocation failures, no leaks\n", + sizeof(cases) / sizeof(cases[0]) + sizeof(parseCases) / sizeof(parseCases[0]) + 5, failures); } diff --git a/core/libs/tests/KernelError.cpp b/core/libs/tests/KernelError.cpp index 9355bd4b64..52c41c28db 100644 --- a/core/libs/tests/KernelError.cpp +++ b/core/libs/tests/KernelError.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "prx/libkernel/KernelErrors.hpp" #include @@ -6,9 +8,6 @@ #include #include -extern "C" std::int32_t APS5_VABI sceKernelError(std::int32_t); -extern "C" int* APS5_VABI __error_nid_postfix(); - static void Require(bool value) { if (!value) throw std::runtime_error("Kernel error conversion check failed"); } int main() { diff --git a/core/libs/tests/Mspace.cpp b/core/libs/tests/Mspace.cpp index 0741744299..a50f82f104 100644 --- a/core/libs/tests/Mspace.cpp +++ b/core/libs/tests/Mspace.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include @@ -8,42 +9,6 @@ #include #include -extern "C" { -int* APS5_VABI __error_nid_postfix(); -void* APS5_VABI sceLibcMspaceCreate_nid_postfix(const char*, void*, std::size_t, unsigned); -int APS5_VABI sceLibcMspaceDestroy_nid_postfix(void*); -void* APS5_VABI sceLibcMspaceMalloc_nid_postfix(void*, std::size_t); -void* APS5_VABI sceLibcMspaceCalloc_nid_postfix(void*, std::size_t, std::size_t); -void* APS5_VABI sceLibcMspaceRealloc_nid_postfix(void*, void*, std::size_t); -void APS5_VABI sceLibcMspaceFree_nid_postfix(void*, void*); -int APS5_VABI sceLibcMspacePosixMemalign_nid_postfix(void*, void**, std::size_t, std::size_t); -std::size_t APS5_VABI sceLibcMspaceMallocUsableSize_nid_postfix(const void*); -void* APS5_VABI sceLibcMspaceMemalign_nid_postfix(void*, std::size_t, std::size_t); -void* APS5_VABI sceLibcMspaceAlignedAlloc_nid_postfix(void*, std::size_t, std::size_t); -void* APS5_VABI sceLibcMspaceReallocalign_nid_postfix(void*, void*, std::size_t, std::size_t); -int APS5_VABI sceLibcMspaceMallocStats_nid_postfix(void*, void*); -int APS5_VABI sceLibcMspaceMallocStatsFast_nid_postfix(void*, void*); -void* APS5_VABI sceLibcPafMspaceCreate_nid_postfix(const char*, void*, std::size_t, unsigned, const void*); -int APS5_VABI sceLibcPafMspaceDestroy_nid_postfix(void*); -void* APS5_VABI sceLibcPafMspaceMalloc_nid_postfix(void*, std::size_t, const void*); -void APS5_VABI sceLibcPafMspaceFree_nid_postfix(void*, void*, const void*); -void* APS5_VABI sceLibcPafMspaceCalloc_nid_postfix(void*, std::size_t, std::size_t, const void*); -void* APS5_VABI sceLibcPafMspaceRealloc_nid_postfix(void*, void*, std::size_t, const void*); -void* APS5_VABI sceLibcPafMspaceReallocalign_nid_postfix(void*, void*, std::size_t, std::size_t, const void*); -void* APS5_VABI sceLibcPafMspaceMemalign_nid_postfix(void*, std::size_t, std::size_t, const void*); -int APS5_VABI sceLibcPafMspacePosixMemalign_nid_postfix(void*, void**, std::size_t, std::size_t, const void*); -int APS5_VABI sceLibcPafMspaceMallocStats_nid_postfix(void*, void*); -int APS5_VABI sceLibcPafMspaceMallocStatsFast_nid_postfix(void*, void*); -} -struct MallocManagedSize { - std::uint16_t size; - std::uint16_t version; - std::uint32_t reserved; - std::size_t maxSystemSize; - std::size_t currentSystemSize; - std::size_t maxInuseSize; - std::size_t currentInuseSize; -}; static void Require(bool value) { if (!value) { std::fputs("Mspace check failed\n", stderr); std::abort(); } } @@ -87,6 +52,7 @@ static void CheckPaf() { sceLibcPafMspaceFree_nid_postfix(arena, aligned, &owner); sceLibcPafMspaceFree_nid_postfix(arena, posixAligned, &owner); sceLibcPafMspaceFree_nid_postfix(arena, nullptr, &owner); + Require(sceLibcPafMspaceDestroy_nid_postfix(arena) == 0); Require(sceLibcPafMspaceDestroy_nid_postfix(arena) == -1); } @@ -205,14 +171,17 @@ int main() { Require(sceLibcMspaceCalloc_nid_postfix(arena, std::numeric_limits::max(), 2) == nullptr); sceLibcMspaceFree_nid_postfix(arena, blocker); sceLibcMspaceFree_nid_postfix(arena, aligned); + Require(sceLibcMspaceRealloc_nid_postfix(arena, grown, 0) == nullptr); void* large = sceLibcMspaceMalloc_nid_postfix(arena, storage.size() - 256); Require(large != nullptr); // freeing coalesced all the fragmented blocks sceLibcMspaceFree_nid_postfix(arena, large); + void* head = sceLibcMspaceMalloc_nid_postfix(arena, 64); Require(head != nullptr && sceLibcMspaceRealloc_nid_postfix(arena, head, 1024) == head); Require(sceLibcMspaceMallocUsableSize_nid_postfix(head) == 1024); sceLibcMspaceFree_nid_postfix(arena, head); + std::array small{}; for (auto& pointer : small) { pointer = sceLibcMspaceMalloc_nid_postfix(arena, 16); @@ -224,6 +193,7 @@ int main() { large = sceLibcMspaceMalloc_nid_postfix(arena, storage.size() - 256); Require(large != nullptr); sceLibcMspaceFree_nid_postfix(arena, large); + std::array workers; for (auto& worker : workers) worker = std::thread([&] { for (int i = 0; i < 1000; ++i) { @@ -232,6 +202,7 @@ int main() { std::memset(pointer, 42, 97); Require(sceLibcMspaceMallocUsableSize_nid_postfix(pointer) >= 97); sceLibcMspaceFree_nid_postfix(arena, pointer); + } }); for (auto& worker : workers) worker.join(); @@ -263,6 +234,7 @@ int main() { Require(rounded && (reinterpret_cast(rounded) & 127) == 0); Require(sceLibcMspaceMallocStatsFast_nid_postfix(arena, &stats) == 0 && stats.currentInuseSize >= 100); sceLibcMspaceFree_nid_postfix(arena, memaligned); + void* region = sceLibcMspaceMalloc_nid_postfix(arena, 8192); Require(region != nullptr); Require(sceLibcMspaceCreate_nid_postfix("outside", static_cast(region) + 8192, 4096, 0) == nullptr); @@ -274,6 +246,7 @@ int main() { Require(sceLibcMspaceCreate_nid_postfix("flags", storage.data(), storage.size(), 2) == nullptr); Require(sceLibcMspaceDestroy_nid_postfix(nested) == 0); sceLibcMspaceFree_nid_postfix(arena, region); + Require(sceLibcMspaceDestroy_nid_postfix(arena) == 0); Require(sceLibcMspaceMalloc_nid_postfix(arena, 8) == nullptr); Require(sceLibcMspaceCreate_nid_postfix("reuse", storage.data(), storage.size(), 0) == arena); diff --git a/core/libs/tests/NetBlockingSend.cpp b/core/libs/tests/NetBlockingSend.cpp index 466cbc279a..6dba4d4900 100644 --- a/core/libs/tests/NetBlockingSend.cpp +++ b/core/libs/tests/NetBlockingSend.cpp @@ -130,6 +130,14 @@ int main(int argc, char** argv) { { Connection connection; auto sending = std::async(std::launch::async, [&] { return Send(api, connection.sender, bytes); }); + const auto entered = std::chrono::steady_clock::now() + std::chrono::seconds(5); + char peeked = 0; + bool arrived = false; + while (!arrived && std::chrono::steady_clock::now() < entered) { + arrived = sceNetRecv(connection.receiver, &peeked, 1, NET_MSG_PEEK | NET_MSG_DONTWAIT) > 0; + if (!arrived) std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } + Require(arrived, "send did not reach the receiver before abort"); Require(sending.wait_for(std::chrono::milliseconds(50)) == std::future_status::timeout, "send did not wait before abort"); Require(sceNetSocketAbort(connection.sender, 0) == 0, "abort a blocked send"); Require(sending.wait_for(std::chrono::seconds(2)) == std::future_status::ready, "abort did not wake a blocked send"); diff --git a/core/libs/tests/NetDontWait.cpp b/core/libs/tests/NetDontWait.cpp index 7507f2fde5..c91b7d0bb7 100644 --- a/core/libs/tests/NetDontWait.cpp +++ b/core/libs/tests/NetDontWait.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libSceNet/include/Net.hpp" #include "SceTypes.hpp" #include #include @@ -12,42 +14,6 @@ #include #include -struct NetIovec { - void* base; - std::uint64_t length; -}; - -struct NetMsghdr { - void* name; - std::uint32_t nameLength; - NetIovec* iov; - int iovLength; - void* control; - std::uint32_t controlLength; - int flags; -}; - -extern "C" { -int APS5_VABI sceNetSocket(const char*, int, int, int); -int APS5_VABI sceNetSocketClose(int); -int APS5_VABI sceNetSocketAbort(int, int); -int APS5_VABI sceNetBind_nid_postfix(int, const void*, std::uint32_t); -int APS5_VABI sceNetGetsockname(int, void*, std::uint32_t*); -int APS5_VABI sceNetListen(int, int); -int APS5_VABI sceNetConnect(int, const void*, std::uint32_t); -int APS5_VABI sceNetAccept(int, void*, std::uint32_t*); -int APS5_VABI sceNetSetsockopt(int, int, int, const void*, std::uint32_t); -int APS5_VABI sceNetGetsockopt(int, int, int, void*, std::uint32_t*); -std::int64_t APS5_VABI sceNetSend(int, const void*, std::size_t, int); -std::int64_t APS5_VABI sceNetSendto(int, const void*, std::size_t, int, const void*, std::uint32_t); -std::int64_t APS5_VABI sceNetSendmsg(int, const NetMsghdr*, int); -std::int64_t APS5_VABI sceNetRecv(int, void*, std::size_t, int); -std::int64_t APS5_VABI sceNetRecvfrom(int, void*, std::size_t, int, void*, std::uint32_t*); -std::int64_t APS5_VABI sceNetRecvmsg(int, NetMsghdr*, int); -int* APS5_VABI sceNetErrnoLoc(); -int APS5_VABI fcntl_nid_postfix(int, int, ...); -} - namespace { constexpr int DontWait = 0x80; diff --git a/core/libs/tests/NetEmptyStream.cpp b/core/libs/tests/NetEmptyStream.cpp index af88d91872..5757b2bdb1 100644 --- a/core/libs/tests/NetEmptyStream.cpp +++ b/core/libs/tests/NetEmptyStream.cpp @@ -1,4 +1,4 @@ -#include "SceTypes.hpp" +#include "prx/libSceNet/libSceNet.hpp" #include #include #include @@ -8,38 +8,6 @@ #include #include -struct NetIovec { - void* base; - std::uint64_t length; -}; - -struct NetMsghdr { - void* name; - std::uint32_t nameLength; - NetIovec* iov; - int iovLength; - void* control; - std::uint32_t controlLength; - int flags; -}; - -extern "C" { -int APS5_VABI sceNetSocket(const char*, int, int, int); -int APS5_VABI sceNetSocketClose(int); -int APS5_VABI sceNetBind_nid_postfix(int, const void*, std::uint32_t); -int APS5_VABI sceNetGetsockname(int, void*, std::uint32_t*); -int APS5_VABI sceNetListen(int, int); -int APS5_VABI sceNetConnect(int, const void*, std::uint32_t); -int APS5_VABI sceNetAccept(int, void*, std::uint32_t*); -int APS5_VABI sceNetSetsockopt(int, int, int, const void*, std::uint32_t); -std::int64_t APS5_VABI sceNetSend(int, const void*, std::size_t, int); -std::int64_t APS5_VABI sceNetSendto(int, const void*, std::size_t, int, const void*, std::uint32_t); -std::int64_t APS5_VABI sceNetRecv(int, void*, std::size_t, int); -std::int64_t APS5_VABI sceNetRecvfrom(int, void*, std::size_t, int, void*, std::uint32_t*); -std::int64_t APS5_VABI sceNetRecvmsg(int, NetMsghdr*, int); -int* APS5_VABI sceNetErrnoLoc(); -} - namespace { void Require(bool value, const char* message) { @@ -104,9 +72,9 @@ Result Receive(std::string_view api, int descriptor, int flags, bool nullBuffer, NetMsghdr message{address.data(), addressLength, nullBuffer ? nullptr : &vector, nullBuffer ? 0 : 1, &control, 1, 0x4000}; count = sceNetRecvmsg(descriptor, &message, flags); if (count >= 0) { - Require(message.controlLength == 0, "control length is not zero"); + Require(message.control_length == 0, "control length is not zero"); Require(message.flags == (datagram ? 0x10 : 0), "unexpected output flags"); - addressLength = message.nameLength; + addressLength = message.name_length; } } const int error = *sceNetErrnoLoc(); diff --git a/core/libs/tests/PthreadStart.cpp b/core/libs/tests/PthreadStart.cpp index 8750d5eb5e..8dac3f063a 100644 --- a/core/libs/tests/PthreadStart.cpp +++ b/core/libs/tests/PthreadStart.cpp @@ -1,3 +1,5 @@ +#include "prx/libkernel/include/Api.hpp" +#include "prx/libkernel/Pthread/include/ThreadLifecycle.hpp" #include "prx/libkernel/Pthread/include/Pthread.hpp" #include #include @@ -6,17 +8,6 @@ #include #endif -extern "C" int APS5_VABI scePthreadCreate(Pthread* thread, const PthreadAttr* attr, PthreadEntry entry, void* arg, const char* name); -extern "C" int APS5_VABI scePthreadJoin(Pthread thread, void** retval); -extern "C" int APS5_VABI scePthreadAttrInit(PthreadAttr* attr); -extern "C" int APS5_VABI scePthreadAttrDestroy(PthreadAttr* attr); -extern "C" int APS5_VABI scePthreadAttrGet(Pthread thread, PthreadAttr* attr); -extern "C" int APS5_VABI scePthreadAttrSetstacksize(PthreadAttr* attr, std::size_t size); -extern "C" int APS5_VABI scePthreadAttrGetstack(const PthreadAttr* attr, void** address, std::size_t* size); -extern "C" Pthread APS5_VABI scePthreadSelf(); -extern "C" void APS5_VABI scePthreadExit(void* retval); -extern "C" int APS5_VABI scePthreadDetach(Pthread thread); - struct ThreadContext { Pthread thread = nullptr; std::promise checked; diff --git a/core/libs/tests/SaveDataMemoryGrowth.cpp b/core/libs/tests/SaveDataMemoryGrowth.cpp index 87d06e2a33..908bc48688 100644 --- a/core/libs/tests/SaveDataMemoryGrowth.cpp +++ b/core/libs/tests/SaveDataMemoryGrowth.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceSaveData/include/Api.hpp" #include "SceTypes.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -12,12 +13,6 @@ #include #endif -extern "C" { -int APS5_VABI sceSaveDataInitialize3(const void*); -int APS5_VABI sceSaveDataTerminate(); -int APS5_VABI sceSaveDataSetupSaveDataMemory2(const SaveDataMemorySetup2*, SaveDataMemorySetupResult*); -} - static void Check(bool value, int line) { if (!value) { std::fprintf(stderr, "Save-data memory growth check failed at line %d\n", line); diff --git a/core/libs/tests/SaveDataMemoryJournal.cpp b/core/libs/tests/SaveDataMemoryJournal.cpp index e661a1fd1f..b1af602123 100644 --- a/core/libs/tests/SaveDataMemoryJournal.cpp +++ b/core/libs/tests/SaveDataMemoryJournal.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceSaveData/include/Api.hpp" #include "SceTypes.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include @@ -13,14 +14,6 @@ #include #include -extern "C" { -int APS5_VABI sceSaveDataInitialize3(const void*); -int APS5_VABI sceSaveDataTerminate(); -int APS5_VABI sceSaveDataGetSaveDataMemory2(SaveDataMemoryGet2*); -int APS5_VABI sceSaveDataSetSaveDataMemory2(const SaveDataMemorySet2*); -int APS5_VABI sceSaveDataSetupSaveDataMemory2(const SaveDataMemorySetup2*, SaveDataMemorySetupResult*); -} - static void Check(bool value, int line) { if (!value) { std::fprintf(stderr, "Save-data memory journal check failed at line %d\n", line); diff --git a/core/libs/tests/SaveDataMemoryMetadata.cpp b/core/libs/tests/SaveDataMemoryMetadata.cpp index b3acb20559..f498a26fef 100644 --- a/core/libs/tests/SaveDataMemoryMetadata.cpp +++ b/core/libs/tests/SaveDataMemoryMetadata.cpp @@ -1,3 +1,5 @@ +#include "prx/libSceSaveData/include/Api.hpp" +#include "prx/libSceSaveData.native/include/Api.hpp" #include "SceTypes.hpp" #include #include @@ -25,16 +27,6 @@ #include #endif -extern "C" { -int APS5_VABI sceSaveDataInitialize3(const void*); -int APS5_VABI sceSaveDataTerminate(); -int APS5_VABI sceSaveDataCreateTransactionResource(std::uint32_t); -int APS5_VABI sceSaveDataDeleteTransactionResource(std::int32_t); -int APS5_VABI sceSaveDataSetSaveDataMemory2(const SaveDataMemorySet2*); -int APS5_VABI sceSaveDataSyncSaveDataMemory(const void*); -int APS5_VABI sceSaveDataSetupSaveDataMemory2(const SaveDataMemorySetup2*, SaveDataMemorySetupResult*); -} - namespace { constexpr int kSaveDataNotInitialized = -2137063423; } diff --git a/core/libs/tests/SaveDataWriteReplacement.cpp b/core/libs/tests/SaveDataWriteReplacement.cpp index e874060c9f..ef57bfe136 100644 --- a/core/libs/tests/SaveDataWriteReplacement.cpp +++ b/core/libs/tests/SaveDataWriteReplacement.cpp @@ -1,3 +1,4 @@ +#include "prx/libSceSaveData/include/Api.hpp" #include "SceTypes.hpp" #include "prx/libc/include/general/VabiMacros.hpp" @@ -13,11 +14,9 @@ #include extern "C" { -int APS5_VABI sceSaveDataInitialize3(const void*); -int APS5_VABI sceSaveDataTerminate(void); -int APS5_VABI sceSaveDataSetupSaveDataMemory2(const SaveDataMemorySetup2*, SaveDataMemorySetupResult*); + #ifndef SAVEDATA_NATIVE_BACKEND -int APS5_VABI sceSaveDataSyncSaveDataMemory(const void*); + #endif } diff --git a/core/libs/tests/SslContextLifetime.cpp b/core/libs/tests/SslContextLifetime.cpp new file mode 100644 index 0000000000..198e1c7cbe --- /dev/null +++ b/core/libs/tests/SslContextLifetime.cpp @@ -0,0 +1,182 @@ +#include "prx/libSceSsl/Export.cpp" + +#include +#include +#include +#include +#include +#include + +extern "C" bool KernelLookupSocketNative_nid_no_patch(int, std::shared_ptr*, std::uintptr_t*) { + std::fputs("unexpected native socket lookup in SSL lifetime test\n", stderr); + std::abort(); +} + +namespace { + +void Check(bool condition, const char* message) { + if (!condition) throw std::runtime_error(message); +} + +int CreateContext() { + const int id = sceSslInit_nid_postfix(1024 * 1024); + Check(id > 0, "context creation failed"); + return id; +} + +int CreateConnection(int context) { + const int id = sceSslCreateConnection(context, -1, "localhost"); + Check(id > 0, "connection creation failed"); + return id; +} + +void DeleteBeforeTerm() { + for (int cycle = 0; cycle < 3; ++cycle) { + const int context = CreateContext(); + const int connection = CreateConnection(context); + Check(sceSslDeleteConnection(connection) == 0, "delete before term failed"); + Check(sceSslTerm_nid_postfix(context) == 0, "term after delete failed"); + Check(State().connections.empty() && State().contexts.empty(), "delete-first cycle retained records"); + } + std::puts("SSL delete-first control: 3 cycles, no retained records"); +} + +void TermBeforeDelete() { + bool clean = true; + for (int cycle = 0; cycle < 3; ++cycle) { + const auto before = State().connections.size(); + const int context = CreateContext(); + const int connection = CreateConnection(context); + const auto created = State().connections.size(); + Check(sceSslTerm_nid_postfix(context) == 0, "term before delete failed"); + const auto terminated = State().connections.size(); + Check(sceSslDeleteConnection(connection) == ErrorInvalidId, "post-term delete result changed"); + const auto deleted = State().connections.size(); + Check(State().contexts.empty(), "context survived termination"); + clean = clean && before == 0 && created == 1 && terminated == 0 && deleted == 0; + std::printf("SSL term-first cycle %d: connections %zu -> %zu -> %zu -> %zu\n", cycle + 1, before, created, terminated, deleted); + } + Check(clean, "termination retained orphan connection records"); +} + +void SeparateContexts() { + const int first = CreateContext(); + const int second = CreateContext(); + const int firstConnection = CreateConnection(first); + const int secondConnection = CreateConnection(second); + const int extraConnection = CreateConnection(first); + std::weak_ptr lifetime = State().contexts.at(first); + Check(sceSslTerm_nid_postfix(first) == 0, "selective term failed"); + Check(lifetime.expired(), "idle terminated context survived"); + Check(State().connections.size() == 1 && State().connections.contains(secondConnection), "term did not isolate connection ownership"); + Check(!State().connections.contains(firstConnection) && !State().connections.contains(extraConnection), "term retained a child connection"); + Check(sceSslTerm_nid_postfix(first) == ErrorInvalidId, "repeated term result changed"); + Check(sceSslCreateConnection(first, -1, "localhost") == ErrorInvalidId, "create accepted a terminated context"); + Check(sceSslDeleteConnection(firstConnection) == ErrorInvalidId, "delete accepted a terminated connection"); + Check(sceSslSetVerifyCallback(firstConnection, nullptr, nullptr) == ErrorInvalidId, "callback accepted a terminated connection"); + Check(sceSslConnect(firstConnection) == ErrorInvalidId && sceSslClose(firstConnection) == ErrorInvalidId, "I/O accepted a terminated connection"); + Check(sceSslSetVerifyCallback(secondConnection, nullptr, nullptr) == 0, "term invalidated another context's connection"); + Check(sceSslDeleteConnection(secondConnection) == 0 && sceSslTerm_nid_postfix(second) == 0, "unrelated context cleanup failed"); + Check(State().connections.empty() && State().contexts.empty(), "selective term retained records"); +} + +void ConcurrentLifecycle() { + for (int cycle = 0; cycle < 32; ++cycle) { + const int context = CreateContext(); + std::array connections{}; + for (auto& id : connections) id = CreateConnection(context); + std::barrier start(3); + std::atomic valid{true}; + std::thread creator([&] { + start.arrive_and_wait(); + for (int attempt = 0; attempt < 16; ++attempt) { + const int id = sceSslCreateConnection(context, -1, "localhost"); + if (id == ErrorInvalidId) continue; + if (id <= 0) { valid = false; continue; } + const int result = sceSslDeleteConnection(id); + if (result != 0 && result != ErrorInvalidId) valid = false; + } + }); + std::thread deleter([&] { + start.arrive_and_wait(); + for (const auto id : connections) { + const int result = sceSslDeleteConnection(id); + if (result != 0 && result != ErrorInvalidId) valid = false; + } + }); + start.arrive_and_wait(); + const int result = sceSslTerm_nid_postfix(context); + creator.join(); + deleter.join(); + Check(result == 0 && valid, "concurrent lifecycle returned an unexpected error"); + Check(State().connections.empty() && State().contexts.empty(), "concurrent termination retained records"); + } + std::puts("SSL concurrent create/delete/term: 32 cycles, no retained records"); +} + +struct CallbackState { + std::latch entered{1}; + std::latch resume{1}; + int context = 0; + bool valid = false; +}; + +int APS5_VABI PendingCallback(int context, unsigned int, void**, int count, void* argument) { + auto& state = *static_cast(argument); + state.valid = context == state.context && count == 0; + state.entered.count_down(); + state.resume.wait(); + return 0; +} + +void InFlightSession() { + const int context = CreateContext(); + const int connection = CreateConnection(context); + auto owner = State().contexts.at(context); + std::weak_ptr contextLifetime = owner; + auto session = std::make_shared(context, owner, std::shared_ptr{}, 0); + { + PoolScope scope(owner->pool); + session->Configure("localhost", "", InitialVerifyOptions); + } + Check(owner->pool.current > 0, "session did not allocate backend state"); + session->verified = true; + session->verifyResult = ErrorCallbackCheck; + State().connections.at(connection).session = session; + std::weak_ptr sessionLifetime = session; + CallbackState callback; + callback.context = context; + Check(sceSslSetVerifyCallback(connection, PendingCallback, &callback) == 0, "callback setup failed"); + owner.reset(); + session.reset(); + int operationResult = ErrorInvalidId; + std::thread operation([&] { operationResult = sceSslConnect(connection); }); + callback.entered.wait(); + const int result = sceSslTerm_nid_postfix(context); + const bool removed = State().connections.empty() && State().contexts.empty(); + const bool retained = !sessionLifetime.expired() && !contextLifetime.expired(); + callback.resume.count_down(); + operation.join(); + Check(result == 0 && removed, "term did not remove the in-flight connection"); + Check(retained, "term destroyed an in-flight session or its pool"); + Check(callback.valid && operationResult == 0, "in-flight verification callback did not finish"); + Check(sessionLifetime.expired() && contextLifetime.expired(), "finished operation retained its session or pool"); + Check(sceSslConnect(connection) == ErrorInvalidId && sceSslDeleteConnection(connection) == ErrorInvalidId, "post-term connection became usable"); + std::puts("SSL in-flight callback completed; session and pool released after completion"); +} + +} + +int main() { + try { + DeleteBeforeTerm(); + TermBeforeDelete(); + SeparateContexts(); + ConcurrentLifecycle(); + InFlightSession(); + std::puts("SSL context lifetime passed"); + } catch (const std::exception& error) { + std::fprintf(stderr, "SSL context lifetime failed: %s\n", error.what()); + return 1; + } +} diff --git a/core/libs/tests/UnwindCallbackAbi.cpp b/core/libs/tests/UnwindCallbackAbi.cpp index 18fb85df1d..c0fbcbbc2b 100644 --- a/core/libs/tests/UnwindCallbackAbi.cpp +++ b/core/libs/tests/UnwindCallbackAbi.cpp @@ -1,3 +1,5 @@ +#include "prx/libc/include/exceptions/Runtime.hpp" +#include "prx/libc/include/Api.hpp" #include "prx/libc/include/exceptions/Unwind.hpp" #include @@ -5,11 +7,6 @@ #include #include -extern "C" _Unwind_Reason_Code APS5_VABI _Unwind_Backtrace_nid_postfix(_Unwind_Trace_Fn trace, void* argument); -extern "C" _Unwind_Reason_Code APS5_VABI _Unwind_ForcedUnwind_nid_postfix(_Unwind_Exception* exception, _Unwind_Stop_Fn stop, void* argument); -extern "C" _Unwind_Ptr APS5_VABI _Unwind_GetRegionStart_nid_postfix(_Unwind_Context* context); -extern "C" void* APS5_VABI __cxa_begin_catch_nid_postfix(void* exception); -extern "C" void APS5_VABI __cxa_end_catch_nid_postfix(); extern "C" [[gnu::noinline]] void BacktraceFromHere(); extern "C" [[gnu::noinline]] void ForceUnwindFromHere(); @@ -85,6 +82,7 @@ void CheckDeleteException() { exception.exception_class = ForeignClass; exception.exception_cleanup = GuestCleanup; _Unwind_DeleteException_nid_postfix(&exception); + CheckCleanup(exception); } @@ -94,6 +92,7 @@ void CheckEndCatch(std::uint64_t exceptionClass, Cleanup function) { exception.exception_cleanup = function; __cxa_begin_catch_nid_postfix(&exception); __cxa_end_catch_nid_postfix(); + CheckCleanup(exception); } @@ -110,6 +109,7 @@ extern "C" void ForceUnwindFromHere() { _Unwind_Exception exception {}; exception.exception_class = ForeignClass; _Unwind_ForcedUnwind_nid_postfix(&exception, Stop, &stopArgument); + Require(stop.count == 1, "_Unwind_ForcedUnwind calls the stop function once"); Require(stop.version == 1, "the stop function gets version 1"); Require(stop.actions == (_UA_CLEANUP_PHASE | _UA_FORCE_UNWIND), "the stop function gets _UA_CLEANUP_PHASE | _UA_FORCE_UNWIND"); diff --git a/core/libs/tests/WindowsBacktraceReport.cpp b/core/libs/tests/WindowsBacktraceReport.cpp index d16340e2b3..b7c91f7aa4 100644 --- a/core/libs/tests/WindowsBacktraceReport.cpp +++ b/core/libs/tests/WindowsBacktraceReport.cpp @@ -1,3 +1,4 @@ +#include "prx/libc/include/Api.hpp" #include #include #include @@ -6,8 +7,6 @@ #include "../prx/libc/include/general/VabiMacros.hpp" #include "../prx/libc/include/FailureReport.hpp" -extern "C" int* APS5_VABI __error_nid_postfix(); - namespace { void KeptReport() noexcept { diff --git a/core/libs/tests/test_public_headers.py b/core/libs/tests/test_public_headers.py new file mode 100644 index 0000000000..8aa05f692b --- /dev/null +++ b/core/libs/tests/test_public_headers.py @@ -0,0 +1,218 @@ +import argparse +import concurrent.futures +import importlib.util +import json +import re +import subprocess +import sys +from functools import cache +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[3] +LIBS = ROOT / "core/libs" +sys.dont_write_bytecode = True +SPEC = importlib.util.spec_from_file_location("nid_names", ROOT / "tools/nid_names.py") +NIDS = importlib.util.module_from_spec(SPEC) +SPEC.loader.exec_module(NIDS) +DECLARATION = re.compile(r"(?:\bAPS5_VABI\s+|^[ \t]*[A-Za-z_][\w:*&<> \t]*?[ \t]+)(\w+)\s*\([^;{}]*\)\s*(?:noexcept\s*)?;", re.M) +INCLUDE = re.compile(r'^\s*#\s*include\s*"([^"]+)"', re.M) +TYPE_TOKEN = re.compile(r"\bnamespace\s*([\w:]*)\s*\{|\bextern\s*\{|\b(?:struct|union|class)\s+(\w+)\s*([;{])|\busing\s+(\w+)\s*=|[{}]") + + +@cache +def code(text): + return NIDS.CPP_TOKEN.sub(lambda match: match.group() if match.group("code") else re.sub(r"[^\n]", " ", match.group()), text) + + +def declared_types(text): + scopes = [] + result = set() + for token in TYPE_TOKEN.finditer(text): + namespace, name, ending, alias = token.groups() + if namespace is not None: + scopes.append(namespace or None) + elif name or alias: + if None not in scopes: + result.add("::".join([scope for scope in scopes if scope] + [name or alias])) + if ending == "{": + scopes.append(name) + elif token.group().startswith("extern"): + scopes.append("") + elif token.group() == "{": + scopes.append(None) + elif scopes: + scopes.pop() + return result + + +@cache +def source_text(path): + return path.read_text(encoding="utf-8") + + +@cache +def included_headers(header): + result = [] + for name in INCLUDE.findall(source_text(header)): + candidates = {path.resolve() for path in (header.parent / name, LIBS / name) if path.is_file()} + if len(candidates) != 1: + raise RuntimeError(f"{header}: include {name} resolves to {len(candidates)} files") + result.append(candidates.pop()) + return result + + +def reachable(header, visited): + if header in visited: + return + visited.add(header) + for included in included_headers(header): + reachable(included, visited) + + +def exported_definitions(text): + text = text.replace("\\\n", "").replace("\\\r\n", "") + masked = code(text) + ranges = [] + for match in re.finditer(r"\bnamespace\s*\{", masked): + depth = 1 + end = match.end() + while depth and end < len(masked): + depth += (masked[end] == "{") - (masked[end] == "}") + end += 1 + ranges.append((match.start(), end)) + result = set() + position = 0 + parentheses = 0 + for match in NIDS.DEFINITION.finditer(masked): + prefix = masked[position:match.start()] + parentheses += prefix.count("(") - prefix.count(")") + position = match.start() + if parentheses: + continue + if any(start < match.start() < end for start, end in ranges): + continue + start = max(masked.rfind(delimiter, 0, match.start()) for delimiter in ";{}") + 1 + if re.search(r"\b(?:static|GCC_HIDDEN_FN)\b", masked[start:match.start()]): + continue + result.add(match.group(1)) + return result + + +def audit(): + umbrellas = sorted(path / f"{path.name}.hpp" for path in (LIBS / "prx").iterdir() if path.is_dir()) + if not umbrellas: + raise RuntimeError("No library umbrella headers found") + missing = [str(path.relative_to(ROOT)) for path in umbrellas if not path.is_file()] + if missing: + raise RuntimeError("Missing library umbrella headers: " + ", ".join(missing)) + exports = {} + for umbrella in umbrellas: + included = set() + reachable(umbrella.resolve(), included) + for source in NIDS.source_files(umbrella.parent): + if "tools" in source.relative_to(umbrella.parent).parts: + continue + text = source_text(source).replace("\\\n", "").replace("\\\r\n", "") + aliases = {name for nid, name in NIDS.source_aliases(text)} if "APS5_EXPORT" in text else set() + definitions = exported_definitions(text) + if any(macro in text for macro in NIDS.ASM_FUNCTION_MACROS): + definitions.update(NIDS.source_assembly_definitions(text)) + for name in definitions | aliases: + if name.endswith(("_nid_no_patch", "_nid_no_patch_cut")): + continue + exports.setdefault(name, []).append((source, included)) + declarations = {name: [] for name in exports} + for source in sorted((ROOT / "core").rglob("*")): + if source.suffix not in {".cpp", ".h", ".hpp"}: + continue + text = code(source_text(source)) + resolved = source.resolve() + for match in DECLARATION.finditer(text): + if match.group(1) not in declarations: + continue + prefix = match.group()[:match.start(1) - match.start()] + if re.search(r"\b(?:return|co_return|throw|else|case)\b|&&|\|\|", prefix): + continue + declarations[match.group(1)].append((resolved, text.count("\n", 0, match.start()) + 1)) + errors = [] + headers = set(umbrellas) + for name, definitions in exports.items(): + found = declarations[name] + if len(found) != 1 or found[0][0].suffix not in {".h", ".hpp"}: + locations = ", ".join(f"{path.relative_to(ROOT)}:{line}" for path, line in found) + errors.append(f"{name}: expected exactly one header declaration; found {len(found)}: {locations}") + continue + header = found[0][0] + headers.add(header) + for source, included in definitions: + if header not in included: + errors.append(f"{name}: {header.relative_to(ROOT)} is not included by {source.parent} library umbrella") + if errors: + raise RuntimeError("\n".join(errors)) + public_types = set() + for header in headers: + text = code(source_text(header)) + public_types.update(declared_types(text)) + for source in sorted((ROOT / "core").rglob("*.cpp")): + text = code(source_text(source)) + types = declared_types(text) + for name in sorted(public_types & types): + errors.append(f"{source.relative_to(ROOT)}: duplicate public type {name}; include its header") + if errors: + raise RuntimeError("\n".join(errors)) + return umbrellas, sorted(headers), len(exports) + + +def compile_headers(compiler, compiler_args, groups, workers=4): + macros = subprocess.run([compiler, *compiler_args, "-dM", "-E", "-x", "c++", "-"], input="", text=True, capture_output=True, check=True).stdout + warnings = ["-Werror"] + if re.search(r"^#define __clang__\b", macros, re.M): + warnings.append("-Wno-return-type-c-linkage") + + def compile_one(group): + includes = "".join(f'#include "{header.relative_to(LIBS).as_posix()}"\n' for header in group) + result = subprocess.run([compiler, *compiler_args, "-std=c++20", *warnings, "-fsyntax-only", "-x", "c++", f"-I{LIBS}", f"-I{ROOT / '3rdparty/freetype/include'}", "-"], input=includes * 2, text=True, capture_output=True) + if result.returncode: + raise RuntimeError(f"Header compilation failed: {group}\n{result.stdout}{result.stderr}") + + with concurrent.futures.ThreadPoolExecutor(max_workers=workers) as pool: + list(pool.map(compile_one, groups)) + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("--compiler") + parser.add_argument("--compiler-arg", action="append", default=[]) + parser.add_argument("--manifest", type=Path) + parser.add_argument("--audit-only", action="store_true") + parser.add_argument("--batch-index", type=int) + parser.add_argument("--batch-count", type=int, default=64) + args = parser.parse_args() + if args.batch_count < 1: + parser.error("--batch-count must be positive") + if args.audit_only and args.batch_index is not None: + parser.error("--audit-only cannot be combined with --batch-index") + if not args.audit_only and not args.compiler: + parser.error("--compiler is required for header compilation") + if args.batch_index is not None: + if not args.manifest or not 0 <= args.batch_index < args.batch_count: + parser.error("a batch requires --manifest and an index within --batch-count") + groups = [[LIBS / name for name in group] for group in json.loads(args.manifest.read_text(encoding="utf-8"))] + selected = groups[args.batch_index::args.batch_count] + if not selected: + raise RuntimeError("Header compilation batch is empty") + compile_headers(args.compiler, args.compiler_arg, selected, workers=1) + print(f"Batch {args.batch_index}: {len(selected)} header compilation units verified") + return + umbrellas, headers, count = audit() + groups = [[header] for header in headers] + [umbrellas] + if args.manifest: + args.manifest.write_text(json.dumps([[header.relative_to(LIBS).as_posix() for header in group] for group in groups]), encoding="utf-8") + print(f"{len(umbrellas)} libraries, {count} exports: unique declarations and umbrella coverage verified", flush=True) + if not args.audit_only: + compile_headers(args.compiler, args.compiler_arg, groups) + print("Standalone headers verified") + + +if __name__ == "__main__": + main() diff --git a/core/relinker/CMakeLists.txt b/core/relinker/CMakeLists.txt index 55968ce9c2..dd1f8daae6 100644 --- a/core/relinker/CMakeLists.txt +++ b/core/relinker/CMakeLists.txt @@ -576,6 +576,8 @@ if(BUILD_TESTING) ${CMAKE_CURRENT_SOURCE_DIR}/relinker/tests/test_linux_executable_exports.py $) add_test(NAME executable_tls_relocations COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/relinker/tests/test_executable_tls_relocations.py $) + add_test(NAME executable_export_bounds COMMAND ${Python3_EXECUTABLE} + ${CMAKE_CURRENT_SOURCE_DIR}/relinker/tests/test_executable_export_bounds.py $) add_test(NAME macos_empty_tls COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/relinker/tests/test_macos_empty_tls.py $) set_tests_properties(macos_empty_tls PROPERTIES TIMEOUT 60) @@ -782,6 +784,8 @@ if(BUILD_TESTING) ${CMAKE_CURRENT_SOURCE_DIR}/relinker/tests/test_call_registry.py $) add_test(NAME jmprel_table_bounds COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/relinker/tests/test_jmprel_table_bounds.py $) + add_test(NAME copy_relocations COMMAND ${Python3_EXECUTABLE} + ${CMAKE_CURRENT_SOURCE_DIR}/relinker/tests/test_copy_relocations.py $) if(WIN32) add_test(NAME windows_diagnostic_fixture_isolation COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/elfpatcher/tests/test_windows_diagnostic_fixture_isolation.py $) diff --git a/core/relinker/cli/include/NativeModules.hpp b/core/relinker/cli/include/NativeModules.hpp index 66139266ca..862acfcf0c 100644 --- a/core/relinker/cli/include/NativeModules.hpp +++ b/core/relinker/cli/include/NativeModules.hpp @@ -1,11 +1,13 @@ #pragma once #include +#include namespace Cli { struct NativeModules { std::filesystem::path Root; + std::vector Directories; std::vector RuntimeDirectories; std::vector Modules; }; @@ -14,4 +16,6 @@ bool SameDirectory(const std::filesystem::path& first, const std::filesystem::pa NativeModules ReadModules(const std::filesystem::path& inputPath, const std::filesystem::path& sceModulePath, const std::set& excludedModules, const std::vector& moduleDirectories); +void ReportUnconvertedNeeded(const NativeModules& modules, const std::vector& neededLibraries, bool foldCase, std::ostream& out); + } diff --git a/core/relinker/cli/src/CliArgs.cpp b/core/relinker/cli/src/CliArgs.cpp index 47166d9972..6ab190a572 100644 --- a/core/relinker/cli/src/CliArgs.cpp +++ b/core/relinker/cli/src/CliArgs.cpp @@ -22,7 +22,7 @@ namespace { constexpr std::string_view kVerifyRejectedOptions[] = { "--windows", "--macos", "--windows-gui", "--windows-diagnostics", "--windows-fixed-base", "--trace-imports", "--linux-fixed-base", "--macos-fixed-base", - "--to-intel", "--to-rosetta", "--skip-syscall-check", "--trap-sdk-syscall-stubs", "unused-filter=", + "--to-intel", "--to-rosetta", "--frame-red-zone", "--skip-syscall-check", "--trap-sdk-syscall-stubs", "unused-filter=", "--rpath", "--registry", "--lazy-binding", "--autorun", "--patches", "--no-patches", }; diff --git a/core/relinker/cli/src/NativeModules.cpp b/core/relinker/cli/src/NativeModules.cpp index f01ac374d4..6163063c69 100644 --- a/core/relinker/cli/src/NativeModules.cpp +++ b/core/relinker/cli/src/NativeModules.cpp @@ -2,13 +2,59 @@ #include #include #include +#include #include +#include #include #include #include +#include +#include +#include +#include namespace Cli { +namespace { + +struct CandidateHeader { + bool Elf = false; + bool Self = false; + std::uint16_t Type = 0; +}; + +std::optional TryReadCandidateHeader(const std::filesystem::path& path) { + std::ifstream stream(path, std::ios::binary); + if (!stream) return std::nullopt; + char header[18]{}; + stream.read(header, sizeof header); + if (stream.bad()) return std::nullopt; + CandidateHeader result; + if (stream.gcount() < 4) return result; + const auto byte = [&](const std::size_t index) { return static_cast(header[index]); }; + result.Self = (byte(0) == 0x4f && byte(1) == 0x15 && byte(2) == 0x3d && byte(3) == 0x1d) || (byte(0) == 0x54 && byte(1) == 0x14 && byte(2) == 0xf5 && byte(3) == 0xee); + result.Elf = byte(0) == 0x7f && header[1] == 'E' && header[2] == 'L' && header[3] == 'F'; + if (result.Elf && stream.gcount() == sizeof header) result.Type = static_cast(byte(16) | (byte(17) << 8)); + return result; +} + +CandidateHeader ReadCandidateHeader(const std::filesystem::path& path) { + const auto header = TryReadCandidateHeader(path); + if (!header) throw Domain::RelinkerException("Cannot read guest candidate: " + Io::Utf8Path(path)); + return *header; +} + +std::string FoldedName(std::string name, const bool foldCase) { + if (foldCase) for (auto& character : name) if (character >= 'A' && character <= 'Z') character = static_cast(character + ('a' - 'A')); + return name; +} + +std::string_view ModuleStem(const std::string_view name) { + return name.substr(0, name.size() - Domain::ModuleSuffix(name).size()); +} + +} + bool SameDirectory(const std::filesystem::path& first, const std::filesystem::path& second) { if (std::filesystem::exists(first) && std::filesystem::exists(second)) return std::filesystem::equivalent(first, second); return std::filesystem::weakly_canonical(first) == std::filesystem::weakly_canonical(second); @@ -45,17 +91,6 @@ NativeModules ReadModules(const std::filesystem::path& inputPath, const std::fil } std::vector paths; std::set unmatchedExclusions = excludedModules; - const auto isElf = [](const std::filesystem::path& path, bool& self) { - std::ifstream stream(path, std::ios::binary); - if (!stream) throw Domain::RelinkerException("Cannot read guest candidate: " + Io::Utf8Path(path)); - char magic[4]{}; - stream.read(magic, 4); - if (stream.bad()) throw Domain::RelinkerException("Cannot read guest candidate magic: " + Io::Utf8Path(path)); - if (stream.gcount() != 4) return false; - const auto byte = [&](const std::size_t index) { return static_cast(magic[index]); }; - self = (byte(0) == 0x4f && byte(1) == 0x15 && byte(2) == 0x3d && byte(3) == 0x1d) || (byte(0) == 0x54 && byte(1) == 0x14 && byte(2) == 0xf5 && byte(3) == 0xee); - return byte(0) == 0x7f && magic[1] == 'E' && magic[2] == 'L' && magic[3] == 'F'; - }; for (const auto& directory : directories) { if (!std::filesystem::is_directory(directory)) throw Domain::RelinkerException("Guest module path is not a directory: " + Io::Utf8Path(directory)); for (const auto& entry : std::filesystem::directory_iterator(directory)) { @@ -66,9 +101,9 @@ NativeModules ReadModules(const std::filesystem::path& inputPath, const std::fil } if (!entry.is_regular_file()) continue; if (Io::SameFile(entry.path(), inputPath)) continue; - bool self = false; - if (isElf(entry.path(), self)) paths.push_back(entry.path()); - else if (self) + const auto header = ReadCandidateHeader(entry.path()); + if (header.Elf) paths.push_back(entry.path()); + else if (header.Self) std::cout << "Skipping SELF container: " << entry.path().lexically_relative(root).generic_string() << " (unwrap it before relinking)\n"; } @@ -77,6 +112,7 @@ NativeModules ReadModules(const std::filesystem::path& inputPath, const std::fil std::sort(paths.begin(), paths.end()); NativeModules result; result.Root = root; + result.Directories = std::move(directories); result.RuntimeDirectories = std::move(runtimeDirectories); for (const auto& path : paths) result.Modules.push_back({path, Io::FileReader().Read(Io::Utf8Path(path))}); std::map sonames; @@ -107,4 +143,49 @@ NativeModules ReadModules(const std::filesystem::path& inputPath, const std::fil return result; } +void ReportUnconvertedNeeded(const NativeModules& modules, const std::vector& neededLibraries, const bool foldCase, std::ostream& out) { + std::map> stems; + for (const auto& name : neededLibraries) { + const auto folded = FoldedName(name, foldCase); + if (!Domain::ModuleSuffix(folded).empty()) stems[std::string(ModuleStem(folded))].push_back(name); + } + if (stems.empty()) return; + struct Found { + std::filesystem::path Relative; + std::string Name; + bool Self; + }; + std::vector found; + std::error_code error; + for (auto entry = std::filesystem::recursive_directory_iterator(modules.Root, std::filesystem::directory_options::skip_permission_denied, error); !error && entry != std::filesystem::recursive_directory_iterator(); entry.increment(error)) { + const bool directory = entry->is_directory(error); + if (error) { + error.clear(); + continue; + } + if (directory) { + if (std::any_of(modules.Directories.begin(), modules.Directories.end(), [&](const auto& scanned) { return std::filesystem::equivalent(scanned, entry->path(), error) && !error; })) entry.disable_recursion_pending(); + error.clear(); + continue; + } + const auto filename = FoldedName(Io::Utf8Path(entry->path().filename()), foldCase); + if (Domain::ModuleSuffix(filename).empty()) continue; + const auto stem = stems.find(std::string(ModuleStem(filename))); + if (stem == stems.end()) continue; + if (!entry->is_regular_file(error) || error) { + error.clear(); + continue; + } + const auto header = TryReadCandidateHeader(entry->path()); + if (!header || (!header->Self && !(header->Elf && header->Type == 0xfe18))) continue; + for (const auto& name : stem->second) found.push_back({entry->path().lexically_relative(modules.Root), name, header->Self}); + } + std::sort(found.begin(), found.end(), [](const auto& left, const auto& right) { return std::tie(left.Relative, left.Name) < std::tie(right.Relative, right.Name); }); + for (const auto& [relative, name, self] : found) { + const auto directory = relative.parent_path().generic_string(); + out << "Needed module not converted: " << name << " at " << relative.generic_string() << "; add --module-dir " << (directory.empty() ? "." : directory) + << (self ? " and unwrap the SELF container" : "") << '\n'; + } +} + } diff --git a/core/relinker/cli/tests/CliArgsTests.cpp b/core/relinker/cli/tests/CliArgsTests.cpp index 8f18c4c963..3cd3069dc1 100644 --- a/core/relinker/cli/tests/CliArgsTests.cpp +++ b/core/relinker/cli/tests/CliArgsTests.cpp @@ -322,7 +322,7 @@ void verifyMode() { expectThrows({"--verify-patches", "p.toml", "--verify-output", "out.elf", "--exclude-sce-module", "x.prx"}, noEffect); expectThrows({"--verify-patches", "p.toml", "--verify-output", "out.elf", "--skip-sce-module"}, noEffect); expectThrows({"--verify-patches", "p.toml", "in.elf", "extra"}, "unexpected argument: extra"); - for (const auto* option : {"--windows", "--macos", "--to-intel", "--to-rosetta", "--trace-imports", "--lazy-binding", "--autorun", "--registry", "--skip-syscall-check", "--no-patches"}) + for (const auto* option : {"--windows", "--macos", "--to-intel", "--to-rosetta", "--frame-red-zone", "--trace-imports", "--lazy-binding", "--autorun", "--registry", "--skip-syscall-check", "--no-patches"}) expectThrows({"--verify-patches", "p.toml", option, "in.elf"}, std::string(option) + " cannot be used with --verify-patches"); expectThrows({"--verify-patches", "p.toml", "--rpath", "x", "in.elf"}, "--rpath cannot be used with --verify-patches"); expectThrows({"--verify-patches", "p.toml", "--patches", "q.toml", "in.elf"}, "--patches cannot be used with --verify-patches"); diff --git a/core/relinker/codegen/src/x86/Sha1Operands.cpp b/core/relinker/codegen/src/x86/Sha1Operands.cpp index 69ea10a68a..aa49ed27d5 100644 --- a/core/relinker/codegen/src/x86/Sha1Operands.cpp +++ b/core/relinker/codegen/src/x86/Sha1Operands.cpp @@ -20,16 +20,18 @@ Sha1Operands DecodeSha1(const std::uint8_t* data, const std::size_t length) { pos += 1; continue; } + if (b == PrefixLock) { + throw CodegenException("SHA-1 instruction with a LOCK prefix"); + } if (b == PrefixOperandSize || b == PrefixRepne || b == PrefixRep) { throw CodegenException("Not a SHA-1 instruction"); } - if (b != PrefixLock && b != PrefixAddressSize && + if (b != PrefixAddressSize && b != PrefixSegCs && b != PrefixSegSs && b != PrefixSegDs && b != PrefixSegEs && b != PrefixSegFs && b != PrefixSegGs) { break; } - if (b != PrefixLock) - prefixes.push_back(b); + prefixes.push_back(b); rex = 0; pos += 1; } diff --git a/core/relinker/codegen/src/x86/Sha256Operands.cpp b/core/relinker/codegen/src/x86/Sha256Operands.cpp index a090514a15..51af8ec376 100644 --- a/core/relinker/codegen/src/x86/Sha256Operands.cpp +++ b/core/relinker/codegen/src/x86/Sha256Operands.cpp @@ -20,16 +20,18 @@ Sha256Operands DecodeSha256(const std::uint8_t* data, const std::size_t length) pos += 1; continue; } + if (b == PrefixLock) { + throw CodegenException("SHA-256 instruction with a LOCK prefix"); + } if (b == PrefixOperandSize || b == PrefixRepne || b == PrefixRep) { throw CodegenException("Not a SHA-256 instruction"); } - if (b != PrefixLock && b != PrefixAddressSize && + if (b != PrefixAddressSize && b != PrefixSegCs && b != PrefixSegSs && b != PrefixSegDs && b != PrefixSegEs && b != PrefixSegFs && b != PrefixSegGs) { break; } - if (b != PrefixLock) - prefixes.push_back(b); + prefixes.push_back(b); rex = 0; pos += 1; } diff --git a/core/relinker/codegen/src/x86/Sse4aOperands.cpp b/core/relinker/codegen/src/x86/Sse4aOperands.cpp index cf492728c2..2a664f1140 100644 --- a/core/relinker/codegen/src/x86/Sse4aOperands.cpp +++ b/core/relinker/codegen/src/x86/Sse4aOperands.cpp @@ -19,11 +19,14 @@ Sse4aOperands DecodeSse4a(const std::uint8_t* data, const std::size_t length) { pos += 1; continue; } + if (b == PrefixLock) { + throw CodegenException("SSE4a instruction with a LOCK prefix"); + } if (b == PrefixOperandSize) { operandSizeOverride = true; } else if (b == PrefixRepne) { repnePrefix = true; - } else if (b != PrefixLock && b != PrefixRep && b != PrefixAddressSize && + } else if (b != PrefixRep && b != PrefixAddressSize && b != PrefixSegCs && b != PrefixSegSs && b != PrefixSegDs && b != PrefixSegEs && b != PrefixSegFs && b != PrefixSegGs) { break; diff --git a/core/relinker/codegen/tests/Amd64OnlyConverterTests.cpp b/core/relinker/codegen/tests/Amd64OnlyConverterTests.cpp index ca2cf46715..e18ac588f4 100644 --- a/core/relinker/codegen/tests/Amd64OnlyConverterTests.cpp +++ b/core/relinker/codegen/tests/Amd64OnlyConverterTests.cpp @@ -208,6 +208,8 @@ void decoderTwoByteOpcodeLengths() { } void sse4aOperands() { + requireFailure([] { const Bytes bytes = {0xF0, 0x66, 0x0F, 0x78, 0xC0, 0x08, 0x00}; (void)Codegen::DecodeSse4a(bytes.data(), bytes.size()); }, "LOCK EXTRQ was accepted"); + requireFailure([] { const Bytes bytes = {0xF2, 0xF0, 0x0F, 0x79, 0xC1}; (void)Codegen::DecodeSse4a(bytes.data(), bytes.size()); }, "LOCK INSERTQ was accepted"); const auto check = [](const Bytes& site, const bool insertq, const int dst, const int src, const int length, const int index) { const auto operands = Codegen::DecodeSse4a(site.data(), site.size()); require(operands.Insertq == insertq && !operands.RegisterForm && operands.Destination == dst && operands.Source == src && operands.Length == length && operands.Index == index, "SSE4a operands were decoded incorrectly"); @@ -231,6 +233,8 @@ void sse4aOperands() { } void sha256Operands() { + requireFailure([] { const Bytes bytes = {0xF0, 0x0F, 0x38, 0xCB, 0xCA}; (void)Codegen::DecodeSha256(bytes.data(), bytes.size()); }, "LOCK SHA256RNDS2 was accepted"); + requireFailure([] { const Bytes bytes = {0x2E, 0xF0, 0x0F, 0x38, 0xCC, 0x08}; (void)Codegen::DecodeSha256(bytes.data(), bytes.size()); }, "LOCK SHA256MSG1 memory form was accepted"); const auto check = [](const Bytes& site, const Codegen::Sha256Operation operation, const int dst, const int src) { const auto operands = Codegen::DecodeSha256(site.data(), site.size()); require(operands.Operation == operation && operands.Destination == dst && operands.Source == src, "SHA-256 operands were decoded incorrectly"); @@ -261,6 +265,8 @@ void sha256Operands() { } void sha1Operands() { + requireFailure([] { const Bytes bytes = {0xF0, 0x0F, 0x3A, 0xCC, 0xCA, 0x00}; (void)Codegen::DecodeSha1(bytes.data(), bytes.size()); }, "LOCK SHA1RNDS4 was accepted"); + requireFailure([] { const Bytes bytes = {0x2E, 0xF0, 0x0F, 0x38, 0xC9, 0x08}; (void)Codegen::DecodeSha1(bytes.data(), bytes.size()); }, "LOCK SHA1MSG1 memory form was accepted"); const auto check = [](const Bytes& site, const Codegen::Sha1Operation operation, const int dst, const int src, const int function) { const auto operands = Codegen::DecodeSha1(site.data(), site.size()); require(operands.Operation == operation && operands.Destination == dst && operands.Source == src && operands.Function == function, "SHA-1 operands were decoded incorrectly"); @@ -561,6 +567,9 @@ void converterSha256() { 0x90, 0xC3}; std::copy(text.begin(), text.end(), file.begin() + 0x200); + auto locked = file; + locked.insert(locked.begin() + 0x200, 0xF0); + require(failureOffset([&] { (void)converter->Convert(locked, {segmentHeader(text.size() + 1)}); }, "LOCK SHA-256 was accepted") == 0x200, "LOCK SHA-256 failure does not carry the file offset"); const auto result = converter->Convert(file, {segmentHeader(text.size())}); require(result.Trampolines.size() == 2 && result.Reports.size() == 2 && result.Bytes == file, "SHA-256 sites were not lowered through stubs"); const auto& rounds = result.Trampolines[0]; @@ -596,6 +605,9 @@ void converterSha1() { 0x90, 0xC3}; std::copy(text.begin(), text.end(), file.begin() + 0x200); + auto locked = file; + locked.insert(locked.begin() + 0x200, 0xF0); + require(failureOffset([&] { (void)converter->Convert(locked, {segmentHeader(text.size() + 1)}); }, "LOCK SHA-1 was accepted") == 0x200, "LOCK SHA-1 failure does not carry the file offset"); const auto result = converter->Convert(file, {segmentHeader(text.size())}); require(result.Trampolines.size() == 3 && result.Reports.size() == 3 && result.Bytes == file, "SHA-1 sites were not lowered through stubs"); require(result.Trampolines[0].Offset == 0x200 && result.Trampolines[0].Length == 5 && result.Reports[0].InstructionName == "SHA1RNDS4", "SHA1RNDS4 was not lowered as one site"); diff --git a/core/relinker/elfpatcher/include/elfpatcher/windows/WindowsPeFormat.hpp b/core/relinker/elfpatcher/include/elfpatcher/windows/WindowsPeFormat.hpp index 790dfdf3ae..c9436e4915 100644 --- a/core/relinker/elfpatcher/include/elfpatcher/windows/WindowsPeFormat.hpp +++ b/core/relinker/elfpatcher/include/elfpatcher/windows/WindowsPeFormat.hpp @@ -13,6 +13,7 @@ inline constexpr std::uint32_t SectionAlignment = 0x1000; inline constexpr std::uint32_t FileAlignment = 0x200; inline constexpr std::uint32_t LoadRva = 0x10000; inline constexpr std::uint64_t ImageBase = 0x140000000; +inline constexpr std::uint64_t ExecutableBase = 0x400000; inline constexpr std::uint32_t SectionRead = 0x40000000; inline constexpr std::uint32_t SectionWrite = 0x80000000; inline constexpr std::uint32_t SectionExecute = 0x20000000; diff --git a/core/relinker/elfpatcher/include/elfpatcher/windows/WindowsPeWriter.hpp b/core/relinker/elfpatcher/include/elfpatcher/windows/WindowsPeWriter.hpp index db44e19058..46e9e66fed 100644 --- a/core/relinker/elfpatcher/include/elfpatcher/windows/WindowsPeWriter.hpp +++ b/core/relinker/elfpatcher/include/elfpatcher/windows/WindowsPeWriter.hpp @@ -2,13 +2,12 @@ #define ELFPATCHER_WINDOWS_PEWRITER_HPP #include -#include namespace Elfpatcher::Windows { class WindowsPeWriter { public: - std::vector Write(const std::vector& sections, std::uint32_t entryRva, const std::array& directories, bool windowsGui = false, std::optional fixedImageBase = std::nullopt, bool dynamicBase = true) const; + std::vector Write(const std::vector& sections, std::uint32_t entryRva, const std::array& directories, bool windowsGui = false, std::uint64_t imageBase = ImageBase, bool fixedBase = false, bool dynamicBase = true) const; }; } diff --git a/core/relinker/elfpatcher/src/linux/LinuxElfPatcher.cpp b/core/relinker/elfpatcher/src/linux/LinuxElfPatcher.cpp index b2f84ae52d..2c406e732b 100644 --- a/core/relinker/elfpatcher/src/linux/LinuxElfPatcher.cpp +++ b/core/relinker/elfpatcher/src/linux/LinuxElfPatcher.cpp @@ -81,7 +81,6 @@ std::vector RebasedRelocations(const std::vector& ta } case R_X86_64_64: case R_X86_64_PC32: - case R_X86_64_COPY: case R_X86_64_GLOB_DAT: case R_X86_64_JUMP_SLOT: case R_X86_64_32: diff --git a/core/relinker/elfpatcher/src/windows/WindowsEntryStubBuilder.cpp b/core/relinker/elfpatcher/src/windows/WindowsEntryStubBuilder.cpp index 2be086cc21..012c397f06 100644 --- a/core/relinker/elfpatcher/src/windows/WindowsEntryStubBuilder.cpp +++ b/core/relinker/elfpatcher/src/windows/WindowsEntryStubBuilder.cpp @@ -114,6 +114,15 @@ WindowsEntryStub WindowsEntryStubBuilder::Build(const std::uint32_t dataRva, con const auto logName = addWideString(logFileName); const auto shellLibrary = addString("shell32.dll"); const auto parseArguments = addString("CommandLineToArgvW"); + const auto runtimeModule = reserve(8); + const auto runtimeIobFunction = reserve(8); + const auto runtimeFreopenFunction = reserve(8); + const auto msvcrtLibrary = addWideString(u"msvcrt.dll"); + const auto ucrtbaseLibrary = addWideString(u"ucrtbase.dll"); + const auto msvcrtIobFunctionName = addString("__iob_func"); + const auto ucrtbaseIobFunctionName = addString("__acrt_iob_func"); + const auto runtimeFreopenName = addString("_wfreopen"); + const auto runtimeAppendMode = addWideString(u"a"); const auto handles = reserve(libraries.size() * 8); const auto guestFinished = reserve(4); const WindowsGuestStartup guestStartup; @@ -413,7 +422,7 @@ WindowsEntryStub WindowsEntryStubBuilder::Build(const std::uint32_t dataRva, con code.U32(units); code.Emit({0x66, 0xf3, 0xa5}); code.Rip({0x48, 0x8d, 0x0d}, modulePath); - code.Emit({0xba, 0, 0, 0, 0x40, 0x41, 0xb8, 3, 0, 0, 0, 0x45, 0x31, 0xc9}); + code.Emit({0xba, 4, 0, 0, 0, 0x41, 0xb8, 3, 0, 0, 0, 0x45, 0x31, 0xc9}); code.Emit({0x48, 0xc7, 0x44, 0x24, 0x20, 2, 0, 0, 0, 0x48, 0xc7, 0x44, 0x24, 0x28, 0x80, 0, 0, 0, 0x48, 0xc7, 0x44, 0x24, 0x30, 0, 0, 0, 0}); call("CreateFileW"); code.Emit({0x66, 0x41, 0xc7, 0x04, 0x24, 0x00, 0x00}); @@ -431,6 +440,51 @@ WindowsEntryStub WindowsEntryStubBuilder::Build(const std::uint32_t dataRva, con code.PatchBranch(failed, done); }; + const auto rebindPreloadedRuntimeLog = [&](const std::uint32_t runtimeLibrary, const std::uint32_t iobFunctionName, const bool indexedIob) { + code.Rip({0x48, 0x8d, 0x0d}, runtimeLibrary); + call("GetModuleHandleW"); + code.Emit({0x48, 0x85, 0xc0}); + std::vector absent = {code.Branch({0x0f, 0x84})}; + code.Rip({0x48, 0x89, 0x05}, runtimeModule); + code.Emit({0x48, 0x89, 0xc1}); + code.Rip({0x48, 0x8d, 0x15}, iobFunctionName); + call("GetProcAddress"); + code.Emit({0x48, 0x85, 0xc0}); + absent.push_back(code.Branch({0x0f, 0x84})); + code.Rip({0x48, 0x89, 0x05}, runtimeIobFunction); + code.Rip({0x48, 0x8b, 0x0d}, runtimeModule); + code.Rip({0x48, 0x8d, 0x15}, runtimeFreopenName); + call("GetProcAddress"); + code.Emit({0x48, 0x85, 0xc0}); + absent.push_back(code.Branch({0x0f, 0x84})); + code.Rip({0x48, 0x89, 0x05}, runtimeFreopenFunction); + for (const auto& stream : {std::pair{0xfffffff5u, 1}, {0xfffffff4u, 2}}) { + code.Emit({0xb9}); + code.U32(stream.first); + call("GetStdHandle"); + code.Emit({0x48, 0x85, 0xc0}); + const auto missing = code.Branch({0x0f, 0x84}); + code.Rip({0x48, 0x3b, 0x05}, logHandle); + const auto notRedirected = code.Branch({0x0f, 0x85}); + if (indexedIob) { + code.Emit({0xb9, stream.second, 0, 0, 0}); + code.Rip({0xff, 0x15}, runtimeIobFunction); + code.Emit({0x49, 0x89, 0xc0}); + } else { + code.Rip({0xff, 0x15}, runtimeIobFunction); + code.Emit({0x4c, 0x8d, 0x40, static_cast(48 * stream.second)}); + } + code.Rip({0x48, 0x8d, 0x0d}, logName); + code.Rip({0x48, 0x8d, 0x15}, runtimeAppendMode); + code.Rip({0xff, 0x15}, runtimeFreopenFunction); + const auto next = code.GetRva(); + code.PatchBranch(missing, next); + code.PatchBranch(notRedirected, next); + } + const auto done = code.GetRva(); + for (const auto branch : absent) code.PatchBranch(branch, done); + }; + code.Emit({0x53, 0x55, 0x56, 0x57, 0x41, 0x54, 0x48, 0x83, 0xec, 0x60}); code.Rip({0x48, 0x8d, 0x0d}, parentVariable); code.Rip({0x48, 0x8d, 0x15}, parentText); @@ -505,6 +559,8 @@ WindowsEntryStub WindowsEntryStubBuilder::Build(const std::uint32_t dataRva, con code.Rip({0x48, 0x8d, 0x0d}, modulePath); call("SetCurrentDirectoryW"); requireNonzero(directoryError, 0xc000000du); + rebindPreloadedRuntimeLog(msvcrtLibrary, msvcrtIobFunctionName, false); + rebindPreloadedRuntimeLog(ucrtbaseLibrary, ucrtbaseIobFunctionName, true); if (dependencyDiagnostics) { code.Rip({0x4c, 0x8d, 0x05}, programPath); writeUtf8(programText); diff --git a/core/relinker/elfpatcher/src/windows/WindowsPePatcher.cpp b/core/relinker/elfpatcher/src/windows/WindowsPePatcher.cpp index 063af7924b..36e88bf315 100644 --- a/core/relinker/elfpatcher/src/windows/WindowsPePatcher.cpp +++ b/core/relinker/elfpatcher/src/windows/WindowsPePatcher.cpp @@ -39,7 +39,7 @@ std::vector WindowsPePatcher::Patch(std::vector sour const auto report = [&](std::uint64_t completed) { if (progress) progress(completed, 10000); }; report(0); diagnostics.clear(); - WindowsLoadImage image(sourceElf, originalHeaders, true, fixedBase ? *fixedBase - LoadRva : ImageBase); + WindowsLoadImage image(sourceElf, originalHeaders, true, fixedBase.value_or(ExecutableBase) - LoadRva); if (originalPltGotVaddr != 0) image.GetRva(originalPltGotVaddr, 8); report(500); @@ -111,7 +111,7 @@ std::vector WindowsPePatcher::Patch(std::vector sour } directories[2] = icon ? WindowsIconResourceBuilder().Build(*icon, iconName, sections, nextRva) : PeDirectory{}; report(9500); - auto result = WindowsPeWriter().Write(sections, entryRva, directories, windowsGui, fixedBase ? std::optional(image.GetImageBase()) : std::nullopt, false); + auto result = WindowsPeWriter().Write(sections, entryRva, directories, windowsGui, image.GetImageBase(), fixedBase.has_value(), false); report(10000); return result; } diff --git a/core/relinker/elfpatcher/src/windows/WindowsPeWriter.cpp b/core/relinker/elfpatcher/src/windows/WindowsPeWriter.cpp index 48d867f0f5..96dfbf91b3 100644 --- a/core/relinker/elfpatcher/src/windows/WindowsPeWriter.cpp +++ b/core/relinker/elfpatcher/src/windows/WindowsPeWriter.cpp @@ -5,7 +5,7 @@ namespace Elfpatcher::Windows { -std::vector WindowsPeWriter::Write(const std::vector& sections, const std::uint32_t entryRva, const std::array& directories, const bool windowsGui, const std::optional fixedImageBase, const bool dynamicBase) const { +std::vector WindowsPeWriter::Write(const std::vector& sections, const std::uint32_t entryRva, const std::array& directories, const bool windowsGui, const std::uint64_t imageBase, const bool fixedBase, const bool dynamicBase) const { constexpr std::size_t peOffset = 0x80; constexpr std::size_t optionalOffset = peOffset + 24; constexpr std::size_t sectionTable = optionalOffset + 240; @@ -18,12 +18,12 @@ std::vector WindowsPeWriter::Write(const std::vector& s Io::WriteU16(result, peOffset + 4, 0x8664); Io::WriteU16(result, peOffset + 6, static_cast(sections.size())); Io::WriteU16(result, peOffset + 20, 240); - if (fixedImageBase && (directories[5].Size != 0 || *fixedImageBase < 0x10000 || (*fixedImageBase & 0xffff) != 0)) - throw Domain::RelinkerException("Invalid fixed Windows image base or base relocations"); - Io::WriteU16(result, peOffset + 22, fixedImageBase ? 0x23 : 0x22); + if (imageBase < 0x10000 || (imageBase & 0xffff) != 0 || (fixedBase && directories[5].Size != 0)) + throw Domain::RelinkerException("Invalid Windows image base or base relocations"); + Io::WriteU16(result, peOffset + 22, fixedBase ? 0x23 : 0x22); Io::WriteU16(result, optionalOffset, 0x20b); Io::WriteU32(result, optionalOffset + 16, entryRva); - Io::WriteU64(result, optionalOffset + 24, fixedImageBase.value_or(ImageBase)); + Io::WriteU64(result, optionalOffset + 24, imageBase); Io::WriteU32(result, optionalOffset + 32, SectionAlignment); Io::WriteU32(result, optionalOffset + 36, FileAlignment); Io::WriteU16(result, optionalOffset + 40, 6); @@ -72,7 +72,7 @@ std::vector WindowsPeWriter::Write(const std::vector& s } if (!foundEntry) throw Domain::RelinkerException("PE entry point is not inside executable section data", entryRva); - if (fixedImageBase && *fixedImageBase > 0x7fffffffffff - static_cast(endRva)) + if (fixedBase && imageBase > 0x7fffffffffff - static_cast(endRva)) throw Domain::RelinkerException("Fixed Windows image exceeds the user address space"); Io::WriteU32(result, optionalOffset + 4, codeSize); Io::WriteU32(result, optionalOffset + 8, dataSize); diff --git a/core/relinker/elfpatcher/src/windows/WindowsTlsBuilder.cpp b/core/relinker/elfpatcher/src/windows/WindowsTlsBuilder.cpp index b78a010b40..f923bafd63 100644 --- a/core/relinker/elfpatcher/src/windows/WindowsTlsBuilder.cpp +++ b/core/relinker/elfpatcher/src/windows/WindowsTlsBuilder.cpp @@ -221,8 +221,14 @@ PeDirectory WindowsTlsBuilder::Build(const std::vector& source, co } report(9000); - for (const auto& [rva, length] : gsTraps) + std::sort(branchTargets.begin(), branchTargets.end()); + branchTargets.erase(std::unique(branchTargets.begin(), branchTargets.end()), branchTargets.end()); + for (const auto& [rva, length] : gsTraps) { + const auto target = std::upper_bound(branchTargets.begin(), branchTargets.end(), rva); + if (target != branchTargets.end() && *target < rva + length) + throw Domain::RelinkerException("Branch enters a guest GS instruction", *target); trapInstruction(sections, rva, length); + } if (tls == nullptr) { if (!accesses.empty()) throw Domain::RelinkerException("Guest TLS access without PT_TLS"); @@ -274,9 +280,6 @@ PeDirectory WindowsTlsBuilder::Build(const std::vector& source, co code.PatchBranch(skipCallback, code.GetRva()); code.Emit({0xc3}); - std::sort(branchTargets.begin(), branchTargets.end()); - branchTargets.erase(std::unique(branchTargets.begin(), branchTargets.end()), branchTargets.end()); - std::uint64_t patched = 0; for (const auto& access : accesses) { if (patched % 256 == 0) report(9000 + 900 * patched / accesses.size()); diff --git a/core/relinker/elfpatcher/tests/WindowsImportIdentityTests.cpp b/core/relinker/elfpatcher/tests/WindowsImportIdentityTests.cpp index ffe753bfaf..03243cea6b 100644 --- a/core/relinker/elfpatcher/tests/WindowsImportIdentityTests.cpp +++ b/core/relinker/elfpatcher/tests/WindowsImportIdentityTests.cpp @@ -74,7 +74,7 @@ void generateProbe(const Fs::path& file, const std::string& libraries, const std directories[1] = imports.Directory; directories[3] = startup.ExceptionDirectory; directories[12] = imports.AddressTable; - const auto image = WindowsPeWriter().Write({entry, got, imports.Section, startup.Data, startup.Code}, startup.Code.Rva, directories, false, ImageBase, false); + const auto image = WindowsPeWriter().Write({entry, got, imports.Section, startup.Data, startup.Code}, startup.Code.Rva, directories, false, ImageBase, true, false); std::ofstream stream(file, std::ios::binary); stream.write(reinterpret_cast(image.data()), static_cast(image.size())); require(static_cast(stream), "Cannot write " + file.string()); diff --git a/core/relinker/elfpatcher/tests/WindowsMsvcrt.def b/core/relinker/elfpatcher/tests/WindowsMsvcrt.def index c163db8f44..741b17b119 100644 --- a/core/relinker/elfpatcher/tests/WindowsMsvcrt.def +++ b/core/relinker/elfpatcher/tests/WindowsMsvcrt.def @@ -2,3 +2,4 @@ LIBRARY msvcrt.dll EXPORTS __iob_func fputs + fflush diff --git a/core/relinker/elfpatcher/tests/WindowsMsvcrtStdioHost.cpp b/core/relinker/elfpatcher/tests/WindowsMsvcrtStdioHost.cpp index 4c370e0924..2a77b5b41f 100644 --- a/core/relinker/elfpatcher/tests/WindowsMsvcrtStdioHost.cpp +++ b/core/relinker/elfpatcher/tests/WindowsMsvcrtStdioHost.cpp @@ -13,10 +13,13 @@ static_assert(sizeof(_iobuf) == 48); extern "C" _iobuf* __cdecl __iob_func(); extern "C" int __cdecl fputs(const char*, _iobuf*); +extern "C" int __cdecl fflush(_iobuf*); extern "C" int shared() { auto* streams = __iob_func(); fputs("Windows DLL stdout probe\n", streams + 1); fputs("Windows DLL stderr probe\n", streams + 2); + fflush(streams + 1); + fflush(streams + 2); return 11; } diff --git a/core/relinker/elfpatcher/tests/WindowsStdioHost.cpp b/core/relinker/elfpatcher/tests/WindowsStdioHost.cpp index 72a29373f4..3d996c8df4 100644 --- a/core/relinker/elfpatcher/tests/WindowsStdioHost.cpp +++ b/core/relinker/elfpatcher/tests/WindowsStdioHost.cpp @@ -3,5 +3,7 @@ extern "C" int shared() { std::fputs("Windows DLL stdout probe\n", stdout); std::fputs("Windows DLL stderr probe\n", stderr); + std::fflush(stdout); + std::fflush(stderr); return 11; } diff --git a/core/relinker/main.cpp b/core/relinker/main.cpp index 6f2a15fe2e..a69ef856ff 100644 --- a/core/relinker/main.cpp +++ b/core/relinker/main.cpp @@ -45,11 +45,12 @@ ConvertedExecutable Convert(const Cli::Args& args, const std::string& inputPath, input.Executable = fileReader.Read(inputPath); input.InputPath = std::filesystem::absolute(Io::NativePath(inputPath)).lexically_normal(); input.OutputPath = Io::NativePath(absPath); + Cli::NativeModules modules; if (!args.skipSceModule) { - auto modules = Cli::ReadModules(std::filesystem::absolute(Io::NativePath(args.inputPath)).lexically_normal(), Io::NativePath(args.sceModulePath), args.excludedSceModules, args.moduleDirectories); - input.ModuleRoot = std::move(modules.Root); + modules = Cli::ReadModules(std::filesystem::absolute(Io::NativePath(args.inputPath)).lexically_normal(), Io::NativePath(args.sceModulePath), args.excludedSceModules, args.moduleDirectories); + input.ModuleRoot = modules.Root; input.Modules = std::move(modules.Modules); - input.RuntimeDirectories = std::move(modules.RuntimeDirectories); + input.RuntimeDirectories = modules.RuntimeDirectories; } const auto iconPath = Io::NativePath(args.inputPath).parent_path() / "sce_sys" / "icon0.png"; if (args.toWindows && std::filesystem::exists(iconPath)) input.Icon = fileReader.Read(Io::Utf8Path(iconPath)); @@ -76,6 +77,7 @@ ConvertedExecutable Convert(const Cli::Args& args, const std::string& inputPath, progress.IncludeFile(Io::Utf8Path(input.OutputPath)); for (const auto& module : input.Modules) progress.IncludeFile(Io::Utf8Path(module.Path)); auto converted = Relinker::Conversion(progress).Convert(std::move(input), options); + if (!args.skipSceModule) Cli::ReportUnconvertedNeeded(modules, converted.Analysis.DynamicSection.NeededLibraries, args.toWindows, std::cout); return {inputPath, absPath, std::move(converted.Analysis), std::move(converted.Modules), std::move(converted.Executable), std::move(converted.WindowsDiagnostics), std::move(converted.AppliedPatches), converted.LinuxBase}; } diff --git a/core/relinker/relinker/src/analysis/ValidationPolicy.cpp b/core/relinker/relinker/src/analysis/ValidationPolicy.cpp index 47d65ac011..b9d67a3069 100644 --- a/core/relinker/relinker/src/analysis/ValidationPolicy.cpp +++ b/core/relinker/relinker/src/analysis/ValidationPolicy.cpp @@ -11,7 +11,6 @@ void ValidationPolicy::_initializeSupportedRelocationTypes() { R_X86_64_NONE, R_X86_64_64, R_X86_64_PC32, - R_X86_64_COPY, R_X86_64_GLOB_DAT, R_X86_64_JUMP_SLOT, R_X86_64_RELATIVE, diff --git a/core/relinker/relinker/src/pipeline/RelinkerPipeline.cpp b/core/relinker/relinker/src/pipeline/RelinkerPipeline.cpp index 77044446d2..b560a7cb6a 100644 --- a/core/relinker/relinker/src/pipeline/RelinkerPipeline.cpp +++ b/core/relinker/relinker/src/pipeline/RelinkerPipeline.cpp @@ -277,6 +277,8 @@ RelinkResult RelinkerPipeline::Relink() { for (auto& [fst, snd] : neededLibraryNamesByStrOffset) { snd = readCStr(fst); + if (snd.empty() || snd.find_first_of("\\:$\r\n") != std::string::npos) + throw RelinkerException("Invalid dependency: " + snd, dynStrTabOffset + fst); neededLibraries.push_back(snd); } @@ -312,8 +314,8 @@ RelinkResult RelinkerPipeline::Relink() { return type == R_X86_64_DTPMOD64 || type == R_X86_64_DTPOFF64 || type == R_X86_64_TPOFF64; }; - const bool hasTlsSegment = std::any_of(programHeaders.begin(), programHeaders.end(), - [](const ProgramHeader& ph) { return ph.Type == PT_TLS; }); + const bool hasNonEmptyTlsSegment = std::any_of(programHeaders.begin(), programHeaders.end(), + [](const ProgramHeader& ph) { return ph.Type == PT_TLS && ph.MemorySize != 0; }); const auto definedTlsSymbolValue = [&](const std::uint32_t symIdx, const FileByteOffset pos) -> std::optional { const FileByteOffset symOff = symbolEntryPos(symIdx); @@ -434,13 +436,42 @@ RelinkResult RelinkerPipeline::Relink() { std::memcpy(&sourceName, symbol, sizeof(sourceName)); auto name = readCStr(sourceName); name.resize(name.find('#') == std::string::npos ? name.size() : name.find('#')); + const FileByteOffset entryOffset = dynSymTabOffset + off; + const auto type = symbol[4] & 15; + std::uint64_t value = 0; + std::uint64_t size = 0; + std::memcpy(&value, symbol + 8, sizeof(value)); + std::memcpy(&size, symbol + 16, sizeof(size)); + if (type == STT_TLS) { + if (section >= SHN_LORESERVE) + throw RelinkerException("Unsupported executable TLS export section: " + name, entryOffset); + const auto tls = std::find_if(programHeaders.begin(), programHeaders.end(), + [](const ProgramHeader& ph) { return ph.Type == PT_TLS; }); + if (tls == programHeaders.end()) + throw RelinkerException("Executable TLS export has no PT_TLS segment: " + name, entryOffset); + if (value > tls->MemorySize || size > tls->MemorySize - value) + throw RelinkerException("Executable TLS export exceeds PT_TLS: " + name, entryOffset); + } else if (section != SHN_ABS) { + if (section >= SHN_LORESERVE) + throw RelinkerException("Unsupported executable export section: " + name, entryOffset); + const std::uint32_t flags = type == STT_FUNC ? PF_X : 0; + const auto extent = std::max(size, 1); + const bool mapped = std::any_of(programHeaders.begin(), programHeaders.end(), [&](const ProgramHeader& ph) { + return ph.Type == PT_LOAD && (ph.Flags & flags) == flags && value >= ph.MappedAddress && + value - ph.MappedAddress < ph.MemorySize && extent <= ph.MemorySize - (value - ph.MappedAddress); + }); + if (!mapped) { + std::ostringstream message; + message << "Executable export " << name << " at 0x" << std::hex << value + << (size > 1 ? " (" + std::to_string(size) + " bytes) does not fit inside " : " is not inside ") + << (flags != 0 ? "an executable" : "a") << " PT_LOAD segment"; + throw RelinkerException(message.str(), entryOffset); + } + } exportedSymbols.emplace_back(off, std::move(name)); const auto binding = symbol[4] >> 4; - if ((binding == STB_GLOBAL || binding == STB_WEAK) && (symbol[4] & 15) == STT_FUNC) { - VirtualAddress address = 0; - std::memcpy(&address, symbol + 8, sizeof(address)); - exportedFunctions.push_back(address); - } + if ((binding == STB_GLOBAL || binding == STB_WEAK) && type == STT_FUNC) + exportedFunctions.push_back(value); } } @@ -545,8 +576,8 @@ RelinkResult RelinkerPipeline::Relink() { continue; offset = *value; } - if (!hasTlsSegment) - throw RelinkerException("TLS relocation in an executable without a PT_TLS segment", pos); + if (!hasNonEmptyTlsSegment) + throw RelinkerException("TLS relocation in an executable without a non-empty PT_TLS segment", pos); if (relType == R_X86_64_DTPMOD64 && rAddend != 0) throw RelinkerException("DTPMOD64 relocation has a nonzero addend", pos); const auto addend = relType == R_X86_64_DTPMOD64 ? 0 : static_cast(offset + static_cast(rAddend)); diff --git a/core/relinker/relinker/tests/test_copy_relocations.py b/core/relinker/relinker/tests/test_copy_relocations.py new file mode 100644 index 0000000000..5a1677e26e --- /dev/null +++ b/core/relinker/relinker/tests/test_copy_relocations.py @@ -0,0 +1,62 @@ +"""R_X86_64_COPY relocations in DT_RELA and in the PLT table are rejected by validation, before any +target code runs, with the same error for every output target; GLOB_DAT and JUMP_SLOT are accepted. The +Linux output gives every import symbol st_size 0, so a dynamic loader would copy MIN(st_size of the +definition, 0) = 0 bytes and the variable would stay zero.""" + +from pathlib import Path +import subprocess +import sys +import tempfile + +from test_jmprel_table_bounds import fixture + +R_X86_64_COPY = 5 +TARGETS = {(): "linux", ("--lazy-binding",): "lazy", ("--windows",): "windows", ("--macos",): "macos"} +ERROR = "Unsupported relocation type 0x5" + +CASES = [ + ("copy-rela", fixture(linux=True, data_relocations=True, relocation_type=R_X86_64_COPY), True), + ("copy-jmprel", fixture(linux=True, relocation_type=R_X86_64_COPY), True), + ("glob-dat-rela", fixture(linux=True, data_relocations=True), False), + ("jump-slot-jmprel", fixture(linux=True), False), +] + + +def relink(relinker, work, name, image, flags): + source = work / (name + ".elf") + output = work / (name + ".out") + source.write_bytes(image) + result = subprocess.run([str(relinker), "--skip-sce-module", *flags, str(source), str(output)], + capture_output=True, text=True, timeout=20) + return result, output + + +def fail_lines(result): + return [line for line in result.stderr.splitlines() if line.startswith("FAIL: ")] + + +def main(): + relinker = Path(sys.argv[1]).resolve() + with tempfile.TemporaryDirectory(prefix="anyps5-copy-") as directory: + work = Path(directory) + for case, image, rejected in CASES: + failures = {} + for flags, target in TARGETS.items(): + name = f"{case}-{target}" + result, output = relink(relinker, work, name, image, flags) + if rejected: + assert result.returncode == 2 and ERROR in result.stderr and not output.exists(), ( + name, result.returncode, result.stdout, result.stderr) + failures[target] = fail_lines(result) + else: + assert result.returncode == 0 and output.exists(), ( + name, result.returncode, result.stdout, result.stderr) + output.unlink() + if rejected: + assert failures["linux"] and all(lines == failures["linux"] for lines in failures.values()), ( + case, failures) + print("COPY relocation test passed") + + +if __name__ == "__main__": + main() diff --git a/core/relinker/relinker/tests/test_executable_export_bounds.py b/core/relinker/relinker/tests/test_executable_export_bounds.py new file mode 100644 index 0000000000..0b5ea1a71c --- /dev/null +++ b/core/relinker/relinker/tests/test_executable_export_bounds.py @@ -0,0 +1,129 @@ +"""An exported symbol of the executable must lie inside the image it is exported from, the rule +GuestImageReader applies to every symbol of a guest module and the macOS target applied to the executable +alone. A defined symbol that is not local, hidden or internal must lie inside a PT_LOAD segment that is +executable for STT_FUNC, together with its size and at least one byte; a non-TLS export in SHN_ABS is exempt, +any other special section index is rejected, and an STT_TLS export must lie inside PT_TLS with a regular +section index. Symbols that are not exports are not checked. The check runs before any target-specific code, +so an export it rejects fails with the same line, at the symbol entry's file offset, on every target.""" + +from pathlib import Path +import struct +import subprocess +import sys +import tempfile + +from test_linux_load_alignment import fixture + +PT_LOAD = 1 +PT_TLS = 7 +NOTYPE, OBJECT, FUNC, TLS = 0, 1, 2, 6 +LOCAL, GLOBAL, WEAK = 0, 1, 2 +SHN_ABS = 0xfff1 +SHN_SPECIAL = 0xff01 +TARGETS = {(): "linux", ("--lazy-binding",): "lazy", ("--windows",): "windows", ("--macos",): "macos"} +SYMBOL_OFFSET = 0x4900 + 24 +TLS_MEMSZ, TLS_ALIGN = 0x24, 16 + + +def case(name, kind, value, size, message=None, binding=GLOBAL, section=1, visibility=0, tls=False): + return name, kind, value, size, message, binding, section, visibility, tls + + +CASES = [ + case("func_in_text", FUNC, 0x200, 6), + case("object_in_data", OBJECT, 0x1100, 8), + case("object_fills_load_end", OBJECT, 0x1ff8, 8), + case("notype_zero_size_inside", NOTYPE, 0x1ff0, 0), + case("func_last_byte", FUNC, 0xfff, 0), + case("weak_object", OBJECT, 0x1100, 8, binding=WEAK), + case("absolute", OBJECT, 0x123456789, 8, section=SHN_ABS), + case("tls_inside", TLS, 0x10, 4, tls=True), + case("hidden_outside_ignored", OBJECT, 0x9000, 8, visibility=2), + case("local_outside_ignored", OBJECT, 0x9000, 8, binding=LOCAL), + case("internal_outside_ignored", OBJECT, 0x9000, 8, visibility=1), + case("tls_fills", TLS, 0x20, 4, tls=True), + case("func_outside", FUNC, 0x9000, 6, + "Executable export {} at 0x9000 (6 bytes) does not fit inside an executable PT_LOAD segment"), + case("object_outside", OBJECT, 0x9000, 8, + "Executable export {} at 0x9000 (8 bytes) does not fit inside a PT_LOAD segment"), + case("object_past_end", OBJECT, 0x1ffc, 8, + "Executable export {} at 0x1ffc (8 bytes) does not fit inside a PT_LOAD segment"), + case("object_straddles_text_end", OBJECT, 0xffc, 8, + "Executable export {} at 0xffc (8 bytes) does not fit inside a PT_LOAD segment"), + case("protected_outside", OBJECT, 0x9000, 8, + "Executable export {} at 0x9000 (8 bytes) does not fit inside a PT_LOAD segment", visibility=3), + case("marker_at_end", NOTYPE, 0x2000, 0, + "Executable export {} at 0x2000 is not inside a PT_LOAD segment"), + case("func_in_data", FUNC, 0x1100, 6, + "Executable export {} at 0x1100 (6 bytes) does not fit inside an executable PT_LOAD segment"), + case("func_straddles_text_end", FUNC, 0xffc, 8, + "Executable export {} at 0xffc (8 bytes) does not fit inside an executable PT_LOAD segment"), + case("func_zero_in_data", FUNC, 0x1100, 0, + "Executable export {} at 0x1100 is not inside an executable PT_LOAD segment"), + case("special_section", OBJECT, 0x1100, 8, + "Unsupported executable export section: {}", section=SHN_SPECIAL), + case("tls_beyond", TLS, 0x20, 8, + "Executable TLS export exceeds PT_TLS: {}", tls=True), + case("tls_without_segment", TLS, 0x10, 4, + "Executable TLS export has no PT_TLS segment: {}"), + case("tls_special_section", TLS, 0x10, 4, + "Unsupported executable TLS export section: {}", section=SHN_ABS, tls=True), +] + + +def image(name, kind, value, size, binding, section, visibility, tls): + strings = b"\0" + name.encode("ascii") + b"\0" + data = fixture() + struct.pack_into("(image.atomic) << 24u) ^ (static_cast(mode.dimension) << 16u) ^ (static_cast(mode.depthCompare) << 8u) ^ static_cast(kind)); + const auto hash = hashWords(element, (static_cast(image.atomic64) << 25u) ^ (static_cast(image.atomic) << 24u) ^ (static_cast(mode.dimension) << 16u) ^ (static_cast(mode.depthCompare) << 8u) ^ static_cast(kind)); auto index = elementIndex.Find(hash, [&](std::uint32_t known) { const auto& entry = out.elements[known]; - return entry.words == element && entry.dimension == mode.dimension && entry.depthCompare == mode.depthCompare && entry.kind == kind && entry.atomic == image.atomic; + return entry.words == element && entry.dimension == mode.dimension && entry.depthCompare == mode.depthCompare && entry.kind == kind && entry.atomic == image.atomic && entry.atomic64 == image.atomic64; }); if (!index.has_value() && out.elements.size() >= Abi::ImageElementBudget) { record[Abi::ImageRecordFlags] = poison(resource, PoisonReason::Budget, &words); } else { if (!index.has_value()) { index = static_cast(out.elements.size()); - out.elements.push_back({element, mode.dimension, mode.depthCompare, kind, 0u, image.atomic}); + out.elements.push_back({element, mode.dimension, mode.depthCompare, kind, 0u, image.atomic, image.atomic64}); elementIndex.Insert(hash, *index); } out.elements[*index].samplers |= directSamplers[resource]; diff --git a/core/shader/recompiler/Optimization/src/ResourceTracker.cpp b/core/shader/recompiler/Optimization/src/ResourceTracker.cpp index ee6873ef41..d0d0482387 100644 --- a/core/shader/recompiler/Optimization/src/ResourceTracker.cpp +++ b/core/shader/recompiler/Optimization/src/ResourceTracker.cpp @@ -1775,7 +1775,7 @@ private: continue; } image.table = next++; - if (image.atomic64 || image.packed || image.byElements != 0u) { + if (image.packed || image.byElements != 0u) { image.tableOperation = TableOperation::Unsupported; } } diff --git a/core/shader/recompiler/Recompiler.cpp b/core/shader/recompiler/Recompiler.cpp index fad7606ef9..5d4ecc297a 100644 --- a/core/shader/recompiler/Recompiler.cpp +++ b/core/shader/recompiler/Recompiler.cpp @@ -353,11 +353,22 @@ IrProgram PrepareResourceProgram(const RecompileRequest& request, ShaderPreparat // A materialized result of one variant over one snapshot (Recompile(request, capture)): the // shared immutable object every later capture that reproduces the snapshot receives, so Populate // and the per-request copy run once per distinct snapshot. +struct MemoPatch { + static constexpr std::uint32_t NoBinding = ~0u; + std::vector>> buffers; + std::vector userWords; + std::uint32_t shaderData = NoBinding; + std::uint32_t flattenedSrt = NoBinding; + bool pushData = false; + bool valid = false; +}; + struct ResultMemoEntry { std::uint64_t variantId = 0; std::uint64_t hash = 0; std::shared_ptr result; std::uint64_t used = 0; + std::shared_ptr patch; }; struct EmissionFailure { @@ -387,6 +398,7 @@ struct SourceEntry : std::enable_shared_from_this { std::vector> variants; std::vector emissionFailures; std::unique_ptr memo; + std::unique_ptr maskedMemo; std::uint64_t memoClock = 0; }; @@ -743,12 +755,19 @@ CompiledVariant compileVariant(const RecompileRequest& request, IrProgram progra struct SpecializedModule { std::uint64_t specializationId = 0; - SharedSpirv spirv; std::vector bindings; bool pushData = false; + SpirvContentHash hash; + mutable std::mutex mutex; + mutable SharedSpirv::Weak spirv; }; -std::shared_ptr buildSpecializedModule(const CompiledShaderArtifact& artifact, std::span classes, std::span constants, const SpirvTarget& target) { +struct SpecializedSpirv { + std::shared_ptr module; + SharedSpirv spirv; +}; + +std::vector specializeWords(const CompiledShaderArtifact& artifact, std::span classes, std::span constants, const SpirvTarget& target) { auto source = SpecializeVertexInputTypes(artifact, classes); std::map supplied; for (const auto& constant : constants) { @@ -842,6 +861,11 @@ std::shared_ptr buildSpecializedModule(const CompiledSh #if ANYPS5_ENABLE_SPIRV_TOOLS materialized = ValidateAndOptimizeSpirv(materialized, target.vulkanVersion, target.spirvVersion, target.nonConstantImageOffsets, false); #endif + return materialized; +} + +SpecializedSpirv buildSpecializedModule(const CompiledShaderArtifact& artifact, std::span classes, std::span constants, const SpirvTarget& target) { + auto materialized = specializeWords(artifact, classes, constants, target); auto module = std::make_shared(); std::map bindingNumbers; std::unordered_set functionLdsBuffer; @@ -856,9 +880,20 @@ std::shared_ptr buildSpecializedModule(const CompiledSh } cursor += count; } - module->spirv = InternSpirv(std::move(materialized)); + auto spirv = InternSpirv(std::move(materialized)); + module->hash = spirv.ContentHash(); + module->spirv = spirv.Weaken(); module->specializationId = constants.empty() ? 0u : nextVariantId(); - return module; + return {std::move(module), std::move(spirv)}; +} + +SharedSpirv specializedWords(const SpecializedModule& module, const CompiledShaderArtifact& artifact, std::span classes, std::span constants, const SpirvTarget& target) { + std::lock_guard lock(module.mutex); + if (auto spirv = module.spirv.Lock(); !spirv.empty()) return spirv; + auto spirv = InternSpirv(specializeWords(artifact, classes, constants, target)); + if (spirv.ContentHash() != module.hash) throw std::runtime_error("ShaderRecompiler: a specialized module built again from its key differs from its first build"); + module.spirv = spirv.Weaken(); + return spirv; } struct SpecializedModuleEntry { @@ -888,7 +923,12 @@ struct RegistrationModuleEntry { std::shared_ptr module; }; -std::shared_ptr registrationModule(std::uint64_t variantId, std::span moduleKey, const std::function()>& specialize) { +SharedSpirv lockedWords(const SpecializedModule& module) { + std::lock_guard lock(module.mutex); + return module.spirv.Lock(); +} + +SpecializedSpirv registrationModule(std::uint64_t variantId, std::span moduleKey, const std::function& specialize) { std::vector key{variantId}; key.insert(key.end(), moduleKey.begin(), moduleKey.end()); static PrimedSharedMutex mutex; @@ -903,15 +943,20 @@ std::shared_ptr registrationModule(std::uint64_t varian const auto found = modules.find(key); entry = found != modules.end() ? found->second : modules.emplace(key, std::make_shared()).first->second; } + SharedSpirv built; std::call_once(entry->ready, [&] { try { - entry->module = specialize(); + auto specialized = specialize(); + entry->module = std::move(specialized.module); + built = std::move(specialized.spirv); } catch (...) { entry->failure = std::current_exception(); } }); if (entry->failure) std::rethrow_exception(entry->failure); - return entry->module; + if (built.empty()) built = lockedWords(*entry->module); + if (built.empty()) built = specialize().spirv; + return {entry->module, std::move(built)}; } std::shared_ptr preparedBindingPlan(const CompiledVariant& variant, const ResourceSnapshot& snapshot, std::span exports, bool fragmentDescriptorSet) { @@ -964,7 +1009,7 @@ std::shared_ptr preparedBindingPlan(const CompiledVariant& return plan; } -std::shared_ptr specializeModule(const CompiledShaderArtifact& artifact, std::span classes, std::span constants, const SpirvTarget& target) { +SpecializedSpirv specializeModule(const CompiledShaderArtifact& artifact, std::span classes, std::span constants, const SpirvTarget& target) { struct ModuleKeyStorage {}; auto& key = HostThreadLocal, ModuleKeyStorage>(); key.clear(); @@ -982,15 +1027,19 @@ std::shared_ptr specializeModule(const CompiledShaderAr const auto found = modules.find(key); entry = found != modules.end() ? found->second : modules.emplace(key, std::make_shared()).first->second; } + SharedSpirv built; std::call_once(entry->ready, [&] { try { - entry->module = buildSpecializedModule(artifact, classes, constants, target); + auto specialized = buildSpecializedModule(artifact, classes, constants, target); + entry->module = std::move(specialized.module); + built = std::move(specialized.spirv); } catch (...) { entry->failure = std::current_exception(); } }); if (entry->failure) std::rethrow_exception(entry->failure); - return entry->module; + if (built.empty()) built = specializedWords(*entry->module, artifact, classes, constants, target); + return {entry->module, std::move(built)}; } const ResourceSnapshot& mergeTargetImage(const CompiledVariant& variant, const RecompileRequest& request, const ResourceSnapshot& snapshot, bool registrationDefaults, ResourceSnapshot& merged) { @@ -1008,7 +1057,28 @@ const ResourceSnapshot& mergeTargetImage(const CompiledVariant& variant, const R return merged; } -RecompileResult materializeResult(const CompiledVariant& variant, const RecompileRequest& request, const ResourceSnapshot& captured, bool registrationDefaults = false) { +void recordMemoPatch(MemoPatch& patch, const DescriptorBindingPlan& plan, const CompiledVariant& variant) { + const auto& layout = variant.bindings.layout; + patch = {}; + for (std::size_t index = 0; index < plan.bindings.size(); ++index) { + const auto& binding = plan.bindings[index]; + const auto position = static_cast(index); + if (binding.descriptor.role == DescriptorRole::GuestBuffers) { + patch.buffers.push_back({position, binding.resources}); + } else if (binding.descriptor.role == DescriptorRole::FlattenedSrt) { + patch.flattenedSrt = position; + } else if (binding.descriptor.role == DescriptorRole::ShaderData) { + patch.shaderData = position; + } + } + patch.pushData = layout.UsesPushData(); + if (patch.pushData || plan.storageData) { + for (const auto reg : layout.userDataRegisters) patch.userWords.push_back(reg - variant.info.userDataBase); + } + patch.valid = layout.userDataRegisters.size() <= layout.DispatchThreadLimitDword() && (patch.userWords.empty() || patch.pushData || patch.shaderData != MemoPatch::NoBinding); +} + +RecompileResult materializeResult(const CompiledVariant& variant, const RecompileRequest& request, const ResourceSnapshot& captured, bool registrationDefaults = false, MemoPatch* patch = nullptr) { ResourceSnapshot merged; const auto& snapshot = mergeTargetImage(variant, request, captured, registrationDefaults, merged); RecompileResult result; @@ -1112,7 +1182,7 @@ RecompileResult materializeResult(const CompiledVariant& variant, const Recompil const auto found = plan->modules.find(moduleKey); entry = found != plan->modules.end() ? found->second : plan->modules.emplace(moduleKey, std::make_shared()).first->second; } - const auto prepare = [&] { + const auto specialize = [&] { auto constants = plan->bindings.specialization; std::size_t index = 0; if (variant.bindings.layout.UsesPushData()) constants.push_back({PipelineSpecialization::PushDataOffset, moduleKey[index++]}); @@ -1137,11 +1207,17 @@ RecompileResult materializeResult(const CompiledVariant& variant, const Recompil constants.push_back({first + 5u, kind}); } } - const auto module = artifact.registrationModule && plan->bindings.specialization.empty() ? registrationModule(artifact.variantId, moduleKey, [&] { return specializeModule(variant.artifact, vertexClasses, constants, request.target); }) : specializeModule(variant.artifact, vertexClasses, constants, request.target); + return artifact.registrationModule && plan->bindings.specialization.empty() ? registrationModule(artifact.variantId, moduleKey, [&] { return specializeModule(variant.artifact, vertexClasses, constants, request.target); }) : specializeModule(variant.artifact, vertexClasses, constants, request.target); + }; + SharedSpirv built; + const auto prepare = [&] { + auto specialized = specialize(); + const auto& module = specialized.module; if (variant.bindings.layout.UsesPushData() && !module->pushData) throw std::runtime_error("specialization removed the prepared push constant interface"); auto selected = DescriptorBindingBuilder{}.Select(plan->bindings, module->bindings); entry->bindings = std::move(selected); entry->module = module; + built = std::move(specialized.spirv); }; std::call_once(entry->ready, [&] { try { @@ -1152,8 +1228,10 @@ RecompileResult materializeResult(const CompiledVariant& variant, const Recompil }); if (entry->failure) std::rethrow_exception(entry->failure); const auto& module = entry->module; + if (built.empty()) built = lockedWords(*module); + if (built.empty()) built = specialize().spirv; result.specializationId = module->specializationId; - result.spirv = module->spirv; + result.spirv = std::move(built); bindingPlan = &entry->bindings; } else { result.spirv = artifact.spirv; @@ -1162,6 +1240,7 @@ RecompileResult materializeResult(const CompiledVariant& variant, const Recompil const auto& tables = *resolved; BindingAllocationResult bindings; DescriptorBindingBuilder{}.Populate(bindings, variant.bindings, *bindingPlan, variant.info.userDataBase, snapshot, partialThreads(request), &tables); + if (patch != nullptr) recordMemoPatch(*patch, *bindingPlan, variant); result.workgroupMemoryDwords = WorkgroupMemoryStrideDwords(variant.info.info); result.bindings = std::move(bindings.bindings); if (std::ranges::none_of(result.bindings, [](const DescriptorBinding& binding) { return binding.role == DescriptorRole::BdaPagetable || binding.role == DescriptorRole::FaultBuffer; })) result.bdaAbiVersion = 0u; @@ -1211,13 +1290,16 @@ SharedSpirv InternSpirv(std::vector words) { SharedSpirv spirv(std::move(words)); const auto hash = spirv.ContentHash(); static std::mutex mutex; - static std::unordered_map> interned; + static std::unordered_map> interned; std::lock_guard lock(mutex); - auto& candidates = interned[hash.low ^ (hash.high * 0x9e3779b97f4a7c15ull)]; - for (const auto& candidate : candidates) { + const auto bucket = hash.low ^ (hash.high * 0x9e3779b97f4a7c15ull); + auto& candidates = interned[bucket]; + std::erase_if(candidates, [](const SharedSpirv::Weak& candidate) { return candidate.Expired(); }); + for (const auto& weak : candidates) { + const auto candidate = weak.Lock(); if (candidate.ContentHash() == hash && candidate == spirv) return candidate; } - candidates.push_back(spirv); + candidates.push_back(spirv.Weaken()); return spirv; } @@ -1357,21 +1439,78 @@ bool ResultMemo() { return resultMemo; } -ResultMemoEntry* memoSet(SourceEntry& source, std::uint64_t index) { - if (source.memo == nullptr) return nullptr; - return source.memo->data() + static_cast((index ^ (index >> 32u)) % ResultMemoSets) * ResultMemoWays; +bool MaskedResultMemo() { + static const bool masked = std::getenv("APS5_NO_MASKED_RESULT_MEMO") == nullptr; + return masked; +} + +bool VerifyMaskedResultMemo() { + static const bool verify = std::getenv("APS5_VERIFY_MASKED_RESULT_MEMO") != nullptr; + return verify; +} + +ResultMemoEntry* memoSet(const std::unique_ptr& table, std::uint64_t index) { + if (table == nullptr) return nullptr; + return table->data() + static_cast((index ^ (index >> 32u)) % ResultMemoSets) * ResultMemoWays; } struct ResultMemoCounters { - std::atomic hits{0}, misses{0}, evictions{0}, populateNanoseconds{0}; + std::atomic hits{0}, patched{0}, misses{0}, evictions{0}, populateNanoseconds{0}, patchNanoseconds{0}, mismatches{0}; std::atomic lastReport{0}; }; +void applyMemoPatch(RecompileResult& result, const MemoPatch& patch, const ResourceSnapshot& snapshot) { + for (const auto& [binding, resources] : patch.buffers) { + auto& words = result.bindings.at(binding).guestDescriptor; + if (words.size() != resources.size() * 4u) throw std::runtime_error("a patched guest buffer binding changed its width"); + for (std::size_t element = 0; element < resources.size(); ++element) std::copy_n(snapshot.buffers.at(resources[element]).dwords.begin(), 4u, words.begin() + element * 4u); + } + if (!patch.userWords.empty()) { + if (patch.pushData) { + if (patch.userWords.size() * sizeof(std::uint32_t) > result.pushConstants.size()) throw std::runtime_error("patched user data lies outside the push data"); + for (std::size_t word = 0; word < patch.userWords.size(); ++word) std::memcpy(result.pushConstants.data() + word * sizeof(std::uint32_t), &snapshot.userData.at(patch.userWords[word]), sizeof(std::uint32_t)); + } else { + auto& words = result.bindings.at(patch.shaderData).guestDescriptor; + if (patch.userWords.size() > words.size()) throw std::runtime_error("patched user data lies outside the shader data"); + for (std::size_t word = 0; word < patch.userWords.size(); ++word) words[word] = snapshot.userData.at(patch.userWords[word]); + } + } + if (patch.flattenedSrt != MemoPatch::NoBinding) result.bindings.at(patch.flattenedSrt).guestDescriptor = snapshot.flattenedSrt; + result.poisonedSrtReads = static_cast(snapshot.srtPoison.size()) + snapshot.nullRootReads; +} + +const char* patchedResultDifference(const RecompileResult& patched, const RecompileResult& full) { + if (patched.bindings.size() != full.bindings.size()) return "binding count"; + if (patched.pushConstants != full.pushConstants) return "push constants"; + if (patched.specializationId != full.specializationId || patched.spirv.ContentHash() != full.spirv.ContentHash()) return "module"; + if (patched.poisonedSrtReads != full.poisonedSrtReads) return "poisoned SRT reads"; + if (patched.shaderDataUserWords != full.shaderDataUserWords) return "shader data user words"; + if (patched.specialization.size() != full.specialization.size()) return "specialization"; + for (std::size_t index = 0; index < patched.specialization.size(); ++index) { + if (patched.specialization[index].id != full.specialization[index].id || patched.specialization[index].value != full.specialization[index].value) return "specialization"; + } + for (std::size_t index = 0; index < patched.bindings.size(); ++index) { + const auto& left = patched.bindings[index]; + const auto& right = full.bindings[index]; + if (left.role != right.role || left.binding != right.binding || left.count != right.count) return "binding shape"; + if (left.guestDescriptor != right.guestDescriptor) return "binding words"; + } + return nullptr; +} + ResultMemoCounters& resultMemoCounters() { static ResultMemoCounters counters; return counters; } +void verifyPatchedResult(const RecompileResult& patched, const RecompileResult& full, std::uint64_t variantId) { + const auto* difference = patchedResultDifference(patched, full); + if (difference == nullptr) return; + resultMemoCounters().mismatches.fetch_add(1, std::memory_order_relaxed); + static std::atomic printed{0}; + if (const auto index = printed.fetch_add(1, std::memory_order_relaxed); index < 20u) std::fprintf(stderr, "[recompile] masked result memo mismatch %u: variant %016llx differs in its %s\n", index + 1u, static_cast(variantId), difference); +} + void reportResultMemo() { static const bool profile = std::getenv("APS5_PROFILE_DRAW") != nullptr; if (!profile) return; @@ -1384,16 +1523,20 @@ void reportResultMemo() { } if (now - last < 10'000'000'000ll || !counters.lastReport.compare_exchange_strong(last, now, std::memory_order_relaxed)) return; const auto hits = counters.hits.exchange(0, std::memory_order_relaxed); + const auto patched = counters.patched.exchange(0, std::memory_order_relaxed); const auto misses = counters.misses.exchange(0, std::memory_order_relaxed); const auto evictions = counters.evictions.exchange(0, std::memory_order_relaxed); const auto populate = counters.populateNanoseconds.exchange(0, std::memory_order_relaxed); - std::fprintf(stderr, "[recompile] result memo (10 s): %llu hits, %llu misses (%.1f%% hits), Populate %.1f us per miss / %.1f ms in total, %llu evictions\n", static_cast(hits), static_cast(misses), hits + misses != 0 ? 100.0 * static_cast(hits) / static_cast(hits + misses) : 0.0, misses != 0 ? static_cast(populate) / 1000.0 / static_cast(misses) : 0.0, static_cast(populate) / 1e6, static_cast(evictions)); + const auto patching = counters.patchNanoseconds.exchange(0, std::memory_order_relaxed); + const auto mismatches = counters.mismatches.exchange(0, std::memory_order_relaxed); + const auto total = static_cast(hits + patched + misses); + std::fprintf(stderr, "[recompile] result memo (10 s): %llu hits, %llu patched, %llu misses (%.1f%% hits, %.1f%% patched), Populate %.1f us per miss / %.1f ms in total, patch %.1f us each / %.1f ms in total, %llu evictions, %llu patch mismatches\n", static_cast(hits), static_cast(patched), static_cast(misses), total != 0.0 ? 100.0 * static_cast(hits) / total : 0.0, total != 0.0 ? 100.0 * static_cast(patched) / total : 0.0, misses != 0 ? static_cast(populate) / 1000.0 / static_cast(misses) : 0.0, static_cast(populate) / 1e6, patched != 0 ? static_cast(patching) / 1000.0 / static_cast(patched) : 0.0, static_cast(patching) / 1e6, static_cast(evictions), static_cast(mismatches)); } // Everything materializeResult reads besides the variant: the snapshot (the descriptor words, the // flattened SRT, the user data, the uniform fill) and, for the vertex family, the V# table the // attributes are resolved from. -std::uint64_t snapshotHash(const RecompileRequest& request, const ResourceSnapshot& snapshot) { +std::uint64_t snapshotHash(const RecompileRequest& request, const ResourceSnapshot& snapshot, bool masked) { std::uint64_t hash = 0xcbf29ce484222325ull; const auto mix = [&](std::uint64_t value) { hash ^= value; @@ -1411,11 +1554,28 @@ std::uint64_t snapshotHash(const RecompileRequest& request, const ResourceSnapsh for (std::uint32_t i = 0; i < value.dwordCount && i < value.dwords.size(); ++i) mix(value.dwords[i]); } }; - mixDescriptors(snapshot.buffers); + if (masked) { + mix(snapshot.buffers.size()); + for (const auto& value : snapshot.buffers) { + mix(value.dwordCount); + mix(value.availableDwordMask); + const bool present = value.dwords[2] != 0u && (value.dwords[0] != 0u || (value.dwords[1] & 0xffffu) != 0u); + mix(present ? 4u | (value.dwords[0] & 3u) : 0u); + mix(value.dwords[1] & 0xffff0000u); + for (std::uint32_t i = 3; i < value.dwordCount && i < value.dwords.size(); ++i) mix(value.dwords[i]); + } + } else { + mixDescriptors(snapshot.buffers); + } mixDescriptors(snapshot.images); mixDescriptors(snapshot.samplers); - mixWords(snapshot.flattenedSrt); - mixWords(snapshot.userData); + if (masked) { + mix(snapshot.flattenedSrt.size()); + mix(snapshot.userData.size()); + } else { + mixWords(snapshot.flattenedSrt); + mixWords(snapshot.userData); + } mix(static_cast(snapshot.uniformFill.kind)); mix(snapshot.uniformFill.resource); for (const auto stride : snapshot.uniformFill.groupStride) mix(stride); @@ -1474,16 +1634,16 @@ std::uint64_t snapshotHash(const RecompileRequest& request, const ResourceSnapsh // as good). `memoHit` reports the hit. std::shared_ptr materializePreparedMemoized(SourceEntry& source, const std::shared_ptr& variant, const RecompileRequest& request, const ResourceSnapshot& snapshot, bool cacheHit, bool* memoHit) { static const bool profile = std::getenv("APS5_PROFILE_DRAW") != nullptr; - const auto hash = snapshotHash(request, snapshot); - std::uint64_t index = 0; + const auto variantId = variant->artifact.variantId; + const auto hash = snapshotHash(request, snapshot, false); + const auto index = (variantId * 0x9e3779b97f4a7c15ull) ^ hash; auto& counters = resultMemoCounters(); { std::lock_guard lock(source.mutex); - index = (variant->artifact.variantId * 0x9e3779b97f4a7c15ull) ^ hash; - if (auto* set = memoSet(source, index)) { + if (auto* set = memoSet(source.memo, index)) { for (std::size_t way = 0; way < ResultMemoWays; ++way) { auto& entry = set[way]; - if (entry.result == nullptr || entry.variantId != variant->artifact.variantId || entry.hash != hash) continue; + if (entry.result == nullptr || entry.variantId != variantId || entry.hash != hash) continue; entry.used = ++source.memoClock; counters.hits.fetch_add(1, std::memory_order_relaxed); if (memoHit != nullptr) *memoHit = true; @@ -1492,32 +1652,61 @@ std::shared_ptr materializePreparedMemoized(SourceEntry& } } } - const auto started = profile ? std::chrono::steady_clock::now() : std::chrono::steady_clock::time_point{}; - auto result = std::make_shared(materializeResult(*variant, request, snapshot)); - result->cacheHit = cacheHit; - if (profile) counters.populateNanoseconds.fetch_add(static_cast(std::chrono::duration_cast(std::chrono::steady_clock::now() - started).count()), std::memory_order_relaxed); - counters.misses.fetch_add(1, std::memory_order_relaxed); - std::shared_ptr shared = std::move(result); - { + const bool masking = MaskedResultMemo(); + const auto maskedHash = masking ? snapshotHash(request, snapshot, true) : 0u; + const auto maskedIndex = (variantId * 0x9e3779b97f4a7c15ull) ^ maskedHash; + std::shared_ptr donor; + std::shared_ptr donorPatch; + if (masking) { std::lock_guard lock(source.mutex); - if (source.memo == nullptr) source.memo = std::make_unique(); - auto* set = memoSet(source, index); - auto* victim = set; - bool present = false; - for (std::size_t way = 0; way < ResultMemoWays && !present; ++way) { - auto& entry = set[way]; - if (entry.result != nullptr && entry.variantId == variant->artifact.variantId && entry.hash == hash) { + if (auto* set = memoSet(source.maskedMemo, maskedIndex)) { + for (std::size_t way = 0; way < ResultMemoWays; ++way) { + auto& entry = set[way]; + if (entry.result == nullptr || entry.variantId != variantId || entry.hash != maskedHash) continue; entry.used = ++source.memoClock; - shared = entry.result; - present = true; - } else if (entry.used < victim->used) { - victim = &entry; + donor = entry.result; + donorPatch = entry.patch; + break; } } - if (!present) { - if (victim->result != nullptr) counters.evictions.fetch_add(1, std::memory_order_relaxed); - *victim = {variant->artifact.variantId, hash, shared, ++source.memoClock}; + } + const auto started = profile ? std::chrono::steady_clock::now() : std::chrono::steady_clock::time_point{}; + std::shared_ptr result; + std::shared_ptr patch; + if (donor != nullptr) { + result = std::make_shared(*donor); + applyMemoPatch(*result, *donorPatch, snapshot); + if (VerifyMaskedResultMemo()) verifyPatchedResult(*result, materializeResult(*variant, request, snapshot), variantId); + if (profile) counters.patchNanoseconds.fetch_add(static_cast(std::chrono::duration_cast(std::chrono::steady_clock::now() - started).count()), std::memory_order_relaxed); + counters.patched.fetch_add(1, std::memory_order_relaxed); + } else { + if (masking) patch = std::make_shared(); + result = std::make_shared(materializeResult(*variant, request, snapshot, false, patch.get())); + if (profile) counters.populateNanoseconds.fetch_add(static_cast(std::chrono::duration_cast(std::chrono::steady_clock::now() - started).count()), std::memory_order_relaxed); + counters.misses.fetch_add(1, std::memory_order_relaxed); + } + result->cacheHit = cacheHit; + std::shared_ptr shared = std::move(result); + const auto insert = [&](std::unique_ptr& table, std::uint64_t at, std::uint64_t key, std::shared_ptr recipe, bool count) { + if (table == nullptr) table = std::make_unique(); + auto* set = memoSet(table, at); + auto* victim = set; + for (std::size_t way = 0; way < ResultMemoWays; ++way) { + auto& entry = set[way]; + if (entry.result != nullptr && entry.variantId == variantId && entry.hash == key) { + entry.used = ++source.memoClock; + return entry.result; + } + if (entry.used < victim->used) victim = &entry; } + if (count && victim->result != nullptr) counters.evictions.fetch_add(1, std::memory_order_relaxed); + *victim = {variantId, key, shared, ++source.memoClock, std::move(recipe)}; + return shared; + }; + { + std::lock_guard lock(source.mutex); + shared = insert(source.memo, index, hash, nullptr, true); + if (patch != nullptr && patch->valid) static_cast(insert(source.maskedMemo, maskedIndex, maskedHash, patch, false)); } reportResultMemo(); return shared; diff --git a/core/shader/recompiler/Recompiler.hpp b/core/shader/recompiler/Recompiler.hpp index 9462ba0721..212e6b2f8d 100644 --- a/core/shader/recompiler/Recompiler.hpp +++ b/core/shader/recompiler/Recompiler.hpp @@ -603,6 +603,8 @@ inline std::uint64_t HashSpirvWords(std::span words, std::u // reference, or the per-dispatch copy this class removes comes back without a compiler hint. // ContentHash is computed once per shared holder, on first use, and dropped by a write. class SharedSpirv { + struct Holder; + public: SharedSpirv() = default; SharedSpirv(std::vector words) : holder(std::make_shared(std::move(words), nullptr, std::span{})) {} @@ -639,6 +641,25 @@ public: std::vector::iterator insert(std::vector::const_iterator where, std::initializer_list values) { return Mutable().insert(where, values); } friend bool operator==(const SharedSpirv& left, const SharedSpirv& right) { return std::ranges::equal(left.Words(), right.Words()); } + class Weak { + public: + [[nodiscard]] SharedSpirv Lock() const { + SharedSpirv spirv; + spirv.holder = holder.lock(); + return spirv; + } + [[nodiscard]] bool Expired() const { return holder.expired(); } + + private: + friend class SharedSpirv; + std::weak_ptr holder; + }; + [[nodiscard]] Weak Weaken() const { + Weak weak; + weak.holder = holder; + return weak; + } + private: struct Holder { Holder(std::vector words, std::shared_ptr owner, std::span view) : words(std::move(words)), owner(std::move(owner)), view(view) {} diff --git a/core/shader/recompiler/ShaderCacheVersion.cmake b/core/shader/recompiler/ShaderCacheVersion.cmake index f4477ed1e1..b3cbea2c75 100644 --- a/core/shader/recompiler/ShaderCacheVersion.cmake +++ b/core/shader/recompiler/ShaderCacheVersion.cmake @@ -36,11 +36,10 @@ endforeach() set(failures) set(manifest "${EXTRA}\n") set(switches) -foreach(source IN LISTS sources) +foreach(source sourceReal IN ZIP_LISTS sources sourcesReal) if(NOT EXISTS "${source}") continue() endif() - get_filename_component(sourceReal "${source}" REALPATH) file(READ "${source}" text) string(REPLACE "\r\n" "\n" text "${text}") string(SHA256 digest "${text}") @@ -65,7 +64,11 @@ foreach(source IN LISTS sources) set(resolved) foreach(directory IN ITEMS "${sourceDirectory}" ${includeDirectories}) if(EXISTS "${directory}/${included}" AND NOT IS_DIRECTORY "${directory}/${included}") - get_filename_component(resolved "${directory}/${included}" REALPATH) + string(SHA1 includedKey "${directory}/${included}") + if(NOT DEFINED includedReal_${includedKey}) + get_filename_component(includedReal_${includedKey} "${directory}/${included}" REALPATH) + endif() + set(resolved "${includedReal_${includedKey}}") break() endif() endforeach() diff --git a/core/shader/recompiler/Translation/src/RoundingMode.cpp b/core/shader/recompiler/Translation/src/RoundingMode.cpp index 0edeca52f0..0e648acaa9 100644 --- a/core/shader/recompiler/Translation/src/RoundingMode.cpp +++ b/core/shader/recompiler/Translation/src/RoundingMode.cpp @@ -89,6 +89,7 @@ RoundingUse RoundingUseOf(RdnaOpcode opcode) { case RdnaOpcode::VCvtF32I32: case RdnaOpcode::VCvtF32U32: case RdnaOpcode::VLdexpF32: + case RdnaOpcode::VCvtPkU8F32: return {round32, RoundingUseKind::Directed32}; case RdnaOpcode::VCvtF16F32: case RdnaOpcode::VCvtF16U16: @@ -120,7 +121,6 @@ RoundingUse RoundingUseOf(RdnaOpcode opcode) { case RdnaOpcode::VMadmkF32: case RdnaOpcode::VMadakF32: case RdnaOpcode::VFractF32: - case RdnaOpcode::VCvtPkU8F32: case RdnaOpcode::VCvtF32F64: case RdnaOpcode::VDivScaleF32: case RdnaOpcode::VDivFmasF32: diff --git a/core/shader/recompiler/Translation/src/VectorInstructions.cpp b/core/shader/recompiler/Translation/src/VectorInstructions.cpp index f94148689f..804535419f 100644 --- a/core/shader/recompiler/Translation/src/VectorInstructions.cpp +++ b/core/shader/recompiler/Translation/src/VectorInstructions.cpp @@ -111,7 +111,6 @@ std::uint32_t TranslationContext::f32DenormalFlushFor(const RdnaInstruction& ins case RdnaOpcode::VCmpxNleF32: case RdnaOpcode::VCmpxNlgF32: case RdnaOpcode::VCmpxNltF32: - return floatMode.has_value() && ((floatMode->floatMode >> 4u) & 1u) != 0u ? 0u : 1u; case RdnaOpcode::VCvtI32F32: case RdnaOpcode::VCvtU32F32: case RdnaOpcode::VCvtRpiI32F32: @@ -123,6 +122,7 @@ std::uint32_t TranslationContext::f32DenormalFlushFor(const RdnaInstruction& ins case RdnaOpcode::VCvtPkU8F32: case RdnaOpcode::VCvtPkrtzF16F32: case RdnaOpcode::VCvtF16F32: + return floatMode.has_value() && ((floatMode->floatMode >> 4u) & 1u) != 0u ? 0u : 1u; case RdnaOpcode::VDivScaleF32: case RdnaOpcode::VDivFixupF32: case RdnaOpcode::VMadMixloF16: diff --git a/demo/web/app.mjs b/demo/web/app.mjs index 4e0b534145..cfe101fc32 100644 --- a/demo/web/app.mjs +++ b/demo/web/app.mjs @@ -67,8 +67,9 @@ function update() { const totalBytes = sum(summaries.map(summary => summary.totalBytes)); const modules = sum(summaries.map(summary => summary.modules)); const sizeText = value => value === null ? "beyond the supported size range" : bytes(value); + const countText = value => value === null ? "beyond the supported range" : value; $("archive-info").textContent = multi - ? `${selectedInputs.length} apps · ${sizeText(totalFiles)} files · ${sizeText(totalBytes)} expanded · ${sizeText(modules)} modules · ${sizeText(selectedBytes)} ${target} conversion input` + ? `${selectedInputs.length} apps · ${countText(totalFiles)} files · ${sizeText(totalBytes)} expanded · ${countText(modules)} modules · ${sizeText(selectedBytes)} ${target} conversion input` : `${summaries[0].files} files · ${bytes(summaries[0].totalBytes)} expanded · ${summaries[0].modules} modules · ${bytes(target === "windows" ? summaries[0].windowsSelectedBytes : summaries[0].selectedBytes)} ${target} conversion input` + (summaries[0].root ? ` · Root: ${summaries[0].root}` : ""); } $("save-note").textContent = multi ? $("save").value === "memory" ? "Creates one ZIP with each app in its own folder. The complete bundle must fit in the 256 MiB memory-download budget." : "Writes one compressed ZIP containing each app in its own folder, without holding the whole bundle in memory." : $("save").value === "disk" ? "Creates a subfolder with the executable, libs and app0. No ZIP compression. Incomplete output folders are removed after cancellation or failure. Browsers may block DLL and other restricted files; use ZIP for those apps." : $("save").value === "zip" ? "Writes a compressed ZIP directly to disk without holding the whole archive in memory." : "Up to 256 MiB including expanded files and output overhead."; diff --git a/docs/dev/ARCHITECTURE.md b/docs/dev/ARCHITECTURE.md index 6c47cfa197..5ac78599df 100644 --- a/docs/dev/ARCHITECTURE.md +++ b/docs/dev/ARCHITECTURE.md @@ -128,13 +128,13 @@ flowchart LR - A compute shader whose LDS plus its lock dword exceeds the host's `maxComputeSharedMemorySize` is not given a `Workgroup` array. `Recompile` sets `ShaderInfo::sharedMemoryBytes` for it and the SPIR-V backend addresses the LDS in a coherent storage buffer at descriptor set 1 (`WorkgroupMemoryDescriptorSet`), with a slice of `RecompileResult::workgroupMemoryDwords` per workgroup, indexed by `WorkgroupID` and `NumWorkGroups`. `VulkanDevice` keeps one such buffer, sized from the dispatch dimensions, and binds it after the resource set; programs that fit keep using shared memory. - `Driver::RegisterShader` splits shader preparation in two. `PlanRegistered` runs on the registering guest thread: it validates the registers and entry point, decodes the code and builds the recompile request, so invalid registrations still fail there. The RDNA to IR translation and resource plan (`PrepareShader`) run on a background pool of `hardware_concurrency() / 2` detached threads (at least 2, 64 MiB stacks). - A thread that needs the GPU mutex, the committer's next item or the end of the committer's queue spins before it blocks (`HandoffSpin.hpp`): `GpuMutexType::lock` retries `try_lock` for the window, the committer polls its item count, and `DrawPipeline::Drain` polls it for twice the window, so a hand-off that completes within the window costs no kernel wake-up. The window is 150 us when the process may run on more than 8 logical processors (its affinity mask, via `CpuTopology`) and 0 otherwise, where the spinning threads would compete with the holder; `APS5_HANDOFF_SPIN_US=` sets it (0 turns it off, at most 10000). Ordering and the lock's semantics are unchanged. -- Queue 0's packet worker decodes, captures and prepares a draw and hands its recording (`Graphics::Draw` under the GPU lock) to a committer thread in [`DrawPipeline.cpp`](../../core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawPipeline.cpp), so the next packet is decoded while the previous draw is recorded. Each queued item carries the guest ranges it will write (`DrawWriteRanges`: written buffers and storage images, color targets with their DCC and CMASK, depth and stencil). A later packet that reads or writes one of those ranges, or that the pipeline can't order, drains it first; labels, submission ends, buffer fills and (with `APS5_PIPELINE_DMA=1`) DMA packets are queued as items instead. With `APS5_PIPELINE_DISPATCH=1` (off by default), a `DISPATCH_DIRECT` whose dispatch-cache entry hits with a recipe is queued as an item too, carrying the dispatch's written buffers and storage images (`DispatchWriteRanges`); the capture and the cache lookup stay on the worker and the recipe is recorded on the committer. A dispatch still drains when its lookup misses, when what it reads overlaps a write still pending, when the hit is verified against data or when its writes cannot be ranged (bindless access, GDS, fault buffer). An indirect draw resolved on the CPU (its records read by the worker) drains only when its records or its count overlap a queued write; the records it draws inline drain first, and its last drawn record is queued like a direct draw (`APS5_NO_PIPELINED_INDIRECT=1` drains at every indirect draw). An exception thrown by a commit is rethrown on the worker at its next enqueue or drain, as an inline draw error would be. On by default; `APS5_PIPELINED_DRAWS=0` records every draw inline, and `APS5_EXACT_DRAW_WRITES=0` widens the color and depth ranges to estimates. +- Queue 0's packet worker decodes, captures and prepares a draw and hands its recording (`Graphics::Draw` under the GPU lock) to a committer thread in [`DrawPipeline.cpp`](../../core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawPipeline.cpp), so the next packet is decoded while the previous draw is recorded. Each queued item carries the guest ranges it will write (`DrawWriteRanges`: written buffers and storage images, color targets with their DCC and CMASK, depth and stencil). A later packet that reads or writes one of those ranges, or that the pipeline can't order, drains it first; labels, submission ends, buffer fills and DMA packets are queued as items instead. With `APS5_PIPELINE_DISPATCH=1` (off by default), a `DISPATCH_DIRECT` whose dispatch-cache entry hits with a recipe is queued as an item too, carrying the dispatch's written buffers and storage images (`DispatchWriteRanges`); the capture and the cache lookup stay on the worker and the recipe is recorded on the committer. A dispatch still drains when its lookup misses, when what it reads overlaps a write still pending, when the hit is verified against data or when its writes cannot be ranged (bindless access, GDS, fault buffer). An indirect draw resolved on the CPU (its records read by the worker) drains only when its records or its count overlap a queued write; the records it draws inline drain first, and its last drawn record is queued like a direct draw (`APS5_NO_PIPELINED_INDIRECT=1` drains at every indirect draw). An exception thrown by a commit is rethrown on the worker at its next enqueue or drain, as an inline draw error would be. On by default; `APS5_PIPELINED_DRAWS=0` records every draw inline, and `APS5_EXACT_DRAW_WRITES=0` widens the color and depth ranges to estimates. - A dispatch's resource build runs stage A (binding plan, buffers, descriptor set) without the GPU lock and stage B (image lookups) under it. Between them `VulkanDevice::presync` waits, still without the lock, for recorded work that writes a surface stage B would read on the CPU and for recorded work that writes the DCC keys of an image the dispatch binds (`ShaderResources::PresyncSurfaces`), so the locked `WaitForKeyWriters` finds nothing pending to synchronize with. A key range is waited for only when recorded work writes it, the key-store memo does not give its value (`DccKeyWritersPending`, without the mutex) and the pending stores do not give it either (`DccKeyWriterNeedsSync`, under the mutex, the same test `WaitForKeyWriters` makes before it synchronizes). Stage A's own key scan runs before that wait, and stage B compares it with the keys it reads under the lock as before. `APS5_NO_DCC_PRESYNC=1` leaves the key ranges out; `APS5_NO_PRESYNC=1` disables the whole pre-sync. - `APS5_DRAW_PIPELINE=1` (off by default, meant with `APS5_PIPELINED_DRAWS=32 APS5_PIPELINE_DISPATCH=1`) takes more of a draw off the worker. A `DrawFinisher` thread runs the second half of a direct pipelined draw (stage materialization, the draw cache insert and the hand-off to the committer) while the worker reads the next packets; the worker drains it before the next draw's cache lookup, before packets other than register writes and draws, and before guest reads, and finishes in place a draw whose stages may write memory (`ProgramWritesMemory`) or write through the BDA page table. The committer skips the fragment-output validation and storage-image layer scans whose inputs match its last commit (`CommitTrims`), and a resource or storage image proved current keeps its proof for the rest of the collect epoch until `GuestMemory::BreakProofs` (a CPU write, a write-back, a recorded write) moves `ProofSerial`. Color metadata passes go through the pipeline with their write ranges (`PipelinedColorMetadataPassWrites`) instead of draining it. A data-only hit whose shape entry belongs to an older draw replaces that entry in place at the second sight of the same read user words. On Linux the main image's pages get a page table entry, and capture pages are pooled across threads. `APS5_VERIFY_DRAW_PIPELINE=1` runs a full check next to 1 in 64 reused proofs and prints `[epoch-proofs]` counts. - The shader registry maps a code address to every header registered for that code, in registration order. Static, graphics and rectangle ABI resolution pick the header at the bound address (or one equal to it, `SameHeader`, which also takes a hull header fused by `sceAgcFuseShaderHalves` (type 3) as the registered back half (type 7) it copies, the fused registers aside; graphics ABI resolution then uses the fused header's shader registers); draws and dispatches pick the program by the stage's binary type (`RegisteredProgram`), and a front entry matching both type 2 and type 4 throws. Within a type the last registration wins; re-registering an identical earlier header makes its snapshot current again without preparing it again, and changed code drops the older headers. - The snapshot is published as pending. `SourceHandleFor`, `InvocationFor` and `ShaderPreparationTransaction::Edit` / `Read` wait for the pending job before reading `PreparedShaders`, and rethrow its failure. `APS5_SYNC_SHADER_PREPARE=1` prepares on the registering thread instead. - `APS5_LAZY_SHADER_PREPARE=1` retains registration validation and decoding but discards the temporary plan without queueing preparation. The snapshot is deferred, not pending; draws and dispatches prepare and cache it on first use. A compute or pixel stage's explicit ABI resolution (`ResolveShaderAbi`) plans the stage with the ABI's state, records the ABI and leaves its preparation to the shader's first use, which prepares it with that state (`PreparedShaders::deferredAbis`), so a shader that never draws or dispatches stays unprepared; a graphics-stage ABI is still prepared when it is resolved. This opt-in mode takes precedence over synchronous registration preparation and trades background CPU/memory use for possible first-use stalls; disk caches and shader output are unchanged. -- On devices with graphics pipeline libraries (`SpirvTarget::registrationModules`), a vertex or pixel artifact is emitted in registration form: the buffer V# words, image modes, swizzles and mip ranges, depth-compare state, export mappings and vertex component selectors it used to specialize on per draw are read at run time (image `ResourceMetadata` and a few state dwords in the shader data), descriptor heaps keep every element in place (an unused one gets a null or placeholder descriptor), and the pixel stage's bindings live in descriptor set 1 so each stage's library depends only on its own set layout (`INDEPENDENT_SETS`). An artifact above `registrationWordLimit` SPIR-V words is re-emitted specialized, and `CompiledShaderArtifact::registrationModule` records which form it has. For artifacts in registration form, `RegistrationResult` materializes the module once, and `PrebuildStageLibrary` builds its pre-rasterization or fragment-shader library on a separate one-thread pool (`APS5_PREBUILD_THREADS`) with a fixed default state, pairing it with a stub stage. A later draw with that state finds both libraries in the store and only links. +- On devices with graphics pipeline libraries (`SpirvTarget::registrationModules`), a vertex or pixel artifact is emitted in registration form: the buffer V# words, image modes, swizzles and mip ranges, depth-compare state, export mappings and vertex component selectors it used to specialize on per draw are read at run time (image `ResourceMetadata` and a few state dwords in the shader data), descriptor heaps keep every element in place (an unused one gets a null or placeholder descriptor), and the pixel stage's bindings live in descriptor set 1 so each stage's library depends only on its own set layout (`INDEPENDENT_SETS`). An artifact above `registrationWordLimit` SPIR-V words is re-emitted specialized, and `CompiledShaderArtifact::registrationModule` records which form it has. For artifacts in registration form, `RegistrationResult` materializes the module once, and `PrebuildStageLibrary` builds its pre-rasterization or fragment-shader library on a separate one-thread pool (`APS5_PREBUILD_THREADS`) with a fixed default state, pairing it with a stub stage. A later draw with that state finds both libraries in the store and only links. Ahead-of-time dispatch resolution (`resolveGroupAhead` in [`DispatchAhead.cpp`](../../core/libs/prx/libSceAgcDriver/Execution/src/Driver/Dispatch/DispatchAhead.cpp)) scans the upcoming dispatch run up to the next wait or synchronization packet, moves still-pending registered compute shaders to the front of the registration preparation queue (`PrioritizeRegistrationPreparation`) and queues preparation (`SubmitRegistrationPreparation`) for registered compute shaders that have no prepared entries yet (such as under `APS5_LAZY_SHADER_PREPARE=1`) with the previewed register state and entry offset; when a dispatch resolved ahead misses the dispatch cache in [`Dispatch.cpp`](../../core/libs/prx/libSceAgcDriver/Execution/src/Driver/Dispatch/Dispatch.cpp), `PrebuildComputePipeline` is submitted to the same `APS5_PREBUILD_THREADS` pool so the compute `VkPipeline` is built before the worker reaches the packet. - A draw or dispatch whose state matches no artifact prepared at registration (a title that builds its static ABI state itself, without `sceAgcDriverResolve*Abi`) gets one prepared at use by `SourceHandleFor` or `InvocationFor`, logged once per artifact and kept in the snapshot for the next use. - A stage that `sceAgcDriverResolve*Abi` cannot prepare for the state the title creates its pipeline with (a compute shader that calls user-data pointers, a descriptor the resource plan rejects) is left to its first use like a stage deferred at registration: `ResolveShaderAbi` and `PrepareGraphicsStages` catch the failure inside their own preparation transaction, so the `ShaderPreparationScope` the title's call runs in still commits, log it once per shader, mark the shader deferred and record the ABI key, so a repeated call prepares nothing; `ResolvePreparedGraphics` skips a deferred stage's rectangles until a draw has prepared it. A draw or dispatch that cannot prepare the stage either fails as before. Driver failures, `ProcessShutdown` and a failure stored by the shader's registration preparation still propagate from the ABI call. - A compute shader whose `s_swappc_b64` calls a user-data pointer cannot be linked at registration, because the callee's address is only known at dispatch. `InvocationFor` in [`ShaderRegistry.cpp`](../../core/libs/prx/libSceAgcDriver/Execution/src/Driver/Shaders/ShaderRegistry.cpp) reads each callee from guest memory, appends one copy per call after the caller (`LinkUserDataCalls`) and prepares that linked code, so a different callee gets its own prepared entry. @@ -145,7 +145,7 @@ flowchart LR - Guest memory reaches the GPU through host imports (`VK_EXT_external_memory_host`) where the driver accepts them, and through copies otherwise ([`GuestBufferMemory.cpp`](../../core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp)). A registered range larger than the import window (64 MiB) is imported per window for buffer and fill accesses and whole for an address-based build. Live imports stay under a budget, with the least recently used import retired first (see TechnicalDebt, Host import windows and budget). - A guest protect or unmap that overlaps a plain host-pointer import retires the whole import before changing the guest range (`WaitForLeasesAndImports` in [`GuestBufferMemory.cpp`](../../core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp)). Later accesses import surviving registered ranges again; imports never keep the pages across a cut pinned in a trimmed state. `GuestAllocations::Range::backingSerial` distinguishes the original pages from replacements: untouched pieces of a split keep their serial, newly mapped or protected pieces get a fresh one, and every span passed to `RequireUnpinned` (including the other mappings of remapped direct memory and the resident runs touched by a 2 MiB unmap or remap) gets a fresh serial when the mutation ends. - A draw binds its vertex and index ranges in place from a host import, except with NVIDIA's Windows driver, which reads a host import of guest memory far slower than a buffer it allocated (Astro Bot at Crash Site on an RTX 5070 Ti: 164 against 45 ms of draws per frame), so they are copied there (`DrawInputsInPlaceUsable`, `Context::drawInputsInPlace`). `APS5_DRAW_INPUTS_IN_PLACE=1` binds them in place and `APS5_NO_DRAW_INPUTS_IN_PLACE=1` copies them on any device; the second wins. -- On Windows, a host import of private `MEM_WRITE_WATCH` memory (singly mapped direct memory) stays on `GetWriteWatch` when `ProbeImportWriteProtection` shows the driver reports nothing written after the second GPU read and a GPU write, and a CPU store is collected (`decideImportWatch`). The driver marks every page of such an import written, asynchronously, until a GPU use of it completes (a read on the settle queue ends it even while main-queue work that used the import first is still running, and the first use of an earlier import of the same pages after that read marks nothing), so `settleImport` in [`GuestBufferMemory.cpp`](../../core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp) copies 4 bytes out of the new import on a second queue of the graphics family, or on a queue of another copy-capable family when the graphics family has only one (`Context::settleQueue`, own pool and mutex) inside `ImportWatched`'s window and waits for it, for imports of 1 MiB or more; the main queue can't be used there because `importAllocation` holds the imports lock and `GpuMutex` comes before it in the lock order. A smaller import is compared when it is made, so a title that maps, imports and unmaps a small buffer around every submission does not block its mapping thread. Its 4-byte read is queued instead: the next import lookup that holds `GpuMutex` while the imports match the registry (`settleUnwatchedImports`) records the queued reads into one batch on the main queue, with barriers ordering earlier and later writes around the reads. Submission does not wait on the CPU, and once the batch's fence has signalled a later lookup returns the import's whole 64 KiB blocks to the write watch (`GuestMemory::Rewatch` drops their marks and stamps every block as a CPU store), unless a live storage image overlaps them. Such an import stays compared: an image that took its generation before the stamp would take the stamp for a CPU store over the results it produces after it, and drop them. A settled import whose range had already left the watch returns the same way, and an import retired while its read is in flight is kept with that batch and freed once the batch has completed, without waiting for it; a guest unmap of its memory waits for the batch instead. `APS5_NO_DEFERRED_SETTLES` (any value) keeps every import under 1 MiB compared. Imports through a section alias keep tracking on the guest views, and every other Windows host import is compared. A device without such a queue keeps the comparisons. On Linux the settle queue is made when the device imports dma-buf memory, and every dma-buf import of 1 MiB or more is settled right after it is made, for another reason: the kernel maps an import's pages for the GPU at the first submission that uses it, which took about 2 s for a 3 GiB import on RADV and held up the title's frame. The import's buffer is shared with the settle queue's family instead of aliased, since a sparse import is bound to many memory objects. +- On Windows, a host import of private `MEM_WRITE_WATCH` memory (singly mapped direct memory) stays on `GetWriteWatch` when `ProbeImportWriteProtection` shows the driver reports nothing written after the second GPU read and a GPU write, and a CPU store is collected (`decideImportWatch`). The driver marks every page of such an import written, asynchronously, until a GPU use of it completes (a read on the settle queue ends it even while main-queue work that used the import first is still running, and the first use of an earlier import of the same pages after that read marks nothing), so `settleImport` in [`GuestBufferMemory.cpp`](../../core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp) copies 4 bytes out of the new import on a second queue of the graphics family, or on a queue of another copy-capable family when the graphics family has only one (`Context::settleQueue`, own pool and mutex) inside `ImportWatched`'s window and waits for it, for imports of 1 MiB or more; the main queue can't be used there because `importAllocation` holds the imports lock and `GpuMutex` comes before it in the lock order. A smaller import is compared when it is made, so a title that maps, imports and unmaps a small buffer around every submission does not block its mapping thread. Its 4-byte read is queued instead: the next import lookup that holds `GpuMutex` while the imports match the registry (`settleUnwatchedImports`) records the queued reads into one batch on the main queue, with barriers ordering earlier and later writes around the reads. Submission does not wait on the CPU, and once the batch's fence has signalled a later lookup returns the import's pages to the write watch (`GuestMemory::Rewatch` drops the marks of every 64 KiB block they touch and stamps those blocks as a CPU store; the rest of a block the import only partly covers stays unwatched), unless a live storage image overlaps those blocks. Such an import stays compared: an image that took its generation before the stamp would take the stamp for a CPU store over the results it produces after it, and drop them. A settled import whose range had already left the watch returns the same way, and an import retired while its read is in flight is kept with that batch and freed once the batch has completed, without waiting for it; a guest unmap of its memory waits for the batch instead. `APS5_NO_DEFERRED_SETTLES` (any value) keeps every import under 1 MiB compared. Imports through a section alias keep tracking on the guest views, and every other Windows host import is compared. A device without such a queue keeps the comparisons. On Linux the settle queue is made when the device imports dma-buf memory, and every dma-buf import of 1 MiB or more is settled right after it is made, for another reason: the kernel maps an import's pages for the GPU at the first submission that uses it, which took about 2 s for a 3 GiB import on RADV and held up the title's frame. The import's buffer is shared with the settle queue's family instead of aliased, since a sparse import is bound to many memory objects. ### Log output diff --git a/docs/dev/BUILD.md b/docs/dev/BUILD.md index 3693189557..6646a5c33c 100644 --- a/docs/dev/BUILD.md +++ b/docs/dev/BUILD.md @@ -12,7 +12,7 @@ ctest --test-dir build-relinker --output-on-failure Python must be found during CMake configuration for Python tests to be registered. List registered tests with `ctest --test-dir build-relinker -N` and look for `input_magic`, a Python-backed relinker test. If automatic discovery fails, add `-DPython3_EXECUTABLE="C:/path/to/python.exe"` to the configure command, using the path to your Python interpreter, then list the tests again. -This mode builds the conversion tool and its tests on Linux, Windows and macOS, including Apple Silicon. macOS uses AppleClang from the Xcode command-line tools. Windows uses MinGW-w64 GCC with C++20 support and accepts distributions with static or shared runtimes; the full build also requires the exception support described below. The executable is `build-relinker/core/relinker/relinker` (`relinker.exe` on Windows with Ninja). +This mode builds the conversion tool and its tests on Linux, Windows and macOS, including Apple Silicon. macOS uses AppleClang from the Xcode command-line tools (`xcode-select --install`); CMake and Ninja come from Homebrew (`brew install cmake ninja`). Windows uses MinGW-w64 GCC with C++20 support and accepts distributions with static or shared runtimes; the full build also requires the exception support described below. The executable is `build-relinker/core/relinker/relinker` (`relinker.exe` on Windows with Ninja). The output is x86-64: Linux ELF by default, Windows PE with `--windows` or Mach-O with `--macos` ([usage](../user/USAGE.md#input-and-conversion)). Converted games need system libraries built for the target OS and a compatible x86-64 host. This mode does not build those libraries, and releases ship them for Linux and Windows only. Tests inspect all three output formats; execution checks run only on their compatible hosts. @@ -248,7 +248,7 @@ The switch combines with `APS5_TRACE_FRAMES` or `APS5_TRACE_SECONDS`. The interv Set `APS5_TRACE_BENCH=1` together with `APS5_TRACE_SUMMARY_EVERY` to also keep every interval's frame times for a benchmark report. At each interval the presenter hands the kept intervals to a writer thread, which formats and compresses the file and rewrites `aps5-bench--.json.gz` in `APS5_TRACE_DIR` or the working directory: one JSON object with `format` (`aps5-bench/1`), the identity fields of the summary line (`commit`, `dirty`, `env`, `gpu`, `driver`, `os`, `cpu`, `cpu_threads`, `memory_mib` and, with `param.json`, `title_id`, `title` and `content_version`), `intervals_dropped` and `intervals`. Each interval has `start_s`, `end_s`, `first_present`, `resolution`, `gpu_busy_ms` (the interval's total) and `frame_us`, the whole microseconds between consecutive presents. The file keeps the last 240 intervals; `intervals_dropped` counts older ones it no longer holds. Any other value, or the switch without `APS5_TRACE_SUMMARY_EVERY`, fails the first present. The file is written to `.tmp` and then moved over the previous one, so a crash or kill during a rewrite leaves the last complete report. Only the newest report waits for the writer: one handed over while an older one is still pending replaces it. The frame times cost 4 bytes per present in memory. -`python tools/trace_digest.py aps5-summary.jsonl` prints the interval lines of such a file as one row per interval (frame p50, p90, p99, max, GPU busy per present, the busiest queue worker and the largest phase) and a text sparkline of the frame p99 and of the GPU busy time; lines of window captures in the file are skipped, and a change of commit, environment, GPU, driver or OS between intervals is reported. `--json` prints the rows as JSON. +`python tools/trace_digest.py aps5-summary.jsonl` prints the interval lines of such a file as one row per interval (frame p50, p90, p99, max, GPU busy per present, the busiest queue worker and the largest phase) and a text sparkline of the frame p99 and of the GPU busy time; lines of window captures in the file are skipped, and changes to build, environment, host, resolution or title metadata between intervals are reported. `--json` prints the rows, the first interval's identity and the indices of identity changes as JSON. With `APS5_TRACE_SUMMARY_EVERY` set, the recorder writes a timestamp pair per batch for the whole run and every `PerformanceTimer` scope adds its time to the thread's totals, two clock reads per scope. A thread's totals are read while it runs, so a scope that straddles an interval boundary is counted in one interval or the other. diff --git a/docs/dev/CONVENTIONS.md b/docs/dev/CONVENTIONS.md index 87c674dac4..fdf0b83768 100644 --- a/docs/dev/CONVENTIONS.md +++ b/docs/dev/CONVENTIONS.md @@ -20,7 +20,7 @@ There's no need to add image files to the repository. You can add images to the Host code that writes into guest memory through the kernel or a native library must hold a `GuestArena::HostWrite` ([GuestArena.hpp](../../core/libs/prx/libc/include/GuestArena.hpp)) over the destination range for the whole write. This covers file reads (`ReadFile`, `read`, `pread`), socket receives, `DeviceIoControl` and other calls that fill a caller's buffer. -The write watch can leave guest pages read-only between collections: every watched page on macOS, and stable resident runs of at least 256 KiB on Windows (see the write-watch entries in [debt/libc.md](debt/libc.md)). A kernel-mode write into such a page doesn't fault into the watch. It fails instead, with `EFAULT` on macOS and `ERROR_NOACCESS` on Windows. `HostWrite` opens the pages and makes sure the write is recorded. +The write watch can leave guest pages read-only between collections: every watched page on macOS, and on Windows the pages of shared views (shared memory, shared file mappings, and direct memory mapped at more than one guest address), which it tracks by write protection (see the write-watch and Windows direct-memory backing entries in [debt/libc.md](debt/libc.md)). A kernel-mode write into such a page doesn't fault into the watch. It fails instead, with `EFAULT` on macOS and `ERROR_NOACCESS` on Windows. `HostWrite` opens the pages and makes sure the write is recorded. - A write that completes later on another thread (overlapped I/O, completion ports, asynchronous reads) is bracketed where the bytes land, not where the request was issued. - Ordinary CPU stores from host C++ code need no bracket: the write watch records them (through a fault where the page is protected). diff --git a/docs/dev/ENVIRONMENT.md b/docs/dev/ENVIRONMENT.md index 3a728911cd..1d8ecab03a 100644 --- a/docs/dev/ENVIRONMENT.md +++ b/docs/dev/ENVIRONMENT.md @@ -39,6 +39,7 @@ The code reads environment names through `getenv`, `IsEnvironmentSet`, `kibSetti | `APS5_NO_CODE_HASH_KEY` | presence | `core/shader/recompiler/CacheKey.hpp` | | appends every code word to the cache key instead of hashing the code | | `APS5_NO_FAILURE_MEMO` | presence | `core/shader/recompiler/Recompiler.cpp` | | rebuilds a program whose compilation failed instead of reusing the memoized failure | | `APS5_NO_IMAGE_TABLES` | presence | `core/shader/recompiler/Optimization/src/ResourceTracker.cpp` | | disables image tables, leaving table-loaded descriptors unplanned | +| `APS5_NO_MASKED_RESULT_MEMO` | presence | `core/shader/recompiler/Recompiler.cpp` | | materializes every result memo miss instead of patching the buffer descriptors, user data and flattened SRT of a cached result whose snapshot differs only in those words | | `APS5_NO_PERF_DISK_PLANS` | presence | `core/shader/recompiler/Recompiler.cpp` | | disables the disk cache of planning results | | `APS5_NO_PERF_DOM_INTERSECTION` | presence | `core/shader/recompiler/ControlFlow/src/Structurizer.cpp` | | computes dominator intersections into a fresh vector instead of intersecting in place | | `APS5_NO_PERF_ITERATION_SELECTION` | presence | `core/shader/recompiler/ControlFlow/src/Structurizer.cpp` | | recomputes the post-dominator sets when finding a loop's iteration-selection merge instead of reusing them | @@ -55,6 +56,7 @@ The code reads environment names through `getenv`, `IsEnvironmentSet`, `kibSetti | `APS5_TRACE_BDA` | presence | `core/shader/recompiler/Optimization/src/ResourceTracker.cpp` | | prints the first few accesses that make a program take the address-based path | | `APS5_TRACE_BUFFER_WRITTEN` | presence | `core/shader/recompiler/Optimization/src/DescriptorBindingBuilder.cpp` | | prints how many guest buffer elements a program may store to and how many it only loads | | `APS5_TRACE_IMAGE_TABLE` | presence | `core/shader/recompiler/Optimization/src/ResourceMaterializer.cpp` | | traces image-table resolution | +| `APS5_VERIFY_MASKED_RESULT_MEMO` | presence | `core/shader/recompiler/Recompiler.cpp` | | also materializes every patched result memo hit, prints the first twenty whose patched result differs and counts them in the result memo report of `APS5_PROFILE_DRAW` | | `APS5_VERIFY_SRT_COMPACT` | presence | `core/shader/recompiler/Optimization/src/SrtWalker/SrtDescriptorEvaluation.cpp` | | walks every SRT descriptor a second time through the IR evaluator and throws when the two walks differ | | `APS5_VERIFY_SRT_TAPE` | presence | `core/shader/recompiler/Optimization/src/SrtWalker/SrtTape.cpp` | | walks a plan's runtime sources a second time through the evaluator, adopts its answers where the two differ and prints the first twenty differences | | `APS5_WAVE_LDS_SUBGROUP` | presence | `core/shader/recompiler/SpirvBackend/src/SpirvEmitter.cpp` | | restores subgroup-scope LDS barriers for single-wave workgroups instead of workgroup scope | @@ -63,7 +65,7 @@ The code reads environment names through `getenv`, `IsEnvironmentSet`, `kibSetti | Name | Kind | Source | Default | Description | |------|------|--------|---------|-------------| -| `APS5_TRACE_LABEL` | integer | `core/libs/prx/libSceAgc/Cb/src/Sync.cpp` | 0 | hex guest address of a RELEASE_MEM label whose packet is logged when recorded | +| `APS5_TRACE_LABEL` | integer | `core/libs/prx/libSceAgc/Cb/src/Sync.cpp`, `core/libs/prx/libSceAgcDriver/Execution/src/Driver/Synchronization/LabelHistory.cpp` | 0 | hex guest address; logs a matching RELEASE_MEM when recorded, and nearby RELEASE_MEM, WRITE_DATA, COPY_DATA, DMA_DATA and WAIT_REG_MEM packets when executed | ### libSceAgcDriver @@ -347,7 +349,6 @@ The code reads environment names through `getenv`, `IsEnvironmentSet`, `kibSetti | `APS5_PACKET_EPOCH` | presence | `core/libs/prx/libSceAgcDriver/Execution/src/Driver/Synchronization/WaitStatistics.cpp` | | makes queue workers bump the collect epoch before every packet | | `APS5_PIPELINED_DRAWS` | integer | `core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawPipeline.cpp` | 8 | depth of the queue-0 draw pipeline: 0 records draws inline, 1 selects the default depth of 8, and any other value is the depth capped at 256 | | `APS5_PIPELINE_DISPATCH` | presence | `core/libs/prx/libSceAgcDriver/Execution/src/Driver/Dispatch/Dispatch.cpp` | | records an eligible dispatch as an item in the queue-0 pipeline instead of running it inline | -| `APS5_PIPELINE_DMA` | presence | `core/libs/prx/libSceAgcDriver/Execution/src/Driver/Packets/PacketMemory.cpp` | | records a queue-0 DMA data packet in the draw pipeline instead of executing it inline | | `APS5_PIPELINE_DRAIN_FILLS` | presence | `core/libs/prx/libSceAgcDriver/Execution/src/Driver/Memory/BufferFill.cpp` | | runs queue-0 buffer fills through the draw pipeline to keep their order; any value stores them in place instead | | `APS5_PIPELINE_DRAIN_LABELS` | presence | `core/libs/prx/libSceAgcDriver/Execution/src/Driver/Packets/PacketExecution.cpp` | | answers a queue-0 wait from the draw pipeline's own pending labels while it is busy; any value drains the pipeline at the wait | | `APS5_PIPELINE_DRAIN_SUBMISSIONS` | presence | `core/libs/prx/libSceAgcDriver/Execution/src/Driver/Packets/PacketExecution.cpp` | | lets a submission end without submitting its recorded work, so it joins a later submit with the pipeline's queue; any value drains the pipeline and submits at the end of the submission | @@ -379,7 +380,8 @@ The code reads environment names through `getenv`, `IsEnvironmentSet`, `kibSetti | `APS5_SKIP_INVALID_INDIRECT_REGISTERS` | presence | `core/libs/prx/libSceAgcDriver/Execution/src/Driver/Packets/PacketExecution.cpp` | | skips the entries whose offset dword is no register offset in a SET_*_REG_INDIRECT list read again where its packet executes, and writes its valid entries, instead of stopping | | `APS5_SKIP_REFUSED_DRAWS` | presence | `core/libs/prx/libSceAgcDriver/Execution/src/Driver/Diagnostics.cpp` | | skips a draw whose graphics stage the recompiler refuses, reporting each refused shader once, instead of failing the queue | | `APS5_SKIP_REQUEST_DUMPS` | integer | `core/libs/prx/libSceAgcDriver/Execution/src/Driver/Shaders/ShaderDiagnostics.cpp` | 8 | caps RecompileRequest dumps per shader-skip reason | -| `APS5_SKIP_SHADER` | integer | `core/libs/prx/libSceAgcDriver/Execution/src/Driver/Diagnostics.cpp` | 0 | hex program address of a shader to skip preparing | +| `APS5_SKIP_SHADER` | integer | `core/libs/prx/libSceAgcDriver/Execution/src/Driver/Diagnostics.cpp` | 0 | hex program address of a shader whose draws and dispatches are dropped | +| `APS5_SKIP_SHADER_FILE` | path | `core/libs/prx/libSceAgcDriver/Execution/src/Driver/Diagnostics.cpp` | | file of whitespace-separated hex program addresses (`#` starts a comment) whose draws and dispatches are dropped; re-read within 500 ms of a change; a token that is not a whole 64-bit hex number is reported and ignored | | `APS5_SNAPSHOT_CHECK_FATAL` | presence | `core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp` | | throws on the first snapshot that differs from registered memory instead of only counting them | | `APS5_SPANNED_WAVE` | presence | `core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp` | | spans a single-wave wave64 compute program over two full 32-lane subgroups | | `APS5_SPIRV_OPT` | string | `core/libs/prx/libSceAgcDriver/tests/SpirvOptimizer.cpp` | | selects the SPIR-V optimization pipeline: `full` restores the performance pipeline, `none` skips optimization | diff --git a/docs/dev/GAME_TESTING.md b/docs/dev/GAME_TESTING.md index 6e74085f0e..82afb1ccfc 100644 --- a/docs/dev/GAME_TESTING.md +++ b/docs/dev/GAME_TESTING.md @@ -12,7 +12,7 @@ For user options see [USAGE](../user/USAGE.md); for internals see [ARCHITECTURE] - Linux: `relinker --registry src/eboot.elf app.elf` - Windows: `relinker --windows --registry src/eboot.elf app.exe`. Without `--windows` the output is an ELF file whatever its name, and Windows refuses to start it (exit code 216, "not compatible with the version of Windows"). - A dump whose `app0` holds `ampr_assets.index` and `ampr_assets-*.pak` was repacked for [ampr_emu](https://github.com/drakmor/ampr_emu): the packed files were removed from `app0`, and only ampr_emu reads the packs. Restore them first with ampr_emu's `tools/ampr_pack.py unpack --index app0/ampr_assets.index --output ` and copy the files missing from `app0`. Without them a Unity title stops at start-up on the missing `Media/Resources/unity default resources`. -- Convert every module the title loads from its own folders (`sce_module/`, `Media/Modules/`, `Media/Plugins/`). Unity titles need `--module-dir Media/Modules --module-dir Media/Plugins`. Put each printed `Guest module:` file next to its original `.prx` in `app0/`, and keep the original there. +- Convert every module the title loads from its own folders (`sce_module/`, `Media/Modules/`, `Media/Plugins/`). Unity titles need `--module-dir Media/Modules --module-dir Media/Plugins`. The relinker writes each converted module as `.guest.prx` into `app0/` beside the output, in the module's own folder, and lists it in the `Arrange the files like this` tree it prints. Keep the original `.prx` next to it. - `libs/` holds only AnyPS5's own libraries, from `build/core/libs/libs` (not `unpatched/`). A game module placed there fails to load (error 193 on Windows). A self-built `libs/` on Windows also needs `libgcc_s_seh-1.dll`, `libstdc++-6.dll` and `libwinpthread-1.dll` from the toolchain's `mingw64/bin`, or every library fails with error 126 ([USAGE](../user/USAGE.md#input-and-conversion)). - Run `tools/import_audit.py` on the registries. Exit code 1 lists imports that will fail or throw. - Run one title at a time. Titles share the GPU and the controller file. Some titles start a second process (Peace Walker's `mgspw.mgspw.elf`) that can outlive a time cap on the first: check that every process of the previous run is gone. diff --git a/docs/dev/TRACING.md b/docs/dev/TRACING.md index 8cb84bb4a4..ba11ed362f 100644 --- a/docs/dev/TRACING.md +++ b/docs/dev/TRACING.md @@ -45,7 +45,7 @@ Set a switch before starting the emulator. Unless noted, any value enables it. M | `APS5_TRACE_HOST_IMPORT` | Host-import mapping attempts, memory-map details, failures and retirement. | | `APS5_TRACE_IMAGE_TABLE` | Image-table resource materialization and descriptor selection. | | `APS5_TRACE_INDIRECT_DRAWS` | Indirect draw packets that pass the draw precheck. | -| `APS5_TRACE_LABEL` | `RELEASE_MEM` packets that target the address in this hexadecimal value. | +| `APS5_TRACE_LABEL` | A matching `RELEASE_MEM` when recorded, and nearby `RELEASE_MEM`, `WRITE_DATA`, `COPY_DATA`, `DMA_DATA` and `WAIT_REG_MEM` packets when executed. Set the value to the guest address in hexadecimal. | | `APS5_TRACE_LATE_LABELS` | GPU label writes observed after their waiting submission was handled. | | `APS5_TRACE_QUERY` | Every sixteenth guest-memory page query, including cost and caller address. | | `APS5_TRACE_RESOURCE_KEY_MISSES` | Resource-content key changes that cause draw or dispatch resource-cache misses. | diff --git a/docs/dev/TechnicalDebt.md b/docs/dev/TechnicalDebt.md index ee2a2dfd75..a9bed3b21f 100644 --- a/docs/dev/TechnicalDebt.md +++ b/docs/dev/TechnicalDebt.md @@ -29,3 +29,4 @@ Throughout the project, every function at every stage either **does exactly what - `--to-intel` guest module trampolines are covered only by a synthetic relinker test; no game title has been verified with them on Linux or Windows. - [Quick syntax checks](../../tools/check_compile.py) reject unexpanded `@response` arguments rather than parse compiler-specific quoting and risk retaining output flags. Expand response files in `compile_commands.json` before checking; the Ninja fallback expands them with `ninja -t compdb -x`. +- [Quick syntax checks](../../tools/check_compile.py) do not model every compiler option's operand count. A preprocessing mode following an unrecognized option without a joined value is rejected rather than risk removing that option's operand. Compiler wrappers with their own option grammar are not covered. Forwarded frontend actions (`-Xclang`, `-Xpreprocessor` and their joined forms) are rejected. Comma-forwarded options (`-Wp,`) allow only recognized macro/include operands; response-file tokens are rejected even as operands, and other options are rejected because unmodeled actions or output operands could bypass syntax analysis or write outputs. See the [Clang option grammar](https://clang.llvm.org/docs/ClangCommandLineReference.html). diff --git a/docs/dev/debt/libSceAgc.md b/docs/dev/debt/libSceAgc.md index aa30dca0b0..43c8c621b4 100644 --- a/docs/dev/debt/libSceAgc.md +++ b/docs/dev/debt/libSceAgc.md @@ -19,6 +19,7 @@ - [sceAgcDcbContextStateOp](../../../core/libs/prx/libSceAgc/DcbState/src/ContextState.cpp) (libSceAgc) - delegates to `sceAgcDcbContextStateOp_0100` (same packets as KytyPS5's `AgcDcbContextStateOp`); KytyPS5 returns nullptr for an operation above 3, here it throws; the packet words were not compared with a real console - [sceAgcBranchPatchSetThenTarget_0300, sceAgcBranchPatchSetElseTarget_0300](../../../core/libs/prx/libSceAgc/Patch/src/Branch.cpp) (libSceAgc) - names from their NIDs (`7Wa3aeJgeVU`, `rP5xLdOf26k`); the `(packet, cachePolicy, target, sizeInDwords)` signature is inferred from PPSA28416's calls (a branch packet, 0, an aligned target, 4), with the policy stored where `sceAgcCbBranch` puts it - [sceAgcDcbSet{Cx,Sh,Uc}RegistersIndirectGetSize](../../../core/libs/prx/libSceAgc/DcbState/src/Registers.cpp) (libSceAgc) - the count argument is ignored: PPSA28416 calls them with leftover register contents (0xf5f5039c), so the real functions likely take none; the size is 20 bytes either way +- [sceAgcCbSetShRegistersDirect, sceAgcCbSetUcRegistersDirect](../../../core/libs/prx/libSceAgc/Cb/src/Registers.cpp) (libSceAgc) - a register list may start at any byte address, and its 8-byte `{offset, value}` entries are copied byte for byte. PPSA26344 (02.002.000) passes the `sh_registers` lists of compute shader headers that sit 1 byte past an 8-byte boundary in `core_common_subcore.core_b1_fx.sprig.xpps` ([#902](https://github.com/boykopovar/AnyPS5/pull/902)), so those lists start at 1 mod 4 (0x8021363131 in an open-world run). The title runs on the console with these lists, but how the console reads an unaligned list (at the given address, or at a rounded-down one) is not measured - [sceAgcUpdateInterpolantMapping_0100](../../../core/libs/prx/libSceAgc/Misc/src/ShaderFusion.cpp) (libSceAgc) - name from its NID (`k0E7vkgqAuE`); the `(regs, vs, ps)` arguments are the declared ones, behaviour unknown - [sceAgcWriteDataPatchSetDst, sceAgcWriteDataPatchSetCachePolicy and their Async forms](../../../core/libs/prx/libSceAgc/Patch/src/WaitRegMem.cpp) (libSceAgc) - the signatures `(packet, uint8 value)` are inferred from the other patch functions, as no public declaration was found; the value is taken in the encoding of the `dst` and `cachePolicy` arguments of `sceAgcDcbWriteData` (graphics) and `sceAgcAcbWriteData` (Async, compute), and the patched packet is the one those calls would write. `sceAgcAsyncWriteDataPatchSetAddressOrOffset` is assumed to patch the address like `sceAgcWriteDataPatchSetAddressOrOffset`, as the compute WRITE_DATA packet keeps it in the same dwords - [sceAgcCreateInterpolantMapping_10000](../../../core/libs/prx/libSceAgc/Shader/src/InterpolantMapping.cpp) (libSceAgc) - name from its NID (`dbOlWdppb4o`); same arguments as `sceAgcCreateInterpolantMapping_0100`; PPSA26344 passes three pointers at each of nine observed call sites (`0x9F914E`, `0x9F91E2`, `0x9F9216`, `0x1604BBD`, `0x16122D7`, `0x1618285`, `0x161838C`, `0x16184EE`, `0x1618607`), consistent with that argument assumption, but does not read the return value there, so its return type is not established. @@ -48,3 +49,4 @@ - [sceAgcDcbEventWrite](../../../core/libs/prx/libSceAgc/DcbFlow/src/Sync.cpp) (libSceAgc) - non-sample-dump event types (any event other than 0x38 and 0x39) emit a 2-dword PM4 packet 0x46 without address dwords; the address argument is ignored for these events. Void Terrarium (PPSA03061, #5055) passes a non-null address buffer (0x00000002d2a10000) with event type 0x16 (cache flush). - This pending declaration has an unverified signature and behavior; it is a parameterless import-resolution declaration that throws through `NotImplemented_nid_no_patch`: [`sceAgcAcbInitializeDefaultHardwareState`](../../../core/libs/prx/libSceAgc/Unimplemented.cpp). +- [sceAgcAcquireMemSetEngine, sceAgcCbMemsetExclusive](../../../core/libs/prx/libSceAgc/Unimplemented.cpp) (libSceAgc) - declared with canonical signatures from decrypted headers; behavior on retail consoles remains unmeasured. Both throw through `NotImplemented_nid_no_patch`. diff --git a/docs/dev/debt/libSceAgcDriver.md b/docs/dev/debt/libSceAgcDriver.md index 36535fa9b4..1f7edb0bf8 100644 --- a/docs/dev/debt/libSceAgcDriver.md +++ b/docs/dev/debt/libSceAgcDriver.md @@ -11,7 +11,8 @@ - [sceAgcDriverSubmitAcb, sceAgcDriverSubmitMultiAcbs](../../../core/libs/prx/libSceAgcDriver/Submit/src/Acb.cpp) (libSceAgcDriver) accept compute queues 0x20 to 0x57 and throw for any other. On a PS5 (firmware 13.40, measured 2026-10-19 from inside a retail title) `sceAgcDriverSubmitAcb` returned 0 and ran a label-only buffer on queues 0x20, 0x30, 0x40, 0x50, 0x57 and also 0x58, which throws here; queue 0x1F faulted inside the console's driver (SIGSEGV in libkernel on the calling thread), which throws here too. Queues above 0x58 and `sceAgcDriverSubmitMultiAcbs` were not measured. Closes when: the console's highest accepted compute queue is measured -- [sceAgcDriverAcquireHDRScopesACQ, sceAgcDriverHp3dLockEnd, sceAgcDriverHp3dLockStart, sceAgcDriverIsEsvmProcess, sceAgcDriverNopDataWritePacket, sceAgcDriverReleaseHDRScopesACQ, sceAgcDriverSetValueToSharedGds, sceAgcDriverSetWorkloadStreamInactive, sceAgcDriverSubmitReprojectionAcb, sceAgcDriverSuspendPointSubmitCdbg, sceAgcDriverSysGetGfxAppGpuResetStatus](../../../core/libs/prx/libSceAgcDriver/Unimplemented.cpp) (libSceAgcDriver) - signatures and behavior are unverified; these parameterless declarations only resolve imports and throw through `NotImplemented_nid_no_patch`. +- [sceAgcDriverAcquireHDRScopesACQ, sceAgcDriverHp3dLockEnd, sceAgcDriverHp3dLockStart, sceAgcDriverIsEsvmProcess, sceAgcDriverReleaseHDRScopesACQ, sceAgcDriverSetValueToSharedGds, sceAgcDriverSetWorkloadStreamInactive, sceAgcDriverSubmitReprojectionAcb, sceAgcDriverSuspendPointSubmitCdbg, sceAgcDriverSysGetGfxAppGpuResetStatus](../../../core/libs/prx/libSceAgcDriver/Unimplemented.cpp) (libSceAgcDriver) - signatures and behavior are unverified; these parameterless declarations only resolve imports and throw through `NotImplemented_nid_no_patch`. +- [sceAgcDriverNopDataWritePacket](../../../core/libs/prx/libSceAgcDriver/Unimplemented.cpp) (libSceAgcDriver) - writes an IT_NOP packet with 32-bit address at dword 1 and payload at dword 2, returning 2 dwords for null data or zero bytes, and total dwords otherwise. Console behavior for null or unaligned destination remains unmeasured. - [sceAgcDriverGetCoredumpAddress](../../../core/libs/prx/libSceAgcDriver/Unimplemented.cpp) (libSceAgcDriver) returns the driver's shared coredump-area pointer, which is null when no coredump area is allocated. AnyPS5 reports coredump mode disabled and does not allocate this area; the export returns null. Enabling and populating an AGC coredump area is not implemented. - [sceAgcDriverSetTargetRingForDiag](../../../core/libs/prx/libSceAgcDriver/Unimplemented.cpp) (libSceAgcDriver) returns `0x8A6D0001` (`DRIVER_FEATURE_UNAVAILABLE`), matching the retail PS5 export. The retail diagnostic log message is not reproduced. @@ -71,6 +72,7 @@ - [Written staging window on discrete GPUs](../../../core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp) (libSceAgcDriver) - a written buffer element of a dispatch that is not swept is staged device-local up to 8 MiB on a discrete GPU (`Context::discreteGpu`) and up to 2 MiB otherwise; `APS5_WRITTEN_SHADOW_MAX_KIB` replaces either bound. The 8 MiB figure comes from one title on one NVIDIA Windows system (PPSA09911: a 2.5 and a 3.3 MiB skin-cache output written in place cost 55 ms of GPU time per frame, 1.8 ms of extra staging copies once staged); the point where the two copies of a larger element cost more than its in-place stores, and whether AMD or Linux drivers move it, has not been measured. The window is per element and per use, so a kernel that streams once through an element inside the window pays the copy-in and the copy-back on every dispatch. - [Frame capture](../../../core/libs/prx/libSceAgcDriver/Execution/src/FrameRecorder.cpp) (libSceAgcDriver) records guest memory on Windows only (a VirtualQuery walk of the registry allocations and the Windows write tracker); elsewhere a capture throws when it starts. Ranges are captured by allocation and protection, not by mapping: section views, aliases of one direct memory block and file views are snapshotted and replayed as separate private memory, so a store through one alias is not seen through another, and CPU stores to them during the captured frames are not recorded (only write-watched private memory is). Pages of the title's image are recorded during the frames only when a shader header or an array it points to lies in them and their content changed. A capture starts only at a frame boundary where the driver goes idle within 10 s, and gives up after five boundaries that do not. +- [agc_driver_frame_replay](../../../core/libs/prx/libSceAgcDriver/CMakeLists.txt) (libSceAgcDriver) is neither built nor registered on Windows until the recorder fix for [#10711](https://github.com/boykopovar/AnyPS5/issues/10711) lands: the recorder reads a delta block with `ReadCommittedUnsynced` while the second DMA copy into it is still in flight, so the capture can hold zeros for that block and the replay does not reproduce the second copy. Configure with `-DANYPS5_RUN_QUARANTINED_FRAME_REPLAY=ON` to build and register it; Linux is unaffected, as the test only exists on Windows. - [Frame replay](../../../core/libs/prx/libSceAgcDriver/tools/FrameReplay.cpp) (libSceAgcDriver) orders the calls of different captured threads only by their start (a call starts once every earlier call has started), so the driver sees a schedule the title could have produced, not necessarily the one it did. CPU stores a title made from threads that never call the driver are known only by the next recorded call, so the replay applies them early or late when a GPU wait needs them and derives a value from the wait's reference when no recorded store satisfies it (`of_them_synthesized`). Pacing compares the number of submissions in flight, not what they hold. Prologue registrations of shaders whose memory the title reused after registering them fail and are counted (`stale_registrations`). The title's image range must be free in the replaying process, so the tool is linked at a high image base on Windows. - [Workgroup count split](../../../core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp) (libSceAgcDriver) - a direct dispatch over `maxComputeWorkGroupCount` runs as `vkCmdDispatch` chunks, each bound to a pipeline variant whose workgroup offset specialization constants add the chunk's base to `WorkgroupId` and `GlobalInvocationId`. A variant is built when its chunk base is first recorded, not when the dispatch is prepared. A split of a shader with device-memory LDS throws: its slot base reads the chunk's `NumWorkgroups`, not the dispatch's. Chunks are ordered by a compute barrier, which the console does not have between workgroups of one dispatch. - [Experimental submission progress](../../../core/libs/prx/libSceAgcDriver/Execution/include/Driver/Queues/SubmissionProgress.hpp) (AGC driver) - the opt-in two-millisecond pacing budget is not derived from console hardware. Cross-title performance remains unvalidated; host scheduling can overshoot the timeout and pacing can reduce CPU/GPU overlap. @@ -84,7 +86,7 @@ - [Multisampled DCC comp-to-single clears](../../../core/libs/prx/libSceAgcDriver/Graphics/src/MultisampleTarget.cpp) (AGC driver) - RADV's multisampled comp-to-single clear dispatch ([`radv_clear_dcc_comp_to_single`](https://github.com/mihawk-99/PS5_Mesa/blob/1ba9874f478657ccf6da72ce55f0260164cc0bd0/src/amd/vulkan/meta/radv_meta_clear.c#L954)) is recognized by its code and not run. Its clear color (user data 5 to 8, which the shader stores as the four dwords of sample 0's texel) is recorded for the surface its image descriptor names, and DCC keys of 0x10 on a multisampled target of that surface, pipe-bank XOR, size and sample count import as a clear to it, for texels of 8 to 128 bits. A record is dropped when an unmap or allocation removal covers its surface's base. The guest's color memory doesn't get the color at the blocks' first pixels, and the recorded color is assumed to be the one the keys refer to: RADV writes 0x10 keys only in a fast clear that runs this dispatch for the same image right after, and initializes DCC to 0x00 or 0xff on an image's first use ([`radv_init_color_image_metadata`](https://github.com/mihawk-99/PS5_Mesa/blob/1ba9874f478657ccf6da72ce55f0260164cc0bd0/src/amd/vulkan/radv_cmd_buffer.c#L16894)). A new image on memory reused within one mapping, with the same address, XOR, size and sample count, whose clear runs a comp-to-single shader other than the recognized one, would still import the old color. - [Initial depth and stencil planes](../../../core/libs/prx/libSceAgcDriver/Execution/include/QueueState.hpp) - the console's reset values of `DB_Z_INFO` and `DB_STENCIL_INFO` (context `0x010`-`0x011`) are not measured. Both start, and return after `CLEAR_STATE`, at zero (formats `INVALID`), the value of Linux's [GFX10 clear-state table](https://github.com/torvalds/linux/blob/master/drivers/gpu/drm/amd/amdgpu/clearstate_gfx10.h). The public [register-default tables](../../../core/libs/prx/libSceAgc/Command/include/RegisterDefaultsData.hpp) write `0x80000180` and `0x20000180` instead, also with formats `INVALID`; of their other bits, only `TILE_STENCIL_DISABLE` would change a result: the HTILE layout of a multisampled depth plane whose `DB_STENCIL_INFO` was never written. - [Type-0 and type-1 texture descriptors](../../../core/libs/prx/libSceAgcDriver/Graphics/src/GuestTextureResource.cpp) (`TYPE` = 0 or 1 in dword 3) with a nonzero base are bound as null images, like a zero base. TYPE 0 comes from a gfx1036 (RDNA2) measurement in issue #4139 (image sample, load and resinfo return zero, no fault). TYPE 1 comes from a gfx1010 (RDNA1) measurement in #4139 and #5828 (`image_sample_lz`, `image_sample_b`, `image_load` and `image_get_resinfo` return zero, no fault) with format 22 only; TYPE 1 is not measured on RDNA2, with other formats or with depth-compare reads (`image_sample_c*`). Neither type was measured on the console's gfx1013. -- [Multisampled color targets](../../../core/libs/prx/libSceAgcDriver/Graphics/src/MultisampleTarget.cpp) lose their guest-read guards and cannot be reused after a successful allocation removal or unmap covers their full guarded range. The next target, sampled or storage lookup removes retired cache owners; recorded work and sampled views keep their images alive until their last reference is released. Partial unmaps keep the guard; partial allocation reuse and guest access to live multisampled data remain unsupported. +- [Multisampled color targets](../../../core/libs/prx/libSceAgcDriver/Graphics/src/MultisampleTarget.cpp) lose their guest-read guards and cannot be reused after a successful allocation removal or unmap covers their full guarded range. The next target, sampled or storage lookup removes retired cache owners; recorded work and sampled views keep their images alive until their last reference is released. A target made from a multisampled texture that a sample reads before any draw is retired instead when a guest access overlaps it, until a draw, a dispatch's storage write or an absorbed color fill puts samples on the host only; it is rebuilt from guest memory at its next use. Partial unmaps keep the guard; partial allocation reuse and guest access to live multisampled data remain unsupported. - [Stencil reference export replay](../../../core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp) on devices without `VK_EXT_shader_stencil_export` replays the low eight bits of the values proved from constant, select and phi exports, with an export proved on every kept path. An export the prover cannot bound replays all 256 eight-bit values, one pass per value per triangle (logged once per process). It records instances, then their triangles, then the reference classes of each triangle. One pipeline filters fragments at shader termination against a dynamic push value before late stencil and depth tests. The [Vulkan stencil-reference replacement rule](https://docs.vulkan.org/refpages/latest/refpages/source/FragStencilRefEXT.html) discards bits above the attachment's stencil width; supported stencil attachments have eight bits. Numeric subgroup observations throw except bounded own-lane mask plumbing and group control with kept-lane and derivative-helper coverage proved. WQM inputs must exclude helper contributions (a ballot of the active lanes, as in an EXEC copy, covers whole quads and is accepted), since [non-quad subgroup operations may treat helpers as inactive](https://docs.vulkan.org/glslext/latest/glslext/khr/GL_KHR_shader_subgroup.html). Readonly guarded SRT reads may report internal host faults, and read-only BDA reads may report faults; these draws wait and check faults before publishing results, and loops throw. Indirect draws, restart, strips, fans, tessellation, mesh, multisampling, early tests, ordered pixel execution, guest shader memory writes, other fault-producing memory access, clocks, primitive ID inputs, attachment feedback and pipeline face/channel splits throw. An exhausted stage push range throws. Equivalence to console ordering has not been measured on console hardware. - [32-bit depth-bits reads of guest memory](../../../core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp) (libSceAgcDriver): a sampled 32_UINT or 32_SINT T# with a depth swizzle mode that no live depth surface matches reads the guest bytes through an R32_SFLOAT image, as the recompiler's depth-bits read expects, and the shader casts the fetched value back to the stored dword. On RX 6700 XT (gfx1031, AMD Windows driver 32.0.21045.5002) the read keeps float denormals, the sign bit alone and quiet and signaling NaN payloads bit for bit. A host that canonicalizes NaNs or flushes denormals on a 32-bit float fetch would change those dwords, and other drivers are not measured. A live depth surface whose extent or base level differs from the T# is not used; the read takes the guest bytes, as the 32-bit float and 16-bit views already do. @@ -124,11 +126,13 @@ - [Pending storage-image results](../../../core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp) (libSceAgcDriver) are stored when something reads their memory, not when the GPU work that wrote them completes. A title that waits for that work, frees the image and reuses its memory can have the new data overwritten by the late store (#1970). A title's own CPU reads are not seen either, so a title that reads the results after waiting for a label reads stale memory. Explicit-size file writes (`write`, `pwrite`, `writev`, `pwritev`, AIO and `fwrite`) synchronize their source ranges through the [host-read hook](../../../core/libs/prx/libc/src/GuestArena.cpp); other host readers are not covered. `APS5_STORE_AT_FLIP=1` stores every pending result at each flip and `APS5_STORE_AT_LABEL=1` before each label the GPU writes; both store every pending image, not only the ones the waited-for work wrote, and neither is on by default. - [`APS5_SKIP_REFUSED_DRAWS`](../../../core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawCapture.cpp) (libSceAgcDriver) drops a draw whose graphics stage the recompiler refuses instead of failing the queue, so the frame lacks that draw, and the stage is compiled and refused again at each such draw. Compute refusals still fail. - [Pending storage-image results over memory outside the write watch](../../../core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp) (libSceAgcDriver) leave to the CPU the 64 KiB blocks whose bytes differ from the ones saved at the upload, the fill, the image copy, the previous store or the moment their range left the watch (`Unwatch`, or a host import that does not stay watched), and the blocks the watch saw the CPU write before that moment. A store made on the GPU saves its bytes through a host-visible copy that becomes the saved bytes when its batch completes; a store or a refresh that needs them earlier waits for that batch. A unit without a write generation saves the guest bytes when results land in it outside the watch. One whose range leaves the watch while its results are pending saves its bytes through the unwatch hook, which also runs when a failed collect takes a range out of the watch. A range that leaves the watch without the hook running over it (an import fallback that unwatched without saving) leaves its pending results without saved bytes; storing such results throws. A unit whose results were stored while its blocks were watched keeps only a generation; when its blocks leave the watch while nothing is pending, the hook saves nothing, and results that land in it afterwards have neither saved bytes nor a watch, so storing them throws too. +- [Storage images over uncommitted guest memory](../../../core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp) (libSceAgcDriver) - a storage image whose guest range has no committed page when it is created throws in the `StorageTexture` constructor, which aborts the guest. Several titles reach this intermittently in runs of a few minutes, on AMD and NVIDIA alike; in two of the three logs, lines about storage images over released or rewritten memory (`memory no longer registered`, `guest memory changed while GPU results were pending`) come shortly before it. The log does not name the image's address. What the console does with a storage descriptor over memory that is not committed is unknown, and which allocation the guest recreates there was not found. - Windows host-pointer imports of the guest mapping itself are compared instead of write-watched, except writable imports of private `MEM_WRITE_WATCH` memory when the import probe keeps the write watch and a settle queue exists: those of 1 MiB or more stay watched, and smaller ones return to the watch once their settle has completed, unless a storage image overlaps them (see Pages under an import window): a driver can mark imported pages dirty after the synchronous import window. Shared memory imported through a separate writable alias retains protection-based tracking on the guest views; driver access to the import alias does not disarm those views. [GuestMemory](../../../core/libs/prx/libSceAgcDriver/Execution/src/GuestMemory.cpp) excludes every overlapping 64 KiB tracker block while its backing is retained. A full block replaced by fresh private backing regains tracking and gets a new generation; protection changes, partial replacements and shared remappings do not restore it. Excluded blocks keep their write-watch marks as a hint only (`UntrackedHint`): a storage image or a sampled texture snapshot over them compares its bytes again after a mark in its range, a driver store, a mapping change or a recorded GPU write instead of at every collect epoch or lookup, and a mark the driver makes without a CPU store costs one comparison. This preserves CPU edits through byte comparisons but limits snapshot reuse on excluded blocks to draws of one collect epoch and disables unit shadows for them; restoring tracking on import retirement without replacing the backing remains unimplemented. -- [Pages under an import window](../../../core/libs/prx/libSceAgcDriver/Execution/src/GuestMemory.cpp) whose protection an import resolves count as stored only when their bytes change. A same-value CPU store during that window cannot be distinguished from driver activity and does not win over pending results. On Windows, NVIDIA 617.42 marks every private MEM_WRITE_WATCH page after import until a GPU use completes. The driver behavior was measured on this driver; other drivers are unverified. Imports of at least 1 MiB wait for a four-byte read on the separate settle queue inside the window. Smaller imports stay compared until a deferred read completes; a later lookup returns whole blocks to write watching with a new CPU-store stamp. Blocks overlapping a live storage image, blocks of an import retired before rewatching, and imports without a settle queue stay compared. Shared-memory imports retain their separate-alias tracking. -- [Deferred host-import reads](../../../core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp) use the main queue with barriers ordering earlier and later writes around the reads. Submission does not wait on the CPU. The latency cost of placing batches behind main-queue work is unmeasured. The first-use test now checks that earlier main-queue reads finish before the import returns to write watching; the original two-queue canary measured driver marking while those reads were still in flight. The earlier-import canary still checks later use of another import of the same pages. +- [Pages under an import window](../../../core/libs/prx/libSceAgcDriver/Execution/src/GuestMemory.cpp) whose protection an import resolves count as stored only when their bytes change. A same-value CPU store during that window cannot be distinguished from driver activity and does not win over pending results. On Windows, NVIDIA 617.42 marks every private MEM_WRITE_WATCH page after import until a GPU use completes. The driver behavior was measured on this driver; other drivers are unverified. Imports of at least 1 MiB wait for a four-byte read on the separate settle queue inside the window. Smaller imports stay compared until a deferred read completes; a later lookup returns their pages to write watching, stamping their blocks as CPU stores; the rest of a partly covered block stays compared. Blocks overlapping a live storage image, blocks of an import retired before rewatching, and imports without a settle queue stay compared. Shared-memory imports retain their separate-alias tracking. +- [Deferred host-import reads](../../../core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp) use the main queue with barriers ordering earlier and later writes around the reads. Submission does not wait on the CPU. An initial multisampled DCC import needing a range whose import still awaits its read submits it if needed and waits under the GPU mutex (`WatchedAfterSettle`, #9724). Imports of partial 64 KiB blocks get no deferred read; only that path reads them, returning their pages as CPU stores unless a live, trimmed or parked compared import or storage image shares their blocks; one a recorder holds is unseen. The latency cost of placing batches behind main-queue work is unmeasured. The first-use test now checks that earlier main-queue reads finish before the import returns to write watching; the original two-queue canary measured driver marking while those reads were still in flight. The earlier-import canary still checks later use of another import of the same pages. - [Settled dma-buf imports](../../../core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp) (libSceAgcDriver): on Linux a dma-buf import of 1 MiB or more is read by a 4-byte copy on the settle queue right after it is made (`settleImport`), so the kernel maps its pages for the GPU there and not in the first submission that uses it (about 2 s for a 3 GiB import on RADV). The import's buffer is shared with the settle queue's family. An import made at map time settles on the guest thread that maps the range, inside its map call, so that thread waits while the kernel maps the pages: 0.47 to 2.2 s for the 3 GiB range of Hades (PPSA03355) and 0.49 to 4.3 s for the 4.5 GiB range of ASTRO BOT (PPSA21567) on RADV. Both titles map these ranges at start-up; a title that maps large ranges during gameplay stalls its mapping thread for as long. An import made from a submission settles under the GPU mutex, so its frame still pays for it; a smaller import, and every import on a device with no settle queue (one without a copy-capable queue besides the main one), pays in its first submission. A range imported through a host pointer, as lavapipe imports shared memory, is not settled - [Sparse dma-buf imports](../../../core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp) (libSceAgcDriver): on Linux a shared-backed range larger than one 64 MiB udmabuf buffer is imported as one sparse buffer bound to the 64 MiB buffers, on a queue of its own when the device has a second family that binds sparse memory. The path is decided before anything is imported, and a failure after that throws. A range whose offset in the backing file is not a multiple of 64 KiB starts its sparse buffer at the 64 KiB block below it (`HostImport::lead`). A range takes the single udmabuf import instead, which udmabuf's `size_limit_mb` refuses above 64 MiB by default so the range is copied, when the buffer's sparse block size is larger than 64 KiB (it is 64 KiB on RADV), when the sparse buffer does not accept every memory type a chunk import can have, when the backing file ends inside its last chunk, or when it is imported at map time on a device with no second family (the bind then needs the GPU mutex); the NVIDIA proprietary driver imports no dma-buf memory +- [Presentation under the GPU mutex](../../../core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp) (libSceAgcDriver) - on a device whose presentation family has no queue left after the main and settle queues, such as RADV, lavapipe and Intel's Windows driver (Arc Graphics on Meteor Lake, 101.9150), which expose a single graphics queue, `vkQueuePresentKHR` still runs on the main queue under `GuestMemory::GpuMutex`, so the draw committer and the queue workers wait for as long as the present blocks. How long that is on those drivers was not measured; on NVIDIA in FIFO mode it is about 6 ms per present. A device with a free queue in that family presents on it under its own mutex, after the GPU mutex is released. Closes when: a trace on a single-queue device shows no `GpuMutex.wait.*` behind `Vulkan.QueuePresent`. - [Unnormalized S# coordinates](../../../core/libs/prx/libSceAgcDriver/Graphics/src/GuestSamplerResource.cpp) (libSceAgcDriver) - `FORCE_UNNORMALIZED` uses a Vulkan `unnormalizedCoordinates` sampler, so the S# LOD range, LOD bias and mip filter are not applied, which is exact only on a one-level view. - An [unnormalized S#](../../../core/libs/prx/libSceAgcDriver/Graphics/src/GuestSamplerResource.cpp) (libSceAgcDriver) maps clamp mode 0 (repeat) on X and Y to clamp-to-edge as required by Vulkan unnormalized coordinates, and assigns the magnification filter when minification and magnification filters differ (since unnormalized coordinates sample at LOD 0). Anisotropy, TRUNC_COORD, MC_COORD_TRUNC and other clamp modes still throw. Secondary LOD bias (LOD_BIAS_SEC, bits [19:14]) is accepted and ignored, matching RDNA2 hardware measurements across explicit and implicit samples. High on Life (PPSA15388, #4736) uses secondary LOD bias and unnormalized coordinates with clamp mode 0 and differing min/mag filters during home base and city rendering. - [TRUNC_COORD](../../../core/libs/prx/libSceAgcDriver/Graphics/src/GuestSamplerResource.cpp) (libSceAgcDriver) is not applied: the texel a point sample reads and the bilinear weights follow the host sampler's rounding. On RDNA 2 (RX 6700 XT), an S# with TRUNC_COORD 0 rounds the exact scaled coordinate to 8 fractional bits, ties to even, and one with TRUNC_COORD 1 truncates it, for point and bilinear filters. AMD's Windows driver (32.0.21045.5002) truncates for nearest samplers and rounds for linear ones. Under it, a TRUNC_COORD 0 point sample at most 1/512 texel below a texel edge reads the texel below the edge where the console reads the one above, and `k / width` computed in f32 lands there for about half of all k. A TRUNC_COORD 1 bilinear weight can be 1/256 above the console's. Other host drivers are not measured. @@ -172,13 +176,13 @@ - [Cube texture descriptors](../../../core/libs/prx/libSceAgcDriver/Graphics/src/GuestTextureResource.cpp) with equal `BASE_ARRAY` and `DEPTH` expose six faces starting at `BASE_ARRAY`. Measured with `image_load`, `image_sample` and `image_get_resinfo` on RX 6600 (gfx1032), using 64x64 R32_UINT faces and base slices 0, 5 and 6. Other ranges containing fewer than six faces still throw: hardware load bounds and filtered-sample addressing differ. A range of six faces or more that does not end on a whole cube keeps every slice up to `DEPTH`, the bound loads use on hardware; sampling the cube it cuts short is out-of-range cube-array sampling. Out-of-range cube-array sampling remains unimplemented. Samplers with `DISABLE_CUBE_WRAP` are created with `VK_SAMPLER_CREATE_NON_SEAMLESS_CUBE_MAP_BIT_EXT`, the flag RADV maps to that bit (Mesa `src/amd/vulkan/radv_sampler.c`, `src/amd/common/ac_descriptors.c`); without `VK_EXT_non_seamless_cube_map` a cube texture sampled through such a sampler throws. PS5 equivalence has not been measured on console hardware. - [Array layer views](../../../core/libs/prx/libSceAgcDriver/Graphics/src/GuestTextureResource.cpp) (libSceAgcDriver) - `ArrayLayersServeView` lets a 2D texture at a 2D array image's base address, or a 2D array texture over its first layers, view that image (`Texture::CanCopyFrom`). Mesa-built homebrew (ps5-opengl) writes the view's last slice plus one to `CB_COLOR_ATTRIB3.MIP0_DEPTH`, so a slice-0 render target is a two-layer array image, and the title samples it as a plain 2D texture (SuperTuxKart PPSA69421 drew a black 3D scene and minimap without this). The per-layer layout of a mipmapped array is assumed equal to a standalone surface's; it is not measured on the console. A 2D texture at a later slice's address still gets an image of its own. - [Multisampled CMASK](../../../core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp) (libSceAgcDriver) - a multisampled color target's CMASK is decoded under CB_COLOR_INFO FAST_CLEAR (bit 13, as for a single-sample target) or COMPRESSION (bit 14). Which bit a multisampled target sets is inferred: its fast clears were seen on GTA V's multisampled targets through their CMASK fills, not in a register dump. A COMPRESSION-only target's zero CMASK is not read as cleared (inferred: zero means cleared only under FAST_CLEAR), so only a fill after its first use clears it. A slice of a multisampled array is its own image at its own address with its own CB_COLOR0_CMASK (inferred from the register layout). Its CMASK is main's whole-metablock size. -- [Compressed FMASK reads](../../../core/libs/prx/libSceAgcDriver/Graphics/src/MultisampleTarget.cpp) without an exact resident native owner throw. Native reads require eight fragments, one slice and mip, pipe-aligned DCC/CMASK, Z_64KB_X FMASK and unchanged, disjoint watched planes. The host stores independent samples and exposes their expanded indices (`0x76543210`, AMD PAL `c5e80007`, `Gfx9Fmask::GetPackedExpandedValue`); console equivalence is unmeasured. Other layouts, standalone compressed decoding, guest publication and recipe reuse remain unsupported. Metadata writes invalidate the native view, including same-value stores. +- [Compressed FMASK reads](../../../core/libs/prx/libSceAgcDriver/Graphics/src/MultisampleTarget.cpp) without an exact resident native owner throw. Native reads require eight fragments, one slice and mip, pipe-aligned DCC/CMASK, Z_64KB_X FMASK and unchanged, disjoint watched planes; an FMASK import awaiting its Windows deferred read is read first (`WatchedAfterSettle`). The host stores independent samples and exposes their expanded indices (`0x76543210`, AMD PAL `c5e80007`, `Gfx9Fmask::GetPackedExpandedValue`); console equivalence is unmeasured. Other layouts, standalone compressed decoding, guest publication and recipe reuse remain unsupported. Metadata writes invalidate the native view, including same-value stores. - [Multisampled CMASK state](../../../core/libs/prx/libSceAgcDriver/Graphics/src/MultisampleTarget.cpp) (libSceAgcDriver) - a multisampled target has no guest texels, so its CMASK state comes from fills rather than from a read at each draw as a single-sample target's does. A fill of the whole CMASK with 0 clears the host image at the target's next use, one with 0xcccccccc, 0xdddddddd, 0xeeeeeeee or 0xffffffff marks it expanded, and any other pattern, or a fill that covers only part of the CMASK, throws at the next use (inferred: main's rule that a mixed CMASK is unmodeled, applied to the one host image). A FAST_CLEAR target starts from its CMASK keys at its first use, and a COMPRESSION-only target starts expanded. Copies by DMA into the CMASK are not seen, and a later use with another CMASK address throws. The clear does not rewrite the CMASK bytes as expanded, so a new target over the same CMASK (a different extent, so a different image) seeds from them again and clears once more. - [Multisampled DCC CMASK without fast clears](../../../core/libs/prx/libSceAgcDriver/Graphics/src/MultisampleTarget.cpp) (libSceAgcDriver) - the initial CMASK of a multisampled DCC target is not checked when CB_COLOR_INFO enables COMPRESSION but not FAST_CLEAR: it then holds only FMASK compression, and a uniform DCC clear sets every fragment, so the target imports as that clear. What the console reads where such an FMASK names no fragment, as an uninitialized CMASK can, is unverified. - [Multisampled color fills](../../../core/libs/prx/libSceAgcDriver/Graphics/src/MultisampleTarget.cpp) (libSceAgcDriver) - a multisampled target's samples are on the host, so a fill of its color memory is applied at its next use: a uniform fill over the whole of it clears the host image to that value, and a pending CMASK fast clear takes precedence over the fill and over a fill that would throw. Its color memory is a single mip and slice of addrlib's block dimensions for its sample count (ComputeThinBlockDimension). A fill over part of it, a fill reaching the start of a target whose footprint is not computed (linear), and a fill value with no exact clear value in the format (sRGB channels other than 0 and 1) throw at the next use. A fill before the target's first use is not seen (the host image starts at 0), nor are copies or shader writes into its color memory. A uniform compute fill over exactly the whole color memory with an exact clear value is not stored into guest memory, since only the host image holds the samples. A target is retired only when its whole guarded range is unmapped or its allocation removed, so if a title reuses that memory for other data while it stays mapped, a read the guard does not check (a buffer read through a V# or a pointer) sees the bytes from before the fill. - [Multisampled texture no draw rendered to](../../../core/libs/prx/libSceAgcDriver/Graphics/src/MultisampleTarget.cpp) (libSceAgcDriver) - sampling a multisampled texture whose surface no draw rendered to creates the host target from the T# and clears it to the color a single 32-bit value repeated over the whole footprint encodes, padding up to whole tile blocks included. Inferred, not measured on the console: that the samples of such a surface are the guest color memory, as a title that clears its canvas on the CPU (ps5-opengl `ps5_clear_msaa4_color`) relies on. Memory that is not one repeated value, tile modes other than Standard4KB, Standard64KB, Z64KBX, D64KBX and RenderTarget, unmapped memory and values with no exact clear color throw. CPU writes to the surface after its host target exists are not seen by the host. - [Sample 0 of a multisampled color target](../../../core/libs/prx/libSceAgcDriver/Graphics/src/FirstSampleCopy.cpp) (libSceAgcDriver) - a 2D image read of a multisampled color target returns its float, UNORM, SNORM or sRGB sample 0 exactly only where the driver keeps those values through a shader and a color attachment, which Vulkan does not require, and one of a multisampled depth surface throws. The read binds a one-sample copy that a fragment pass (`texelFetch` of sample 0) draws before every such binding; integer formats copy exactly. -- [Multisampled targets in CB passes](../../../core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp) (libSceAgcDriver) - a CB eliminate or DCC pass over a multisampled target throws, since its texels are on the host and only a CB resolve and an FMASK decompress (`CB_COLOR_CONTROL` mode 5) are modeled. The FMASK decompress only applies the pending CMASK fast clear to the host image; it requires a CMASK address, and the target's DCC and FMASK contents are not interpreted. DCC over a multisampled target is accepted only in that pass and throws everywhere else. A CB resolve into a fast-clear destination throws: the resolve writes the destination's texels but not its CMASK, which would still read as cleared. +- [Multisampled targets in CB passes](../../../core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp) (libSceAgcDriver) - a CB eliminate or DCC pass over a multisampled target throws, since its texels are on the host and only a CB resolve and an FMASK decompress (`CB_COLOR_CONTROL` mode 5) are modeled. The FMASK decompress only applies the pending CMASK fast clear to the host image; it requires a CMASK address, and the target's FMASK contents are not interpreted. In that pass as elsewhere, multisampled DCC is accepted only as a native multisampled DCC fast clear or comp-to-single clear. A CB resolve into a fast-clear destination throws: the resolve writes the destination's texels but not its CMASK, which would still read as cleared. - [Multisampled target guest access](../../../core/libs/prx/libSceAgcDriver/Graphics/src/MultisampleTarget.cpp) (libSceAgcDriver) - the memory a multisampled color target throws on (CPU read, index buffer read, fixed-function vertex buffer read, DMA copy, texture or storage image read) uses fragment-aware 64 KiB blocks for the RenderTarget, Z64KBX and D64KBX tile modes. [AMD Addrlib's GFX10 thin-block rule](https://github.com/GPUOpen-Drivers/pal/blob/c5e800072a32f68b6ccc4422936d96167c6e0728/src/core/imported/addrlib/src/core/addrlib2.cpp#L1680-L1712) gives the block width and height from element bytes and fragment count; its [surface-size calculation](https://github.com/GPUOpen-Drivers/pal/blob/c5e800072a32f68b6ccc4422936d96167c6e0728/src/core/imported/addrlib/src/gfx10/gfx10addrlib.cpp#L4000-L4005) rounds both extents to those blocks and multiplies by element bytes and fragments. Thus a 1920x1080 4x RGBA8 surface occupies 0x1fe0000 bytes, leaving the next allocation at +0x2000000 outside the guard. The 2x and 8x block orientations differ from treating the fragments as a larger element. Console address-layout equivalence has not been measured. Other tile modes retain the conservative `max(CB bytes * samples, width * height * element bytes * samples)` bound, which may still reject a distinct allocation. Live targets remain cached per device, surface address, format, extent and sample count. Retired cache owners are removed on the next target, sampled or storage lookup; outstanding recorded work and sampled views retain their images. Ordinary sampled and storage bindings check the color-target guard before resource reuse, including precollected sampled lookups. Reused image tables do not invalidate on multisample color-target registration yet; their per-element fault handling and native multisample sampling require a separate reuse proof. - [DB depth copies](../../../core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawPrecheck.cpp) (libSceAgcDriver) - with `COPY_CENTROID` the copied sample is sample 0, as [radeonsi](https://gitlab.freedesktop.org/mesa/mesa/-/blob/mesa-24.0.0/src/gallium/drivers/radeonsi/si_state.c#L1679-1681) programs it under a full sample mask, so an edge pixel whose sample 0 the draw doesn't cover can differ from the console's first covered sample; not measured on the console. The copy runs as the title's draw with a driver-authored guest pixel program (hand-encoded RDNA2) that loads the sample through a driver-built T# and exports it as `32_R`. A multisampled plane is read without the native multisample import checks. Stencil copies, depth tests, planes other than `Z_32_FLOAT`, mips, a partial sample mask, blending, indirect draws and other targets throw. - [CB resolve sample count](../../../core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp) (libSceAgcDriver) - a draw with CB_COLOR_CONTROL in resolve mode is a CB resolve when either PA_SC_AA_CONFIG or CB_COLOR0_ATTRIB.NUM_SAMPLES is multisampled, and takes its sample count from CB0. Inferred, not from documentation: PPSA36082 resolves its 4x targets with no sample count in PA_SC_AA_CONFIG, and radeonsi sets PA_SC_AA_CONFIG to 0 for a multisampled framebuffer when rasterizer multisampling and line smoothing are off. PA_SC_AA_CONFIG is only compared with CB0 while PA_SC_MODE_CNTL_0.MSAA_ENABLE is set: PPSA08270 resolves a 4x 512x512 target with MSAA_ENABLE off and PA_SC_AA_CONFIG still at 2x (0x00108001) from earlier draws. @@ -192,6 +196,7 @@ - [HDR output override](../../../core/libs/prx/libSceAgcDriver/Execution/src/HostHdr.cpp) - setting `APS5_FORCE_SDR` suppresses HDR availability reported to titles while retaining the detected display and surface capabilities. It selects the existing SDR presentation path; it does not add support for floating-point BT.2100 PQ buffers (`0xC001070722000000` and `0xC001070700000000`), whose presentation remains refused. The override does not change the host display settings. - [DCC key stores](../../../core/libs/prx/libSceAgcDriver/Graphics/src/DccMetadata.cpp) cover the console's DCC extent only for pipe-aligned DCC of single-level, single-layer 4-byte SW_64KB_R_X surfaces; other surfaces, and every texture and color target key read, cover one byte per 256 bytes. - [DCC key fills over other images](../../../core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp) (libSceAgcDriver) - a uniform fill at a live image's `dccAddress`, at least one key per 256 bytes long, is a key fill of that image even when other live images overlap it, but only while it is no longer than the image's key extent (`DccKeyCount`, the pipe-aligned count); a longer one is classified by its overlaps as before. The bound is inferred, not measured on a title: a longer fill also writes the bytes past the keys, which the overlapping image may own. Whether the title's bloom-target key fills stay within the extent was not checked (`APS5_TRACE_DCC_KEYS` prints the length of the fills classified as keys, not of the refused ones). +- [Mipmapped DCC color targets](../../../core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp) (libSceAgcDriver) - the keys of a 2D color target with more than one mip are modeled for its whole surface only, as for a multi-mip storage image. The resident image takes a uniform clear over all of them, then marks them all uncompressed at its first write. The per-draw handling of a single-mip target's keys does not apply. A draw through the copied (non-resident) path leaves the keys as they were, and the CB metadata passes still refuse such a target. Keys that hold a different state per mip, and `ClearRegister` keys (whose value is a CB register), are not modeled for such a target. The keys of mipmapped DCC array and 3D targets are ignored. - [Comp-to-single DCC keys](../../../core/libs/prx/libSceAgcDriver/Graphics/src/DccMetadata.cpp) (libSceAgcDriver) - key 0x10 (`GFX9_DCC_CLEAR_SINGLE` in Mesa `ac_descriptors.h`) uniform over a surface makes every texel the element at the start of its 256-byte block, the top-left texel of the block where radv's `build_clear_dcc_comp_to_single_shader` stores the clear color. Sampled textures and storage images read that expansion (a storage image's first write stores the keys uncompressed, as under a clear code), and a CB DCC decompress pass stores it over the texels. A fast-clear eliminate over such keys throws, as a metadata pass over mixed keys does; color targets that render over such keys use their stored texels, and textures read mixed keys, and comp-to-single keys of a format whose element does not divide 256 bytes, as stored. "Uniform" is judged over the key bytes the driver reads, one per 256 surface bytes (see DCC key stores above), so a pipe-aligned surface whose keys differ past that range is expanded as if all were comp-to-single, as for the other clear codes. Not verified on hardware - [8_SRGB color targets](../../../core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp) (libSceAgcDriver) on a device that cannot attach and blend R8_SRGB render into an RGBA8_SRGB copy of the target, so the sRGB encode, decode and blend rounding are the device's; the console's are not measured. - [8_SRGB color targets](../../../core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp) (libSceAgcDriver) on such a device throw unless they are single-mip 2D surfaces with a resident image; linear targets have none. @@ -214,7 +219,7 @@ - [Packed 16-bit textures](../../../core/libs/prx/libSceAgcDriver/Graphics/src/TextureFormat.cpp) (libSceAgcDriver) - `5_6_5`, `1_5_5_5` and `4_4_4_4` are viewed as R5G6B5, A1R5G5B5 and B4G4R4A4 (the 4-bit format every Vulkan device can sample; R4G4B4A4 is optional and lavapipe lacks it) with a swizzle that reads X from the low bits, and a DST_SEL of the missing W of `5_6_5` reads X. Measured on RDNA2 (gfx1035), not on the console: through `image_load` and `image_sample_lz`, X, Y, Z (and W of `1_5_5_5` and `4_4_4_4`) come from the low, middle and high fields, and W of `5_6_5` returns X (the low 5 bits), not 1. Storage images use compatible R16_UINT views with the [buffer UNORM store conversion](../../../core/shader/recompiler/SpirvBackend/src/SpirvImageEmitter.cpp); quantization uses nearest even and maps NaN to zero. Rounding ties and NaN handling for packed stores have not been checked on AMD or PS5 hardware. - [Min/max S# reduction](../../../core/libs/prx/libSceAgcDriver/Graphics/src/GuestSamplerResource.cpp) (libSceAgcDriver) - `FILTER_MODE` 1 and 2 use Vulkan's min and max reduction (the same `SQ_IMG_FILTER_MODE` values RADV programs). Measured on RDNA2 (gfx1035), not on the console: only texels of non-zero weight are reduced, and the weight is taken after rounding to the 8-bit subtexel grid (a sample within 1/512 texel of a centre reduces that texel alone); a driver with other `subTexelPrecisionBits` reduces a different set there. Gathers ignore the mode. - [Min/max S#](../../../core/libs/prx/libSceAgcDriver/Graphics/src/GuestSamplerResource.cpp) (libSceAgcDriver, shader recompiler) - throws with a linear mip filter, depth or color-texture compare, or bilinear or anisotropic filtering of an image the recompiler point-samples (sint, converted, depth-bits). With anisotropy the host sampler reduces over its own footprint; [RADV](https://github.com/openbsd/xenocara/blob/1b39033df8d928ec247ca64448c4a63c72302db7/lib/mesa/src/amd/vulkan/radv_sampler.c#L185-L232) programs the same S# for such a Vulkan sampler. Measured on RDNA2 (gfx1030 in [#5156](https://github.com/boykopovar/AnyPS5/pull/5156#issuecomment-6155265616), gfx1035 in #5821), not on the console: without derivatives (`image_sample_lz`), min or max with anisotropic bilinear returns the bilinear minimum or maximum and with anisotropic point the point result, at every ratio field 0 to 4; with derivatives (`image_sample_d`, a 4:1 footprint), anisotropic bilinear at ratio field 2 or 4 reduces over the texels of all its anisotropic taps (the minimum or maximum along the major axis), not one bilinear footprint. A host that is not AMD reduces over its own anisotropic footprint, and Vulkan leaves nearest filtering with anisotropy to the host driver. -- [FORCE_DEGAMMA](../../../core/libs/prx/libSceAgcDriver/Graphics/src/Sampler.cpp) (libSceAgcDriver) - not measured on the console. A sampler that forces sRGB decoding throws for a format not measured on RDNA2. The rest follows gfx1035 and gfx1031 (point and bilinear): sRGB textures sample as without the bit, as in shadPS4 (PS4); UNORM `8`, `8_8`, `8_8_8_8`, BC1, BC2, BC3 and BC7 sample through their sRGB view (decoded before filtering), and SNORM `8`, `8_8` and `8_8_8_8` through the sRGB view of their bytes, as gfx1031 reads them; `16`, `16_16` and `16_16_16_16` UNORM, SNORM and FLOAT, `32`, `32_32` and `32_32_32_32` FLOAT, `10_11_11`, `2_10_10_10`, `5_9_9_9`, `5_6_5`, `1_5_5_5`, `4_4_4_4`, BC4, BC5 and BC6H sample as without the bit, as gfx1031 does. +- [FORCE_DEGAMMA](../../../core/libs/prx/libSceAgcDriver/Graphics/src/Sampler.cpp) (libSceAgcDriver) - not measured on the console. A sampler that forces sRGB decoding throws for a format not measured on RDNA2. The rest follows gfx1035 and gfx1031 (point and bilinear): sRGB textures sample as without the bit, as in shadPS4 (PS4); UNORM `8`, `8_8`, `8_8_8_8`, BC1, BC2, BC3 and BC7 sample through their sRGB view (decoded before filtering), and SNORM `8`, `8_8` and `8_8_8_8` through the sRGB view of their bytes, as gfx1031 reads them; `16`, `16_16` and `16_16_16_16` UNORM, SNORM and FLOAT, `32`, `32_32` and `32_32_32_32` FLOAT, `10_11_11` FLOAT, `2_10_10_10` UNORM, `5_9_9_9`, `5_6_5`, `1_5_5_5`, `4_4_4_4`, BC4, BC5 and BC6H sample as without the bit, as gfx1031 does. - [Tessellation factor ring](../../../core/libs/prx/libSceAgcDriver/State/src/Configuration.cpp) (libSceAgcDriver) - `sceAgcDriverSetTFRing` records the ring and `sceAgcDriverGetTFRing` reports it. Before a title sets one, it reports the console's default, 0xFF0000000 and 128 KiB, as measured in [PS5_Vulkan's hardware findings](https://github.com/mihawk-99/PS5_Vulkan/blob/fde9e3798c2ec1d8fccc90d5067cd6060490607f/docs/HARDWARE_FINDINGS.md). Nothing is written to the recorded ring: tessellated draws run as Vulkan tessellation stages, which keep their factors on the host, so a title that reads tessellation factors from the ring finds none. A null base or a zero size throws; [ps5-opengl's AGC runtime](https://github.com/blackbearreloaded/ps5-opengl/blob/67c873f985eaefe0a72f713529e5632eaa01139c/src/platform/ps5_agc_native_runtime.c) calls `sceAgcDriverSetTFRing(0, 0)` in its cleanup, and what that does on the console is unknown. - [VertexBufferReadSize](../../../core/libs/prx/libSceAgcDriver/Graphics/include/VertexInput.hpp) and the [vertex staging copy](../../../core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp) (libSceAgcDriver) - a vertex fetch whose index is at or past the descriptor's `num_records` no longer throws for `OOB_SELECT` 0 and 1. The copy still spans the whole fetch, but the bytes from `num_records * stride` onward read as zeros, so the out-of-range vertex is `(0, 0, 0, 0)`. Measured with `buffer_load_format_xyzw` (`idxen`) through the [hardware oracle](../HW_ORACLE.md) on RDNA2 gfx1036 for PPSA01325's word 3 `0x0004dfac` (`OOB_SELECT` 0) in #2241: indices 3, 4 and 5 over 3 records each return `00000000 00000000 00000000 00000000`, W included, unlike Vulkan `robustBufferAccess`, which returns `(0, 0, 0, 1)`. The zeros come from the record check, not from memory: stored values placed past the records are ignored, and a `num_records` 6 control returns them. `RESOURCE_LEVEL` 1, `OOB_SELECT` 1 and FORMAT 74 `32_32_32_FLOAT` give the same zeros, in wave32 and wave64; gfx1013 (the console) is not measured. `OOB_SELECT` 2 returns the stored values past the records and `OOB_SELECT` 3 compares `num_records` against the byte offset, both measured on the same setup in #2241; the two keep throwing past `num_records` here, since each needs its own rule. Zero-stride descriptors (`stride` 0) keep their separate byte-count check and are not covered here. Each out-of-range fetch is copied alone and outside the draw-snapshot cache, which is neither read nor written for it: a reused snapshot would carry another draw's bytes into the zero region, and a stored zero-padded copy would hand zeros to a later in-range draw at the same address. The valid prefix is still flushed for GPU writes before it is read. - [Draw snapshot buffer descriptors](../../../core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp) rewrite each affected array from element zero, preserving unchanged descriptors. MoltenVK 1.4.2 writes auxiliary buffer lengths at index `i` instead of `start + i` for partial array updates ([MVKDescriptorSet.mm, BufferAuxSize](https://github.com/KhronosGroup/MoltenVK/blob/v1.4.2/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.mm#L1051)). Per-element writes therefore let one buffer length replace another even when Vulkan buffer handles and ranges are correct. @@ -237,7 +242,8 @@ - [16-bit depth with stencil](../../../core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp) (libSceAgcDriver) is stored as `D24_UNORM_S8_UINT`, or `D32_SFLOAT_S8_UINT`, on a device without `D16_UNORM_S8_UINT` as an attachment. Depth comparisons, clears and the depth image see the wider format's precision, so results at the 16-bit quantization boundary can differ from the console; the constant depth bias is scaled by 256 for D24, and a non-zero constant on the D32 float fallback throws. Not measured on console hardware. - [Depth surfaces created over storage writes](../../../core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp) (libSceAgcDriver): a depth surface created without HTILE copies its depth plane from the storage image at the plane's address, a pending one first, when that image has the plane's extent, one level, a 2D view or a 2D array view (its layer 0 is copied) and a 16-bit format for a 16-bit plane or a 32-bit format for a 32-bit plane. A multisampled surface, a surface the device stores in another format, a surface with HTILE and a surface without such an image start from `DB_DEPTH_CLEAR`, and the stencil plane from `DB_STENCIL_CLEAR`; CPU writes to the plane's memory are not read. Not measured on the console, where the plane is that memory. - [Flip packets raise the graphics end-of-pipe event](../../../core/libs/prx/libSceAgcDriver/Execution/src/Driver/Packets/PacketExecution.cpp) (libSceAgcDriver) - a flip delivers the queue's end-of-pipe event (`sceAgcDriverAddEqEvent`) once the work recorded before it completes, as a `RELEASE_MEM` with `INT_SEL` does, but only on a queue that has never delivered an interrupt from such a release: the queue is latched the first time a release interrupt reaches the event queue, and flips on that queue deliver nothing while its own release interrupts keep arriving. The latch is cleared when the queue has flipped five times without another interrupt from its own releases: the fifth flip delivers the event and unlatched the queue, so a title that waits on the flip event after latching recovers only if it submits further flips. The bound cannot be by time: the next release interrupt can arrive seconds later than a suppressed flip across loading stalls, and delivering an unexpected flip event on a queue that pairs flips with releases can crash; no fixed window short enough to unblock a waiting title keeps such a title alive. Whether the console raises the event from the flip itself or from an interrupt its flip sequence contains is not measured; nor is how the console behaves for a title that waits on the flip event and also raises release interrupts on the same queue. -- [Host import windows and budget](../../../core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp) (libSceAgcDriver): a registered range larger than 64 MiB is imported one 64 MiB window at a time for buffer and fill accesses; an access across window edges imports the cells it touches, grown to the union of the range's imports it overlaps. An address-based build (`AcquireRegistered`) imports the range whole and replaces its windows. Live imports stay under a budget: `APS5_HOST_IMPORT_MIB`, else the larger of 6 GiB and half the physical memory, at most the largest host heap less the larger of 2 GiB and half that heap (imports, type-3 mirrors and buffers and textures placed in host memory share it; on a 16 GiB machine whose host heap is half the memory, a 2 GiB reserve left too little for the rest). Where the device enables `VK_EXT_memory_budget`, that host heap's reported budget less its other usage and an eighth, in 64 MiB steps, read at most once a second, also bounds the default budget once an import's `vkAllocateMemory` has failed; a set `APS5_HOST_IMPORT_MIB` is never lowered by the report. The report's other usage includes the host-visible copies and heap mirrors that stand in for refused imports, so it grows with the refusals; the first time the report would lower the budget, `[gpu] host import budget: host heap ...` prints the heap's reported budget and usage and the live imports. An import's `vkAllocateMemory` failure within an eighth of the budget, or the third in a row, lowers the budget to the live imports until the device or the configured budget changes; an isolated failure further below only marks its range failed. Live imports are not capped by `maxMemoryAllocationCount`: NVIDIA's Windows driver reports 4096, while Village held 27,167 live imports without a failure. A new import beyond it retires the least recently used imports not used in the last 256 lookups; one that would not fit even then is refused before anything is retired, and imports made when a range is mapped never evict. A heap mirror, sparse or not, whose range has left the write watch is refreshed in full at each use, every block counted as written; a build plans its range again only once the import path takes the range. A request that may not evict (an address-based build, an import when a range is mapped) remembers a refused range or block, with the live bytes and the budget at the refusal, and is answered from that memory, still counted as refused, until live imports drop below those bytes, the budget changes or one of its ranges changes. A request that may evict remembers its refusal too, answering later requests for the same run from memory with the room the refusal left (a request whose range fits in that room steps down to a smaller block without scanning the imports again, and a refusal that stepped down is remembered for each block it tried), while no import was made or retired, the budget has not grown, the import window and the run are unchanged, and no import can have become evictable since: the use count stays below the first use at which an import that was neither evictable nor held could leave the 256-lookup protection, and either the build floor has not risen or no held import could leave it yet. A join remembers its refusal the same way, apart from other requests for the same run, so a buffer bound across refused ranges does not try the join again at every upload. The shutdown line `[gpu] host imports at shutdown` gives the live, made, refused (and remembered) and failed counts per requester. The 64 MiB window, the 256-lookup protection, the 2 GiB reserve, the eighth, the 64 MiB steps and the three failures are choices, not measured. +- [Host import windows and budget](../../../core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp) (libSceAgcDriver): a registered range larger than 64 MiB is imported one 64 MiB window at a time for buffer and fill accesses; an access across window edges imports the cells it touches, grown to the union of the range's imports it overlaps. An address-based build (`AcquireRegistered`) imports the range whole and replaces its windows. Live imports stay under a budget: `APS5_HOST_IMPORT_MIB`, else the larger of 6 GiB and half the physical memory, at most the largest host heap less the larger of 2 GiB and half that heap (imports, type-3 mirrors and buffers and textures placed in host memory share it; on a 16 GiB machine whose host heap is half the memory, a 2 GiB reserve left too little for the rest). Where the device enables `VK_EXT_memory_budget`, that host heap's reported budget less its other usage and an eighth, in 64 MiB steps, read at most once a second, also bounds the default budget once an import's `vkAllocateMemory` has failed; a set `APS5_HOST_IMPORT_MIB` is never lowered by the report. The report's other usage includes the host-visible copies and heap mirrors that stand in for refused imports, so it grows with the refusals; the first time the report would lower the budget, `[gpu] host import budget: host heap ...` prints the heap's reported budget and usage and the live imports. An import's `vkAllocateMemory` failure within an eighth of the budget, or the third in a row, lowers the budget to the live imports until the device or the configured budget changes; an isolated failure further below only marks its range failed. Live imports are not capped by `maxMemoryAllocationCount`: NVIDIA's Windows driver reports 4096, while Village held 27,167 live imports without a failure. A new import beyond it retires the least recently used imports not used in the last 256 lookups; one that would not fit even then is refused before anything is retired, and imports made when a range is mapped never evict. An address-based build does not evict either, except for a range the budget refused (or remembers refusing) and no mirror serves whose copy would take the build's copies past `APS5_ADDRESS_COPY_MAX_MIB`. A heap mirror, sparse or not, whose range has left the write watch is refreshed in full at each use, every block counted as written; a build plans its range again only once the import path takes the range. A request that may not evict (an address-based build, an import when a range is mapped) remembers a refused range or block, with the live bytes and the budget at the refusal, and is answered from that memory, still counted as refused, until live imports drop below those bytes, the budget changes or one of its ranges changes. A request that may evict remembers its refusal too, answering later requests for the same run from memory with the room the refusal left (a request whose range fits in that room steps down to a smaller block without scanning the imports again, and a refusal that stepped down is remembered for each block it tried), while no import was made or retired, the budget has not grown, the import window and the run are unchanged, and no import can have become evictable since: the use count stays below the first use at which an import that was neither evictable nor held could leave the 256-lookup protection, and either the build floor has not risen or no held import could leave it yet. A join remembers its refusal the same way, apart from other requests for the same run, so a buffer bound across refused ranges does not try the join again at every upload. The shutdown line `[gpu] host imports at shutdown` gives the live, made, refused (and remembered) and failed counts per requester. The 64 MiB window, the 256-lookup protection, the 2 GiB reserve, the eighth, the 64 MiB steps and the three failures are choices, not measured. +- [Piece-split ranges over the host import budget](../../../core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp) (libSceAgcDriver): an address-based build imports a registered range larger than the device's largest allocation in pieces. If the budget refuses a piece, the range is mirrored or copied without the evicting retry other refused ranges get when their copy would pass `APS5_ADDRESS_COPY_MAX_MIB`, so such a copy can still exceed that cap and end the build. - [Device-local staging](../../../core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp) (libSceAgcDriver) - a written or atomic buffer element inside a host import, including one an address-based compute build reaches through its pointers, is copied to device memory before the dispatch and copied back whole after it, so a CPU store into that range in between is rolled back. - [Periodic pipeline cache saves skip busy intervals](../../../core/libs/prx/libSceAgcDriver/Graphics/src/PipelineCache.cpp) (libSceAgcDriver) - the saver thread snapshots the Vulkan pipeline cache only when no pipeline creation holds it (`TryLockForSnapshot`); otherwise it skips that 10 s interval. A blocking snapshot queued behind a long creation (an NVIDIA compile of a 1.5M-word compute pipeline runs for minutes) makes the writer-preferring `shared_mutex` hold every later pipeline creation on every queue until that compile ends, which froze Yōtei's (PPSA26344) loading at frame 797-799 for the whole compile. While creations overlap without a gap, no periodic save happens, so a crash in that stretch loses the pipelines built since the last save; `SaveNow` and the teardown save still wait for the lock. How often busy stretches skip saves in practice is not measured. - [Registration preparation at submit](../../../core/libs/prx/libSceAgcDriver/Execution/src/Driver/Queues/Submission.cpp) (libSceAgcDriver) - `Driver::Submit` waits for every registration-time shader preparation queued before the call, not only those of the shaders the commands use, so a submission behind a long queue of unrelated preparations waits for all of them on the submitting thread. Waiting there instead of in the queue worker keeps the GPU side of a submission short: a title that sees a submission take seconds treats the GPU as hung (Goat Simulator 3, PPSA04159, then stops submitting and its garbage collector fails a 10 s timeout). On the console shaders are compiled ahead of time, so neither wait exists; how long a title tolerates a slow submit call is not known. @@ -260,6 +266,7 @@ - [Long Windows pipeline-cache paths](../../../core/libs/prx/libSceAgcDriver/Graphics/src/PipelineCache.cpp): `readHeader` and the failed-read existence check still use ordinary paths. A filename beyond MAX_PATH can prevent header reuse or be reported missing; the shared content reader and journal normalization do not cover these calls. - [DB_RENDER_CONTROL.STENCIL_CLEAR_ENABLE without a stencil plane](../../../core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp) (libSceAgcDriver): a stencil clear on a depth target whose `DB_STENCIL_INFO` format is `STENCIL_INVALID` is dropped; the depth clear and color writes proceed. AMD PAL ([`gfx9RsrcProcMgr.cpp`](https://github.com/GPUOpen-Drivers/pal/blob/c5e800072a32/src/core/hw/gfxip/rpm/gfx9/gfx9RsrcProcMgr.cpp)) and radeonsi (`si_clear.c`) never set the bit without a stencil plane, and shadPS4 drops it the same way (`vk_rasterizer.cpp`, `StencilValid`). No source states what the hardware does with the bit then; the console was not measured. A read-only stencil plane still throws +- [Swept write-only staging](../../../core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp) (libSceAgcDriver): on a discrete GPU a write-only element whose V# stride is wider than the widest buffer store (16 bytes) and that a direct dispatch sweeps is staged in a device-local shadow. The shadow still takes a copy-in, because the copy-back covers the whole element and the stores may leave part of each record unwritten. A sweep proven to write every byte of the element (from the offsets and widths of its stores within the record) could skip the copy-in, about 10 ms per frame in Diablo II: Resurrected; that proof is not made. Store widths are not recorded per instruction either, so a record of 16 bytes or less stays in place even when its stores are narrower. ### Opt-in draw paths diff --git a/docs/dev/debt/libSceBgft.md b/docs/dev/debt/libSceBgft.md index 2240209a4d..95b8d7ac06 100644 --- a/docs/dev/debt/libSceBgft.md +++ b/docs/dev/debt/libSceBgft.md @@ -4,7 +4,7 @@ - [sceBgftServiceDownloadGetProgress](../../../core/libs/prx/libSceBgft/Export.cpp), `sceBgftServiceIntDownloadGetProgress`, `sceBgftServiceIntDownloadGetGameAndGameAcProgress` and `sceBgftServiceIntDownloadGetPlayGoProgress`: signatures and the shared 88-byte output are confirmed. The library forwards the output through IPC without accessing individual fields; their types remain unresolved. - [sceBgftServiceIntDownloadRegisterTaskByStorageEx](../../../core/libs/prx/libSceBgft/Export.cpp): confirmed parameter pointer and 32-bit task ID output. The input contains 32-bit scalars at offsets 0, 4, 56 and 104, strings at offsets 8, 16, 32, 40, 48, 64, 72, 80 and 88, and a 64-bit scalar at offset 96. The typed layout preserves the unused eight bytes at offset 24; scalar meanings and several string roles remain unresolved. -- [sceBgftServiceIntDownloadGetPatchProgress](../../../core/libs/prx/libSceBgft/Export.cpp) and `sceBgftServiceIntDownloadGetTaskInfo`: neither export nor a caller was found in the supplied decompiled library corpus. Their signatures remain unresolved. +- [sceBgftServiceIntDownloadGetPatchProgress](../../../core/libs/prx/libSceBgft/Export.cpp) and `sceBgftServiceIntDownloadGetTaskInfo`: both throw through `NotImplemented_nid_no_patch`; neither export nor a caller was found in the supplied decompiled library corpus. The `(const char* contentId, BgftProgress*)` and `(int32_t taskId, BgftTaskInfo*)` signatures follow the OpenOrbis headers, whose other Bgft prototypes match the confirmed ones here; they are not measured on a console. The task info layout is unknown. - [sceBgftServiceIntDebugPlayGoClearSetFreeZone](../../../core/libs/prx/libSceBgft/Export.cpp) (libSceBgft) - It is in the intersection of the export table of the console's libSceBgft (function symbols only), the pinned aerolib names and the functions not yet defined anywhere in the repo; names and NIDs are present in the [PS5 3.20 export inventory](https://github.com/DNNDHH/PS5-3.20_Libs/blob/b2a77c09cd71c01f34c790cfbe98c751a13262ad/libSceBgft.c) and the [verified NID name database](https://github.com/zecoxao/sce_symbols/blob/2883963a0a514ba6e77407a08ef4730a65e88254/aerolib.csv), but no credible prototypes were found. It is declared without parameters solely to resolve known imports; this is not an ABI claim and callers must not call them until signatures are verified. - [sceBgftServiceIntDebugPlayGoIsSetFreeZone](../../../core/libs/prx/libSceBgft/Export.cpp) (libSceBgft) - It is in the intersection of the export table of the console's libSceBgft (function symbols only), the pinned aerolib names and the functions not yet defined anywhere in the repo; names and NIDs are present in the [PS5 3.20 export inventory](https://github.com/DNNDHH/PS5-3.20_Libs/blob/b2a77c09cd71c01f34c790cfbe98c751a13262ad/libSceBgft.c) and the [verified NID name database](https://github.com/zecoxao/sce_symbols/blob/2883963a0a514ba6e77407a08ef4730a65e88254/aerolib.csv), but no credible prototypes were found. It is declared without parameters solely to resolve known imports; this is not an ABI claim and callers must not call them until signatures are verified. diff --git a/docs/dev/debt/libSceCesCs.md b/docs/dev/debt/libSceCesCs.md index f0af2576a1..6905596b0a 100644 --- a/docs/dev/debt/libSceCesCs.md +++ b/docs/dev/debt/libSceCesCs.md @@ -2,21 +2,24 @@ ### Silent stubs -- [sceCesMbcsUcsContextInit](../../../core/libs/prx/libSceCesCs/Export.cpp) (libSceCesCs) stores the profile pointer in the first 8 bytes of the caller's context; the console's context layout is not known. It returns the invalid-parameter error for a null context. The signature `int sceCesMbcsUcsContextInit(union* context, const union* mbcsUcsPrf)` follows the [Orbital IDA type database](https://github.com/AlexAltea/orbital/blob/master/tools/ida/db_types.json). `sceCesRefersUcsProfileCp1251` returns a profile accepted by `sceCesSbcToUtf8` and `sceCesUtf8ToSbc` only, with the Windows-1251 table of Microsoft's [bestfit1251.txt](https://unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WindowsBestFit/bestfit1251.txt), where byte 0x98 (unassigned) maps to U+0098 like the unassigned Cp1252 bytes; the console behavior for that byte is not verified -- [EUC-JP (CP51932) conversions](../../../core/libs/prx/libSceCesCs/Export.cpp) (libSceCesCs): `sceCesUcsProfileInitEucJpCp51932` marks the caller's sheet with an 8-byte tag and returns it as the profile. `sceCesUtf8StrToMbcsStr`, `sceCesUcs2StrToMbcsStr`, `sceCesMbcsStrToUtf8Str`, `sceCesMbcsStrToUcs2Str`, their `Get*Len` forms and `sceCesEucJpToUcs2` convert ASCII, the JIS X 0201 half-width katakana (`0x8E` + `0xA1`-`0xDF`, U+FF61-U+FF9F) and the two-byte rows `0xA1`-`0xFE` for that profile, and every character for the CP1252 and CP1251 profiles. The two-byte table ([JisX0208.hpp](../../../core/libs/prx/libSceCesCs/JisX0208.hpp), 7336 of 8836 cells) is Microsoft code page 932 read through the standard JIS row/cell to Shift-JIS arithmetic, so it includes NEC row 13 and the NEC-selected IBM rows 89-92 and maps the Microsoft variants (U+FF5E at `0xA1C1`, U+2225, U+FF0D, U+FFE0-U+FFE2) instead of JIS X 0208's; that the console's CP51932 table equals it is assumed from the Microsoft code page, not measured. A character with several cells encodes to the lowest cell. A well-formed but unassigned cell answers `UNASSIGNED_CODE`, a trail byte outside `0xA1`-`0xFE` `INVALID_ENCODE`, a cut pair `SRC_BUFFER_END`; the console's errors for these are not known. Three-byte JIS X 0212 (`0x8F`) characters convert through a second table ([JisX0212.hpp](../../../core/libs/prx/libSceCesCs/JisX0212.hpp), 6067 of 8836 cells) read from the Unicode consortium's [JIS0212.TXT](https://unicode.org/Public/MAPPINGS/OBSOLETE/EASTASIA/JIS/JIS0212.TXT); that the console's CP51932 table equals it is assumed from that mapping, not measured. A well-formed but unassigned three-byte cell answers `UNASSIGNED_CODE` and a cut triple `SRC_BUFFER_END`. A character with cells in both JIS X 0208 and JIS X 0212 encodes to the two-byte form, and one only in JIS X 0212 to the three-byte form. Signatures follow [orbital](https://github.com/AlexAltea/orbital/blob/master/tools/ida/db_types.json). The string forms stop at the source limit or at a zero code unit, which is neither converted nor counted, and write no terminator; `*Len` outputs count code units consumed and produced. A code point outside the BMP answers `UNASSIGNED_CODE`. Unverified on hardware. -- [Shift-JIS (CP932) conversions](../../../core/libs/prx/libSceCesCs/Export.cpp) (libSceCesCs): `sceCesUcsProfileInitSJis1997Cp932` marks the caller's sheet with an 8-byte tag and returns it as the profile. `sceCesUtf8StrToMbcsStr`, `sceCesUcs2StrToMbcsStr`, `sceCesMbcsStrToUtf8Str`, `sceCesMbcsStrToUcs2Str`, and their `Get*Len` forms convert ASCII, JIS X 0201 half-width katakana (`0xA1`-`0xDF`, U+FF61-U+FF9F), two-byte Shift-JIS sequences (`0x81`-`0x9F` and `0xE0`-`0xFC` lead, `0x40`-`0x7E` and `0x80`-`0xFC` trail) mapped to JIS X 0208 row/cell indices against the CP932 table ([JisX0208.hpp](../../../core/libs/prx/libSceCesCs/JisX0208.hpp)), and the IBM extensions (`0xFA40`-`0xFC4B`, 388 characters) decoded to their corresponding JIS X 0208 code points. The user-defined area (`0xF040`-`0xF9FC`, which CP932 maps to Private Use Area U+E000-U+E757) and unassigned lead/trail combinations answer `UNASSIGNED_CODE`, an invalid lead or trail byte `INVALID_ENCODE`, a cut sequence `SRC_BUFFER_END`. Characters with multiple cells encode to the lowest cell. Signatures follow [orbital](https://github.com/AlexAltea/orbital/blob/master/tools/ida/db_types.json). Unverified on hardware. +- [sceCesMbcsUcsContextInit](../../../core/libs/prx/libSceCesCs/Export.cpp) (libSceCesCs) stores the profile pointer in the first 8 bytes of the caller's context; the console's context layout is not known. It returns the invalid-parameter error for a null context and, as a payload process on a PS5 (firmware 13.60) did, for a null profile. The signature `int sceCesMbcsUcsContextInit(union* context, const union* mbcsUcsPrf)` follows the [Orbital IDA type database](https://github.com/AlexAltea/orbital/blob/master/tools/ida/db_types.json). `sceCesRefersUcsProfileCp1251` returns a profile accepted by `sceCesSbcToUtf8`, `sceCesUtf8ToSbc` and the MBCS context conversions, with the Windows-1251 table of Microsoft's [bestfit1251.txt](https://unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WindowsBestFit/bestfit1251.txt), except byte 0x98, which is unassigned +- [EUC-JP (CP51932) conversions](../../../core/libs/prx/libSceCesCs/Export.cpp) (libSceCesCs): `sceCesUcsProfileInitEucJpCp51932` marks the caller's sheet with an 8-byte tag and returns it as the profile. Decoding follows the console (see the `sceCesEucJpToUtf8` entry), with the Microsoft code page 932 table read through the JIS row/cell arithmetic ([JisX0208.hpp](../../../core/libs/prx/libSceCesCs/JisX0208.hpp)); the console does not decode or encode JIS X 0212 either way (U+02D8 answered `0x805C0020`). Encoding takes the lowest cell of a character. Signatures follow [orbital](https://github.com/AlexAltea/orbital/blob/master/tools/ida/db_types.json) +- [Shift-JIS (CP932) conversions](../../../core/libs/prx/libSceCesCs/Export.cpp) (libSceCesCs): decoding matches a payload process on a PS5 (firmware 13.60) for every two-byte input through `sceCesMbcsStrToUcs2Str`, in result, lengths and output. `sceCesUcsProfileInitSJis1997Cp932` tags the caller's sheet and returns it as the profile. The string conversions decode ASCII, half-width katakana (`0xA1`-`0xDF`) and two-byte sequences (`0x81`-`0x9F` and `0xE0`-`0xFC` lead, `0x40`-`0x7E` and `0x80`-`0xFC` trail) through the CP932 table ([JisX0208.hpp](../../../core/libs/prx/libSceCesCs/JisX0208.hpp)), including the IBM extensions `0xFA40`-`0xFC4B`. The user-defined area `0xF040`-`0xF9FC` and unassigned cells answer `UNASSIGNED_CODE`, an invalid lead or trail `INVALID_ENCODE`, a cut sequence `SRC_BUFFER_END`. Signatures follow [orbital](https://github.com/AlexAltea/orbital/blob/master/tools/ida/db_types.json) ### Unknown function info - [Unicode scalar conversions](../../../core/libs/prx/libSceCesCs/Unicode.cpp) (libSceCesCs) - console error precedence, optional length pointers and length units are unverified. Signatures follow the [Orbital type database](https://github.com/AlexAltea/orbital/blob/b321fcdbd700cc02da1cb1ad25412781d5ec73c6/tools/ida/db_types.json); names are in the aerolib table pinned by `tools/nid_names.py`. Encoding follows [Unicode section 3.9](https://www.unicode.org/versions/Unicode17.0.0/core-spec/chapter-3/). Each call converts one scalar, including zero and U+FEFF, without a terminator or byte-order detection; lengths count bytes for UTF-8 and 16-bit units for UTF-16. Native forms use host byte order (supported hosts are little-endian). Errors follow the existing CES converters, not console measurements, and failure leaves outputs unchanged. No console or title comparison has been run -- [sceCesEucJpToUtf8](../../../core/libs/prx/libSceCesCs/Export.cpp) (libSceCesCs) - the scalar conversion's errors and optional length pointers are unverified against the console. Its signature follows the Orbital type database linked above; it uses the existing CP51932 profile and JIS tables, with their mapping and profile-layout assumptions listed above, converts one character (including zero), and writes no terminator. Failure leaves the output and length pointers unchanged -- [Shift-JIS and EUC-JP scalar conversions](../../../core/libs/prx/libSceCesCs/Export.cpp) (libSceCesCs) - errors, their precedence and the optional length pointers of `sceCesSJisTo*`, `sceCesEucJpTo{Utf16,Utf32}*` and `sceCes{Ucs2,Utf8,Utf16,Utf32}*To{SJis,EucJp}` are unverified against the console. Signatures follow the Orbital type database linked above; the CP932 and CP51932 table and profile assumptions above apply. A profile of another encoding answers `INVALID_PARAMETER`, a surrogate or a value above U+10FFFF `INVALID_ENCODE`, a code point outside the BMP `UNASSIGNED_CODE`. `sceCesSJisCodeToJisX0208` and `sceCesJisX0208ToSJisCode` do not check that the cell is assigned; their `INVALID_ENCODE` for rows or cells outside 1-94 and `INVALID_DST_BUFFER` for a null output are not console measurements +- [sceCesEucJpToUtf8 and sceCesEucJpToUcs2](../../../core/libs/prx/libSceCesCs/Export.cpp) (libSceCesCs) with the CP51932 profile follow a payload process on a PS5 (firmware 13.60): every two-byte input and every `0x8F` three-byte input gives the console's result, length and output (the test pins a hash of both sweeps). Bytes below 0xA0 other than 0x0E, 0x8E and 0x8F convert to themselves; JIS X 0212 is not decoded, so `0x8F` forms return `0x805C0020` in rows X 0212 leaves empty and `0x805C0014` elsewhere; a null profile returns `0x805C0004`, and the lengths are cleared first and then set as the console sets them. Their signatures follow the Orbital type database linked above. The console reads any other profile pointer as a sheet, where these return the invalid-parameter error. +- [Shift-JIS and EUC-JP scalar conversions](../../../core/libs/prx/libSceCesCs/Export.cpp) (libSceCesCs) - errors, their precedence and the optional length pointers of `sceCesSJisTo*`, `sceCesEucJpTo{Utf16,Utf32}*` and `sceCes{Ucs2,Utf8,Utf16,Utf32}*To{SJis,EucJp}` are unverified against the console. Signatures follow the Orbital type database linked above; the CP932 and CP51932 table and profile assumptions above apply. A profile of another encoding answers `INVALID_PARAMETER`, a surrogate or a value above U+10FFFF `INVALID_ENCODE`, a code point outside the BMP `UNASSIGNED_CODE`. UTF-8 input is decoded as `sceCesUtf8ToSbc` decodes it, so overlong forms answer `0x805C0015`. `sceCesSJisCodeToJisX0208` and `sceCesJisX0208ToSJisCode` do not check that the cell is assigned; their `INVALID_ENCODE` for rows or cells outside 1-94 and `INVALID_DST_BUFFER` for a null output are not console measurements - [Strict JIS X 0208 profiles](../../../core/libs/prx/libSceCesCs/Export.cpp) (libSceCesCs) - cell `0x2140` and U+FF3C throw: JIS0208.TXT gives U+005C, glibc 2.39 and Python's `euc_jp` U+FF3C. In `sceCesUcsProfileInitSJis1997X0208`, bytes `0x5C` and `0x7E` and U+005C, U+007E, U+00A5 and U+203E throw: SHIFTJIS.TXT gives JIS X 0201 Roman, CP932 and Python's `shift_jis` ASCII; the console's is unknown. The table, [JIS0208.TXT](https://unicode.org/Public/MAPPINGS/OBSOLETE/EASTASIA/JIS/JIS0208.TXT), is CP932's without rows 13 and 89-92 and with six cells changed, not measured. Per [SharpProspero](https://github.com/SvenGDK/SharpProspero/blob/5dfdb4b0b166e83dc9ae275001afb695f12c7174/src/SharpProspero/Interop/Text/Ces.cs#L57-L67), the `X0208Ss2` profile adds SS2 katakana and `X0208Ss2Ss3` SS3 JIS X 0212. Signatures follow Orbital; the conversions above take these profiles with the same errors, a missing SS2 or SS3 answering `INVALID_ENCODE` and Shift-JIS leads `0xF0`-`0xFC` `UNASSIGNED_CODE` - [UTF-16 and UTF-32 forms of the single-byte and MBCS string conversions](../../../core/libs/prx/libSceCesCs/Export.cpp) (libSceCesCs) - errors, their precedence and the optional length pointers of `sceCesSbcTo{Ucs2,Utf16,Utf32}*`, `sceCes{Ucs2,Utf16,Utf32}*ToSbc`, `sceCesMbcsStr{To,Get}{Utf16,Utf32}*` and `sceCes{Utf16,Utf32}Str{To,Get}Mbcs*` are unverified against the console. Signatures follow the Orbital type database linked above. They follow `sceCesSbcToUtf8`, `sceCesUtf8ToSbc` and the UTF-8 MBCS string forms with the profiles and tables listed above. A surrogate or a value above U+10FFFF answers `INVALID_ENCODE`, a valid code point no profile maps `UNASSIGNED_CODE`. The string forms stop at a zero code unit, write no terminator and count code units - [GBK (CP936) and EUC-CN conversions](../../../core/libs/prx/libSceCesCs/Export.cpp) (libSceCesCs) - `sceCesUcsProfileInitGbkCp936` and `sceCesUcsProfileInitEucCnGb2312` mark the caller's sheet with an 8-byte tag; the console's profile layout is not known. Both use one table ([Cp936.hpp](../../../core/libs/prx/libSceCesCs/Cp936.hpp)) read from Microsoft's [CP936.TXT](https://unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP936.TXT); the EUC-CN profile accepts only its `0xA1`-`0xFE` lead and trail bytes, so it includes the GBK cells inside that range and the CP936 forms of `0xA1A4` (U+00B7) and `0xA1AA` (U+2014) instead of GB 2312's. That the console's GB 2312 and CP936 tables equal it is not measured. User-defined areas and `sceCesGbUcsProfileSet*` are not handled. Errors, their precedence and the length pointers follow the Shift-JIS forms above and are unverified - [GB 18030 profiles](../../../core/libs/prx/libSceCesCs/Export.cpp) (libSceCesCs) - the console's tables are not measured, and the sources disagree on 26 sequences. The 2000 profile follows ICU's `gb-18030-2000.ucm` at icu-data d9d3a6ed (before ICU-8427), which matches Python's codec: `0xA8BC` is U+E7C7 and `0x8135F437` U+1E3F. The 2005 profile follows `gb-18030-2005.ucm` (91850aec), which swaps those two and maps 24 PUA cells to U+FE10-U+FE19, U+9FB4-U+9FBB and six supplementary ideographs, keeping the PUA code points as encode fallbacks. Two-byte cells are CP936 plus [Gb18030.hpp](../../../core/libs/prx/libSceCesCs/Gb18030.hpp); four-byte runs include ICU's `gb18030Ranges`. The inits tag the sheet like GBK's; the `sceCesGb*`, `sceCesMbc*` and MBCS string forms accept them. The full mapping is assumed as the default of `sceCesGbUcsProfileSetUdaMapping` and `Set4ByteCharRange`, which throw. Supplementary characters to UCS-2 answer `UNASSIGNED_CODE`; other errors follow the GBK forms -- [sceCesRefersUcsProfileCp1250](../../../core/libs/prx/libSceCesCs/Export.cpp) (libSceCesCs) - returns a profile accepted by `sceCesSbcToUtf8`, `sceCesUtf8ToSbc` and the MBCS context conversions, with the Windows-1250 table of Microsoft's [bestfit1250.txt](https://unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WindowsBestFit/bestfit1250.txt), where the unassigned bytes map to their Latin-1 control characters as the Cp1252 and Cp1251 tables do; the console behavior for those bytes and the whole profile is not verified. PPSA34501 fails to start without this export (`qYu6y1E0Qbg`) -- [Generic MBCS character and Shift-JIS code helpers](../../../core/libs/prx/libSceCesCs/Export.cpp) (libSceCesCs) - `sceCesMbcTo*` convert one character with any profile the MBCS context accepts, as the per-encoding forms above do. `sceCesSJisGetCode` and `sceCesSJisPutCode` read and write one raw Shift-JIS code (one byte for ASCII and `0xA1`-`0xDF`) without checking that it is assigned. `sceCesSJisCodeToJisX0213` and `sceCesJisX0213ToSJisCode` use the Shift_JIS-2004 arithmetic of JIS X 0213 annex 1 (plane 2 rows 1, 3-5, 8, 12-15 and 78-94 on leads `0xF0`-`0xFC`). `sceCesMbcsUcsContextInitCopy` copies the stored profile pointer. Signatures follow the Orbital type database linked above; errors, their precedence and the optional size pointers follow the other converters and are unverified against the console +- [sceCesRefersUcsProfileCp1250](../../../core/libs/prx/libSceCesCs/Export.cpp) (libSceCesCs) - returns a profile accepted by `sceCesSbcToUtf8`, `sceCesUtf8ToSbc` and the MBCS context conversions, with the Windows-1250 table of Microsoft's [bestfit1250.txt](https://unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WindowsBestFit/bestfit1250.txt), except bytes 0x81, 0x83, 0x88, 0x90 and 0x98, which are unassigned. PPSA34501 fails to start without this export (`qYu6y1E0Qbg`) +- [sceCesSbcToUtf8 and sceCesUtf8ToSbc](../../../core/libs/prx/libSceCesCs/Export.cpp) (libSceCesCs) follow a payload process on a PS5 (firmware 13.60): the three tables match the console byte for byte, with Cp1252 bytes 0x81, 0x8D, 0x8F, 0x90 and 0x9D unassigned; a null profile returns `0x805C0004`; and the length and output are cleared first, as the console does. `sceCesUtf8ToSbc` decodes leads up to 0xFD (5- and 6-byte forms), returns `0x805C0015` for overlong forms and surrogates and reports the measured lengths. The console reads any other profile pointer as a table, where these return the invalid-parameter error; which of a null profile and a scalar above U+10FFFF it reports first is not measured +- [MBCS string conversions](../../../core/libs/prx/libSceCesCs/Export.cpp) (libSceCesCs) - `sceCesUtf8StrToMbcsStr`, `sceCesUcs2StrToMbcsStr`, `sceCesMbcsStrToUtf8Str`, `sceCesMbcsStrToUcs2Str` and their `Get*Len` forms follow a payload process on a PS5 (firmware 13.60) with the Cp1252 and EUC-JP profiles: the lengths are cleared and a terminator is written first, then the context, the source and the output are checked in that order; a source limit of 0 reads up to the terminating zero; the output keeps room for a terminator; and on an error the characters before it stay converted, terminated and counted. They decode UTF-8 as `sceCesUtf8ToSbc` does, and a UTF-16 surrogate answers `0x805C0015`. The UCS-2 forms and the other profiles were not measured beyond these cases. A zero-filled context converted nothing and returned 0 on the console, where this returns the invalid-parameter error +- [EUC-JP and Shift-JIS encoding](../../../core/libs/prx/libSceCesCs/Export.cpp) (libSceCesCs) with the CP51932 and CP932 profiles gives the result, lengths and bytes a payload process read on a PS5 (firmware 13.60) for every UCS-2 value through `sceCesUcs2StrToMbcsStr` (the test pins a hash of both sweeps): the JIS forms U+00A2, U+00A3, U+00A5, U+00AC, U+2014, U+2016, U+203E, U+2212 and U+301C encode to the cells of their Microsoft forms, U+FEFF is consumed and writes nothing, EUC-JP writes U+0080-U+009F other than U+008E and U+008F as single bytes and answers `UNASSIGNED_CODE` for U+000E, and Shift-JIS answers `0x805C0024` for U+0080-U+009F. Decoding those bytes back is unchanged +- [Generic MBCS character and Shift-JIS code helpers](../../../core/libs/prx/libSceCesCs/Export.cpp) (libSceCesCs) - the UTF-8 and UTF-16 buffer forms' errors and size pointers follow the other converters, unverified. The single-character encoders were measured on a PS5 (`sceCesUtf32ToMbc` over U+0000-U+110001 with each MBCS profile, each encoding's `Ucs2To*` and `Utf32To*` on surrogates and a one-byte target): 0x805C0015 for a surrogate, 0x805C0014 past U+10FFFF, the needed length with `DST_BUFFER_END` and a zero length with any other refusal. `sceCesMbcTo*` and `sceCes*ToMbc` convert one character with any profile the MBCS context accepts; an unmapped character answers `UNASSIGNED_CODE`. `sceCesSJisGetCode`/`PutCode` move one raw Shift-JIS code unchecked; `sceCesSJisCodeToJisX0213` and back use JIS X 0213 annex 1 arithmetic. `sceCesMbcsUcsContextInitCopy` copies the profile pointer. Signatures follow Orbital - [Single-byte profiles](../../../core/libs/prx/libSceCesCs/SingleByte.hpp) (libSceCesCs) - the console's tables for these 27 profiles are not verified. Each returns a profile accepted by `sceCesSbcToUtf8`, `sceCesUtf8ToSbc` and the MBCS context conversions, with bytes 0x00-0x7F unchanged and the high half of a public table: ISO 8859-1, -2, -4, -5, -9, -10, -13, -14, -15 and -16 from [unicode.org](https://unicode.org/Public/MAPPINGS/ISO8859/), code pages 437, 737, 775, 850, 852, 855, 860-863, 865 and 866 from [Microsoft's PC tables](https://unicode.org/Public/MAPPINGS/VENDORS/MICSFT/PC/), KOI8-R and KOI8-U from [unicode.org](https://unicode.org/Public/MAPPINGS/VENDORS/MISC/), and 1254, 1256 and 1258 from Microsoft's [best-fit tables](https://unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WindowsBestFit/), whose unassigned bytes map to C1 controls as in Cp1250. Profiles whose public table leaves bytes undefined or maps them to private use still throw -- [libSceCesCs firmware 3.20 pending exports](../../../core/libs/prx/libSceCesCs/PendingExports.cpp) - 70 symbol names are present in [the PS5 3.20 libSceCesCs export list](https://github.com/DNNDHH/PS5-3.20_Libs/blob/b2a77c09cd71c01f34c790cfbe98c751a13262ad/libSceCesCs.c). Their signatures and console behaviour are unverified. The declarations use the existing no-parameter unknown-signature convention solely to resolve imports, and every call throws through `NotImplemented_nid_no_patch`. +- [libSceCesCs firmware 3.20 pending exports](../../../core/libs/prx/libSceCesCs/PendingExports.cpp) - 62 symbol names are present in [the PS5 3.20 libSceCesCs export list](https://github.com/DNNDHH/PS5-3.20_Libs/blob/b2a77c09cd71c01f34c790cfbe98c751a13262ad/libSceCesCs.c). Their signatures and console behaviour are unverified. The declarations use the existing no-parameter unknown-signature convention solely to resolve imports, and every call throws through `NotImplemented_nid_no_patch`. - [EUC-KR, UHC and Big5 conversions](../../../core/libs/prx/libSceCesCs/Export.cpp) (libSceCesCs) - the tables, errors and Big5 duplicate choices are assumed, not measured. `sceCesUcsProfileInitEucKr`, `sceCesUcsProfileInitUhc` and `sceCesUcsProfileInitBig5Cp950` tag the caller's sheet like the EUC-JP profile. The tables are Microsoft's [CP949.TXT](https://unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP949.TXT) and [CP950.TXT](https://unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP950.TXT); EUC-KR is CP949 limited to bytes `0xA1`-`0xFE`. Bytes below `0x80` are ASCII; the KS X 1003 profile (`sceCes*UcsProfileSetSbcs`) is not implemented. User-defined areas (Private Use Area on Windows) answer `UNASSIGNED_CODE`. Big5 encoding takes the lower of two cells except for U+2550, U+255E, U+2561, U+256A, U+5341 and U+5345, as code page 950 does. The scalar calls to and from UCS-2 and UTF-8/16/32 convert one character as the Shift-JIS and EUC-JP scalar conversions do diff --git a/docs/dev/debt/libSceCompanionUtil.md b/docs/dev/debt/libSceCompanionUtil.md index 48d3c1cb47..652949f2b7 100644 --- a/docs/dev/debt/libSceCompanionUtil.md +++ b/docs/dev/debt/libSceCompanionUtil.md @@ -2,4 +2,5 @@ ### Unknown function info -- [sceCompanionUtilGetEvent, sceCompanionUtilGetRemoteOskEvent, sceCompanionUtilInitialize, sceCompanionUtilOptParamInitialize and sceCompanionUtilTerminate](../../../core/libs/prx/libSceCompanionUtil/Export.cpp) (libSceCompanionUtil) - names and NIDs are present in the [PS5 3.20 export inventory](https://github.com/DNNDHH/PS5-3.20_Libs/blob/b2a77c09cd71c01f34c790cfbe98c751a13262ad/libSceCompanionUtil.c), but no credible prototypes were found. The declarations have no parameters solely to resolve known imports; this is not an ABI claim and callers must not call them until signatures are verified +- [sceCompanionUtilGetEvent](../../../core/libs/prx/libSceCompanionUtil/Export.cpp) - the PS5 argument contract, event size and alignment remain unverified for the output pointer. The supplied `libSceCompanionUtil.sprx` export `cE5Msy11WhU` at 0x100 only returns `0x80AD0008`, without reading argument registers or memory. The implementation preserves that return and does not access the buffer. +- [sceCompanionUtilGetRemoteOskEvent, sceCompanionUtilInitialize, sceCompanionUtilOptParamInitialize and sceCompanionUtilTerminate](../../../core/libs/prx/libSceCompanionUtil/Export.cpp) (libSceCompanionUtil) - names and NIDs are present in the [PS5 3.20 export inventory](https://github.com/DNNDHH/PS5-3.20_Libs/blob/b2a77c09cd71c01f34c790cfbe98c751a13262ad/libSceCompanionUtil.c), but no credible prototypes were found. The declarations have no parameters solely to resolve known imports; this is not an ABI claim and callers must not call them until signatures are verified diff --git a/docs/dev/debt/libSceFont.md b/docs/dev/debt/libSceFont.md index 3158492e1f..57d9015321 100644 --- a/docs/dev/debt/libSceFont.md +++ b/docs/dev/debt/libSceFont.md @@ -2,8 +2,10 @@ ### Unknown function info + - [sceFontRenderCharGlyphImage, sceFontRenderCharGlyphImageHorizontal, sceFontRenderCharGlyphImageVertical](../../../core/libs/prx/libSceFont/src/Layout.cpp) (libSceFont) accept a surface whose width or height is 0, with any row stride, and return the glyph metrics and an empty update rectangle without writing to the surface. A negative width, height or stride, a zero stride on a surface with pixels, a null buffer and a pixel size other than 1 or 4 bytes still return `SCE_FONT_ERROR_NO_SUPPORT_SURFACE`; those cases and the exact console result for a zero-extent surface are not measured. The extent-0 behaviour is inferred from the Tekken Dark Resurrection PSP emulator which, to measure a string, initialises the surface with width 0 and height 31 and an unbound stride, renders each character and sums the returned advances. +- [sceFontCreateString](../../../core/libs/prx/libSceFont/src/Text.cpp): a string created from a default-form (0x10) text source gets the direction of its first strong character, 0x11 for right to left and 0x12 for left to right, and 0x12 when there is none; explicit 0x11 and 0x12 sources keep their form and [sceFontStringGetWritingForm](../../../core/libs/prx/libSceFont/src/Text.cpp) returns the stored form. LRM and RLM count as strong, embeddings and overrides do not, and text between an isolate initiator and its PDI is skipped. The rule follows a run of the firmware 13.42 library in a harness reported on the pull request: for non-empty text it was checked before a later glyph-stage failure and only empty text completed, so it is not full native right-to-left rendering. Which characters are strong is decided here by Unicode block ranges, not by the full bidi class tables. - [Typographic design](../../../core/libs/prx/libSceFont/src/Style.cpp): native selector, feature, font-set eligibility and output-clearing rules are recovered. Driver typography selection and queries, feature-cache updates and glyph substitution remain unimplemented and throw instead of storing arbitrary selector/value pairs. - [sceFontSetScriptLanguage and sceFontGetScriptLanguage](../../../core/libs/prx/libSceFont/src/Style.cpp): native script/language ranges, handle-error precedence and clearing of failed getter outputs are implemented. Valid driver queries and updates throw; the previous arbitrary-value map and fabricated zero default are no longer used. Driver selection and actual language-dependent shaping remain unimplemented. - [sceFontGetRenderScaledKerning](../../../core/libs/prx/libSceFont/src/Render.cpp) (libSceFont) - arguments, the cleared output and the bound renderer check taken from `cellFontGetRenderScaledKerning` in [RPCS3](https://github.com/RPCS3/rpcs3/blob/master/rpcs3/Emu/Cell/Modules/cellFont.cpp) (PS3 predecessor of the library), not confirmed on a title. The kerning is the `sceFontGetKerning` one at the render scale @@ -22,9 +24,12 @@ - [sceFontOpenFontSet](../../../core/libs/prx/libSceFont/src/SystemFont.cpp) (libSceFont) - the other script files of a set are chosen from its type, not measured on a console: Vietnamese for low-byte bit 0x10, Thai for script bit 0x10, Japanese for 0x04, simplified Chinese for 0x80 (before Japanese with 0x08), Hangul for 0x20 and Arabic for low-byte bit 0x80, as the SDK set names (`..._JP_AR`, `..._GBCJK_TH`) listed by [shadPS4](https://github.com/shadps4-emu/shadPS4/blob/main/src/core/libraries/font/font_internal.cpp) suggest; the file order and the Hangul file name (`SCEPS4Yoongd-Medium.otf`, `SCEPS4Yoongd-Bold.otf`) also come from shadPS4. A character the primary file lacks is taken from the first of them that has it; kerning between two files is 0, and `sceFontGetCharGlyphCode` and `sceFontGetFontGlyphsCount` answer for the primary file only - [sceFontOpenFontSet](../../../core/libs/prx/libSceFont/src/SystemFont.cpp) (libSceFont) - the console file names are those of the PS4 firmware; the names of the PS5-only JG2 sets (`0x1A......`) are unknown, so they use the SSTJpPro files. When a console file is missing, an openly licensed substitute (Noto Sans, Noto Sans Mono, Noto Sans Thai, Noto Sans Arabic, Noto Sans CJK with its Korean face for Hangul) is loaded instead; its metrics differ, so text width, line height and wrapping differ from the console. System font faces are loaded by FreeType in host memory, not in the font memory the title passes to the library: FreeType needs about 1 MiB per CJK face, which the title's font memory is not sized for. - [sceFontGetCharGlyphMetrics, sceFontGetRenderCharGlyphMetrics](../../../core/libs/prx/libSceFont/src/Layout.cpp) (libSceFont) report the vertical metrics the way the [FreeType driver](../../../core/libs/prx/libSceFontFt/src/Driver.cpp) reports them for a rendered glyph, not confirmed on a title: FreeType's vertical advance, and for a face without vertical metrics a bearing of half the horizontal advance left of the horizontal bearing and of half the advance left over by the glyph height. +- [sceFontGetFontMetrics](../../../core/libs/prx/libSceFont/src/Layout.cpp) (libSceFont) - the 64-byte output, the form fallbacks (2 and 3 fall back to the `hhea` values when OS/2 is missing or gives an empty range, 4 builds vertical values from `vhea` or OS/2) and the raw weight deltas and slant copied from the style are not measured on a console. For a font set the values are those of its primary file; which file the console reports is not recovered. Closes when: measured on a PS5 +- [sceFontGetFontStyleInformation](../../../core/libs/prx/libSceFont/src/Layout.cpp) (libSceFont) - the 24-byte output (FreeType family and style names, italic and bold flags, OS/2 weight class when it is a multiple of 100 from 100 to 900, width class below 10, and 1 plus a right-to-left `head` direction plus 0x80 for vertical metrics) and the font-set record path are not measured on a console. A face without a `head` table, such as a BDF font, throws, as its console result is unknown. Closes when: measured on a PS5 +- [sceFontGetFontGlyphsOutlineProfile](../../../core/libs/prx/libSceFont/src/Layout.cpp) (libSceFont) - the 16-byte output (the `maxp` maximum contours, points, composite contours and composite points) and `SCE_FONT_ERROR_NO_SUPPORT_FUNCTION` for a `maxp` older than 1.0 are not measured on a console. A handle with a font-set record throws, as the maximum over the record's system font entries is not modelled. A face without a `maxp` table throws, as its console result is unknown. Closes when: measured on a PS5 - [Font writing lines](../../../core/libs/prx/libSceFont/src/WritingLine.cpp): visual ordering and spacing originated from PS4 measurements and match the supplied PS5 structure and control flow. Exhaustive floating-point equivalence, including NaN payloads and rounding, has not been verified against a running PS5 module. -- [Font graphics and metric signatures](../../../core/libs/prx/libSceFont/src/Unimplemented.cpp): graphics-device/service creation takes font memory, parameters and a handle output; destruction takes a handle pointer. Attribute selectors and outputs are 32-bit values. Metric, outline-profile, style-information and expansion-buffer outputs remain opaque pending field recovery. Protected implementations are unchanged. +- [Font graphics and metric signatures](../../../core/libs/prx/libSceFont/src/Unimplemented.cpp): graphics-device/service creation takes font memory, parameters and a handle output; destruction takes a handle pointer. Attribute selectors and outputs are 32-bit values. Expansion-buffer outputs remain opaque pending field recovery. Protected implementations are unchanged. - [Font graphics fill and transform signatures](../../../core/libs/prx/libSceFont/src/Unimplemented.cpp): region layout and scalar float arguments are confirmed from assembly, including the extra 32-bit corner flags omitted by the roundish-region decompilation. Fill-method, plot and rates layouts, layout selector meanings and mapping parameter meanings remain unresolved. Protected bodies are unchanged. diff --git a/docs/dev/debt/libSceFreeType.md b/docs/dev/debt/libSceFreeType.md index 5fd44fd1d1..e38b9e4ee8 100644 --- a/docs/dev/debt/libSceFreeType.md +++ b/docs/dev/debt/libSceFreeType.md @@ -8,12 +8,18 @@ - [FT_Cos, FT_Sin, FT_Tan, FT_Vector_Unit and FT_Angle_Diff](../../../core/libs/prx/libSceFreeType/src/Trigonometry.cpp) (libSceFreeType) - console ABI/version and CORDIC equivalence are unverified; the LP64 adapter follows bundled [FreeType 2.13.3](https://github.com/freetype/freetype/blob/42608f77f20749dd6ddc9e0536788eaad70ea4b5/src/base/fttrigon.c). Tangent retains the 64-bit quotient near poles instead of Windows FT_Long truncation. Angle differences whose signed 64-bit subtraction overflows throw; the bundled source's subtraction is undefined there. +- [FT_Outline_Copy](../../../core/libs/prx/libSceFreeType/Export.cpp) (libSceFreeType) - compatibility with the console FreeType build and its errors is unverified. The LP64 guest adapter follows the unsigned counts and copy contract of bundled [FreeType 2.13.3](https://github.com/freetype/freetype/blob/42608f77f20749dd6ddc9e0536788eaad70ea4b5/src/base/ftoutln.c). + +- [FT_Outline_Decompose](../../../core/libs/prx/libSceFreeType/src/OutlineDecompose.cpp) (libSceFreeType) - console callback ABI and FreeType-version equivalence are unverified; the LP64 adapter follows bundled [FreeType 2.13.3](https://github.com/freetype/freetype/blob/42608f77f20749dd6ddc9e0536788eaad70ea4b5/src/base/ftoutln.c). Nonempty outlines with shifts outside 0-62 or signed 64-bit overflow in scaling, translation or midpoint sums throw; native behavior for that arithmetic is undefined. Callers must supply valid point/tag/contour arrays and the callbacks their contours use. + - [FT_Init_FreeType, FT_New_Face, FT_Set_Pixel_Sizes, FT_Get_Char_Index, FT_Load_Glyph, FT_Render_Glyph](../../../core/libs/prx/libSceFreeType/Export.cpp) (libSceFreeType) - the PS4 library is taken to be FreeType 2 built for LP64: the face, size, charmap, glyph slot, bitmap and outline layouts follow the public headers of the bundled FreeType 2.13.3 with a 64-bit `long`, which matches the offsets the OpenOrbis samples read (`face->glyph` at 0x98, `slot->advance` at 0x80, `slot->bitmap` at 0x98, `slot->bitmap_left` at 0xc0). Which FreeType version and options the console library is built with is unknown, so the behaviour and error codes are those of FreeType 2.13.3. The OpenOrbis font, keyboard, threading, system and SDL2 samples import these six functions - [FT_Bitmap_New, FT_Bitmap_Copy, FT_Bitmap_Convert, FT_Bitmap_Done](../../../core/libs/prx/libSceFreeType/src/Bitmap.cpp) (libSceFreeType) - console behaviour and error codes are unmeasured; these follow bundled FreeType 2.13.3. Copy and Convert throw when source and target share a non-null buffer; Convert also throws when they are the same object. Other overlapping storage remains forbidden by the native API contract - [FT_Request_Size](../../../core/libs/prx/libSceFreeType/src/SizeRequest.cpp) (libSceFreeType) - console signature, request layout and errors are unverified; the guest request follows the LP64 public headers of the bundled [FreeType 2.13.3](https://github.com/freetype/freetype/blob/42608f77f20749dd6ddc9e0536788eaad70ea4b5/include/freetype/freetype.h). Host overflow behavior remains that of the bundled build. On Windows, native `FT_Long` is 32 bits; valid requests whose width or height exceeds that range throw before changing the size. +- [FT_Select_Size](../../../core/libs/prx/libSceFreeType/Export.cpp) (libSceFreeType) - console signatures and errors are unverified; the LP64 guest adapter follows the bundled [FreeType 2.13.3](https://github.com/freetype/freetype/blob/42608f77f20749dd6ddc9e0536788eaad70ea4b5/src/base/ftobjs.c). Bitmap-strike selection and size metrics are checked against native FreeType with generated BDF fonts; other font drivers have not been exercised through this entry point. + - [FT_New_Memory_Face, FT_Done_Face and FT_Done_FreeType](../../../core/libs/prx/libSceFreeType/Export.cpp) (libSceFreeType) - console signatures, errors and generic-finalizer ordering are unverified; they follow the bundled [FreeType 2.13.3](https://github.com/freetype/freetype/blob/42608f77f20749dd6ddc9e0536788eaad70ea4b5/include/freetype/freetype.h) with LP64 guest arguments. Caller-owned font bytes must remain valid until the face is freed. - [FT_Outline_Check, FT_Outline_Get_CBox](../../../core/libs/prx/libSceFreeType/src/Outline.cpp) (libSceFreeType) - console signatures, count signedness and errors are unverified; the adapter follows bundled [FreeType 2.13.3](https://github.com/freetype/freetype/blob/42608f77f20749dd6ddc9e0536788eaad70ea4b5/src/base/ftoutln.c), including its unsigned 16-bit counts and contour endpoints. Control-box coordinates use the existing guest LP64 layout and retain their full 64-bit range on Windows; contour checking does not validate point tags diff --git a/docs/dev/debt/libSceGameLiveStreaming.md b/docs/dev/debt/libSceGameLiveStreaming.md index 75299aa071..b52bed6644 100644 --- a/docs/dev/debt/libSceGameLiveStreaming.md +++ b/docs/dev/debt/libSceGameLiveStreaming.md @@ -18,7 +18,7 @@ - [sceGameLiveStreamingScreenSetMode](../../../core/libs/prx/libSceGameLiveStreaming/Export.cpp) (libSceGameLiveStreaming) - unknown signature - [sceGameLiveStreamingPermitLiveStreaming](../../../core/libs/prx/libSceGameLiveStreaming/Export.cpp) (libSceGameLiveStreaming) - unknown signature - [sceGameLiveStreamingSetMaxBitrate](../../../core/libs/prx/libSceGameLiveStreaming/Export.cpp) (libSceGameLiveStreaming) - unknown signature -- [sceGameLiveStreamingGetCurrentStatus](../../../core/libs/prx/libSceGameLiveStreaming/Export.cpp) (libSceGameLiveStreaming) - unknown signature +- [sceGameLiveStreamingGetCurrentStatus](../../../core/libs/prx/libSceGameLiveStreaming/include/Api.hpp) - still throws; the meaning, division and SDK types of the first 12 bytes remain unknown. In the supplied `libSceGameLiveStreaming.sprx`, export `CoPMx369EqM` at 0x1810 takes one output pointer, clears 72 bytes, obtains service command 9's status, copies its first 12 bytes and clears bytes 0x0C..0x47. `GameLiveStreamingStatus` exposes this byte storage without assuming the `GetCurrentStatus2` field layout or SDK alignment. The decompiler's extra SIMD parameter is not an input: the assembly initializes the register before use. - [sceGameLiveStreamingEnableSocialFeedback](../../../core/libs/prx/libSceGameLiveStreaming/Export.cpp) (libSceGameLiveStreaming) - unknown signature - [sceGameLiveStreamingGetSocialFeedbackMessagesCount](../../../core/libs/prx/libSceGameLiveStreaming/Export.cpp) (libSceGameLiveStreaming) - unknown signature - [sceGameLiveStreamingGetSocialFeedbackMessages](../../../core/libs/prx/libSceGameLiveStreaming/Export.cpp) (libSceGameLiveStreaming) - unknown signature diff --git a/docs/dev/debt/libSceInvitationDialog.md b/docs/dev/debt/libSceInvitationDialog.md index e7687fa477..9038d9da62 100644 --- a/docs/dev/debt/libSceInvitationDialog.md +++ b/docs/dev/debt/libSceInvitationDialog.md @@ -2,4 +2,5 @@ ### Unknown function info +- [sceInvitationDialogGetResult](../../../core/libs/prx/libSceInvitationDialog/include/Api.hpp) - still throws; SDK field names and types at offsets 0x00 and 0x0C are unknown. In the supplied `libSceInvitationDialog.sprx`, export `8XKR6wa64iQ` at 0xFF0 takes one result pointer, checks reserved bytes 0x18..0x37 and writes the returned status at 0x08. The helper at 0x410 copies eight bytes from the saved open parameter to 0x00 and eight result bytes to 0x08, then copies 20-byte online IDs through the pointer at 0x10, after a four-byte count. Validation at 0xC20 limits recipients to 1..16. `InvitationDialogRecipients` provides the accessed 324-byte storage; any unused SDK tail is unverified. `InvitationDialogResult` provides the accessed 56 bytes, with unknown fields kept opaque; this is not a recovered SDK source declaration. - [sceInvitationDialogClose](../../../core/libs/prx/libSceInvitationDialog/Export.cpp) (libSceInvitationDialog) - imported by PS4 titles, which do not load without it, and added without an implementation: declared without parameters, every call throws diff --git a/docs/dev/debt/libSceJobManager.md b/docs/dev/debt/libSceJobManager.md index 06f7ba4aac..93d8f3ec8a 100644 --- a/docs/dev/debt/libSceJobManager.md +++ b/docs/dev/debt/libSceJobManager.md @@ -2,8 +2,7 @@ ### Functional -- [sce::Job::JobManager](../../../core/libs/prx/libSceJobManager/Export.cpp) submits commands as work becomes runnable rather than encoding ahead with the rewind protocol recovered from PPSA06888's module (offsets 0x2210 and 0x2650). Commands are recycled after a completed wait. Command capacity is a separate bound from the dispatch count: the native size query measures one register and a 31-character marker, then its exhaustion callback at 0x29d0 traps instead of growing storage. The fallback throws. Original-module execution with the host AGC builders accepts two dispatches with 255 registers and 65,535-character markers, then traps on a third. Console timing equivalence remains unverified. -- The [manager](../../../core/libs/prx/libSceJobManager/Export.cpp) keeps scheduling state and nodes on the host heap; only the header, compute commands and completion labels occupy the caller's block. Blocks smaller than 0x2d8 bytes throw. Worker parking uses host mutexes and condition variables instead of native atomic queues and semaphores; console scheduling and spin timing are unverified. Spin intervals use unscaled host TSC, while the original module reads scaled guest TSC under the host-only `APS5_TIME_SCALE` diagnostic. -- [Sequence and manager operations](../../../core/libs/prx/libSceJobManager/Export.cpp) throw on a compute dispatch on a CPU sequence, a failing `sceAgcDriverAddEqEvent`, a factory priority above 1, and use of a destroyed sequence. `shutdown` throws while compute work is in flight or a caller is blocked in a sequence wait. Worker creation and attribute failures throw where the original does not check. -- [`initialize`](../../../core/libs/prx/libSceJobManager/Export.cpp) returns 0 instead of the result of the final object-registration import (`BG26hBGiNlw`, `_sceUlobjmgrRegisterObject`). The `sceRazorCpuJobManager*` profiler calls are not made. Sequence and factory virtual-function order is recovered from module vtables; no calling title has been run. -- The [fallback](../../../core/libs/prx/libSceJobManager/Export.cpp) differs from the owned module under host kernel services. Native Wait can stall allocating from an exhausted global node pool; the fallback deliberately needs no Wait node and recycles nodes. The owned module also stalls in the zero-spin, zero-persistence `worker_wait` fixture on Windows and Linux, while the fallback wakes a spare worker and completes the child. Console behavior for these cases is unverified. The [reference runner](../../../tools/run_job_manager_reference.py) on this branch supports Windows only; failures remain failures, and Linux runner support follows in #10272. +- [Compute sequences](../../../core/libs/prx/libSceJobManager/Export.cpp) encode ahead across GPU barriers using explicit release packets instead of the native rewind protocol and completion-packet patching recovered from PPSA06888's module (offsets 0x2210 and 0x2650). Commands are recycled after a completed wait. Command capacity is a separate bound from the dispatch count: the native size query measures one register and a 31-character marker, then its exhaustion callback at 0x29d0 traps instead of growing storage. The fallback throws. Original-module execution with the host AGC builders accepts two dispatches with 255 registers and 65,535-character markers, then traps on a third. Console timing equivalence remains unverified. Compute dispatch on a CPU sequence throws. +- [Scheduling](../../../core/libs/prx/libSceJobManager/Export.cpp) uses host mutexes and condition variables instead of native atomic queues and semaphores; spin intervals deliberately use unscaled host TSC, while the original module reads scaled guest TSC under the host-only `APS5_TIME_SCALE` diagnostic. Blocks below 0x2d8 bytes, factory priorities above one, use of destroyed sequences and shutdown from a worker throw. New calls concurrent with shutdown are unverified. +- [Pool allocation](../../../core/libs/prx/libSceJobManager/Export.cpp) reuses freed nodes in a different order; profiler dispatch IDs can differ from native allocation. The fallback Wait deliberately allocates no pool node; native Wait can stall on global pool exhaustion. Resource-creation failures throw after cleanup, where the original does not check every return. Vtable order was checked, but no calling title or PS5 timing equivalence has been tested. +- Console behavior for [worker waits](../../../core/libs/prx/libSceJobManager/Export.cpp) is unverified. The owned original module stalls on the zero-spin, zero-persistence `worker_wait` fixture with native Windows and Linux host kernel services; the fallback wakes a spare worker and completes the child. The reference runner keeps this case selectable but excludes it from the shared-behavior parity suite. diff --git a/docs/dev/debt/libSceLibreSsl.md b/docs/dev/debt/libSceLibreSsl.md index f0d6d1c3bb..a9e5271b10 100644 --- a/docs/dev/debt/libSceLibreSsl.md +++ b/docs/dev/debt/libSceLibreSsl.md @@ -2,9 +2,18 @@ ### Unknown function info -- [libSceLibreSsl pending exports](../../../core/libs/prx/libSceLibreSsl/Export.cpp) - 357 named callable exports are listed in the [PS5 3.20 export table](https://github.com/DNNDHH/PS5-3.20_Libs/blob/b2a77c09cd71c01f34c790cfbe98c751a13262ad/libSceLibreSsl.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`. +- [libSceLibreSsl pending exports](../../../core/libs/prx/libSceLibreSsl/Export.cpp) - 345 named callable exports are listed in the [PS5 3.20 export table](https://github.com/DNNDHH/PS5-3.20_Libs/blob/b2a77c09cd71c01f34c790cfbe98c751a13262ad/libSceLibreSsl.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`. - [MD4, MD5, SHA1, SHA224, SHA256, SHA384 and SHA512 Init/Update/Final and SHA256](../../../core/libs/prx/libSceLibreSsl/src/Digest.cpp) (libSceLibreSsl) - signatures and context layouts follow the [LibreSSL headers](https://github.com/libressl/openbsd/blob/bc9483725c5815efb64b6d9acc52fc5fba139212/src/lib/libcrypto/sha/sha.h), and buffering and `Final` follow its [sources](https://github.com/libressl/openbsd/tree/bc9483725c5815efb64b6d9acc52fc5fba139212/src/lib/libcrypto/sha); the module's LibreSSL version is unknown and nothing is checked on the console. Behaviour that differs between LibreSSL versions throws: `SHA256` with a null digest buffer (older versions return a static buffer) and `SHA512_Final` with the SHA-512/224 or SHA-512/256 digest length. Null contexts, null input with a nonzero length, null digest buffers in the 32-bit `Final` functions and a buffered byte count that is not below the block size, which LibreSSL does not check, throw - [DES_set_key, DES_ecb_encrypt, DES_set_odd_parity](../../../core/libs/prx/libSceLibreSsl/Export.cpp) (libSceLibreSsl) - the 128-byte `DES_key_schedule` holds the 8-byte key followed by zeros instead of LibreSSL's precomputed subkeys, so a title reading its contents sees different bytes; `DES_ecb_encrypt` derives the subkeys through mbedtls on each call. Not compared with the console. Results follow LibreSSL [des_key.c](https://github.com/libressl/openbsd/blob/bc9483725c5815efb64b6d9acc52fc5fba139212/src/lib/libcrypto/des/des_key.c) and [des.c](https://github.com/libressl/openbsd/blob/bc9483725c5815efb64b6d9acc52fc5fba139212/src/lib/libcrypto/des/des.c): `DES_set_key` skips the parity and weak-key checks and returns 0, as it does while `DES_check_key` is 0 (that variable is not in the PS5 export inventory), a nonzero `enc` encrypts, and `DES_set_odd_parity` sets each byte's low bit for odd parity. Null pointers throw where LibreSSL faults - [X509_verify_cert_error_string](../../../core/libs/prx/libSceLibreSsl/Export.cpp) - no console call is verified. The 64-bit argument, low-32-bit lookup, messages and shared numeric fallback follow [LibreSSL 2.5.4](https://github.com/libressl/openbsd/blob/2e2c612066aa993717528a0249c15c51128d61cb/src/lib/libcrypto/x509/x509_txt.c), the version identified in [published firmware 13.40 measurements](https://github.com/boykopovar/AnyPS5/discussions/8981#discussioncomment-19111214). Console modifications and other firmware versions remain unverified. Unknown-code results share an overwritten static buffer and are not safe for concurrent use, as in that release; code 1 and codes above 54 use the numeric fallback. - [RAND_add, RAND_bytes, RAND_status, RAND_load_file, RAND_file_name, CRYPTO_malloc, CRYPTO_free, CRYPTO_set_mem_functions](../../../core/libs/prx/libSceLibreSsl/src/Runtime.cpp) (libSceLibreSsl) - follow LibreSSL's [rand_lib.c, randfile.c](https://github.com/libressl/openbsd/tree/0f0b16dc977f6ca499f0f4540078d992c96da597/src/lib/libcrypto/rand) and [malloc-wrapper.c](https://github.com/libressl/openbsd/blob/0f0b16dc977f6ca499f0f4540078d992c96da597/src/lib/libcrypto/malloc-wrapper.c), which are the same in 2.6.5 (3.4.3 linked); nothing is checked on the console. `RAND_bytes` reads host entropy and `CRYPTO_malloc` and `CRYPTO_free` use the guest heap. `CRYPTO_malloc` returns null for a size of zero or less, as LibreSSL 2.5.4 to 3.4 do; later versions take a `size_t` size and call `malloc`. A null buffer with a positive length throws - [AES_set_encrypt_key, AES_set_decrypt_key, AES_encrypt, AES_decrypt, AES_ecb_encrypt, AES_cbc_encrypt, AES_cfb128_encrypt, AES_ctr128_encrypt](../../../core/libs/prx/libSceLibreSsl/src/Aes.cpp) (libSceLibreSsl) - follow LibreSSL's [aes.h](https://github.com/libressl/openbsd/blob/bc9483725c5815efb64b6d9acc52fc5fba139212/src/lib/libcrypto/aes/aes.h) and [mode code](https://github.com/libressl/openbsd/tree/bc9483725c5815efb64b6d9acc52fc5fba139212/src/lib/libcrypto/modes). Nothing is checked on the console. Key setup follows [LibreSSL 2.5.4's aes_core.c](https://github.com/libressl/openbsd/blob/2e2c612066aa993717528a0249c15c51128d61cb/src/lib/libcrypto/aes/aes_core.c), the version the `X509_verify_cert_error_string` entry names: a null pointer returns -1 and a key length other than 128, 192 or 256 bits returns -2 before the key is written, and only the 44, 52 or 60 words the key length needs are written. The `AES_KEY` schedule uses that file's generic C layout (big-endian words, `rounds` 10, 12 or 14). The 2.5.4 amd64 build uses [aes-x86_64](https://github.com/libressl/openbsd/blob/2e2c612066aa993717528a0249c15c51128d61cb/src/lib/libcrypto/aes/asm/aes-x86_64.pl) instead, which copies the key bytes without swapping, so each word is byte-reversed compared with the C layout (OpenSSL 3.0.13's x86-64 code gives the same schedules byte-reversed); the console's build options are unknown, so a schedule the title reads or fills is unverified. CTR leaves the last keystream block in `ecount_buf` even at a block boundary. Null pointers in the cipher and mode functions, other `rounds` values and a CFB or CTR position outside 0-15 throw +- [ERR_get_error, ERR_peek_error, ERR_clear_error, ERR_remove_thread_state](../../../core/libs/prx/libSceLibreSsl/src/Error.cpp) (libSceLibreSsl) - no export of this library adds an error yet, so the queue stays empty for guest code. The per-thread queue of 16 slots holding 15 codes, its order and the `ERR_PACK` layout follow LibreSSL's [err.c](https://github.com/libressl/openbsd/blob/bc9483725c5815efb64b6d9acc52fc5fba139212/src/lib/libcrypto/err/err.c) and [err.h](https://github.com/libressl/openbsd/blob/bc9483725c5815efb64b6d9acc52fc5fba139212/src/lib/libcrypto/err/err.h); the module's LibreSSL version is unknown and nothing is checked on the console. The queue keeps no file, line or data, as no export reads them. `ERR_remove_thread_state` with a thread id throws: that version asserts a null id, while older versions remove the state of the thread the id names + +- [SSL_CIPHER_get_bits, SSL_CIPHER_get_name and SSL_CIPHER_get_version](../../../core/libs/prx/libSceLibreSsl/src/Cipher.cpp) - the 88-byte guest cipher layout and these calls are not console-verified. They follow [LibreSSL 2.5.4 ssl.h](https://github.com/libressl/openbsd/blob/2e2c612066aa993717528a0249c15c51128d61cb/src/lib/libssl/ssl.h) and [ssl_ciph.c](https://github.com/libressl/openbsd/blob/2e2c612066aa993717528a0249c15c51128d61cb/src/lib/libssl/ssl_ciph.c), matching 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. Protocol labels use the full 64-bit cipher ID, not the protocol flags; TLS 1.2 ciphers still report `TLSv1/SSLv3`, as in that release. + +### Functional + +- [ASN1_INTEGER_get](../../../core/libs/prx/libSceLibreSsl/src/Asn1.cpp) has no console verification for nonpositive lengths. It follows [LibreSSL 2.5.4](https://github.com/libressl/openbsd/blob/2e2c612066aa993717528a0249c15c51128d61cb/src/lib/libcrypto/asn1/a_int.c#L363-L389): valid integer types return zero without reading data when length is zero or negative; invalid types return -1 first. Later LibreSSL versions reject negative lengths through `ASN1_INTEGER_get_int64`; that later contract is not used for this library. + +- [ASN1_INTEGER_get and ASN1_STRING_data/length/type/to_UTF8](../../../core/libs/prx/libSceLibreSsl/src/Asn1.cpp) are unverified on PS5. Signatures, the 24-byte guest string layout and conversions follow [LibreSSL 2.5.4's ASN.1 sources](https://github.com/libressl/openbsd/tree/2e2c612066aa993717528a0249c15c51128d61cb/src/lib/libcrypto/asn1), the version reported for firmware 13.40 in [discussion #8981](https://github.com/boykopovar/AnyPS5/discussions/8981#discussioncomment-19111214). Null accessor inputs, null conversion outputs, missing nonempty data, oversized converted output and unrepresentable signed integer values throw where the source has undefined behaviour. Malformed encodings and allocation failure throw until ASN.1 error-queue reporting is implemented. Conversion buffers use the guest libc allocator and can be released with guest `free`. diff --git a/docs/dev/debt/libSceNet.md b/docs/dev/debt/libSceNet.md index 611efe6936..13c0a4cb82 100644 --- a/docs/dev/debt/libSceNet.md +++ b/docs/dev/debt/libSceNet.md @@ -8,6 +8,7 @@ ### Unknown function info +- [sceNetGetsockopt](../../../core/libs/prx/libSceNet/Export.cpp) - `SO_PROTOCOL` on raw sockets throws: FreeBSD's raw protocol-switch selection has not been mapped to host raw sockets. For stream and datagram sockets, the effective creation protocol and accepted-socket inheritance follow FreeBSD 11.4's [protocol tables](https://github.com/freebsd/freebsd-src/blob/releng/11.4/sys/netinet/in_proto.c) and [sogetopt](https://github.com/freebsd/freebsd-src/blob/releng/11.4/sys/kern/uipc_socket.c); the `0x1016` option and truncated integer output are not measured on PS5. Existing null-pointer validation still returns `EINVAL`. - [sceNetRecv, sceNetRecvfrom and sceNetRecvmsg](../../../core/libs/prx/libSceNet/Export.cpp) (libSceNet) - zero-length TCP receives while connecting, after disconnect, or with a pending host error still use the host receive path. Error and output precedence in those states is unmeasured on a console. The established, error-free case follows FreeBSD 11.4's [`soreceive_generic`](https://github.com/freebsd/freebsd-src/blob/release/11.4.0/sys/kern/uipc_socket.c#L1568-L1583). - [sceNetConfigAddIfaddr](../../../core/libs/prx/libSceNet/Export.cpp) (libSceNet) - disassembly confirms the same interface/address/broadcast/netmask arguments as SetIfaddr, entering its shared handler with add mode selected. GetIfaddr copies up to two 16-byte interface-address records. GetRouteInfo uses a family, record buffer, signed capacity and byte flags; internal statistics output is 16 bytes. The address-record and internal-statistics fields remain incomplete. @@ -30,17 +31,17 @@ ### Functional - [sceNetRecv/sceNetRecvfrom](../../../core/libs/prx/libSceNet/Export.cpp) (libSceNet) translate Windows WSAEMSGSIZE into the copied byte count for datagram sockets, including MSG_PEEK, and retain the sender address. This follows FreeBSD 11.4 recv(2) and Winsock's documented truncated-datagram behavior; the console measurement covered only libkernel_sys `recv` and `recvfrom`, not libSceNet. -- [sceNetUsleep](../../../core/libs/prx/libSceNet/Export.cpp) (libSceNet) prints nothing for a negative count, where the console prints `[LIBNET] usleep ` to standard output before failing with `EINVAL`. What an interrupted sleep returns is unmeasured: AnyPS5 returns the result of libkernel's `sceKernelUsleep`, a cancellation point. The signed 32-bit count (the upper half of the register is ignored) and the 0 result were measured on a PS5 (firmware 13.60) +- [sceNetUsleep](../../../core/libs/prx/libSceNet/Export.cpp) (libSceNet) - whether the console prints its `[LIBNET] usleep ` line for a negative count before `sceNetInit` is unmeasured; nothing is printed here. What an interrupted sleep returns is unmeasured: AnyPS5 returns the result of libkernel's `sceKernelUsleep`, a cancellation point. The signed 32-bit count (the upper half of the register is ignored) and the 0 result were measured on a PS5 (firmware 13.60) - [sceNetIoctl](../../../core/libs/prx/libSceNet/Export.cpp) (libSceNet) - on a `sceNetSocket` socket only `FIONBIO` and `FIONREAD` are handled and other requests fail with `ENOTTY`, as in libkernel's `ioctl`, though FreeBSD 11.4's [`soo_ioctl`](https://github.com/freebsd/freebsd-src/blob/8c639945a44588f6cfdddfb057bb5aad88735da0/sys/kern/sys_socket.c#L156-L262) handles more; not measured on a console. [shadPS4](https://github.com/shadps4-emu/shadPS4/blob/60c42b925c3d1e00008621b8587819999260ec31/src/core/libraries/net/net.cpp#L1839) (PS4) returns `EINVAL` for other requests. `FIONBIO` sets `SO_NBIO`, assumed to be `soo_ioctl`'s `SS_NBIO`. `FIONREAD` asks the host, which on Linux counts only the next datagram where `soo_ioctl` counts all. Libkernel's own sockets go to its `ioctl`; other descriptors get `EBADF`. - [sceNetResolverStartAton6](../../../core/libs/prx/libSceNet/Export.cpp) (libSceNet) reverse-resolves a 16-byte IPv6 address through the host resolver (`getnameinfo` with `NI_NAMEREQD`) into the caller's buffer of `len` bytes, as `sceNetResolverStartAton` does for IPv4. The `(rid, addr, hostname, len, timeout, retry, flags)` signature comes from [SharpProspero](https://github.com/SvenGDK/SharpProspero/blob/5dfdb4b0b166e83dc9ae275001afb695f12c7174/src/SharpProspero/Interop/Net/Socket.cs#L992-L997). An address with no name, or a name longer than `len - 1` bytes, fails with `RESOLVER_ENODNS` (`0x804101E1`) and leaves the buffer untouched; whether the console truncates instead is not verified. Abort flag 2 (ATON preservation) fails the next call with `EINTR` as it does `sceNetResolverStartAton`. Timeout and retry are ignored, and any nonzero flags throw because their meaning is unknown -- [sceNetAccept](../../../core/libs/prx/libSceNet/Export.cpp) (libSceNet) inherits the listener's non-blocking mode through the existing `SO_NBIO` setter, as the libkernel socket path does and FreeBSD's [`sonewconn`](https://github.com/freebsd/freebsd-src/blob/8c639945a44588f6cfdddfb057bb5aad88735da0/sys/kern/uipc_socket.c#L571) copies the socket state. The mode is sampled when accept starts; changes between connection creation and accept are not modelled. Not measured on a console. +- [sceNetAccept](../../../core/libs/prx/libSceNet/Export.cpp) (libSceNet) inherits the listener's non-blocking mode through the existing `SO_NBIO` setter, as the libkernel socket path does and FreeBSD's [`sonewconn`](https://github.com/freebsd/freebsd-src/blob/8c639945a44588f6cfdddfb057bb5aad88735da0/sys/kern/uipc_socket.c#L571) copies the socket state. The mode is read after the host accept returns; changes between connection creation and accept are not modelled. Not measured on a console. - [sceNetConnect to AF_UNSPEC](../../../core/libs/prx/libSceNet/Export.cpp) (libSceNet) dissolves a datagram association as FreeBSD 11.4's `udp_disconnect()` does, which resets the local address to the wildcard address and keeps the port. On Linux a socket bound to an explicit port keeps its local address as well (`127.0.0.1:` stays `127.0.0.1:`), because a bound socket cannot be bound again; one bound to port 0 is bound again to the wildcard address with the port it had - [sceNetSetsockopt](../../../core/libs/prx/libSceNet/Export.cpp) (libSceNet) sets `SO_RCVTIMEO` and `SO_SNDTIMEO` as the host socket's timeouts. Windows sockets stay non-blocking and the library waits for readiness until the stored timeout. Blocking stream sends return the queued byte count on timeout, or `EAGAIN` when no bytes were queued. - [sceNetSetsockopt, sceNetGetsockopt](../../../core/libs/prx/libSceNet/Export.cpp) (libSceNet) take `SO_SNDTIMEO` and `SO_RCVTIMEO` (0x1005, 0x1006) as a 16-byte `struct timeval`, as FreeBSD 11.4's [`sosetopt` and `sogetopt`](https://github.com/freebsd/freebsd-src/blob/d106002967eff712894ab8b5337bbbff106ce5e0/sys/kern/uipc_socket.c#L2657-L2690) do, and Sony's 0x1105 and 0x1106 as an `int` of microseconds. A [console log of ProsperoLight](https://github.com/blackbearreloaded/ProsperoLight/issues/49) (firmware 12.20) shows receives timing out every 100 ms after it gave 0x1006 a `{0, 100000}` timeval. The errors for a value shorter than a timeval (`EINVAL`) or out of range (`EDOM`), and `sceNetGetsockopt` cutting the timeval to the caller's length, follow FreeBSD's `sooptcopyin` and `sooptcopyout` and are not measured on a console - [sceNetSetsockopt](../../../core/libs/prx/libSceNet/Export.cpp) (libSceNet) stores `SO_ONESBCAST` (`0x10000`, [shadPS4's `ORBIS_NET_SO_ONESBCAST`](https://github.com/shadps4-emu/shadPS4/blob/main/src/core/libraries/net/net_types.h)) per socket and `sceNetGetsockopt` reads back the value that was set, as shadPS4 does; PPSA34501 sets it and crashes later when it fails with `EOPNOTSUPP`. Sends ignore it. FreeBSD 11.4's [ip(4)](https://man.freebsd.org/cgi/man.cgi?manpath=FreeBSD+11.4-RELEASE&query=ip&sektion=4) documents the like-named `IPPROTO_IP` option `IP_ONESBCAST`: a datagram sent to an interface's directed broadcast address, such as 192.168.2.255, leaves through that interface with its destination rewritten to 255.255.255.255, and only on a socket allowed to set `SO_BROADCAST`. Here host routing selects the outgoing interface and the destination is not rewritten. shadPS4 also leaves sends unchanged, and its [TODO](https://github.com/shadps4-emu/shadPS4/blob/main/src/core/libraries/net/net.cpp#L2467-L2470) reads the option the other way round: a send to 255.255.255.255 would be converted to the interface's broadcast address. Whether the console's `SOL_SOCKET` option behaves like `IP_ONESBCAST`, and what it reads back, is not verified on hardware. FreeBSD 11.4's `sogetopt()` reads several boolean socket options back as their flag bit (`so_options & optname`, `sys/kern/uipc_socket.c`), not as the value set; whether the console does so for `0x10000` is unknown - [sceNetGetsockopt](../../../core/libs/prx/libSceNet/Export.cpp) (libSceNet) reads `SO_ERROR` from the host socket. Winsock does not clear a socket's pending error when it is read, so on Windows the library reports a pending error once and shows it again only after a new `sceNetConnect`; a second failure with the same code on the same socket without a `sceNetConnect` in between would be hidden. -- [sceNetSetsockopt, sceNetGetsockopt](../../../core/libs/prx/libSceNet/Export.cpp) (libSceNet) set `TCP_NODELAY` (`IPPROTO_TCP`, 1) on the host socket of a stream socket and read it back as `TF_NODELAY` (4) or 0, as FreeBSD 11.4's [`tcp_default_ctloutput`](https://github.com/freebsd/freebsd-src/blob/releng/11.4/sys/netinet/tcp_usrreq.c#L1626-L1650) does. Every other `IPPROTO_TCP` option (`TCP_MAXSEG`, `TCP_NOPUSH` and `TCP_KEEPIDLE` among them, which FreeBSD implements) fails with `ENOPROTOOPT`, and the `IPPROTO_TCP` level on a socket that is not a stream socket fails with `EINVAL`, as [`ip_ctloutput`](https://github.com/freebsd/freebsd-src/blob/releng/11.4/sys/netinet/ip_output.c#L943-L944) answers it. A set on a connection that FreeBSD's [`tcp_ctloutput`](https://github.com/freebsd/freebsd-src/blob/releng/11.4/sys/netinet/tcp_usrreq.c#L1498-L1502) refuses with `ECONNRESET` (refused, reset or in `TIME_WAIT`) succeeds here because the host accepts it. A null value with a nonzero length fails with `EINVAL`, where FreeBSD's `kern_setsockopt` returns `EFAULT`, and a get into less than an `int` fails with `EINVAL`, where `sooptcopyout` truncates. None of this was measured on a console. +- [sceNetSetsockopt, sceNetGetsockopt](../../../core/libs/prx/libSceNet/Export.cpp) - `TCP_MAXSEG`, `TCP_NOPUSH`, `TCP_KEEPIDLE` and other TCP options remain unsupported (`ENOPROTOOPT`). `TCP_NODELAY` sets on refused, reset or `TIME_WAIT` sockets can succeed through the host where FreeBSD 11.4's [tcp_ctloutput](https://github.com/freebsd/freebsd-src/blob/releng/11.4/sys/netinet/tcp_usrreq.c#L1498-L1502) returns `ECONNRESET`. A null setter value returns `EINVAL` rather than `kern_setsockopt`'s `EFAULT`. The non-stream `IPPROTO_TCP` error (`EINVAL`) and `TF_NODELAY` flag readback follow FreeBSD, not PS5 measurements. - [sceNetGetSockInfo](../../../core/libs/prx/libSceNet/Export.cpp) (libSceNet) reports 0 for the name, pid, policy, priority, queue lengths, virtual ports, state, bandwidth, drops and waits, sets no status flag except `SELF` (0x1) and `NONBLOCK` (0x200000), and reports the host's buffer sizes where none was set. An IPv6 socket fails with `EAFNOSUPPORT` and is not counted or listed; shadPS4 lists it with zero addresses. `flags` bits other than 0x40 fail with `EINVAL`, where shadPS4 ignores `flags`; 0x40 adds sockets in TIME_WAIT ([SharpProspero](https://github.com/SvenGDK/SharpProspero/blob/5dfdb4b0b166e83dc9ae275001afb695f12c7174/src/SharpProspero/Interop/Net/Socket.cs)), but closed sockets are not kept. Otherwise the `s` below 0 count and list, the return value and `EINVAL` for a null `info` or an `n` below 1 follow [shadPS4](https://github.com/shadps4-emu/shadPS4/blob/06e813ff8c8e2a6d81b02cabfcc9543c3debf78e/src/core/libraries/net/net.cpp#L1498-L1522). Not measured on a console. - [SO_SNDBUF and SO_RCVBUF validation](../../../core/libs/prx/libSceNet/Export.cpp) remains unverified on PS5, and positive sizes remain subject to host buffer limits. Nonpositive sizes fail with `EINVAL` before changing the native socket, following FreeBSD 11.4 [sosetopt](https://github.com/freebsd/freebsd-src/blob/releng/11.4/sys/kern/uipc_socket.c#L2494-L2509). - [sceNetSendmsg and sceNetRecvmsg](../../../core/libs/prx/libSceNet/Export.cpp) (libSceNet) copy the scatter/gather list through one host buffer and accept only the flags `sceNetSend`/`sceNetRecv` accept. Sending control data throws; a receive never returns control data (`msg_controllen` 0), since no socket option that queues it is supported diff --git a/docs/dev/debt/libSceNgs2.native.md b/docs/dev/debt/libSceNgs2.native.md index 5997a09d48..062ccbe526 100644 --- a/docs/dev/debt/libSceNgs2.native.md +++ b/docs/dev/debt/libSceNgs2.native.md @@ -14,9 +14,10 @@ - [NGS2 submixer UserFx](../../../core/libs/prx/libSceNgs2.native/src/Custom.cpp) (control `0x20000004`) invokes the title's callback after input mixing on every playing grain, including silence. The 40-byte control and 48-byte process context follow [shadPS4](https://github.com/shadps4-emu/shadPS4/blob/945dbc3cc3eee80ac3e053b438502ed936fa6bb2/src/core/libraries/ngs2/ngs2_submixer.h). PPSA03747 installs a peak-meter callback; its code confirms the channel pointers, user data 0, channel count, grain size and sample-rate offsets and returns 0. Other user data words are preserved. Flags are assumed to be 1 after registration/restart and 0 thereafter, following UserFx2's first-process convention; this callback does not inspect them. Null handlers disable the effect, setup clears it, and nonzero callback results throw. These lifecycle and error semantics are unverified on console hardware. - [NGS2 voice callback after setup](../../../core/libs/prx/libSceNgs2.native/src/Voice.cpp) (libSceNgs2.native) - a sampler or mixer setup clears the voice callback with the rest of the voice state. PPSA18216 registers a block-end callback for a streamed music voice, later sets the same voice up again for one-shot ATRAC9 blocks with user data 0, and registers the callback again before it streams again; its callback dereferences the block's user data, so it must not run for the one-shot blocks. A setup made from inside the voice's own callback clears that callback as well, so a callback that sets its voice up again and queues the next block runs once instead of for every block; PPSA18216 never sets a voice up from inside its callback, so that ordering is unverified. Unverified on console hardware. - [NGS2 ATRAC9 streaming](../../../core/libs/prx/libSceNgs2.native/src/Atrac9.cpp) keeps waveform duration and skip counts across compressed input blocks. The shared `APPEND` flag (2), called `ONLY_DATA` in the compressed-data reference, ignores an ATRAC9 continuation block's sample, skip and repeat counts, following [KytyPS5](https://github.com/KytyPS5/KytyPS5/blob/bb98f26433fa9e711c219aac1711fe8ecba5bf3a/src/libs/ngs2.cpp); PPSA03747 confirms a 262044-byte initial buffer declaring 11310532 samples, followed by 16384-byte buffers with flags 3. Incomplete superframes are retained until more input arrives. Input-block completion callbacks allow refills; the final callback of a logical waveform waits for its buffered PCM to drain, preserving the existing complete-block repeat behaviour. This buffering, callback timing, decoded-byte accounting and starvation silence are unverified on hardware. A closed ATRAC9 stream ending before its declared samples throws; fragmented ATRAC9 waveforms with repeats are unsupported. PCM streaming retains its existing append validation and early-close behaviour. -- [NGS2 mastering voice gain](../../../core/libs/prx/libSceNgs2.native/src/Voice.cpp) (libSceNgs2.native) - the param id 0x30000004 is taken from PPSA22520 and the layout from [shadPS4](https://github.com/shadps4-emu/shadPS4)'s `OrbisNgs2MasteringVoiceGainParam`; no reference gives the units or range. The levels are assumed to be linear factors applied when the mastering voice is mixed into the render buffer, so the voice's own samples stay unscaled; the LFE level applies to channel 3 of 6- and 8-channel voices, assuming the L R C LFE order of the AudioOut2 entries above, and the full-band level to the rest. Negative levels are accepted, and a new setup resets both levels to 1 +- [NGS2 mastering voice gain](../../../core/libs/prx/libSceNgs2.native/src/Voice.cpp) (libSceNgs2.native) - the param id 0x30000004 is taken from PPSA22520 and the layout from [shadPS4](https://github.com/shadps4-emu/shadPS4)'s `OrbisNgs2MasteringVoiceGainParam`; no reference gives the units or range. The levels are assumed to be linear factors applied when the mastering voice is mixed into the render buffer, so the voice's own samples stay unscaled; the LFE level applies to channel 3 of 6- and 8-channel voices, assuming the L R C LFE order of the `sceAudioOut2PortCreate` entries in [libSceAudioOut](libSceAudioOut.md), and the full-band level to the rest. Negative levels are accepted, and a new setup resets both levels to 1 - [NGS2 stereo mastering voice into a surround buffer](../../../core/libs/prx/libSceNgs2.native/src/Render.cpp) (libSceNgs2.native) - PPSA21402 renders a 2-channel mastering voice into a 6- or 8-channel render buffer, which the mixing stage rejected. The console's conversion is unknown: the left and right channels are assumed to go to the first two buffer channels (front left and right) and the remaining channels stay silent, with no centre, LFE or surround content. Any other channel count mismatch still throws - [NGS2 voices without a format](../../../core/libs/prx/libSceNgs2.native/src/Voice.cpp) (libSceNgs2.native) - a sampler voice whose setup has no format (all zero) accepts an add of no waveform blocks without `APPEND`, which only applies `RESET` and the `CONTINUE` state, and matrix levels with no levels, which clear that matrix. PPSA36591 sets such a voice up, adds no blocks and sets no levels when a button is pressed at its title screen. Whether the console returns success or an error there is not measured; blocks with data, `APPEND` and an empty matrix on a voice with a format are still refused +- [NGS2 play without setup](../../../core/libs/prx/libSceNgs2.native/src/Voice.cpp) (libSceNgs2.native) - differs from PS5 firmware 3.20 and 4.03 `libSceNgs2.native.sprx` in two cases: a set-up voice given an add of no waveform blocks and played keeps state flags 1 there for as long as it was watched and only until the next render here; an add of no blocks to a voice that already played and ended returns `0x804A8054` there and succeeds here. A `PLAY` on a voice with no channels (never set up; an all-zero setup leaves an earlier setup untouched) returns `0x804A8351` (`SCE_NGS2_ERROR_INVALID_VOICE_ACCESS`) from Control and RunCommands, leaves it idle and skips the rest of the list, as that module does for every rack; PPSA03061 (Void Terrarium) frees its sound slots that way - [NGS2 silent waveform blocks](../../../core/libs/prx/libSceNgs2.native/src/Voice.cpp) (libSceNgs2.native): flag `0x10` (named `SILENCE` here; no public reference names it) lets a waveform block declare samples without data. PPSA04867 adds one block with flags `0x11`, `data_size` 0 and `num_samples` 16385, then another with flags `0x11` and a fully specified 0x800-byte, 1024-sample mono block, which takes the ordinary path. A dataless block under the flag outputs `num_samples` frames of silence, reports them through `decoded_data_size`, and finishes like a complete block; a dataless block without the flag still throws as not fitting its data. The flag's real name, its interaction with ATRAC9 and repeats, and the console's `waveform_data` for silent blocks are unverified on hardware - [NGS2 streaming PCM waveforms](../../../core/libs/prx/libSceNgs2.native/src/Voice.cpp) (libSceNgs2.native) - PPSA21402 streams its music by adding one block whose `num_samples` is the whole track and whose `data_size` is a 16 KiB first piece, with `CONTINUE`, and then adds each following piece with flag `0x2` (called `APPEND` here) and the same `num_samples`. No reference describes flag `0x2`. A 16-bit PCM block without skipped samples or repeats whose `num_samples` exceed its data is assumed to start such a stream; flag `0x2` is assumed to append the block's data to the last streaming block, ignoring its `num_samples`; the voice is assumed to output silence without advancing while it has played all appended data and `CONTINUE` is set; and the waveform is assumed to end at `num_samples` or, once `CONTINUE` is cleared, at the end of the appended data. `sceNgs2VoiceGetState` reports the bytes played as `decoded_data_size`, which the title uses to release its queued data, and the read position as `waveform_data`. Appending to a block that is not a stream, or other formats, skipped samples, repeats and partial frames, throw - [NGS2 matrix levels](../../../core/libs/prx/libSceNgs2.native/src/Voice.cpp) (libSceNgs2.native) - levels are clamped to -4..4 and NaN is kept, as the PS4 firmware 11.00 `libSceNgs2.sprx` stores them; not yet confirmed on the PS5 library. That library rejects a level count of 0 and keeps the matrix; the PS5 error code is unknown, so a count of 0 throws, except on a sampler voice without a format, where it clears the matrix (see NGS2 voices without a format). `sceNgs2VoiceRunCommands` is not in that library, so its matrix levels command is assumed to clamp the same way diff --git a/docs/dev/debt/libSceNpCommon.md b/docs/dev/debt/libSceNpCommon.md index da67369967..be7ac29c21 100644 --- a/docs/dev/debt/libSceNpCommon.md +++ b/docs/dev/debt/libSceNpCommon.md @@ -2,9 +2,8 @@ ### Unknown function info -The 35 declarations below use names mapped from the local `libSceNpCommon.sprx` export table. Each NID was verified against that table and recomputed from its name with `tools/nid_names.py`. The public [PS5 3.20 libSceNpCommon export list](https://github.com/DNNDHH/PS5-3.20_Libs/blob/main/libSceNpCommon.c) contains all 150 symbol names. No prototype or behavior is claimed. Each declaration uses the no-parameter unknown-signature convention solely for import resolution and throws if called. +The 34 declarations below use names mapped from the local `libSceNpCommon.sprx` export table. Each NID was verified against that table and recomputed from its name with `tools/nid_names.py`. The public [PS5 3.20 libSceNpCommon export list](https://github.com/DNNDHH/PS5-3.20_Libs/blob/main/libSceNpCommon.c) contains all 150 symbol names. No prototype or behavior is claimed. Each declaration uses the no-parameter unknown-signature convention solely for import resolution and throws if called. -- [sceNpCloseEventFlag](../../../core/libs/prx/libSceNpCommon/PendingExports.cpp) (NID `+nmn+Z0nWDo`) - the signature and behavior are unknown. The no-parameter declaration only resolves the import; it makes no ABI claim. Calls throw through `NotImplemented_nid_no_patch`. - [sceNpCloseSema](../../../core/libs/prx/libSceNpCommon/PendingExports.cpp) (NID `8hPzfjZzV88`) - the signature and behavior are unknown. The no-parameter declaration only resolves the import; it makes no ABI claim. Calls throw through `NotImplemented_nid_no_patch`. - [sceNpGetNavSdkVersion](../../../core/libs/prx/libSceNpCommon/PendingExports.cpp) (NID `QmDEFikd3VA`) - the signature and behavior are unknown. The no-parameter declaration only resolves the import; it makes no ABI claim. Calls throw through `NotImplemented_nid_no_patch`. - [sceNpIntGetPlatformType](../../../core/libs/prx/libSceNpCommon/PendingExports.cpp) (NID `G6qytFoBJ-w`) - the signature and behavior are unknown. The no-parameter declaration only resolves the import; it makes no ABI claim. Calls throw through `NotImplemented_nid_no_patch`. @@ -54,6 +53,6 @@ The 35 declarations below use names mapped from the local `libSceNpCommon.sprx` - [The string-to-integer exports](../../../core/libs/prx/libSceNpCommon/Strings.cpp) clear `errno` before parsing; the firmware reads whatever `errno` held before the call when the result saturates. - [The integer-to-string exports](../../../core/libs/prx/libSceNpCommon/Strings.cpp) return `0x80558008` when the hexadecimal prefix does not fit; the firmware writes the prefix without checking the size. [The base64 decoders](../../../core/libs/prx/libSceNpCommon/Strings.cpp) treat bytes above 0x7F as invalid; the firmware indexes its table with them as signed values. [sceNpUtilJsonGetOneChar](../../../core/libs/prx/libSceNpCommon/Strings.cpp) checks that a `\u` escape and a surrogate pair fit in the input; the firmware reads past it. - [sceNpUtilGetNpDebug, sceNpUtilGetNpTestPatch, sceNpUtilGetTrcNotify, sceNpUtilGetIgnoreNpTitleId, sceNpUtilGetFakeDisplayNameMode, sceNpUtilGetWebTraceSetting, sceNpUtilGetWebApi2FakeRateLimit, sceNpUtilGetWebApi2FakeRateLimitTarget, sceNpUtilGetFakeRateLimit, sceNpUtilGetDbgCommerce, sceNpUtilGetSystemLanguage, sceNpUtilGetEnv, sceNpUtilGetDateSetAuto and sceNpUtilGetShareTitleCheck](../../../core/libs/prx/libSceNpCommon/PendingExports.cpp) read system and debug registry keys through libSceRegMgr, whose `sceRegMgrNonSysGetInt` and string reads still throw; they throw until those exist. -- [sceNpOpenSema, sceNpCloseSema and sceNpCloseEventFlag](../../../core/libs/prx/libSceNpCommon/PendingExports.cpp) forward to the libkernel open and close calls for named semaphores and event flags, which still throw. +- [sceNpOpenSema and sceNpCloseSema](../../../core/libs/prx/libSceNpCommon/PendingExports.cpp) forward to the libkernel open and close calls for named semaphores, which still throw. - [sceNpSetPlatformType, sceNpIntGetPlatformType, sceNpIntSetPlatformType, sceNpUtilCanonicalizeNpIdForPs4, sceNpUtilCanonicalizeNpIdForPsp2, sceNpUtilJidToNpId and sceNpGetNavSdkVersion](../../../core/libs/prx/libSceNpCommon/PendingExports.cpp) depend on console platform tags, network domain names or a version string of the console; they throw. - [sceNpJsonParse, sceNpJsonParseInit, sceNpJsonParseBuf, sceNpJsonParseBufInit, sceNpJsonParseEx, sceNpJsonParseExInit and the sceNpServerErrorJson exports](../../../core/libs/prx/libSceNpCommon/PendingExports.cpp) are a streaming, schema-checked JSON parser whose event and error rules are not yet specified; they throw. diff --git a/docs/dev/debt/libSceNpSignaling.md b/docs/dev/debt/libSceNpSignaling.md index c0dba40607..1adbc6177b 100644 --- a/docs/dev/debt/libSceNpSignaling.md +++ b/docs/dev/debt/libSceNpSignaling.md @@ -1,9 +1,7 @@ # libSceNpSignaling technical debt -### Unknown function info - -- [sceNpSignalingDeactivateConnection](../../../core/libs/prx/libSceNpSignaling/Export.cpp) (libSceNpSignaling) - imported by PS4 titles, which do not load without it, and added without an implementation: declared without parameters, every call throws - ### Functional - [libSceNpSignaling](../../../core/libs/prx/libSceNpSignaling/Export.cpp) (libSceNpSignaling) - offline only, not measured on a PS5: the checks, their order, context ids 1 to 8 and the NpId rule (`term` 0, 3 to 16 characters, the first an ASCII letter or digit, the rest ASCII letters, digits, `_` or `-`) follow [shadPS4](https://github.com/shadps4-emu/shadPS4/blob/91e6afa69b0a64b0afaa0281b80f8fbb0cd88136/src/core/libraries/np/np_signaling/np_signaling.cpp#L118-L170) and its [state helpers](https://github.com/shadps4-emu/shadPS4/blob/91e6afa69b0a64b0afaa0281b80f8fbb0cd88136/src/core/libraries/np/np_signaling/np_signaling_state.cpp#L120-L170). `sceNpSignalingInitialize` reserves no heap and starts no thread, so its arguments are not checked, and callbacks are never called. `sceNpSignalingActivateConnection` returns `SCE_NP_ERROR_SIGNED_OUT` after shadPS4's checks up to `OWN_NP_ID`, without its rate limit, and creates no connection, so the connection calls answer `CONN_NOT_FOUND` + +- [sceNpSignalingDeactivateConnection](../../../core/libs/prx/libSceNpSignaling/Export.cpp) (libSceNpSignaling) - not measured on a PS5: it has the same checks as `sceNpSignalingTerminateConnection` (not initialized, unknown context, then `CONN_NOT_FOUND`), after shadPS4's [call](https://github.com/shadps4-emu/shadPS4/blob/12a4564543ccec527f9723676d2180580d1d7a94/src/core/libraries/np/np_signaling/np_signaling.cpp#L378-L400). No connection is ever created, so none can be deactivated. diff --git a/docs/dev/debt/libScePad.md b/docs/dev/debt/libScePad.md index 000b382ce7..911bec0271 100644 --- a/docs/dev/debt/libScePad.md +++ b/docs/dev/debt/libScePad.md @@ -14,8 +14,9 @@ - [scePadSetAngularVelocityDeadbandState](../../../core/libs/prx/libScePad/src/PadState.cpp) (libScePad) - with the deadband on, each angular velocity axis whose magnitude is below 0.017453292 rad/s (1 degree per second) reads as 0, before the orientation is integrated; it starts off. Threshold, per-axis test and default follow [duaLib](https://github.com/WujekFoliarz/duaLib/blob/03bad1bea2a36561b520846776f2a07ced6773e0/src/source/duaLib.cpp#L44), which reimplements the PC `libScePad.dll`; the console's threshold is not measured, and the deadband is kept per port slot - [PadQueueLegacyAudioHaptics, PadClearLegacyAudioHaptics](../../../core/libs/prx/libScePad/src/PadState.cpp) (libScePad) - PadQueueLegacyAudioHaptics and PadClearLegacyAudioHaptics route legacy audio haptics only to port 0; multi-port queueing is not modelled - [scePadGetControllerInformation](../../../core/libs/prx/libScePad/Export.cpp) (libScePad) - scePadGetControllerInformation always reports connectedCount = 1 and connected = true; behaviour across multiple open controller handles is not measured on hardware -- [scePadOpen and scePadOpenExt](../../../core/libs/prx/libScePad/Export.cpp) (libScePad) - the special port (type 2) opens a handle per user (`PAD_SPECIAL_HANDLE` + slot, 16 slots for the console's 16 accounts, a 17th user gets the unknown-user code 0x809b0081) that every pad call accepts: reads give the rest record (sticks 0x80, orientation w 1, acceleration y 1, `connected` false), information is zeroed, extended information has device class -1, setters succeed without effect. Not measured: the console's own handle values (fresh per open), a PS5, and the calls the PS4 Pro survey (firmware 10.71, no special controller) did not cover; it measured open, `ALREADY_OPENED`, `scePadGetHandle`, both reads, both informations, the five setters above, close, and that two logged-in users get independent handles. `scePadOpenExt` returns `DEVICE_NOT_CONNECTED` (0x80920007) for special ports, unmeasured; PPSA01317 skips a user on any negative result. Other port types throw +- [scePadOpen and scePadOpenExt](../../../core/libs/prx/libScePad/Export.cpp) (libScePad) - the special port (type 2) opens a handle per user (`PAD_SPECIAL_HANDLE` + slot, 16 slots for the console's 16 accounts, a 17th user gets the unknown-user code 0x809b0081) that every pad call accepts: reads give the rest record (sticks 0x80, orientation w 1, acceleration y 1, `connected` false), information is zeroed, extended information has device class -1, setters succeed without effect. Not measured: the console's own handle values (fresh per open), a PS5, and the calls the PS4 Pro survey (firmware 10.71, no special controller) did not cover; it measured open, `ALREADY_OPENED`, `scePadGetHandle`, both reads, both informations, the five setters above, close, and that two logged-in users get independent handles. `scePadOpenExt` returns `DEVICE_NOT_CONNECTED` (0x80920007) for special ports, unmeasured; PPSA01317 skips a user on any negative result. `scePadOpenExt` throws for other port types - [scePadOpen, scePadGetHandle, scePadRead and scePadReadState for the remote control port](../../../core/libs/prx/libScePad/Export.cpp) (libScePad) - whether a console without a media remote opens the system user's remote control port (type 16), returns `DEVICE_NOT_CONNECTED` or fills other fields is not measured. The host has no remote, so the port opens its own handle (`PAD_REMOTE_HANDLE`) that reads one zeroed entry with no buttons and `connected` false; the other pad calls reject it with `INVALID_HANDLE`. SDL's PS5 video driver maps this port's buttons to keys, so a remote that read the DualSense turned Cross into Return (Raptor PPSA94002). +- [scePadOpen](../../../core/libs/prx/libScePad/Export.cpp) (libScePad) - port types 3 and 4 throw: a payload process on a PS5 (firmware 13.60) let them past the type check, but it cannot open a port for its own logged-in user (0x809b0081), so what they open is unknown. The argument checks it did reach are followed: types 1, 5, 6, 255 and -1, and 16 for a user other than the system user, fail with `INVALID_ARG` before the user is looked at, user -1 with 0x809b0001 on types 0, 2, 3 and 4 and on index 1, and index 1 of a logged-in user with 0x809b0003; whether index 1 of types 3 and 4 fails the same way was not measured; the payload never tried type 16 with the system user (255), which opens the remote control port as below - [scePadVrControllerReadState](../../../core/libs/prx/libScePad/Export.cpp) - the 104-byte output layout is recovered, including buttons, stick, triggers, touch fields, motion, connection state and timestamp. Touch-value semantics and kernel report production remain incomplete; the export still throws. - [scePadVrControllerReadCombinedState](../../../core/libs/prx/libScePad/Export.cpp) - the two handle arguments and 128-byte output are recovered; output field semantics remain incomplete. - [scePadSetVibrationMode](../../../core/libs/prx/libScePad/Export.cpp) (libScePad) - modes 1 to 3 and 5 are accepted and stored. On a PS5 (firmware 13.60) the call returns `0x80920005` before `scePadInit`, then rejects a mode of 0 or below with `INVALID_ARG` before it checks the handle, and returns `INVALID_HANDLE` for a bad handle with any higher mode; whether an open handle accepts modes above 3 was not measured, since the payload could not open a pad; 5 is accepted because PPSA25286 passes it on its open handle at start-up; the meanings of modes 3 and 5 are unknown (PPSA21480 calls it with 3 right after `scePadOpen` and aborts on failure; [SharpProspero](https://github.com/SvenGDK/SharpProspero/blob/main/src/SharpProspero/Interop/Pad/Pad.cs) names only 1 and 2). The stored mode has no other effect @@ -23,7 +24,7 @@ - [scePadIsDS4Connected, scePadIsBlasterConnected and scePadIsMoveConnected](../../../core/libs/prx/libScePad/Export.cpp) (libScePad) - the `bool (int handle)` signatures are recovered; the library reports one DualSense to every title (see Touchpad resolution below), so no DualShock 4, Blaster or Move controller is ever behind a handle and each call answers false for any handle. The console's answer for an invalid handle is not measured - [scePadSetAngularVelocityBiasCorrectionState](../../../core/libs/prx/libScePad/Export.cpp) (libScePad) - inferred signature `(int handle, bool enabled)` follows `scePadSetTiltCorrectionState` and `scePadSetAngularVelocityDeadbandState`; an invalid handle returns `PAD_ERROR_INVALID_HANDLE`, disabling is a no-op, and enabling throws because bias correction is not modelled - [scePadGetAccessibilityControllerState](../../../core/libs/prx/libScePad/Export.cpp) (libScePad) - the value a console reports for a DualSense is not measured; the emulated pad, which is not an Access controller, reports 0. The name hashes to NID `zBsgF0q8DIM`. In the OS 10.01 system module the `(int handle, uint32_t* state)` function returns `0x80920005` before `scePadInit`, then `INVALID_ARG` for a NULL `state` and `INVALID_HANDLE` for a bad handle, and otherwise asks the pad driver for a per-device value of the device behind the handle: 0 when no device is behind it, 1 when the driver has no answer, else the driver's value. What the values mean is unknown -- [scePadGetControllerType](../../../core/libs/prx/libScePad/Export.cpp) (libScePad) - the value a console reports for a DualSense is not measured; the emulated pad reports `PAD_CONTROLLER_TYPE_DUAL_SENSE` (2), following [duaLib](https://github.com/WujekFoliarz/duaLib/blob/master/src/include/duaLib.h)'s `s_SceControllerType` enum where `DUALSENSE = 2`. The signature `(int handle, int32_t* type)` follows duaLib, while the validation order (checking initialization, null pointer, then handle) follows the library's other pad queries; duaLib does not validate null pointers and returns `PAD_ERROR_DEVICE_NOT_CONNECTED` for an invalid pad. +- [scePadGetControllerType](../../../core/libs/prx/libScePad/Export.cpp) (libScePad) - the value a console reports for a DualSense is not measured; the emulated pad reports `PAD_CONTROLLER_TYPE_DUAL_SENSE` (2), following [duaLib](https://github.com/WujekFoliarz/duaLib/blob/master/src/include/duaLib.h)'s `s_SceControllerType` enum where `UNKNOWN = 0` and `DUALSENSE = 2`; special handles report 0 (`UNKNOWN`). The signature `(int handle, int32_t* type)` follows duaLib, while the validation order (checking initialization, null pointer, then handle) follows the library's other pad queries; duaLib does not validate null pointers and returns `PAD_ERROR_DEVICE_NOT_CONNECTED` for an invalid pad. - [libScePad internal data and device control](../../../core/libs/prx/libScePad/Export.cpp) - kernel-owned version, telemetry, Lotus-button and update payload fields remain unresolved. Lotus-button parameter units and the three blinking byte meanings are unknown. Port information occupies 152 bytes; history records occupy 72 bytes; Leonardo unique data occupies 24 bytes. Their complete field semantics remain unresolved. - [libScePad profile writes and virtual devices](../../../core/libs/prx/libScePad/Export.cpp) - profile writes take a handle, profile ID, profile pointer and a 32-bit result pointer; the profile payload direction and fields remain unresolved. Virtual-device creation takes an input record and an output ID pointer, whose width is not exposed by the wrapper. Component information copies 16 bytes; field meanings remain unknown. Virtual trigger state contains two 32-bit states and three control bytes, but the control semantics remain incomplete. diff --git a/docs/dev/debt/libScePosixForWebKit.md b/docs/dev/debt/libScePosixForWebKit.md index efe3b429e8..9c664a7afc 100644 --- a/docs/dev/debt/libScePosixForWebKit.md +++ b/docs/dev/debt/libScePosixForWebKit.md @@ -11,6 +11,7 @@ - [strcasestr](../../../core/libs/prx/libScePosixForWebKit/Export.cpp) (libScePosixForWebKit) - console locale behavior is unmeasured. It follows FreeBSD 11.4's [strcasestr.c](https://github.com/freebsd/freebsd-src/blob/releng/11.4/lib/libc/string/strcasestr.c) in the guest's supported C locale; other guest locales are not implemented. - [mkstemp and isatty](../../../core/libs/prx/libScePosixForWebKit/Filesystem.cpp) (libScePosixForWebKit) follow FreeBSD's [temporary-file API](https://github.com/freebsd/freebsd-src/blob/stable/9/lib/libc/stdio/mktemp.c) and [terminal check](https://github.com/freebsd/freebsd-src/blob/stable/9/lib/libc/gen/isatty.c), without console verification. `mkstemp` replaces all trailing `X` characters, accepts a fixed name, and creates files through the guest path resolver with exclusive read/write access and mode 0600. Windows file permissions follow the existing kernel file implementation. `isatty` tests Windows console handles rather than all character devices; files, pipes and guest sockets return `ENOTTY`, closed descriptors return `EBADF`. - [arc4random](../../../core/libs/prx/libScePosixForWebKit/Export.cpp) (libScePosixForWebKit) returns four bytes of host OS entropy (`getentropy`, `rand_s` on Windows), as `arc4random_buf` does, uniform over the 32-bit range like FreeBSD 11.4's RC4 keystream in [arc4random.c](https://github.com/freebsd/freebsd-src/blob/8c639945a44588f6cfdddfb057bb5aad88735da0/lib/libc/gen/arc4random.c). The console's generator and its reseeding are unknown; `arc4random_uniform`, `arc4random_stir` and `arc4random_addrandom` are not in the module's export set and are absent +- [pthread_setname_np](../../../core/libs/prx/libScePosixForWebKit/Export.cpp) (libScePosixForWebKit) stores the guest thread name in libkernel's thread object, so `pthread_getname_np` returns it, and follows libkernel's `pthread_rename_np`: `EINVAL` (22) for a null thread or name, `ENAMETOOLONG` (63) from 32 bytes on, `0` otherwise, with the name truncated to 31 bytes when read back. It does not apply the Windows thread description or the job affinity that `scePthreadRename` sets, because those helpers are private to libkernel; the console's exact error numbers for this module are unverified - [fnmatch](../../../core/libs/prx/libScePosixForWebKit/Export.cpp) (libScePosixForWebKit) follows FreeBSD 11 [fnmatch.c](https://github.com/freebsd/freebsd-src/blob/stable/11/lib/libc/gen/fnmatch.c) in the C locale: each byte is one character, `FNM_CASEFOLD` folds ASCII letters only, and bracket ranges compare byte values. `[:class:]` names are not character classes: as in FreeBSD 11 through 14, `[[:digit:]]` is the set of `[`, `:`, `d`, `i`, `g`, `t` followed by a literal `]` (classes were added to `fnmatch.c` after 14). Multibyte characters and locale collation are not modelled. A null pattern or string throws - [getservbyname](../../../core/libs/prx/libScePosixForWebKit/Resolver.cpp) (libScePosixForWebKit) searches a built-in copy of 37 lines of FreeBSD 11.4's [etc/services](https://github.com/freebsd/freebsd-src/blob/8c639945a44588f6cfdddfb057bb5aad88735da0/etc/services) (ftp-data, ftp, ssh, telnet, smtp, domain, tftp, http, pop3, ntp, imap, https, rtsp, submission, imaps, pop3s with their aliases and protocols, in file order) the way [getservent.c](https://github.com/freebsd/freebsd-src/blob/8c639945a44588f6cfdddfb057bb5aad88735da0/lib/libc/net/getservent.c) searches the file: case-sensitive name or alias, a null protocol takes the first match, the port in network byte order, the result in per-thread storage. The console's `/etc/services` is unknown, so any other service returns null without setting `errno`, as for a name the file lacks. `getaddrinfo` still resolves service names through the host's service database - [__wrap_access, __wrap_clock_gettime, __wrap_getcwd, __wrap_getenv, __wrap_lstat and __wrap_mmap](../../../core/libs/prx/libScePosixForWebKit/Export.cpp) (libScePosixForWebKit) assume, from the export names alone, the GNU ld [`--wrap`](https://sourceware.org/binutils/docs/ld/Options.html) convention (a reference to `` resolves to `__wrap_`): each takes its target's POSIX signature and forwards to libc's (`access`, `getcwd`, `getenv`) or libkernel's (`clock_gettime`, `lstat`, `mmap`) implementation, which sets `errno`. No PS5 module or WebKit call site was read to confirm that WebKit imports `__wrap_` in place of `` or that the console wrappers only forward. Any sandbox or path handling the console module adds is not modelled, and how the wrappers relate to `getenv_np`, `setenv_np`, `mmap_np` and `clock_gettime_np` (such as a separate environment that `setenv_np` fills) is unknown diff --git a/docs/dev/debt/libScePsml_debug.md b/docs/dev/debt/libScePsml_debug.md index f77c32d0b1..b8bdedf383 100644 --- a/docs/dev/debt/libScePsml_debug.md +++ b/docs/dev/debt/libScePsml_debug.md @@ -3,7 +3,7 @@ ### Unknown function info - [scePsmlMfsrGetSharedResourcesInitRequirement, scePsmlMfsrCreateSharedResources, scePsmlMfsrReleaseSharedResources, scePsmlMfsrGetContextBufferRequirement800M3_2, scePsmlMfsrCreateContext800M3_2, scePsmlMfsrReleaseContext](../../../core/libs/prx/libScePsml_debug/Export.cpp) (libScePsml) - only resource type 0 is supported. The context requirement reports four 2 MiB blocks regardless of its parameters, while the system calculation depends on the context configuration. The descriptor pointer at 0x28 is not read. Validation throws for null pointers, short block lists and foreign handles instead of reproducing the system error and fault behaviour. -- [scePsmlMfsr2GetDispatchPacketsSizeInDwords](../../../core/libs/prx/libScePsml_debug/Export.cpp) (libScePsml_mfsr2) - writes a 32-bit size through the second argument; the unused first argument still needs caller verification. +- [scePsmlMfsr2Init and the other MFSR2 calls](../../../core/libs/prx/libScePsml_debug/Export.cpp) (libScePsml) - only a console without PSSR is modelled. In firmware 13.60 `libScePsml.sprx` (read from disassembly, not measured on a console), `scePsmlMfsr2Init` returns 0x8A8A0012 when `sceKernelIsTrinityMode` returns 0, and until `Init` succeeds every other MFSR2 call returns 0x8A8A0001 without touching its arguments. AnyPS5 reports 0, so `Init` throws only if that changes: the initialization after the check, the shared resource and context requirements, and the 0x800-dword size that `GetDispatchPacketsSizeInDwords` writes through its second argument are not implemented - [scePsmlMfsrGetContextBufferRequirement1100, scePsmlMfsrCreateContext1100, scePsmlMfsrGetDispatchMfsrPacket1100](../../../core/libs/prx/libScePsml_debug/Export.cpp) (libScePsml_debug) - argument layouts unknown; PPSA26344 imports but does not call the first two and at `0x87EFA` passes `(rdi, rsi=&stack, rdx)` as three pointers to `GetDispatchMfsrPacket1100`; before `scePsmlMfsrInit` they return 0x8A810001 (not initialized) and after it they throw. `scePsmlMfsrCreateContext1300` and `scePsmlMfsrGetDispatchMfsrPacket900`, `1000` and `1300` take the same shapes (context slot and parameter; context, command buffer and parameter) and behave the same way. PPSA08330 and PPSA03016 pass `GetDispatchMfsrPacket900`/`1000` the context handle, a `{cursor, size in dwords}` command buffer and the dispatch parameters, and advance their cursor by the size `scePsmlMfsrGetDispatchMfsrPacketSizeInDwords` returned. Whether the 1100 and 1300 versions take these arguments, and the console's error, are unverified - [scePsmlMfsrGetDispatchMfsrPacket1000](../../../core/libs/prx/libScePsml_debug/Export.cpp) (libScePsml) - imported by PPSA25344. libScePsml and libScePsml_debug are built from the same source - [scePsmlMfsrCreateContext1300, scePsmlMfsrGetDispatchMfsrPacket1300](../../../core/libs/prx/libScePsml_debug/Export.cpp) (libScePsml) - imported by PPSA28416 next to `scePsmlMfsrGetContextBufferRequirement1100`. The names are not in the aerolib NID list; they hash to the imported NIDs `kLF7WtQ1-Dg` and `DDVUyPyYHTA` (`tools/nid_names.py`) @@ -11,4 +11,4 @@ ### Functional - [scePsmlMfsrGetDispatchMfsrPacketSizeInDwords, scePsmlMfsrGetMipmapBias, scePsmlMfsrSelectConfig, scePsmlMfsrRequestCapture, scePsmlMfsrIsCaptureInProgress](../../../core/libs/prx/libScePsml_debug/Export.cpp) (libScePsml) - semantics from the APR-EMU `fakelib/libScePsml.sprx`. Guards: `0x8A810001` uninitialized, `0x8A810005` null/foreign handle (fakelib checks an engine id `0xA9C4`/`0x9231`; our map check is the equivalent), `0x8A810009` null output. `GetDispatchMfsrPacketSizeInDwords` writes `0x600`; `GetMipmapBias(context, bias, dimension)` writes `log2f(dimension / context->inputWidth) - 1.0f`, width recorded at `CreateContext800M3_2` from the parameter pair at 0x18 or `descriptor0 + 0x20` for callers that pass a descriptor pointer there (indirection inferred; zero width returns `0x8A810005`). `SelectConfig`, `RequestCapture`, `IsCaptureInProgress` validate then return 0. The `GetDispatchMfsrPacket*` calls still throw: the 0x158-byte template's packet routine is not understood -- [scePsmlMfsrInit](../../../core/libs/prx/libScePsml_debug/Export.cpp) (libScePsml) - succeeds and only sets the initialized state; the shared resources and contexts are bookkeeping objects that use none of the guest blocks. Whether Sony's library fails on hardware without PSSR is unknown. PPSA08330 calls the setup unconditionally and only uses a context when its cached `sceKernelIsTrinityMode` result is set (0x3c643d, 0x567f97; otherwise it stores a -0.25 mip bias itself at 0x567fe2), which AnyPS5 reports as 0 +- [scePsmlMfsrInit](../../../core/libs/prx/libScePsml_debug/Export.cpp) (libScePsml) - succeeds and only sets the initialized state; the shared resources and contexts are bookkeeping objects that use none of the guest blocks. The console's library fails there instead: in firmware 13.60 (read from disassembly, not measured on a console) `scePsmlMfsrInit` returns 0x8A810012 when `sceKernelIsTrinityMode` returns 0, so its later MFSR calls return 0x8A810001. PPSA08330 calls the setup unconditionally and only uses a context when its cached `sceKernelIsTrinityMode` result is set (0x3c643d, 0x567f97; otherwise it stores a -0.25 mip bias itself at 0x567fe2), which AnyPS5 reports as 0 diff --git a/docs/dev/debt/libSceSpSysCallWrapper.md b/docs/dev/debt/libSceSpSysCallWrapper.md index ea6d5fbf4e..1a664e18fd 100644 --- a/docs/dev/debt/libSceSpSysCallWrapper.md +++ b/docs/dev/debt/libSceSpSysCallWrapper.md @@ -2,4 +2,4 @@ ### Unknown function info -- [sceSpGetPid, sceSpKernelGettimeofday, sceSpKernelNanosleep, sceSpNetConnect, sceSpNetEpollAbort, sceSpNetEpollControl, sceSpNetEpollCreate, sceSpNetEpollDestroy, sceSpNetEpollWait, sceSpNetErrnoLoc, sceSpNetPoolCreate, sceSpNetPoolDestroy, sceSpNetRecv, sceSpNetResolverAbort, sceSpNetResolverCreate, sceSpNetResolverDestroy, sceSpNetResolverGetError, sceSpNetResolverStartNtoa, sceSpNetSend, sceSpNetSetsockopt, sceSpNetSocket, sceSpNetSocketClose, sceSpPthreadAttrDestroy, sceSpPthreadAttrInit, sceSpPthreadAttrSetinheritsched, sceSpPthreadAttrSetschedparam, sceSpPthreadAttrSetstacksize, sceSpPthreadCondDestroy, sceSpPthreadCondInit, sceSpPthreadCondSignal, sceSpPthreadCondWait, sceSpPthreadCondattrDestroy, sceSpPthreadCondattrInit, sceSpPthreadCreate, sceSpPthreadDetach, sceSpPthreadExit, sceSpPthreadJoin, sceSpPthreadMutexDestroy, sceSpPthreadMutexInit, sceSpPthreadMutexLock, sceSpPthreadMutexUnlock, sceSpPthreadMutexattrDestroy, sceSpPthreadMutexattrInit, sceSpPthreadMutexattrSetprioceiling, sceSpPthreadMutexattrSetprotocol, sceSpPthreadMutexattrSettype, sceSpPthreadSetprio and sceSpSelect](../../../core/libs/prx/libSceSpSysCallWrapper/Export.cpp) (libSceSpSysCallWrapper) - names and NIDs are present in the [PS5 3.20 export inventory](https://github.com/DNNDHH/PS5-3.20_Libs/blob/b2a77c09cd71c01f34c790cfbe98c751a13262ad/libSceSpSysCallWrapper.c), but no credible prototypes were found. The declarations have no parameters solely to resolve known imports; this is not an ABI claim and callers must not call them until signatures are verified +- [sceSpPthreadMutexattrSetprioceiling](../../../core/libs/prx/libSceSpSysCallWrapper/Export.cpp) (libSceSpSysCallWrapper) - still throws. In firmware 13.60's `libSceSpSysCallWrapper.sprx` it only jumps to libkernel's `scePthreadMutexattrSetprioceiling`, which AnyPS5 does not implement yet (read from disassembly, not measured on a console) diff --git a/docs/dev/debt/libSceSsl.md b/docs/dev/debt/libSceSsl.md index 20e9e19b1d..d42af0068b 100644 --- a/docs/dev/debt/libSceSsl.md +++ b/docs/dev/debt/libSceSsl.md @@ -6,9 +6,11 @@ - [sceSslDisableOption, sceSslDisableOptionInternal, sceSslDisableOptionInternalInsecure, sceSslEnableOption, sceSslEnableOptionInternal, sceSslGetNanoSSLModuleId, sceSslGetPeerCert, sceSslGetSslError, sceSslLoadRootCACert and sceSslSetSslVersion](../../../core/libs/prx/libSceSsl/Export.cpp) (libSceSsl) - the list is the intersection of the export table of the console's libSceSsl (function symbols only), the pinned aerolib names and the functions not yet defined anywhere in the repo. Names and NIDs appear in the [PS5 3.20 export inventory](https://github.com/DNNDHH/PS5-3.20_Libs/blob/b2a77c09cd71c01f34c790cfbe98c751a13262ad/libSceSsl.c) and [verified NID name database](https://github.com/zecoxao/sce_symbols/blob/2883963a0a514ba6e77407a08ef4730a65e88254/aerolib.csv); no credible prototypes were found. They are declared without parameters solely to resolve known imports, not as an ABI claim; callers must not call them until signatures are verified. - [sceSslReuseConnection](../../../core/libs/prx/libSceSsl/Export.cpp) (libSceSsl) - its name and NID appear in the [PS5 3.20 export inventory](https://github.com/DNNDHH/PS5-3.20_Libs/blob/b2a77c09cd71c01f34c790cfbe98c751a13262ad/libSceSsl.c) and [verified NID name database](https://github.com/zecoxao/sce_symbols/blob/2883963a0a514ba6e77407a08ef4730a65e88254/aerolib.csv); its parameter shape follows [SharpProspero's pinned binding](https://github.com/SvenGDK/SharpProspero/blob/5dfdb4b0b166e83dc9ae275001afb695f12c7174/src/SharpProspero/Interop/Net/Http.cs#L2231-L2235). No console observation or reliable implementation source for session reuse was found. -- [sceSslCreateConnection, sceSslDeleteConnection, sceSslSetVerifyCallback, sceSslConnect, sceSslRead, sceSslWrite](../../../core/libs/prx/libSceSsl/Export.cpp) (libSceSsl) - imported by `ffmpeg.prx`. Signatures follow [SharpProspero](https://github.com/SvenGDK/SharpProspero/blob/60977b29103452b9681ae10c7a9011d44965bf16/src/SharpProspero/Interop/Net/Http.cs#L195-L252), which also says the socket stays open after `sceSslDeleteConnection`. The behaviour below was measured on a PS5 on system software 13.40 with a ps5-payload-dev payload (every call printed with its return, a TLS 1.2 test server on the LAN presenting leaves issued by the test fixture root loaded with `sceSslLoadCert`, from an elfldr process rather than a title); what differs for a title process is unknown. An unknown context returns `SSL_ERROR_INVALID_ID` (0x8095F006) from `sceSslCreateConnection`, and every connection call on an unknown or deleted connection id or on a connection whose context was terminated returns `SSL_ERROR_INVALID_ID`. `sceSslCreateConnection` returns `SSL_ERROR_INVALID_VALUE` (0x8095F007) for a null host and does not check the socket: `sceSslConnect` on a descriptor that is not a socket returns `SCE_NET_ERROR_EBADF` (0x80410109). `sceSslConnect` runs a TLS 1.2 client handshake with Mbed TLS 3.6.7 over the host socket that the guest number maps to in the libkernel or libSceNet socket table, and `sceSslRead` and `sceSslWrite` carry application data over it. TLS 1.3 is compiled out: the console offers TLS 1.2 only (its ClientHello carries 12 suites and no supported_versions extension) and a TLS 1.3-only server gets `SSL_ERROR_FATAL_ALERT` (0x8095F010) from it, as from this build. Connection state is allocated from the context's pool and returned to it by `sceSslDeleteConnection`; a connection keeps the pool alive after `sceSslTerm`, whose connections return `SSL_ERROR_INVALID_ID` from then on. The console's pool use for one connection with a two-certificate chain peaked at 80,544 bytes in a 256 KiB pool (5,568 after `sceSslInit`, 12,000 after loading one CA); a 16 KiB pool fails the connect with `SSL_ERROR_OUT_OF_MEMORY` (0x809517D5) there and here. The server's chain is checked against the CAs loaded with `sceSslLoadCert`, the host name the connection was created with (case-insensitively; an IP literal sends no SNI and matches an IP subject alternative name; an empty host sends an empty SNI and fails `CN_CHECK`) and, when enabled, its validity dates, and `sceSslConnect` returns the first failure the connection's verify options select (the verify option entry below lists the bits, codes and initial options); no root bundle is shipped and the console's built-in roots are unknown, so with no CA loaded a connection with the initial options returns `SSL_ERROR_UNKNOWN_CA` (0x8095F00C), as on the console. A client certificate loaded with `sceSslLoadCert` is sent when the server asks for one. A failed verification is final: close_notify is sent, later `sceSslConnect` calls return the same code (also after the `WANT_POLLIN` rounds of a non-blocking socket), and `sceSslRead` and `sceSslWrite` throw, as the console's codes for them were not measured. With a verify callback set it is called once after the handshake, outside the connection's lock, with the context id, the bits of the enabled checks that failed (`KNOWN_CA_CHECK` 0x20, `CN_CHECK` 0x4, the date checks when enabled, 0 when the chain passed), handles to a copy of the peer chain as received (the leaf first, the root last when the server sent it) that the certificate readers of the connection's context accept until the connection is deleted (the handles stay registered in the context until it is terminated; the console frees them at the delete), the chain length and the user argument. A chain fault that no option names (`SSL_ERROR_INVALID_CERT` without a callback) throws when a callback is set, as the bits the console passes for it were not measured. A non-negative return accepts the connection whatever the bits were; a negative return fails the connect with `SSL_ERROR_APPLICATION_VERIFICATION_CALLBACK_CHECK` (0x8095F0FD) and the callback runs again, with the same chain, from every later `sceSslConnect`, `sceSslRead` and `sceSslWrite` of the connection, which return 0x8095F0FD while it keeps refusing and proceed once it accepts. A `sceSslConnect` from inside the callback, or from another thread while it runs, throws. `sceSslRead` and `sceSslWrite` before `sceSslConnect` run the handshake and verification themselves and return its code when it fails. A non-blocking socket that would block returns `SSL_ERROR_WANT_POLLIN` (0x8095F013) or `SSL_ERROR_WANT_POLLOUT` (0x8095F014) from `sceSslConnect`, `sceSslRead` and `sceSslWrite`; the next `sceSslConnect` resumes the handshake, and `sceSslWrite` returns the part it sent before blocking (the console returned 32 KiB of a 64 KiB write). A blocking libSceNet socket whose `SO_RCVTIMEO` expires returns `SSL_ERROR_WANT_POLLIN` as well, and the call can be repeated; `SSL_ERROR_READ_TIMEOUT` (0x80951710) is never returned. libkernel keeps its timeouts above the host socket, so they do not bound SSL reads and writes on a libkernel socket. `sceSslRead` with flags 0 reads until `len` bytes arrived or the stream ended and with flags 1 or 2 returns what the first record delivers. Native flags 3 peek without consuming data; values outside 0 through 3 return `SSL_ERROR_INVALID_VALUE` before connection lookup. A non-blocking read that got some bytes returns them. It returns 0 after the server's close_notify and after a transport that ends without one, every later read 0 again, and `SSL_ERROR_EOF` (0x8095177C) and `SSL_ERROR_SOCKET_CLOSED` (0x8095170D) never from a read. A reset (`ECONNRESET`, `EPIPE`, `WSAECONNRESET`, `WSAECONNABORTED`, `WSAENETRESET`) returns `SCE_NET_ERROR_ECONNRESET` (0x80410136) from `sceSslRead` and `SCE_NET_ERROR_EPIPE` (0x80410120) from `sceSslWrite`, on every later call too; a record that fails its MAC returns 0x80951D55 from `sceSslRead` after the fatal alert goes out. `sceSslWrite` accepts flags 0 only, `SSL_ERROR_INVALID_VALUE` otherwise, sends all of `len`, capped at `INT_MAX`, and returns the count; it keeps writing after the peer's close_notify or a stream that ended without one, as the console does. A fatal alert during the handshake returns `SSL_ERROR_FATAL_ALERT` and ends the transport: later `sceSslConnect` calls return 0, `sceSslRead` 0 and `sceSslWrite` `SSL_ERROR_SOCKET_CLOSED`, as measured. A transport that ends without close_notify or a reset during the handshake returns `SSL_ERROR_SOCKET_CLOSED`, the session is dropped and the next `sceSslConnect` starts over; those two handshake cases and `SSL_ERROR_INVALID_CERT` (0x8095F00A) for a verification failure no option names were not measured. Other handshake and socket failures, a read or write after a failed verification, a write after `sceSslClose`, a null buffer and a read or write from inside the callback throw, as their console codes are unknown. A connection serializes its reads and writes, so a read blocked in one thread holds back a write on the same connection from another. `sceSslDeleteConnection` sends no close_notify and returns `SSL_ERROR_INVALID_ID` when repeated. `sceSslTerm` leaves the context's connections to `sceSslDeleteConnection`, which then returns `SSL_ERROR_INVALID_ID`; a second `sceSslTerm` returns `SSL_ERROR_INVALID_ID` and `sceSslInit` with a pool size of 0 returns `SCE_KERNEL_ERROR_EINVAL` (0x80020016). `sceSslSetVerifyCallback` accepts any callback, null included, and returns 0. The console's first `sceSslConnect` in a process took 23.8 s before its ClientHello left, a one-time initialisation not emulated. `SSL_ERROR_BEFORE_INIT` (0x8095F001) is never returned, as the library keeps no state apart from its contexts +- [sceSslCreateConnection, sceSslDeleteConnection, sceSslSetVerifyCallback, sceSslConnect, sceSslRead, sceSslWrite](../../../core/libs/prx/libSceSsl/Export.cpp) (libSceSsl) - imported by `ffmpeg.prx`. Signatures follow [SharpProspero](https://github.com/SvenGDK/SharpProspero/blob/60977b29103452b9681ae10c7a9011d44965bf16/src/SharpProspero/Interop/Net/Http.cs#L195-L252), which also says the socket stays open after `sceSslDeleteConnection`. The behaviour below was measured on a PS5 on system software 13.40 with a ps5-payload-dev payload (every call printed with its return, a TLS 1.2 test server on the LAN presenting leaves issued by the test fixture root loaded with `sceSslLoadCert`, from an elfldr process rather than a title); what differs for a title process is unknown. An unknown context returns `SSL_ERROR_INVALID_ID` (0x8095F006) from `sceSslCreateConnection`, and every connection call on an unknown or deleted connection id or on a connection whose context was terminated returns `SSL_ERROR_INVALID_ID`. `sceSslCreateConnection` returns `SSL_ERROR_INVALID_VALUE` (0x8095F007) for a null host and does not check the socket: `sceSslConnect` on a descriptor that is not a socket returns `SCE_NET_ERROR_EBADF` (0x80410109). `sceSslConnect` runs a TLS 1.2 client handshake with Mbed TLS 3.6.7 over the host socket that the guest number maps to in the libkernel or libSceNet socket table, and `sceSslRead` and `sceSslWrite` carry application data over it. TLS 1.3 is compiled out: the console offers TLS 1.2 only (its ClientHello carries 12 suites and no supported_versions extension) and a TLS 1.3-only server gets `SSL_ERROR_FATAL_ALERT` (0x8095F010) from it, as from this build. Connection state is allocated from the context's pool and returned to it by `sceSslDeleteConnection`. The console's pool use for one connection with a two-certificate chain peaked at 80,544 bytes in a 256 KiB pool (5,568 after `sceSslInit`, 12,000 after loading one CA); a 16 KiB pool fails the connect with `SSL_ERROR_OUT_OF_MEMORY` (0x809517D5) there and here. The server's chain is checked against the CAs loaded with `sceSslLoadCert`, the host name the connection was created with (case-insensitively; an IP literal sends no SNI and matches an IP subject alternative name; an empty host sends an empty SNI and fails `CN_CHECK`) and, when enabled, its validity dates, and `sceSslConnect` returns the first failure the connection's verify options select (the verify option entry below lists the bits, codes and initial options); no root bundle is shipped and the console's built-in roots are unknown, so with no CA loaded a connection with the initial options returns `SSL_ERROR_UNKNOWN_CA` (0x8095F00C), as on the console. A client certificate loaded with `sceSslLoadCert` is sent when the server asks for one. A failed verification is final: close_notify is sent, later `sceSslConnect` calls return the same code (also after the `WANT_POLLIN` rounds of a non-blocking socket), and `sceSslRead` and `sceSslWrite` throw, as the console's codes for them were not measured. With a verify callback set it is called once after the handshake, outside the connection's lock, with the context id, the bits of the enabled checks that failed (`KNOWN_CA_CHECK` 0x20, `CN_CHECK` 0x4, the date checks when enabled, 0 when the chain passed), handles to a copy of the peer chain as received (the leaf first, the root last when the server sent it) that the certificate readers of the connection's context accept until the connection is deleted (the handles stay registered in the context until it is terminated; the console frees them at the delete), the chain length and the user argument. A chain fault that no option names (`SSL_ERROR_INVALID_CERT` without a callback) throws when a callback is set, as the bits the console passes for it were not measured. A non-negative return accepts the connection whatever the bits were; a negative return fails the connect with `SSL_ERROR_APPLICATION_VERIFICATION_CALLBACK_CHECK` (0x8095F0FD) and the callback runs again, with the same chain, from every later `sceSslConnect`, `sceSslRead` and `sceSslWrite` of the connection, which return 0x8095F0FD while it keeps refusing and proceed once it accepts. A `sceSslConnect` from inside the callback, or from another thread while it runs, throws. `sceSslRead` and `sceSslWrite` before `sceSslConnect` run the handshake and verification themselves and return its code when it fails. A non-blocking socket that would block returns `SSL_ERROR_WANT_POLLIN` (0x8095F013) or `SSL_ERROR_WANT_POLLOUT` (0x8095F014) from `sceSslConnect`, `sceSslRead` and `sceSslWrite`; the next `sceSslConnect` resumes the handshake, and `sceSslWrite` returns the part it sent before blocking (the console returned 32 KiB of a 64 KiB write). A blocking libSceNet socket whose `SO_RCVTIMEO` expires returns `SSL_ERROR_WANT_POLLIN` as well, and the call can be repeated; `SSL_ERROR_READ_TIMEOUT` (0x80951710) is never returned. libkernel keeps its timeouts above the host socket, so they do not bound SSL reads and writes on a libkernel socket. `sceSslRead` with flags 0 reads until `len` bytes arrived or the stream ended and with flags 1 or 2 returns what the first record delivers. Native flags 3 peek without consuming data; values outside 0 through 3 return `SSL_ERROR_INVALID_VALUE` before connection lookup. A non-blocking read that got some bytes returns them. It returns 0 after the server's close_notify and after a transport that ends without one, every later read 0 again, and `SSL_ERROR_EOF` (0x8095177C) and `SSL_ERROR_SOCKET_CLOSED` (0x8095170D) never from a read. A reset (`ECONNRESET`, `EPIPE`, `WSAECONNRESET`, `WSAECONNABORTED`, `WSAENETRESET`) returns `SCE_NET_ERROR_ECONNRESET` (0x80410136) from `sceSslRead` and `SCE_NET_ERROR_EPIPE` (0x80410120) from `sceSslWrite`, on every later call too; a record that fails its MAC returns 0x80951D55 from `sceSslRead` after the fatal alert goes out. `sceSslWrite` accepts flags 0 only, `SSL_ERROR_INVALID_VALUE` otherwise, sends all of `len`, capped at `INT_MAX`, and returns the count; it keeps writing after the peer's close_notify or a stream that ended without one, as the console does. A fatal alert during the handshake returns `SSL_ERROR_FATAL_ALERT` and ends the transport: later `sceSslConnect` calls return 0, `sceSslRead` 0 and `sceSslWrite` `SSL_ERROR_SOCKET_CLOSED`, as measured. A transport that ends without close_notify or a reset during the handshake returns `SSL_ERROR_SOCKET_CLOSED`, the session is dropped and the next `sceSslConnect` starts over; those two handshake cases and `SSL_ERROR_INVALID_CERT` (0x8095F00A) for a verification failure no option names were not measured. Other handshake and socket failures, a read or write after a failed verification, a write after `sceSslClose`, a null buffer and a read or write from inside the callback throw, as their console codes are unknown. A connection serializes its reads and writes, so a read blocked in one thread holds back a write on the same connection from another. `sceSslDeleteConnection` sends no close_notify and returns `SSL_ERROR_INVALID_ID` when repeated. A second `sceSslTerm` returns `SSL_ERROR_INVALID_ID` and `sceSslInit` with a pool size of 0 returns `SCE_KERNEL_ERROR_EINVAL` (0x80020016). `sceSslSetVerifyCallback` accepts any callback, null included, and returns 0. The console's first `sceSslConnect` in a process took 23.8 s before its ClientHello left, a one-time initialisation not emulated. `SSL_ERROR_BEFORE_INIT` (0x8095F001) is never returned, as the library keeps no state apart from its contexts - [sceSslClose](../../../core/libs/prx/libSceSsl/Export.cpp) (libSceSsl) - takes the connection id, as in [SharpProspero](https://github.com/SvenGDK/SharpProspero/blob/60977b29103452b9681ae10c7a9011d44965bf16/src/SharpProspero/Interop/Net/Http.cs#L195-L252). Measured on 13.40 as the connection entry describes: it sends close_notify once if the handshake completed and returns 0, 0 again when repeated and 0 on a connection that never connected, already failed verification or lost its transport to a fatal alert; a close before the handshake changes nothing, so the connection can still connect. After the close `sceSslConnect` returns 0 and `sceSslRead` 0, as on the console; `sceSslWrite` after it throws, as the console's code was not measured. A close_notify that a non-blocking socket cannot take at once returns `SSL_ERROR_WANT_POLLOUT` (0x8095F014) and the close can be repeated; after a reset it returns `SCE_NET_ERROR_ECONNRESET` (0x80410136) every time. The socket is left to the title; an unknown connection returns `SSL_ERROR_INVALID_ID` (0x8095F006). Whether the console closes the socket is unknown - [Certificate readers](../../../core/libs/prx/libSceSsl/Export.cpp): foreign and expired certificate/name handles throw instead of following native unchecked pointers. Name views track certificate lifetime and preserve identity; the native no-op name release is implemented. View storage remains allocated until context destruction. Numeric names for attributes Mbed TLS cannot identify may differ from native names. Fingerprint stack-space validation and backend digest failures are not reproduced. Signatures, valid-context/null-argument precedence, serial truncation, name copy bounds, validity timestamps and supported hash selectors are confirmed by the supplied module. - [sceSslLoadCert, sceSslGetCaList, sceSslFreeCaList, sceSslGetCaCerts, sceSslFreeCaCerts, sceSslUnloadCert](../../../core/libs/prx/libSceSsl/Export.cpp) (libSceSsl) - signatures and layouts follow [SharpProspero](https://github.com/SvenGDK/SharpProspero/blob/5dfdb4b0b166e83dc9ae275001afb695f12c7174/src/SharpProspero/Interop/Net/Http.cs). PPSA15508/01.002.000 calls `sceSslLoadCert` with one 1,408-byte PEM CA and null client certificate/key arguments; this confirms that call shape, not console error behavior. Mbed TLS parses DER/PEM chains. CA imports still commit together instead of preserving successful entries before a later failure. Client certificate replacement clears the previous identity; raw private keys load independently and are parsed when configuring TLS. Partial client chains on decode failure, native key parse errors and incomplete identities during TLS setup remain unsupported. CA queries return independently owned snapshots; unload clears active credentials while outstanding snapshots remain valid. Appending repeated CA imports, snapshot lifetime across unload, memory overhead and error precedence have not been measured on a PS5. Invalid loads, malformed material, exhausted pools and unsupported keys throw rather than inventing console error codes. Native CA queries include built-in roots; the host still queries loaded authorities and returns `NOT_FOUND` for an empty context. No native root bundle is copied. Null-output and invalid-context precedence, output preservation on invalid contexts and the SDK 7.50 unload error boundary are recovered. Legacy clearing of foreign raw CA lists remains unchanged. Certificate reader queries reflect active certificates or outstanding snapshots. Loading credentials does not start a TLS connection; `sceSslConnect` verifies the server against the loaded CAs and offers the loaded client certificate - [sceSslEnableVerifyOption, sceSslDisableVerifyOption, sceSslSetMinSslVersion, sceSslSetAlpn, sceSslGetAlpnSelected](../../../core/libs/prx/libSceSsl/Export.cpp) (libSceSsl) - signatures follow [SharpProspero](https://github.com/SvenGDK/SharpProspero/blob/60977b29103452b9681ae10c7a9011d44965bf16/src/SharpProspero/Interop/Net/Http.cs), the source of the other connection signatures; the behaviour was measured on a PS5 on system software 13.40 with a ps5-payload-dev payload (every call printed with its return, a TLS 1.2 test server on the LAN presenting leaves issued by the test fixture root loaded with `sceSslLoadCert`, from an elfldr process rather than a title). The verify options select which verification failures `sceSslConnect` reports (see the connection entry above), with the bit values SharpProspero's `SceSslVerifyOption` gives: `SERVER_VERIFY` 0x1, `CN_CHECK` 0x4, `NOT_AFTER_CHECK` 0x8, `NOT_BEFORE_CHECK` 0x10, `KNOWN_CA_CHECK` 0x20. The initial options are `SERVER_VERIFY`, `CN_CHECK` and `KNOWN_CA_CHECK` (0x25): the console accepted an expired and a not-yet-valid server certificate until 0x8 or 0x10 was enabled, which then returned `SSL_ERROR_NOT_AFTER_CHECK` (0x8095F00D) and `SSL_ERROR_NOT_BEFORE_CHECK` (0x8095F00E); whether 0x2 (`CLIENT_VERIFY`) starts enabled was not determined and it is kept off. A check that is disabled is not reported, whatever the chain. Bits outside 0x3F return `SSL_ERROR_INVALID_VALUE` (0x8095F007) from both calls. Disabling 0x1, 0x4 or 0x20 from the payload stopped its process through the kernel's debug exception path (`mDBG: Sending signal ... signo: 0xa0020101`, 6 of 6 attempts; disabling 0x2, 0x8 and 0x10 returned 0), so whether a title may clear them is unknown; this build clears them, as titles import the call. `sceSslSetMinSslVersion` accepts the `SceSslVersion` values 2 (SSL 3.0) to 5 (TLS 1.2) and returns `SSL_ERROR_INVALID_VALUE` for 0, 1 and anything above 5; the console has no TLS 1.3 value. Every accepted value gives the same handshake, as Mbed TLS 3 speaks TLS 1.2 and nothing older and TLS 1.3 is compiled out, which matches the console offering TLS 1.2 only. `sceSslSetAlpn` stores the string up to its terminator, split on commas into the protocols offered in the handshake (the console sent `h2,http/1.1` as the two names and a wire-format string as one name), a second call replaces the list, an empty string returns `SSL_ERROR_BAD_LENGTH` (0x80951773), and a null list clears the configured protocols. Native inspection confirms that replacement clears the old list even on failure, that each comma-separated name must contain 1-255 bytes and that the whole string must be shorter than 65535 bytes. `sceSslGetAlpnSelected` returns the protocol the server selected, still after `sceSslClose`, or null before the handshake and when none was selected; the pointer is owned by the connection. An unknown connection and a connection whose context was terminated return `SSL_ERROR_INVALID_ID` (0x8095F006) from the four setters and null from `sceSslGetAlpnSelected`, as confirmed by the supplied native module - [sceSslGetPem](../../../core/libs/prx/libSceSsl/Export.cpp): native argument validation, CRLF line endings, 64-character Base64 lines, NUL-inclusive length and buffer clearing on insufficient capacity are recovered. Foreign and expired certificate handles throw instead of performing native unchecked pointer access. DER reserialization differences for noncanonical certificates remain unverified. + +- This pending declaration has an unverified signature and behavior; it is a parameterless import-resolution declaration and throws through `NotImplemented_nid_no_patch`: [`sceSslSetServerName`](../../../core/libs/prx/libSceSsl/Export.cpp). diff --git a/docs/dev/debt/libSceSulphaDrv.md b/docs/dev/debt/libSceSulphaDrv.md index 88b6f9091f..990eaa1951 100644 --- a/docs/dev/debt/libSceSulphaDrv.md +++ b/docs/dev/debt/libSceSulphaDrv.md @@ -1,5 +1,5 @@ # libSceSulphaDrv technical debt -### Inventory exports declared elsewhere +### Unknown function info -sceSulphaGetClientInfo, sceSulphaGetConnectedClientCount, sceSulphaGetDefaultConfig, sceSulphaGetNeededMemory, sceSulphaInit, sceSulphaMessage, sceSulphaSetBookmark and sceSulphaShutdown are the complete PS5 3.20 export table of this module per the [PS5 3.20 export inventory](https://github.com/DNNDHH/PS5-3.20_Libs/blob/b2a77c09cd71c01f34c790cfbe98c751a13262ad/libSceSulphaDrv.c), but all eight are currently declared by #7416 in libSceSulpha, so this module keeps its `APS5_DUMMY_FUN` skeleton to respect the duplicate-export rule. Declare them here (with no parameters, matching the `1b5004d77` unknown-prototype shape) if that PR's module attribution is rejected. +- [libSceSulphaDrv](../../../core/libs/prx/libSceSulphaDrv/Export.cpp) - signatures and behavior remain unknown for `sceSulphaGetClientInfo`, `sceSulphaGetConnectedClientCount`, `sceSulphaGetNeededMemory`, `sceSulphaInit`, `sceSulphaMessage`, `sceSulphaSetBookmark` and `sceSulphaShutdown`. Their no-parameter declarations resolve imports and throw through `NotImplemented_nid_no_patch`; they make no ABI claim. diff --git a/docs/dev/debt/libSceUsbd.md b/docs/dev/debt/libSceUsbd.md index 3f234ef7b4..e7e535f68b 100644 --- a/docs/dev/debt/libSceUsbd.md +++ b/docs/dev/debt/libSceUsbd.md @@ -6,8 +6,10 @@ ### Unknown function info -- [sceUsbdClearHalt, sceUsbdDetachKernelDriver, sceUsbdEventHandlerActive, sceUsbdGetDevice, sceUsbdGetDeviceSpeed, sceUsbdGetMaxIsoPacketSize, sceUsbdGetMaxPacketSize, sceUsbdHandleEvents, sceUsbdHandleEventsLocked, sceUsbdLockEventWaiters, sceUsbdLockEvents, sceUsbdOpenDeviceWithVidPid, sceUsbdSetInterfaceAltSetting, sceUsbdTryLockEvents, sceUsbdUnlockEventWaiters, sceUsbdUnlockEvents, sceUsbdWaitForEvent](../../../core/libs/prx/libSceUsbd/Export.cpp) (libSceUsbd) - signatures follow the console type database in [orbital](https://github.com/AlexAltea/orbital/blob/cc408367da6a6ebbf5ac1ac559fefeadc73b2831/tools/ida/db_types.json#L2268-L2322), but their behavior is unknown and each call throws; not measured on a console +- [sceUsbdEventHandlerActive, sceUsbdHandleEvents, sceUsbdHandleEventsLocked, sceUsbdLockEventWaiters, sceUsbdLockEvents, sceUsbdTryLockEvents, sceUsbdUnlockEventWaiters, sceUsbdUnlockEvents, sceUsbdWaitForEvent](../../../core/libs/prx/libSceUsbd/Export.cpp) (libSceUsbd) - signatures follow the console type database in [orbital](https://github.com/AlexAltea/orbital/blob/cc408367da6a6ebbf5ac1ac559fefeadc73b2831/tools/ida/db_types.json#L2268-L2322), but their behavior is unknown and each call throws; not measured on a console ### Functional - [sceUsbdGetConfiguration, sceUsbdGetConfigDescriptorByValue, sceUsbdGetDescriptor, sceUsbdGetStringDescriptorAscii](../../../core/libs/prx/libSceUsbd/Export.cpp) (libSceUsbd) - not measured on a console; they follow FreeBSD 11.4 ([libusb10_desc.c](https://github.com/freebsd/freebsd-src/blob/d106002967eff712894ab8b5337bbbff106ce5e0/lib/libusb/libusb10_desc.c), [libusb20.c](https://github.com/freebsd/freebsd-src/blob/d106002967eff712894ab8b5337bbbff106ce5e0/lib/libusb/libusb20.c)). The configuration and descriptor queries return host libusb errors. `sceUsbdGetStringDescriptorAscii` rebuilds `libusb20_dev_req_string_simple_sync` with only its 255-byte read: libusb's Windows HID backend reports the requested length as `bLength`, cutting a 4-byte header read to one character. Unlike the host `libusb_get_string_descriptor_ascii` it accepts index 0, drops non-printable characters and `<>` instead of writing `?`, and fails with `0x802400FF`. Closes when: measured on a PS5 +- [sceUsbdGetDevice, sceUsbdGetDeviceSpeed, sceUsbdGetMaxPacketSize, sceUsbdGetMaxIsoPacketSize, sceUsbdOpenDeviceWithVidPid](../../../core/libs/prx/libSceUsbd/Export.cpp) (libSceUsbd) - not measured on a console; they follow FreeBSD 11.4 [libusb10.c](https://github.com/freebsd/freebsd-src/blob/d106002967eff712894ab8b5337bbbff106ce5e0/lib/libusb/libusb10.c) over the host libusb. The packet sizes are searched in the active configuration and the iso size is scaled as FreeBSD does, not through the host's versions, which differ for an unreadable configuration and for SuperSpeed endpoints. A host SuperSpeed+ device reports SuperSpeed, the fastest speed FreeBSD 11.4 has. A null device in `sceUsbdGetMaxIsoPacketSize` throws, as FreeBSD dereferences it. A device stays known while a handle to it is open, so the device of a handle from `sceUsbdOpenDeviceWithVidPid` can be used until that handle is closed. Closes when: measured on a PS5 +- [sceUsbdSetInterfaceAltSetting, sceUsbdClearHalt, sceUsbdDetachKernelDriver](../../../core/libs/prx/libSceUsbd/Export.cpp) (libSceUsbd) - not measured on a console; they follow FreeBSD 11.4 [libusb10.c](https://github.com/freebsd/freebsd-src/blob/d106002967eff712894ab8b5337bbbff106ce5e0/lib/libusb/libusb10.c) over the host libusb. `sceUsbdSetInterfaceAltSetting` checks the interface range and this library's record of claimed interfaces, and returns `0x802400FF` for any other failure; it throws while the device has transfers in flight, which FreeBSD cancels first. `sceUsbdClearHalt` returns 0, or `0x802400FF` for an endpoint the host does not find; FreeBSD ignores the result of the clear itself, so the host's other errors throw, and so does a null handle, which FreeBSD dereferences. `sceUsbdDetachKernelDriver` returns `0x802400FF` for any failure, which on Windows is every call, as libusb cannot detach drivers there. Closes when: measured on a PS5 diff --git a/docs/dev/debt/libSceVrTracker2.md b/docs/dev/debt/libSceVrTracker2.md index 29b19cc61c..5bb664cbf1 100644 --- a/docs/dev/debt/libSceVrTracker2.md +++ b/docs/dev/debt/libSceVrTracker2.md @@ -2,11 +2,11 @@ ### Silent stubs -- [libSceVrTracker2](../../../core/libs/prx/libSceVrTracker2/Export.cpp) never initializes; initialized tracking behavior is absent. Its uninitialized responses were measured on firmware 13.60 without a headset: most exports return 0x8A740001 without writes, while specific output/reset helpers clear buffers or write defaults. These helpers still lack complete signatures. Named export signatures and play-area output layouts are recovered; initialization option semantics and result fields need reconstruction. Anonymous exports remain grouped by their observed response rather than their individual contracts. +- [libSceVrTracker2](../../../core/libs/prx/libSceVrTracker2/Export.cpp) never initializes; initialized tracking behavior is absent. Its uninitialized responses were measured without a headset: most exports return 0x8A740001 without writes, while specific output/reset helpers clear buffers or write defaults. These helpers still lack complete signatures. Named export signatures and play-area output layouts are recovered; initialization option semantics and result fields need reconstruction. Anonymous exports remain grouped by their observed response rather than their individual contracts. ### Unknown function info -- [sceVrTracker2Initialize](../../../core/libs/prx/libSceVrTracker2/Export.cpp) - the 72-byte parameter layout is recovered, including thread priorities, CPU affinity masks, work memory, size/alignment and coordinate system. Meanings of the 32-bit option at 0x30 and byte options at 0x38/0x39 remain unresolved; initialization remains unimplemented. +- [sceVrTracker2Initialize](../../../core/libs/prx/libSceVrTracker2/Export.cpp) - never initializes: after validation it returns the first non-zero libSceHmd2 tracking or LED-detector open/start result and resets to uninitialized, and throws if all four succeed or for modes 1000/1001, whose application category the host lacks. Unverified: the mode 0 category query is assumed to succeed, the `sceKernelGetAppInfo2` attribute checks are skipped (the host has no such record; a zeroed one passes), the daemon IPC client and work-memory heap are not created, rollback only undoes what the call opened, and the meanings of the options at 0x30, 0x38 and 0x39 remain unknown (0x39 is only range-checked). The behaviour is not measured on a console; the -1 a no-headset host gets relies on libSceHmd2's measured pre-initialization answers. PPSA05666 calls it with no headset and, with #7463, #7690 and #7658 applied, stopped on the NotImplemented. - [libSceVrTracker2](../../../core/libs/prx/libSceVrTracker2/Export.cpp) - the seven anonymous throwing exports now have their consumed argument slots restored. Calibration output (`jRmuXjsknsI`) uses a 32-bit capacity with 608/1216-byte variants; its fields remain unresolved. Mesh requirements (`NBhWy+Gl0tY`) contain four 32-bit counts/sizes. The mode/buffer/capacity/size export (`9R6W33Au4B4`) uses 64-bit sizes. The 32/48-byte result parameters are recovered; result output and pose parameters still need full layouts; the telemetry input (`oZDm1bynCaA`) spans 7024 bytes. Their bodies remain unimplemented. - [Anonymous tracking queries](../../../core/libs/prx/libSceVrTracker2/Export.cpp) still lack initialized behavior. The paired option setter/getter consume 28/40-byte records with three integer options, a reset byte and one/two float vectors; option meanings remain unresolved. The scalar query uses an 8-byte size/float record. Diagnostic output spans 4096 bytes, extended output 0xD02E8 bytes, and tracking configuration input 1024 bytes; their fields remain unresolved. The relative-pose query uses two coordinate-system selectors and a 64-byte output containing a pose and 32 cleared bytes; the counter query uses a 64-bit output and a 32-bit selector whose meaning remains unresolved. Remaining aliases still need individual signatures. diff --git a/docs/dev/debt/libc.md b/docs/dev/debt/libc.md index 2d4e0fc01d..1d060c03aa 100644 --- a/docs/dev/debt/libc.md +++ b/docs/dev/debt/libc.md @@ -2,7 +2,7 @@ ### Unknown function info -- [strtonum](../../../core/libs/prx/libc/src/StringExtensions.cpp) (libc) is unverified on the console. Its signature, decimal parsing, inclusive bounds, error strings, error precedence and errno preservation follow [FreeBSD 11.4 strtonum.c](https://github.com/freebsd/freebsd-src/blob/8c639945a44588f6cfdddfb057bb5aad88735da0/lib/libc/stdlib/strtonum.c). Parsing uses the host `strtoll` with base 10. +- [strtonum](../../../core/libs/prx/libc/src/StringExtensions.cpp) (libc) is unverified on the console. Its signature, decimal parsing, inclusive bounds, error strings, error precedence and errno preservation follow [FreeBSD 11.4 strtonum.c](https://github.com/freebsd/freebsd-src/blob/8c639945a44588f6cfdddfb057bb5aad88735da0/lib/libc/stdlib/strtonum.c). Parsing uses the host `strtoll` with base 10. It is not exported by `libSceLibcInternal.sprx` on a PS5 (firmware 13.60), so a payload process cannot call it there - [fegetexcept](../../../core/libs/prx/libc/src/FloatingPoint.cpp) (libSceLibcInternal, implemented in libc) has not been read from the PS5 library or measured on a console. It follows FreeBSD 11.4 amd64 [fenv.h](https://github.com/freebsd/freebsd-src/blob/4554bee35405b36ea19e9e60d6abe6ea534e36e0/lib/msun/x86/fenv.h#L121-L133), reporting the six unmasked x87 exceptions independently of MXCSR; whether the PS5 uses the same rule when the units disagree is unverified. - [sceLibcBacktraceGetBufferSize, sceLibcBacktraceSelf](../../../core/libs/prx/libc/src/Backtrace.cpp) (libc) - signatures and frame record layout inferred from a title (next pointer, u32 module offset, module name at +0x10); the u32 at +0xC is unknown and written as 0. Module names are host file names without the `.guest.prx` suffix, so their case may differ from the PS5 module name. On Windows, unwinding uses `_Unwind_Backtrace` and stops at a frame without `.ehmeta` or `.ehfram` tables whose PE unwind data has an exception or termination handler, leaving the trace empty or cut short while still returning 0. Implemented only on Linux and Windows; other platforms throw @@ -11,7 +11,7 @@ - [scriptingGetMem, scriptingFreeMem](../../../core/libs/prx/libc/src/ApplicationHeap.cpp) (libc) - runtime allocator hooks for Unity titles. The allocation signature `(alignment, size)`, minimum alignment 16 and null result for a non-power-of-two alignment follow [KytyPS5](https://github.com/KytyPS5/KytyPS5/blob/df5b9b92be7dfd463b47756b707d6d356a9f0550/src/libs/libKernel.cpp); the free hook's one-pointer signature follows [Raeen's recorded contract](https://github.com/Whoisraeen/Raeen/blob/2db56923204b89719916b95e29c2f3c4e1d9f90b/docs/unity-dlsym-blocker.md). Both use libc's own guest heap, not the title's registered allocator. A title that ships its own `libc.prx` (Metal Gear Solid Master Collection, PPSA18194) has already initialized that allocator, and reaching it from here would run its initializer a second time. That title's IL2CPP runtime looks up only `scriptingGetMem`, by name from `Il2cppUserAssemblies.prx`, and asks it for 256 KiB blocks aligned to 4 KiB. Which console library exports the hooks is unknown, and there is no console measurement. Allocation failure and sizes that overflow return null. - [_Mtx_trylock](../../../core/libs/prx/libc/src/Threads.cpp) (libc, NID `k6pGNMwJB08`) - returns busy for a non-recursive mutex already owned by the caller, assumed to match `_Mtx_lock`'s ownership handling; exact console behavior is unverified. -- [nearbyintf](../../../core/libs/prx/libc/src/Math.cpp) (libc, NID `c+4r-T-tEIc`) uses the host rounding mode, not the console's; console rounding mode state remains unverified. +- [nearbyintf](../../../core/libs/prx/libc/src/Math.cpp) (libc, NID `c+4r-T-tEIc`) rounds with the MXCSR rounding mode, as the console's `libSceLibcInternal.sprx` does in a payload process on a PS5 (firmware 13.60): with the x87 mode set to upward and MXCSR to nearest it rounded 2.5 to 2, and with MXCSR upward to 3, and the four modes gave the results the host gives. The console also raised `FE_INEXACT` for those inexact inputs, which the host's `nearbyintf` does not; whether it does for exact inputs was not measured - [__std_find_trivial_unsized_N](../../../core/libs/prx/libc/src/VectorAlgorithms.cpp) (libc) - matches the `libc.prx` bundled with PPSA08427 (disassembly, and that binary run side by side on random inputs): when nothing matches between `first` and the end of its 32-byte-aligned block, the console rescans that whole block without masking and so can return a match up to 31 bytes before `first` - [_Thrd_sleep](../../../core/libs/prx/libc/src/Threads.cpp) (libc, NID `jfRI3snge3o`) follows the Dinkumware threads library shipped with [Visual C++ 2013](https://github.com/adityaramesh/concurrency_runtime/tree/master/VS2013_SP2/crt/src/thr) (`xtime.c`) and C11 Annex K, without console verification. It reads a 16-byte xtime (64-bit seconds and nanoseconds) on the guest `CLOCK_REALTIME`, normalizes the nanoseconds and sleeps through `nanosleep` on POSIX, retrying on `EINTR`, or high-resolution waitable timers on Windows; a null xtime or one whose normalization overflows throws. Guest thread cancellation is not integrated with this wait. The console's `_Thrd_sleep` (disassembled from a title's `libc.prx`) also takes an optional `xtime*` of remaining time and returns `int`; here the sleep is never cut short, so it returns 0 and leaves the remaining time untouched. - [_Mtx_init_with_name](../../../core/libs/prx/libc/src/Threads.cpp) (libc, NID `tgioGpKtmbE`) forwards to `_Mtx_init` and ignores the mutex name parameter. @@ -45,10 +45,10 @@ - [memcpy_s, memmove_s, strcpy_s, strncpy_s, strcat_s, strncat_s, wmemcpy_s, wmemmove_s, wcsncpy_s, wcscat_s, wcsncat_s](../../../core/libs/prx/libc/src/Strings.cpp) (libc) use the C11 Annex K destination size constraints, with RSIZE_MAX taken as (SIZE_MAX >> 1) / sizeof(char16_t) for wide operations and SIZE_MAX >> 1 for byte operations. An oversized destination size returns ERANGE (34) without touching the destination; the console's RSIZE_MAX and exact error value are unverified. Constraint violations return an error without invoking the registered constraint handler, as before. - [wcsncat_s and wcscat_s](../../../core/libs/prx/libc/src/Strings.cpp) (libc) refuse a copy as overlapping only when the written range `[dest + len1, dest + len1 + len2)` meets the read range `[src, src + len2)`. The rule comes from a static reading of the console's `wcsncat_s` in `libc.prx` (not run on a console); `wcscat_s` gets it through `wcsncat_s`, and its own console code was not read. The narrow `strncat_s` keeps a wider rule, `[dest, dest + used + length + 1)` against `[src, src + length + 1)`, whose console code was not read either, so it refuses some copies whose wide equivalent proceeds. - [snwprintf_s](../../../core/libs/prx/libc/src/FormattingWide.cpp) (libc) - follows C11 K.3.9.1.3 with `RSIZE_MAX` assumed to be `SIZE_MAX >> 1`. A runtime-constraint violation only returns a negative value: the handler installed with `set_constraint_handler_s` is not invoked, and the console's default handler is unknown. An invalid multibyte `%s` argument is copied byte by byte instead of being reported as an encoding error, as in `vswprintf` -- [swprintf_s and vswprintf_s](../../../core/libs/prx/libc/src/FormattingWide.cpp) (libc) - follow C11 K.3.9.1.4 with `RSIZE_MAX` assumed to be `SIZE_MAX >> 1`: the complete output, including the terminating null, must fit in the buffer, otherwise it is a runtime-constraint violation that sets `buffer[0]` to zero and returns a negative value, and the buffer is not partially written. Argument and encoding checks match `snwprintf_s` +- [swprintf_s and vswprintf_s](../../../core/libs/prx/libc/src/FormattingWide.cpp) (libc) - follow C11 K.3.9.1.4 with `RSIZE_MAX` assumed to be `(SIZE_MAX >> 1) / sizeof(char16_t)`: the complete output, including the terminating null, must fit in the buffer, otherwise it is a runtime-constraint violation that sets `buffer[0]` to zero and returns a negative value, and the buffer is not partially written. Argument and encoding checks match `snwprintf_s` - [strerror](../../../core/libs/prx/libc/src/Errors.cpp) (libc) - follows the `libc.prx` that CUSA04865 and CUSA12435 ship, loaded on a PS4 Pro (firmware 10.71): 0 gives "No error", 1 to 94 the FreeBSD texts, any other number "error_code=0x%08x", and errno is left alone. The console's system libc, which homebrew without a bundled `libc.prx` uses, answers differently ("No error information" for 0 and unknown numbers, 95 and 96 named). `strerror_r` and `perror` keep "No error: 0" and "Unknown error: %d"; they are not measured. - [strerror_s and strerrorlen_s](../../../core/libs/prx/libc/src/WideConversion.cpp) (libc) follow [C11 K.3.7.4.2 and K.3.7.4.3](https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf), using the existing FreeBSD error messages and unknown-error formatting. Truncation writes an ellipsis when capacity exceeds 3; constraint failures leave the destination untouched and invoke the registered guest-ABI handler. The console's `RSIZE_MAX` (`SIZE_MAX >> 1` here), nonzero returns (`EINVAL` 22 for constraints, `ERANGE` 34 for truncation), handler arguments and default abort behavior are unverified. Messages remain in the C locale, and guest errno is preserved. -- [getw and putw](../../../core/libs/prx/libc/src/BinaryWordIo.cpp) (libc) follow FreeBSD 11.4 [getw.c](https://github.com/freebsd/freebsd-src/blob/8c639945a44588f6cfdddfb057bb5aad88735da0/lib/libc/stdio/getw.c) and [putw.c](https://github.com/freebsd/freebsd-src/blob/8c639945a44588f6cfdddfb057bb5aad88735da0/lib/libc/stdio/putw.c): one 32-bit little-endian word, `getw` returns -1 for EOF or an error, and `putw` returns 0 on success or -1 on error while holding the stream lock. They use the existing host-backed streams, so buffering and error timing follow the host CRT. Null streams throw and closed streams return -1 with `EBADF`, as existing byte I/O does. Console behavior is unverified. +- [getw and putw](../../../core/libs/prx/libc/src/BinaryWordIo.cpp) (libc) follow FreeBSD 11.4 [getw.c](https://github.com/freebsd/freebsd-src/blob/8c639945a44588f6cfdddfb057bb5aad88735da0/lib/libc/stdio/getw.c) and [putw.c](https://github.com/freebsd/freebsd-src/blob/8c639945a44588f6cfdddfb057bb5aad88735da0/lib/libc/stdio/putw.c): one 32-bit little-endian word, `getw` returns -1 for EOF or an error, and `putw` returns 0 on success or -1 on error while holding the stream lock. They use the existing host-backed streams, so buffering and error timing follow the host CRT. Null streams throw and closed streams return -1 with `EBADF`, as existing byte I/O does. Console behavior is unverified. A payload process on a PS5 (firmware 13.60) gave the same results: two words written little-endian, -1 with end of file after them and for a 2-byte file, and -1 with the error flag for `putw` on a read-only stream - [vsnwprintf_s](../../../core/libs/prx/libc/src/FormattingWide.cpp) (libc) - `va_list` counterpart of `snwprintf_s` (C11 K.3.9.1.3): truncates to the buffer and returns the full length, with the same constraints and argument checks - [strndup and strdup](../../../core/libs/prx/libc/src/AllocatingStrings.cpp) (libc) return null with `errno` set to `EINVAL` (22) when `source` is null, preventing a host segfault on invalid guest input. POSIX.1-2008 and FreeBSD 11.4 libc leave `strndup(NULL)` and `strdup(NULL)` undefined (faulting); exact console behavior on hardware is unverified. - [snprintf_s and vsnprintf_s](../../../core/libs/prx/libc/src/Formatting.cpp) (libc) - follow C11 K.3.5.3.5 and K.3.5.3.12 with `RSIZE_MAX` assumed to be `SIZE_MAX >> 1`, as `snwprintf_s` does: a null buffer or format, `size` of 0 or above `RSIZE_MAX`, any `%n` and a null `%s`, `%ls` or `%S` argument return a negative value and set `buffer[0]` to zero when the buffer and size allow it; otherwise the output is truncated to the buffer and the full length is returned. A violation only returns: the constraint handler is not invoked, and the console's error value is unverified. Not confirmed on a PS5 title @@ -68,20 +68,20 @@ - [_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`) returns the host's `std::thread::hardware_concurrency()` (which may be 0 when unknown) instead of the console's processor count; no reference implements it and the value a title expects (PPSA34015 imports it) is unverified. - [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. -- [_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. +- [_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 +- [_Divide, _FDivide, _Recip and _FRecip](../../../core/libs/prx/libc/src/DinkumwareInternals.cpp) (libc) follow the Dinkumware CRT division and reciprocal contracts with IEEE-754 signed-zero, infinity and NaN behavior. The exact console results, signaling-NaN handling and floating-point exception behavior are not verified. - [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. - [memmem and memccpy](../../../core/libs/prx/libc/src/Strings.cpp) (libc) - `memmem` searches for needle occurrences in memory buffers and `memccpy` copies buffers until a character match, following FreeBSD and POSIX specifications; behavior is unverified on console. - [strtof and wcstof](../../../core/libs/prx/libc/src/Strings.cpp) (libc) round to the nearest float, where the console's `_Stof` in `libSceLibcInternal.sprx` (0x734a0) does not always: about a third of decimal inputs within a relative 2^-51 of a point halfway between two floats, and some hexadecimal inputs with more than 24 significant bits, come out one unit apart in the last place (`1e-40` is `0x1.16c3p-133` there and `0x1.16c2p-133` here). The console's own rounding is not reproduced - [strtof and wcstof](../../../core/libs/prx/libc/src/Strings.cpp) (libc) - `ERANGE` follows the `libc.prx` bundled with PPSA08427 (J03547016) and PPSA03671 (J03848509), both run side by side with this libc on a Linux host: a decimal input whose result is a nonzero subnormal sets it only when inexact, a hexadecimal one only when it lies below the smallest subnormal and rounds up to it, and underflow to zero and overflow set it. Both builds also take a `NAN(...)` payload in `strtof` from the sequence's leading digits (`nan(0x123)` is `0x7fc00123`, `-nan(5)` is `0xffc00005`); the sign is kept here, the payload is not. `libSceLibcInternal`'s `_Stof` differs: no `ERANGE` for hexadecimal input, a positive `nan`, and after a minus sign a failed parse is `-0.0` for a lone sign and `+0.0` before an `inf`/`nan` spelling, the reverse of `libc.prx`. Decimal `strtod` sets `ERANGE` for a nonzero subnormal in J03547016 but not in J03848509 or `libSceLibcInternal`, whose result is kept. -- [Guest time conversions](../../../core/libs/prx/libc/src/Time.cpp) rewrite the host process `TZ` when a guest changes its own `TZ`, so other host consumers of that variable (including libSceRtc local time) shift too; code outside libc does not take the zone lock. Zone syntax follows the host C runtime, not FreeBSD: Windows only accepts the `std offset [dst]` form, treats an empty guest `TZ` as `UTC0` and reads `:Europe/Berlin` as an abbreviation (for example `rop`); only Linux honours zone file names. If the guest accepts a `TZ` value that the host rejects (on Windows, for example, one longer than the host environment limit), conversions throw `std::runtime_error`. A `tm_zone` saved before a `TZ` change can refer to storage now holding the new zone name, changing `%Z` output. +- [Guest time conversions](../../../core/libs/prx/libc/src/Time.cpp) rewrite the host process `TZ` when a guest changes its own `TZ`, so other host consumers of that variable (including libSceRtc local time) shift too; code outside libc does not take the zone lock. Zone syntax follows the host C runtime, not FreeBSD: Windows only accepts the `std offset [dst]` form, treats an empty guest `TZ` as `UTC0` and reads `:Europe/Berlin` as an abbreviation (for example `rop`); only Linux honours zone file names. If the guest accepts a `TZ` value that the host rejects (on Windows, for example, one longer than the host environment limit), conversions throw `std::runtime_error`. A `tm_zone` saved before a `TZ` change can refer to storage now holding the new zone name; `strftime` does not read it. - [cbrtf](../../../core/libs/prx/libc/src/Math.cpp) (libc) is FreeBSD msun's [`s_cbrtf.c`](https://github.com/freebsd/freebsd-src/blob/release/11.4.0/lib/msun/src/s_cbrtf.c): a 5-bit first guess from the exponent bits, then two Newton steps in double precision. It sets no `errno`, as the `libc.prx` that titles ship does not. Floating-point exceptions are not compared. It gives the same bits as the `cbrtf` of the `libc.prx` bundled with PPSA07923, PPSA05916 and PPSA13934 for all 2^32 arguments, run on a Windows host. -- [__isfinitel](../../../core/libs/prx/libc/src/Math.cpp) - classifies the x87 80-bit exponent without narrowing to double or performing floating-point comparisons, following [FreeBSD msun](https://github.com/freebsd/freebsd-src/blob/main/lib/msun/src/s_isfinite.c). The signature and classification follow FreeBSD; console behaviour is unmeasured. Requires little-endian x87 long double stored in 16 bytes, as the existing guest long-double ABI does. +- [__isfinitel](../../../core/libs/prx/libc/src/Math.cpp) - classifies the x87 80-bit exponent without narrowing to double or performing floating-point comparisons, following [FreeBSD msun](https://github.com/freebsd/freebsd-src/blob/main/lib/msun/src/s_isfinite.c). The signature and classification follow FreeBSD; console behaviour is unmeasured. Requires little-endian x87 long double stored in 16 bytes, as the existing guest long-double ABI does. On a PS5 (firmware 13.60) `__isfinitel` returned 1 for 0, -0, 1, a denormal and ±1e4000, and 0 for a NaN and for the maximum exponent without the integer bit, which this classification gives too - [logf](../../../core/libs/prx/libc/src/Math.cpp) (libc) is FreeBSD msun's [`e_logf.c`](https://github.com/freebsd/freebsd-src/blob/release/11.4.0/lib/msun/src/e_logf.c), with `vzero` read at run time as msun's `volatile` read does. As in the `libc.prx` that titles ship, `errno` is set to `ERANGE` for ±0 and to `EDOM` for every argument with the sign bit set, negative NaNs and -inf included; positive NaNs and +inf leave it unchanged. Floating-point exceptions are not compared. It gives the same bits and `errno` as the `logf` of the `libc.prx` bundled with PPSA07923 and PPSA05916 for all 2^32 arguments, run on a Windows host. The FMA-contracted build bundled with PPSA13934 differs from it by 1 ulp on 961,881 arguments, so no single port matches every title's last bit. - Windows direct-memory backing reserves a paging-file section. A [direct memory page](../../../core/libs/prx/libc/include/WindowsMappings.hpp) mapped at one guest address is private write-watched memory at that address and is not committed in the section; a page mapped at a second address moves its whole resident run into the section (committed there) and every address becomes a view of it, tracked by write protection. An unmapped resident page that is not all zeros is kept in a private reservation until it is mapped again. Committed section contents remain across unmap/remap and are released when the backing and its remaining views are destroyed. A host import alias over part of a resident run is refused. Linux retains its existing backing. Peak gameplay memory and Windows versions other than the tested host remain unverified. -- Stable Windows resident runs of at least 256 KiB use temporary read-only protection for clean write-watch proofs. The first CPU write restores the logical protection of the whole run; that run remains on native write watching until it is remapped, so repeatedly rewritten runs stay writable. Native kernel writes into guest buffers must hold [GuestArena::HostWrite](../../../core/libs/prx/libc/include/GuestArena.hpp), as shared views already require: an unbracketed WinAPI ReadFile can fail with ERROR_NOACCESS while the resident proof is armed. Guest read, pread and socket receive paths already bracket their destinations. GPU host-import access suppresses resident rearming without inventing shared-page stores. This is a host integration requirement, not a change to guest logical protection. - [getc_unlocked, putc_unlocked, getchar_unlocked, putchar_unlocked](../../../core/libs/prx/libc/src/StandardStreams.cpp) (libc) - byte I/O uses the host unlocked operations; guest EOF/error flags and macro counters follow `FileStream`. Linux status queries use `feof_unlocked`/`ferror_unlocked` because [glibc `feof`](https://github.com/bminor/glibc/blob/d2097651cc57834dbfcaa102ddfacae0d86cfb66/libio/feof.c) and [`ferror`](https://github.com/bminor/glibc/blob/d2097651cc57834dbfcaa102ddfacae0d86cfb66/libio/ferror.c) can acquire the stream lock. Windows uses [the CRT no-lock byte operations](https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/fgetc-nolock-fgetwc-nolock) and `feof`/`ferror`, verified under a held stream lock on UCRT. Console behavior and other host CRTs remain unverified. - [strcasecmp and strncasecmp](../../../core/libs/prx/libc/src/Strings.cpp) (libc) - console locale behavior is unmeasured. They use the guest's C-locale case conversion and return -1, 0 or 1, the sign of the folded unsigned-byte difference, as the `libc.prx` bundled with eleven titles does (FreeBSD 11.4's [strcasecmp.c](https://github.com/freebsd/freebsd-src/blob/releng/11.4/lib/libc/string/strcasecmp.c) returns the difference itself); other guest locales are not implemented. - [feof_unlocked and ferror_unlocked](../../../core/libs/prx/libc/src/StandardStreams.cpp) (libSceLibcInternal, implemented in libc) have no console measurement. The firmware 3.20 [export inventory](https://github.com/DNNDHH/PS5-3.20_Libs/blob/b2a77c09cd71c01f34c790cfbe98c751a13262ad/libSceLibcInternal.c) names NIDs `NuydofHcR1w` and `yxbGzBQC5xA`. They follow FreeBSD 11 [feof.c](https://github.com/freebsd/freebsd-src/blob/release/11.0.0/lib/libc/stdio/feof.c) and [ferror.c](https://github.com/freebsd/freebsd-src/blob/release/11.0.0/lib/libc/stdio/ferror.c), returning 0 or 1 from the stream status without acquiring the stream lock. They inherit the host CRT limitations of the unlocked byte operations above. @@ -98,15 +98,17 @@ - [strtod, strtof, strtold](../../../core/libs/prx/libc/src/Strings.cpp) (libc) - `strtod` and `wcstod` (and `atof`, which calls `strtod` here) read a `NAN(...)` sequence as FreeBSD 11's gdtoa [`hexnan`](https://github.com/freebsd/freebsd-src/blob/release/11.0.0/contrib/gdtoa/hexnan.c) does: hexadecimal digits with an optional `0x`, blanks starting a new 32-bit word, the first 16 digits kept and the payload cut to 52 bits, a zero payload made 1, any other character giving the default NaN but consuming up to the closing parenthesis, and an unterminated sequence keeping its payload while consuming only `nan`. The payload goes under the quiet bit with the sign, as in gdtoa's [`strtod`](https://github.com/freebsd/freebsd-src/blob/release/11.0.0/contrib/gdtoa/strtod.c#L316-L328). `strtof`, `wcstof`, `strtold` and `wcstold` return the positive default quiet NaN (`0x7fc00000`; exponent `0x7fff`, significand `0xc000000000000000`) whatever the sign and the sequence, and consume a sequence of letters, digits and underscores up to its closing parenthesis. The console's `libSceLibcInternal.sprx`, called from a payload process on a PS5 (firmware 12.70), gives these results for the 64 NaN inputs tried through `strtod` and `strtof`, 50 of them also through `strtold` and `wcstod`, and 18 through `wcstof` and `wcstold`, and, through `strtod`, for `nan(1 2)` and for `nan( ` followed by NUL and `)`; that a title's own `libc.prx` does the same is assumed. In `hexnan`, a blank after a payload digit, while a 32-bit word of the payload is still free, starts a blank skip that has no NUL check, so when only blanks follow up to the terminating NUL the console's `strtod` reads past it: `nan(1 ` followed by NUL and `)` consumes the `)` after the NUL, so the result depends on the bytes after the string, and here that case throws. A blank right after `nan(` is skipped with a NUL check, and the console stopped at the NUL there - [remquol](../../../core/libs/prx/libc/src/MathExact.cpp) (libc) leaves `*quo` unchanged when the result is NaN; the `libc.prx` bundled with PPSA08427 writes a value that depends on earlier x87 state (`remquol(1, 0)` stored 0 on a first call and 4 on later ones) - [_Stod, _Stodx, _Stofx, _Stoldx, _Stof and _Stold](../../../core/libs/prx/libc/src/DinkumwareInternals.cpp) (libSceLibcInternal, implemented in libc) throw for hexadecimal text with a non-zero power-of-ten scale. The console's result there does not follow a simple rule: `0x3` with a scale of -1 gives 0.29999999999999999. A nonzero subnormal result sets neither `errno` nor the error argument, as measured in firmware 13.60's `libSceLibcInternal.sprx` run in a Linux host process, not on a console; there about a fifth of decimal inputs with a subnormal result come out one unit apart in the last place (`_Stodx("2.2250738585072014e-308", 0)` is the largest subnormal), which is not reproduced +- [_LDivide, _LRecip and _LLog](../../../core/libs/prx/libc/src/DinkumwareInternals.cpp) (libc) follow the public Dinkumware CRT contracts: long-double division and reciprocal, and the `_LLog` base flag (`0` natural, positive base 10, negative base 2). The exact console results, signaling-NaN behavior and floating-point exception behavior are not verified. - [Long double math in MathExact.cpp](../../../core/libs/prx/libc/src/MathExact.cpp) (libc) was compared with the `libc.prx` bundled with PPSA08427 only for canonical 80-bit encodings; unnormals, pseudo-denormals and pseudo-infinities passed to arithmetic functions (not the classifiers) follow the host x87 instead of the console - [atanf](../../../core/libs/prx/libc/src/Math.cpp) (libc) is FreeBSD msun's [`s_atanf.c`](https://github.com/freebsd/freebsd-src/blob/release/11.4.0/lib/msun/src/s_atanf.c), with `atanlo[3]` read at run time as msun's `volatile` does. Tiny arguments return `x` without raising `FE_INEXACT`. It gives the same bits as the `atanf` of the `libc.prx` bundled with PPSA07923, PPSA05916 and PPSA13934 for all 2^32 arguments, run on a Windows host, and none of those sets `errno`. Whether other titles' builds differ is unverified. -- [rename, sceKernelRename](../../../core/libs/prx/libc/include/RenameDot.hpp) (libc, libkernel) fail a last path component of `.` or `..` with `EINVAL`, after FreeBSD 11.4's [`lookup`](https://github.com/freebsd/freebsd-src/blob/release/11.4.0/sys/kern/vfs_lookup.c), which refuses `.` and, through its `ISDOTDOT` and `ISLASTCN` flags, `..` as the last component for the `DELETE` and `RENAME` operations. `rmdir("dir/.")`, `unlink("dir/.")` and the same calls with `..` follow the same lookup rule in FreeBSD but are not changed here: the guest still resolves the dot component away and acts on `dir` or its parent. Both arguments are checked before any host access, so `rename` of a missing source onto `dir/.` answers `EINVAL`, where FreeBSD's [`kern_renameat`](https://github.com/freebsd/freebsd-src/blob/release/11.4.0/sys/kern/vfs_syscalls.c) looks the source up first and answers `ENOENT`. A backslash counts as a path separator here (the guest path resolver turns it into `/`); FreeBSD treats it as an ordinary name character. None of this was measured on a console. -- [nan and nanf](../../../core/libs/prx/libc/src/Math.cpp) (libc) return fixed quiet NaN values (`0x7fc00000` and `0x7ff8000000000000`), ignoring the tag argument as observed in the console's `libc.prx` (both exports load a global constant via `mov rax,[rip+..]; vmovsd xmm0,[rax]; ret`); VLC (PPSA85300) stops on nanf at start-up after strsep. +- [rename, sceKernelRename](../../../core/libs/prx/libc/include/RenameDot.hpp) (libc, libkernel) fail a last path component of `.` or `..` with `EINVAL`, after FreeBSD 11.4's [`lookup`](https://github.com/freebsd/freebsd-src/blob/release/11.4.0/sys/kern/vfs_lookup.c), which refuses `.` and, through its `ISDOTDOT` and `ISLASTCN` flags, `..` as the last component for the `DELETE` and `RENAME` operations. `unlink`, `rmdir`, `sceKernelUnlink` and `sceKernelRmdir` follow the same rule. Both arguments are checked before any host access, so `rename` of a missing source onto `dir/.` answers `EINVAL`, where FreeBSD's [`kern_renameat`](https://github.com/freebsd/freebsd-src/blob/release/11.4.0/sys/kern/vfs_syscalls.c) looks the source up first and answers `ENOENT`. A backslash counts as a path separator here (the guest path resolver turns it into `/`); FreeBSD treats it as an ordinary name character. None of this was measured on a console. +- [nan and nanf](../../../core/libs/prx/libc/src/Math.cpp) (libc) return fixed quiet NaN values (`0x7fc00000` and `0x7ff8000000000000`), ignoring the tag argument as observed in the console's `libc.prx` (both exports load a global constant via `mov rax,[rip+..]; vmovsd xmm0,[rax]; ret`); VLC (PPSA85300) imports nanf. - [jrand48 and mrand48](../../../core/libs/prx/libc/src/Random.cpp) (libSceLibcInternal, implemented in libc) return the high 32 bits of the new 48-bit state zero-extended to 64 bits, as the console's `libSceLibcInternal.sprx` does when called from a homebrew payload process on a PS5 (firmware 12.70): a result with bit 31 set comes back between 0x80000000 and 0xFFFFFFFF, as FreeBSD 11.0's [`jrand48`](https://github.com/freebsd/freebsd-src/blob/release/11.0.0/lib/libc/gen/jrand48.c#L23) and [`mrand48`](https://github.com/freebsd/freebsd-src/blob/release/11.0.0/lib/libc/gen/mrand48.c#L25) return it; FreeBSD 11.1 and later cast it to `int32_t` ([`jrand48`](https://github.com/freebsd/freebsd-src/blob/release/11.1.0/lib/libc/gen/jrand48.c#L26), [`mrand48`](https://github.com/freebsd/freebsd-src/blob/release/11.1.0/lib/libc/gen/mrand48.c#L28)), which makes it negative. `lrand48` and `nrand48` matched FreeBSD there. Whether a title's own libc does the same is unverified - [seed48 and lcong48](../../../core/libs/prx/libc/src/Random.cpp) (libSceLibcInternal, implemented in libc) follow the console's `libSceLibcInternal.sprx` (SDK 4.5x build of `J03950001`, 0x6F460 and 0x6F420): the multiplier and addend are shared by the whole `rand48` family, including `erand48`, `nrand48` and `jrand48` on a caller's seed; `lcong48` sets them with the seed, and `srand48` and `seed48` restore 0x5DEECE66D and 0xB. Unlike FreeBSD, `seed48` returns a static copy of the new seed rather than the previous one. A null argument, which the console dereferences, throws - [lgamma and signgam](../../../core/libs/prx/libc/src/Math.cpp) (libc) - `lgamma` returns the host's `lgamma` and stores the sign of Γ(x) in the exported `signgam` (NID `5gOOC0kzW0c`, starting at 0 as in FreeBSD 11's [`s_signgam.c`](https://github.com/freebsd/freebsd-src/blob/stable/11/lib/msun/src/s_signgam.c)) by the rules of [`e_lgamma_r.c`](https://github.com/freebsd/freebsd-src/blob/stable/11/lib/msun/src/e_lgamma_r.c): -1 for -0 and for a negative non-integer whose floor is odd, 1 otherwise, including poles, infinities and NaN. Taken from the FreeBSD source, not measured on the console. The NID is in the aerolib symbol list; no title is known to read `signgam`. PPSA99004 imports `lgamma` - [coshf](../../../core/libs/prx/libc/src/Math.cpp) (libc) follows FreeBSD msun's [`e_coshf.c`](https://github.com/freebsd/freebsd-src/blob/5aa554c7e5b6fd9042986df07f12ac5687e41392/lib/msun/src/e_coshf.c), using the `expm1f` and `expf` paths already inlined for `sinhf` below; the Windows UCRT differed from the `libc.prx` copies in PPSA07923 and PPSA13934 on 500,554 and 500,614 of 20 million inputs in the #9707 survey. The exact system `libSceLibcInternal` behavior and the FMA-contracted `libc.prx` results remain unverified - [expm1](../../../core/libs/prx/libc/src/Math.cpp) (libc) does not compare floating-point exceptions, and its double inputs are checked by sampling, not exhaustively. It is FreeBSD msun's [`s_expm1.c`](https://github.com/freebsd/freebsd-src/blob/release/11.4.0/lib/msun/src/s_expm1.c) with `huge` read at run time, and sets `ERANGE` only when a finite argument overflows to infinity, as the titles' `libc.prx` does. It gives the same bits and `errno` as the `expm1` bundled with PPSA07923 and PPSA05916 on 320 million random and 47,222 structured arguments on a Windows host; the FMA-contracted build bundled with PPSA13934 differs on 43,433 of the random ones. +- [log1p](../../../core/libs/prx/libc/src/Math.cpp) (libc) does not compare floating-point exceptions, and its double inputs are checked by sampling, not exhaustively. It is FreeBSD msun's [`s_log1p.c`](https://github.com/freebsd/freebsd-src/blob/release/11.4.0/lib/msun/src/s_log1p.c). As the titles' `libc.prx` does, it sets `EDOM` at msun's NaN return (arguments below -1, `-inf` and negative NaNs) and leaves `errno` alone for `log1p(-1)`, where it returns `-inf`. It gives the same bits, NaN payloads included, and `errno` as the `log1p` bundled with PPSA07923 and PPSA05916 on 320 million random and 68,216 structured arguments on a Windows host. The FMA-contracted build bundled with PPSA13934 differs on 73,682 of the random ones. - [sinhf](../../../core/libs/prx/libc/src/Math.cpp) (libc) follows the `sinhf` of the `libc.prx` bundled with PPSA28319 (disassembly): FreeBSD msun's [`e_sinhf.c`](https://github.com/freebsd/freebsd-src/blob/5aa554c7e5b6fd9042986df07f12ac5687e41392/lib/msun/src/e_sinhf.c) from before `__ldexp_expf`, which squares `expf(|x| / 2)` between `logf(FLT_MAX)` and the overflow threshold, calling msun's [`expm1f`](https://github.com/freebsd/freebsd-src/blob/59bc2f095289a10b8cfa55cbb2b45c3bd6c2d4ae/lib/msun/src/s_expm1f.c) and [`expf`](https://github.com/freebsd/freebsd-src/blob/59bc2f095289a10b8cfa55cbb2b45c3bd6c2d4ae/lib/msun/src/e_expf.c), whose paths for the arguments it passes are inlined here. Past the threshold Sony's error helper sets `errno` to `ERANGE` before returning `x * 1e37`; msun itself sets no `errno`. That code, run on a Windows host, gives the same bits as this implementation for every finite argument up to the threshold, of both signs; it was not run on Linux. That the system `libSceLibcInternal`, which Ruffle (PPSA68091) and RetroArch (PPSA99169) import while bundling a zero-return `libc.prx`, has the same code is assumed - [acoshf](../../../core/libs/prx/libc/src/Math.cpp) (libc) uses FreeBSD msun's [`e_acoshf.c`](https://github.com/freebsd/freebsd-src/blob/5aa554c7e5b6fd9042986df07f12ac5687e41392/lib/msun/src/e_acoshf.c) range handling; the Windows UCRT differed from the `libc.prx` copies in PPSA07923 and PPSA13934 on 216,017 and 216,024 of 20 million inputs in the #9707 survey. The invalid-domain path raises `FE_INVALID` without setting `errno` as the source does. The exact system `libSceLibcInternal` behavior and FMA-contracted results remain unverified - [acoshl, asinhl, atanhl, atan2l, cbrtl, erfl, erfcl, expm1l, hypotl, log1pl, log2l, lgammal, tgammal, j0f, j1f, jnf, y0f, y1f and ynf](../../../core/libs/prx/libc/src/Math.cpp) (libc) return the host C library's results (the float Bessel functions through its double ones), not those of the console's own code, so the last bits can differ (`y0f`, `y1f`, `ynf` follow the console at `+-0`). As in the console's `libSceLibcInternal.sprx` (SDK 4.5x build of `J03950001`, 0x56410), `lgammal` does not store the sign in `signgam`; `hypotl` returns infinity for an infinite argument even when the other is a NaN, as C11 F.10.4.3 requires. [hypot3, hypot3f and hypot3l](../../../core/libs/prx/libc/src/Math.cpp) follow that module (0x51D30, 0x520D0, 0x52420): the first NaN of x, y and z is returned unchanged, any infinity gives positive infinity, a zero argument gives the two-argument hypot of the other two, and otherwise the largest magnitude is combined with the hypot of the other two @@ -135,19 +137,22 @@ - [wctomb_s, wcrtomb_s, mbstowcs_s and mbsrtowcs_s](../../../core/libs/prx/libc/src/BoundsChecking.cpp) (libc) follow the console's `libc.prx`, but convert in the single-byte C locale of `wctomb`, `wcrtomb` and `mbrtowc` (`MB_CUR_MAX` 1): a character above 0xFF is `EILSEQ` in `wctomb_s` and `wcrtomb_s`, and each byte is one wide character in `mbstowcs_s` and `mbsrtowcs_s`. The locale of a title's `libc.prx` was not measured. The `wcrtomb_s` path where a character does not fit `smax` and the `EILSEQ` paths of `mbstowcs_s` and `mbsrtowcs_s` are not reached - [wcsrtombs_s](../../../core/libs/prx/libc/src/Multibyte.cpp) (libc) follows the console's `libc.prx`, but a runtime-constraint violation only returns its error: the default handler there writes the message and a newline to `stderr` before returning, which is not done here. Conversion uses the C locale of `wcrtomb` (`MB_CUR_MAX` 1), so the path where a multibyte character does not fit the remaining space is not reached - [c16rtomb, c32rtomb, mbrtoc16 and mbrtoc32](../../../core/libs/prx/libc/src/Multibyte.cpp) (libSceLibcInternal, implemented in libc) - a null state, which the console dereferences, throws. Otherwise they follow the console's `libSceLibcInternal.sprx` (0x7D480 to 0x7D920), read from disassembly: UTF-8 whatever the locale, up to six bytes per sequence, with no surrogate or 0x10FFFF check when encoding. The state holds the value in its first eight bytes and the expected byte count (0x10 for a pending low surrogate, 1 for a stored high one) as 16 bits at 0xA. `mbrtoc16` builds a low surrogate from the value the state last held, `c16rtomb` returns -1 without `errno` for an unpaired high surrogate, and `EILSEQ` is 86. On a PS5 (13.60) the system library's default locale converts UTF-8 in `wcrtomb`, `wctomb`, `mbrtowc` and `mblen`; a title's bundled `libc.prx` does too until `setlocale` installs a table ([disassembly](https://github.com/boykopovar/AnyPS5/pull/8855#issuecomment-6335267758)) -- [The narrow printf family](../../../core/libs/prx/libc/src/Formatting.cpp) (libc) follows a payload process on a PS5 (firmware 13.60): each 16-bit unit of a `%ls` or `%lc` argument is encoded alone, so a surrogate pair gives two 3-byte sequences; a NaN keeps its sign and the `+` and space flags, and `0` pads it with spaces; argument positions above 99 work (up to 400 measured; above 65535 throw here); an unknown conversion such as `%m` or `%k` prints `%` and its letter, padded to the width, without taking an argument. The guest's `wcrtomb` and locales are not used. On Linux the formats without those conversions go to glibc, which prints NaN the same way. The `_s` forms throw for an unknown conversion, `%m` included, which was not measured +- [The narrow printf family](../../../core/libs/prx/libc/src/Formatting.cpp) (libc) follows a payload process on a PS5 (firmware 13.60): each 16-bit unit of a `%ls` or `%lc` argument is encoded alone, so a surrogate pair gives two 3-byte sequences; a NaN keeps its sign and the `+` and space flags, and `0` pads it with spaces; argument positions above 99 work (up to 400 measured; above 65535 throw here); an unknown conversion such as `%m` or `%k` prints `%` and its letter, padded to the width, without taking an argument. The guest's `wcrtomb` and locales are not used. On Linux the formats without those conversions or a floating-point conversion go to glibc, which prints NaN the same way. The `_s` forms throw for an unknown conversion, `%m` included, which was not measured +- [%a and %A](../../../core/libs/prx/libc/include/WindowsFormatting.hpp) (libc) format a finite double as the `libc.prx` that titles ship does, instead of through the host: a subnormal is normalised (`0x1p-1074`), a shorter precision rounds half up on the dropped hexadecimal digits and a carry stays in the leading digit (`%.3a` of `0x0.fffffffffffffp-1022` is `0x2.000p-1023`), and `-` overrides `0`. Checked by running the copies of PPSA13934, PPSA07923 and PPSA05916 side by side on 7 million random formats, not measured on a console. Infinities and `long double` still go to the host; NaN keeps its sign and flags through the formatter on current main. +- [%e, %f and %g](../../../core/libs/prx/libc/include/WindowsFormatting.hpp) (libc) format a finite `double` or `long double` as the `libc.prx` that titles ship does, instead of through the host. It keeps the exact decimal digits down to position `4 * floor(k / 4) - 20`, where `k` is the `frexp` exponent times 30103 / 100000 truncated, and prints zeros after them; a shorter precision rounds half up on the kept digits, except that an exact tie rounds down when `k` is at least 8 (`%.0f` of 67108865.5 is `67108865`). The console computes the kept digits in extended precision, so about 7% of outputs longer than 17 significant digits end one unit lower than here (`%f` of 1e22 is `9999999999999999999999.000000`). Checked by running the copies of PPSA07923, PPSA05916 and PPSA13934 side by side, not measured on a console. The wide printf family still formats through the host. - [%p and %lp](../../../core/libs/prx/libc/include/WindowsFormatting.hpp) (libc) follow the console's `libSceLibcInternal.sprx` measured from a homebrew payload on firmware 12.70 ([#7549](https://github.com/boykopovar/AnyPS5/issues/7549)), not FreeBSD: bare lowercase hex with no `0x` prefix even under `#`, `0` for a null pointer, `+` and the space flag ignored, the width counting only the digits, `-` padding on the right, `0` padding with zeros when there is no precision, the precision as the minimum number of digits, nothing for a null pointer under `%.0p`, and `l` accepted. Only `snprintf` and `swprintf` of that module were measured, from a payload process rather than a title process, so a width beside `%.0p`, the `0` flag beside a precision (which C17 ignores) and `%.0p` of a non-null pointer follow this formatter's own rules and are not measured; `swprintf` was not run with `%lp`, so the wide family still refuses that conversion and returns -1. Linux routes `%p` and `%lp` to this formatter because glibc prints the FreeBSD form and `(nil)` for a null pointer, which means a format that combines `%p` with a conversion this formatter refuses, such as an argument position above 99, throws there instead of reaching glibc - [collate and collate _Getcat](../../../core/libs/prx/libc/src/LocaleSupport.cpp) (libc) build the facet for the C locale only and throw for any other locale name, the wide entry point following the narrow one it sits next to. The wide facet carries its own vtable, whose `compare`, `transform` and `hash` take the guest's 16-bit characters, so the length of a range is a count of characters: `compare` orders by 16-bit value (the C locale, as Dinkumware's `char_traits::compare` does), `transform` copies the characters into the result and records size and capacity in 16-bit elements (inline capacity 7, heap capacity `length | 7`, `(capacity + 1) * 2` bytes including the terminator), following Dinkumware's [VC12 `basic_string`](https://github.com/ganboing/crt.vc12/blob/f1d47126bf13d1c9dccaa6c53b72217fd0474968/src/xstring#L500-L531), and `hash` mixes one whole character per round, so wide text below 0x100 hashes like its narrow spelling and a character above 0xff hashes as one value instead of the two bytes it holds. The console's `libc.prx` exports both `_Getcat` (NIDs BSVJqITGCyI and 2wz4rthdiy8) with identical 0x19d-byte bodies, believed to build the same 0x20-byte facet; the console bodies themselves are unreadable (obfuscated dynsym, and the text of the relinked `libc.prx` is zeroed), so the wide entries follow the narrow algorithm and the C locale instead of the console's wide code, and no console run checks the two. The console's `libc.prx` stores pointers to its collation state tables at offsets 0x10 and 0x18 of the facet; ours leaves them null, as only the facet's own functions read them. `do_transform` throws for input with embedded null characters, which the console drops depending on the output buffer size. The narrow result capacity (`length | 15`) and the over-aligned storage of results of 4080 characters or more follow the console's `libc.prx` code and are not checked on hardware. No module of the PPSA59322, PPSA76677 or PPSA97358 dumps in this tree imports either `_Getcat`, so neither has been exercised by a title. - [codecvt, numpunct, num_put and time_put _Getcat](../../../core/libs/prx/libc/src/LocaleSupport.cpp) (libc) build facets matching a bundled console `libc.prx` (dynsym decoded by NID, vtables disassembled): categories 2, 4, 4 and 5, sizes 0x10, 0x30, 0x10 and 0xb8. `codecvt` reproduces the console virtuals (`noconv` conversions, `length` the shorter range); `numpunct` copies its C-locale table (`""`, `.`, `,`, `false`, `true`). `num_put`/`time_put` formatting virtuals throw rather than fabricate output, and `time_put`'s `_Locinfo` table is unpopulated — the console's `do_put` bodies were not mirrored. The facets share the no-op `destroy`/`deleteObject`/`retain`/`release` base used for `collate`, so `numpunct`'s static C-locale strings are never freed. Unlike `collate`, these `_Getcat` entries ignore the locale argument and always build the C-locale facet; the console's behaviour for a non-C name is unverified. `std::clog` and `std::wclog` are 0x400-byte zeroed objects like the rest of the `NSTDSTR` stream set (the console's `libc.prx` sizes `std::clog` at 96 bytes, measured from its dynsym `st_size`), and the `numpunct::id` and `time_put::id` objects are 8-byte zeros like the other facet ids. - [std::__throw_bad_variant_access](../../../core/libs/prx/libc/src/exception/StandardExceptions.cpp) (libc) throws `std::bad_variant_access` with the `what()` string `bad_variant_access`, the one [LLVM libc++](https://github.com/llvm/llvm-project/blob/main/libcxx/src/variant.cpp) returns, since the export carries libc++'s `__throw_bad_variant_access` name; the console's string is unverified. Onimusha: Way of the Sword (PPSA27836 01.000.001) imports it from `libc`, and its bundled `libc.prx` does not export it. -- [std::bad_optional_access and std::_Throw_bad_optional_access](../../../core/libs/prx/libc/src/exception/StandardExceptions.cpp) (libc) provide the exception type, constructor, destructor, and `what()` exports alongside `_Throw_bad_optional_access`, returning the `what()` string `bad_optional_access` matching Dinkumware and libc++ conventions; the console libc.prx string is unverified. PPSA26578 (issue #7624) and PPSA34015 import `_ZSt26_Throw_bad_optional_accessv` (`KwzEip7m6TM`) from `libc`, and fail to load on main with unresolved import (0xC0000139). +- [std::bad_optional_access and std::_Throw_bad_optional_access](../../../core/libs/prx/libc/src/exception/StandardExceptions.cpp) (libc) provide the exception type, constructor, destructor, and `what()` exports alongside `_Throw_bad_optional_access`, returning the `what()` string `bad_optional_access` matching Dinkumware and libc++ conventions; the console libc.prx string is unverified. PPSA26578 (issue #7624) and PPSA34015 import `_ZSt26_Throw_bad_optional_accessv` (`KwzEip7m6TM`) from `libc`. - [The scanf family](../../../core/libs/prx/libc/src/Formatting.cpp) (libc), the `_s` forms included, decodes the input of the 16-bit wide conversions (`%ls`, `%lc`, `%l[`, `%S`, `%C`) on Linux as UTF-8, mirroring the narrow printf family, where FreeBSD uses the locale's `mbrtowc` (one byte per character in the C locale); the console's locale encoding is unverified. Input that is not UTF-8, a character outside the BMP, a scanset member outside ASCII, positional arguments next to a wide conversion and wide conversions in `fscanf` throw. Each character is stored as one 16-bit unit, widths and `_s` sizes count characters, and a `%lc` field cut short by the end of the input keeps what it read, as FreeBSD's `convert_wchar` does. Windows hands `%ls`, `%lc` and `%l[` to the host, whose `wchar_t` is 16 bits - [The scanf family](../../../core/libs/prx/libc/include/WindowsScanning.hpp) (libc) on Windows returns 0, as C17 and FreeBSD do, when input fails after only suppressed conversions have completed (`sscanf("12", "%*d%d", &value)`). Linux hands the format to glibc, which returns `EOF` there. On Windows the host stops a `%x`, `%X`, `%i` or `%p` after the `x` of a `0x` that no hex digit follows (or that the width cuts off), and a float conversion (`%e`, `%f`, `%g`, `%a`) after the `e` of an exponent with no digits (`1e`), where C17 and FreeBSD stop before the `x` or the `e` - [Guest path resolution](../../../core/libs/prx/libc/src/General.cpp) falls back to ASCII case-insensitive component lookup, following [shadPS4's host filesystem](https://github.com/shadps4-emu/shadPS4/blob/945dbc3cc3eee80ac3e053b438502ed936fa6bb2/src/core/file_sys/backends/host_fs.cpp). PPSA03747 requests `Skyrim.INI`, `Data/Video` and lowercase archive/plugin names that differ from the dump's filenames. Exact host names take precedence; multiple fallback matches throw instead of selecting an arbitrary file. Existing parent names are resolved when creating a new file, and guest mount aliases use the same ASCII comparison. Results are not cached, so renames and newly created files remain visible. Unicode case folding and PS5 behaviour for case-colliding host entries are unverified; host roots are used as supplied. Explicit native Windows drive and UNC paths bypass guest parent-component validation.. A relinked module's `.guest.prx` is matched the same way when the original module is not beside it: Borderlands 4 (PPSA01494) loads `/app0/prx/libRenoirCore.PS5.prx`, which it ships as `librenoircore.ps5.prx`. A relinked module request that misses both the exact and the case-insensitive `.guest.prx` takes the sibling whose stem (the name without its last extension, ASCII case ignored) equals the requested stem and that ends with `.guest.prx`, shortest name first: Unity IL2CPP titles load `Media/Modules/.prx` and `Media/Plugins/.prx`, and the relinker names the converted module after the ELF it was built from, `.elf.guest.prx`. The console's module namespace is assumed to ignore case and the extension; several stem matches pick the shortest name instead of throwing, which is not measured on a console +- [Guest file names on Windows](../../../core/libs/prx/libc/src/General.cpp) (libc) are not escaped or mapped before the host call, so names Windows treats specially differ from FreeBSD, where only `/` and NUL are special. `a*b`, `a?b`, `ac`, `a|b` and `a"b` fail with `EINVAL` (22) where FreeBSD creates them. `trail.` and `trail ` both create the host file `trail`, so three FreeBSD names are one file here. `NUL` and a reopen of it succeed, but no file is created. `con`, `aux.txt` and `COM1` create ordinary files. Colons are under Colons in guest names. Measured on Windows 11 (10.0.26200), MinGW-w64 GCC 15.2.0 r7, with `open` (`O_CREAT|O_EXCL|O_WRONLY`), a one-byte write and a listing of the host directory; not measured on Linux or a console. A fix needs a guest-to-host name mapping. - [Colons in guest names](../../../core/libs/prx/libc/src/General.cpp) (libc) - on Windows (NTFS) a guest name containing `:` is not a plain file name: `name:stream` opens or creates the alternate data stream `stream` of the file `name`. Creating `/savedata0/C:file` makes an empty file `C` whose stream `file` holds the data, and `stat` of `/savedata0/C` then reports a regular file. `mkdir` of a name containing `:`, such as `C:` or `dir:x`, fails with EINVAL. `name:stream` already behaved this way before drive-letter components were kept under their mount -- [tzname](../../../core/libs/prx/libc/src/Time.cpp) (libc) points at the host's zone names, read at load and again by `tzset`: the abbreviations a `TZ` string gives (`EST5EDT` is `EST` and `EDT` on both hosts), but on Windows without `TZ` the CRT's full names such as `GMT Standard Time`, which ICU's [uprv_tzname](https://github.com/unicode-org/icu/blob/457157a92aa053e632cc7fcfd0e12f8a943b2d11/icu4c/source/common/putil.cpp#L1244-L1264) (ES-DE in PPSA99169) cannot map to a zone ID. The console's names are not known +- [tzname](../../../core/libs/prx/libc/src/Time.cpp) (libc) points at the host's zone names, read at load and again by `tzset`: the abbreviations a `TZ` string gives (`EST5EDT` is `EST` and `EDT` on both hosts), but on Windows without `TZ` the CRT's full names such as `GMT Standard Time`, which ICU's [uprv_tzname](https://github.com/unicode-org/icu/blob/457157a92aa053e632cc7fcfd0e12f8a943b2d11/icu4c/source/common/putil.cpp#L1244-L1264) (ES-DE in PPSA99169) cannot map to a zone ID. A payload process on a PS5 (firmware 13.60) read both names empty with `TZ` unset, and its `%Z` printed nothing whatever `tm_zone` held; the names a title process sees are not known - [localtime, mktime](../../../core/libs/prx/libc/src/Time.cpp) (libc) on Windows convert through the CRT's `localtime_s` and `mktime`, which accept about 1970 to January 3001 UTC and apply the CRT's daylight-saving rule. A time outside that range is converted a whole number of 400-year Gregorian cycles away, where the calendar repeats, so it gets the rule the CRT applies to that year and not the zone's historical one. On macOS `mktime` converts through the host's `mktime`, which refuses every year before 1900. A local time before 1900 is instead solved for directly: the offset `localtime_r` gives for a candidate time, which follows the zone's history (local mean time before its first transition), is subtracted from the local fields, and the step is repeated until the offset holds. `tm_isdst` is not consulted there, so a time with `tm_isdst` set where the zone had no daylight offset is taken as standard time. FreeBSD's [`time1`](https://github.com/freebsd/freebsd-src/blob/stable/11/contrib/tzcode/stdtime/localtime.c#L2036) would instead shift it by the difference between one of the zone's daylight types and a standard one. `gmtime` converts every time whose year fits an `int` on both hosts. -- [strftime and asctime](../../../core/libs/prx/libc/src/Time.cpp) (libc) follow FreeBSD 11 [strftime.c](https://github.com/freebsd/freebsd-src/blob/5ed7eb0d97ba4436218e810f61bd059acba984c2/lib/libc/stdtime/strftime.c) and [asctime.c](https://github.com/freebsd/freebsd-src/blob/5ed7eb0d97ba4436218e810f61bd059acba984c2/contrib/tzcode/stdtime/asctime.c) with the C locale on every host, not measured on the console; other locales are not implemented. `%s` follows FreeBSD 9 and 11 and is the local-time `mktime` of the broken-down time (current FreeBSD uses `tm_gmtoff`), which is -1 on Windows outside the range above. `%Z` is `tm_zone`, or `tzname[tm_isdst != 0]` when it is null and `tm_isdst` is not negative. The two-digit year warning FreeBSD writes to `stderr` when `CHECK_STRFTIME_FORMATS_FOR_TWO_DIGIT_YEARS` is set is not written +- [strftime and asctime](../../../core/libs/prx/libc/src/Time.cpp) (libc) follow a payload process on a PS5 (firmware 13.60) in the C locale. `%G`, `%g` and `%V` throw for a negative `tm_yday`, a `tm_yday` past the year or a `tm_wday` below -6, where no rule fits the console: `%V` is 01, 00, 00 and 52 for `tm_yday` -25, -13, -12 and -1 (`tm_wday` 5), `tm_yday` 400 of 2026 is week 01 of 2027 but 415 of 1997 is week 59 and 365 of 2013 week 53, and `tm_wday` -12 with `tm_yday` 18 is week 04. `%k`, `%l`, `%P`, `%s`, `%+`, `%v`, flags and widths are copied as written, `E` or `O` before an unknown conversion is dropped, and a format ending in either throws, where the console crashed. Negative fields print 0 and fields wrap at 100 (`%j` at 1000, `%u` and `%w` at 10); `%Y` and `%G` are the year mod 10000, `%C` is `tm_year / 100 + 19`. A negative weekday or month gives `Sun` or `Jan`. `%z` and `%Z` ignore `tm_gmtoff` and `tm_zone` and use the guest zone and `tzname` - [wcsftime](../../../core/libs/prx/libc/src/Time.cpp) (libc) converts the format to UTF-8, runs this library's `strftime` and converts the result back, where the console's `libSceLibcInternal.sprx` (0x854e0) copies literal wide characters and expands each conversion straight into the buffer; the results match for the formats tried, and it has the `strftime` gaps above. A result that does not fit returns 0 with the buffer untouched, where the console leaves the characters written so far. A null buffer returns 0, where the console writes through it, and a size too large for the narrow buffer returns 0 with `EINVAL`, where the console formats as usual. A null format or `tm` throws - [syslog](../../../core/libs/prx/libc/src/Syslog.cpp) (libc) writes each message to `stderr` as `[syslog:] `, with a newline added when missing, instead of sending it to the console's system log. Priority and facility handling follow FreeBSD's `vsyslog`: `%m` expands to the guest errno's message, unknown bits are reported (as priority 0x23, since FreeBSD passes `LOG_ERR|LOG_CONS|LOG_PERROR|LOG_PID` as the priority) and masked, a missing facility becomes `LOG_USER` or the facility set by `openlog`, and errno is preserved. `openlog` applies its identity and `LOG_PID`; a null identity retains the previous one, and a valid nonzero facility replaces the default. `closelog` clears the identity but retains the options and facility, as in FreeBSD 11; when no identity is set, FreeBSD falls back to the program name, which this backend does not emit. `LOG_PERROR` has no extra effect because stderr is the emulated log sink; `LOG_NDELAY`/`LOG_ODELAY`, `LOG_NOWAIT` and `LOG_CONS` have no daemon, child or console backend to control. `setlogmask` follows [FreeBSD 11](https://github.com/freebsd/freebsd-src/blob/8d2708de5d6112a492744d367cfdfb8fd219227a/lib/libc/gen/syslog.c): the process-wide mask defaults to 0xff, zero queries it, and nonzero values replace it; masked messages are skipped before formatting, including the unknown-priority diagnostic. The console's mask behaviour is unverified - [fwscanf, vfwscanf, wscanf, vwscanf and their `_s` forms](../../../core/libs/prx/libc/src/ScanningWide.cpp) (libc) run the `swscanf` scanner on characters read with `fgetwc`, so everything listed for `swscanf` in this file applies to them. As in the console's `libc.prx`, a field takes characters while they can still begin a valid item, so a failed field such as `0x` for `%x` stays consumed, and only the character that ended the scan goes back to the stream. That character is pushed back as its UTF-8 bytes with `ungetc`, because `ungetwc` takes single bytes only; the Windows C runtime guarantees one byte of push-back, so a non-ASCII lookahead can be lost there. A null stream or format returns `EOF`; the console checks them only in the `_s` forms. @@ -157,6 +162,7 @@ - [std::_Throw_Cpp_error](../../../core/libs/prx/libc/src/exception/StandardExceptions.cpp) (libc) follows Dinkumware `thread0.cpp` ([VC12](https://github.com/ganboing/crt.vc12/blob/f1d47126/src/thread0.cpp), [STL](https://github.com/microsoft/STL/blob/da52dc0f/stl/src/thread0.cpp)), without console verification. Codes outside 0..6 throw `std::out_of_range`, the deleting destructor throws, and STREAMS errnos absent from FreeBSD 11.4 [`errno.h`](https://github.com/freebsd/freebsd-src/blob/releng/11.4/sys/sys/errno.h) (`ENODATA`, `ENOSR`, `ENOSTR`, `ETIME`) are omitted. Codes 0..6 throw a 32-byte [VC12 `system_error`](https://github.com/ganboing/crt.vc12/blob/f1d47126/src/system_error) with FreeBSD errnos (16, 22, 3, 12, 1, 11, 35), a static `generic_category` (not `_Generic_object`), and unverified 40-byte [GuestLocale::String](../../../core/libs/prx/libc/include/GuestLocale.hpp) messages from [`syserror.cpp`](https://github.com/ganboing/crt.vc12/blob/f1d47126/src/syserror.cpp) - [Call tracing](../../../core/libs/prx/libc/src/specifics/x86_64/CallTrace.cpp) (`--trace-imports`, `APS5_TRACE_CALLS`) is missing on macOS and records only the entry of a call, not its arguments or result. One process-wide ring keeps the last 65536 calls, so a busy thread pushes the others out; the reporting thread's own calls are listed only while they are still in that ring. Calls are counted per traced target; an import bound to a target already traced under another name is counted under the first name. The thunk saves the integer argument registers and `xmm0` to `xmm7`; wider vector arguments survive only while the recording code avoids AVX, which is untested. Linux has no crash report, so it prints the trace only on `SIGABRT` (guest or host `abort()`), not on `SIGSEGV`; a caller in a module loaded after the last traced import prints without a module name, and a thread aborting while another writes the report waits for it at most 2 seconds - [_Dtest](../../../core/libs/prx/libc/src/Math.cpp) (libc) follows Dinkumware double classification matching _FDtest: finite values return -1, subnormals -2, zeros 0, infinities 1, and NaNs 2. +- [exp2f](../../../core/libs/prx/libc/src/Math.cpp) (libc) is FreeBSD msun's [`s_exp2f.c`](https://github.com/freebsd/freebsd-src/blob/release/11.4.0/lib/msun/src/s_exp2f.c), with `huge` and `twom100` read at run time and `x + redux` rounded to float, as msun's `volatile` reads and `STRICT_ASSIGN` do. As in the `libc.prx` that titles ship, `errno` is set to `ERANGE` only in msun's overflow (`x >= 128`) and underflow (`x <= -150`) branches, so a subnormal result leaves it unchanged. Floating-point exceptions are not compared. It gives the same bits and `errno` as the `exp2f` of the `libc.prx` bundled with PPSA07923, PPSA05916 and PPSA13934 for all 2^32 arguments, run on a Windows host. - [app0.zar](../../../core/libs/prx/libc/src/AppArchive.cpp) (libc) - a [ZArchive](https://github.com/Exzap/ZArchive) beside `app0/` is a read-only layer under it: a path missing from `app0/` is looked up in the archive, case-insensitively. It is not a console format; titles ship their files in a PFS image instead. Resolving an archive-only path through any call other than the archive-aware libkernel ones throws, so `fopen`, `stat`, `access`, `opendir` and the rest do not read the archive yet, and `opendir` of a directory that exists in both places, `app0/` itself included, and `fdopen` of an archived descriptor throw instead of missing its entries or reading the null device. A damaged compressed block throws instead of returning `EIO` - [fopen_s](../../../core/libs/prx/libc/src/FileAndHeap.cpp) (libc) - returns the errno of the failed open, as C11 K.3.5.2.1 leaves the nonzero value open and Microsoft's CRT returns errno; the console's Dinkumware `fopen_s` is not verified - [codecvt vtable](../../../core/libs/prx/libc/src/LocaleSupport.cpp) (libc, NID `H-TDszhsYuY`) is thirteen zeroed `uintptr_t` slots matching `st_size` 104 on title `libc.prx` from PPSA26344 and on `libSceLibcInternal.sprx` (offset-to-top, typeinfo, two destructors, `_Incref`/`_Decref`, and seven conversion virtuals). Facet calls through the object fault until those methods are wired. diff --git a/docs/dev/debt/libkernel.md b/docs/dev/debt/libkernel.md index ead756f295..9a5292f65c 100644 --- a/docs/dev/debt/libkernel.md +++ b/docs/dev/debt/libkernel.md @@ -65,6 +65,7 @@ - [sceKernelSyncOnAddressWait](../../../core/libs/prx/libkernel/SyncOnAddress/src/SyncOnAddress.cpp) (libkernel) - the only known caller passes a null timeout and a name string as the fourth argument; the timeout is assumed to point to microseconds like the other kernel waits, and the name is ignored - [sceKernelSyncOnAddressWait8 / sceKernelSyncOnAddressWait16 / sceKernelSyncOnAddressWait32 / sceKernelSyncOnAddressWait64](../../../core/libs/prx/libkernel/SyncOnAddress/src/SyncOnAddress.cpp) (libkernel) - libc's `__std_atomic_wait_direct_8/16/32/64` pass a microsecond timeout or null and ignore the result; the by-value comparand, return values and the 2- and 8-byte alignment of Wait16 and Wait64 are assumed - [scePthreadRwlockDestroy, pthread_rwlock_destroy](../../../core/libs/prx/libkernel/Pthread/src/Rwlock.cpp) (libkernel) - measured on a PS5 (firmware 13.60): destroying a rwlock returns 0 whether it is free or held for reading or writing, and leaves 1 in the handle; every call on that handle then returns `EINVAL` until it is initialized again, and a zero handle is initialized on first use by the `scePthreadRwlock` calls as by the POSIX ones. A rwlock destroyed while held is not freed, so its memory leaks. Destroying a rwlock while another thread is acquiring it is not guarded +- [scePthreadMutexTimedlock](../../../core/libs/prx/libkernel/Pthread/src/Mutex.cpp), [scePthreadRwlockTimedrdlock, scePthreadRwlockTimedwrlock](../../../core/libs/prx/libkernel/Pthread/src/Rwlock.cpp) (libkernel) - a timed lock of a mutex the caller holds, or of a rwlock it holds for writing, sleeps until its timeout before returning `ETIMEDOUT` (`0x8002003c`), as FreeBSD 11.4 libthr does ([mutex](https://github.com/freebsd/freebsd-src/blob/8c639945a44588f6cfdddfb057bb5aad88735da0/lib/libthr/thread/thr_mutex.c#L878-L928)); whether the console waits is not measured. The prosper oracle measured only the result, for a default mutex and a rwlock with a 1000 us timeout ([kernelx.golden.tsv](https://github.com/mattias800/prosper/blob/3ea5cb9a846b6dcd00f5073360462bbda4f72288/prosper/tests/data/console_oracle/kernelx.golden.tsv#L16-L47)); the other mutex types and the POSIX timed locks follow the same rule unmeasured. - [scePthreadCondWait / scePthreadCondTimedwait](../../../core/libs/prx/libkernel/Pthread/src/Cond.cpp) (libkernel) - before waiting, FreeBSD libthr's [`cond_wait_common`](https://github.com/freebsd/freebsd-src/blob/main/lib/libthr/thread/thr_cond.c#L1992-L2029) checks ownership through [`_mutex_owned`](https://github.com/freebsd/freebsd-src/blob/main/lib/libthr/thread/thr_mutex.c#L1166-L1178): an unowned mutex returns `EPERM`, while its destroyed marker returns `EINVAL`. An untouched adaptive static initializer (slot value 1) therefore returns `EPERM`; the test covers this, an uninitialized slot, a mutex owned by another thread, and the destroyed marker for both timed and untimed sce and POSIX waits. A recursive mutex locked several times is released completely for the wait and relocked to the same depth afterwards, as FreeBSD libthr does (`_mutex_cv_unlock`, `_mutex_cv_lock`). These FreeBSD-derived behaviors remain unverified on console hardware. Cancellation follows the [POSIX condition wait contract](https://pubs.opengroup.org/onlinepubs/9799919799/functions/pthread_cond_clockwait.html): the original mutex and recursive depth are restored before cleanup, and a canceled waiter forwards a wake to the remaining waiters. The host condition state is retained across mutex reacquisition so the guest can destroy and free its condition after notification; cancellation ordering and signal replacement are not measured on a console - [sceKernelOpenEventFlag](../../../core/libs/prx/libkernel/EventFlag/src/EventFlag.cpp) (libkernel) - opens only flags this process created with attribute 0x100. On the console, other processes' 0x100 flags, such as the shell's `SceShellCoreUtilAppFocus`, can be opened too. They do not exist here, so opening them returns `SCE_KERNEL_ERROR_ESRCH`. A null output with the name of an openable flag returns `SCE_KERNEL_ERROR_EFAULT`, the host's answer to the console's fault there, not a measured code. With a plain flag's name it returns `SCE_KERNEL_ERROR_ESRCH`, as measured; with a missing name it also returns `SCE_KERNEL_ERROR_ESRCH`, which was not measured. - [sceKernelCreateEventFlag](../../../core/libs/prx/libkernel/EventFlag/src/EventFlag.cpp) (libkernel) - when a call has both an invalid attribute and a name of 32 bytes or more, `SCE_KERNEL_ERROR_EINVAL` is returned, because the attribute checks run before the name length check. The console was only measured with long names and valid attributes (0x20 and 0x120), so which error it returns first is not known. Event flag handles are host addresses here, while the console returns small IDs. @@ -77,16 +78,18 @@ - [sceKernelGetAvailableCpumask](../../../core/libs/prx/libkernel/Pthread/src/Thread.cpp) (libkernel) - returns the default thread affinity, 0x1FFF (CPUs 0 to 12), as KytyPS5 does. Titles pin threads within it (PPSA02664 passes 0x1FFB, Hades II PPSA36082 0x3 and 0x3F); whether CPU 13 is available to a title is not confirmed - [sceKernelGetCurrentCpu](../../../core/libs/prx/libkernel/System/src/Process.cpp) (libkernel) - guest affinities are not applied to host threads, so the host CPU index is mapped into the calling thread's affinity clipped to `sceKernelGetAvailableCpumask` (the available mask when they do not overlap): host CPU n reports the (n modulo the CPU count)-th CPU of that mask, so a thread pinned to one CPU reports that CPU, as a FreeBSD `cpuset` guarantees on the console. Which CPU the console reports for a thread allowed on several is not known; shadPS4 returns 0 - [pthread_attr_setsolosched_np](../../../core/libs/prx/libkernel/Pthread/Posix/Attr.cpp) (libkernel) takes `(attr, int)` and stores the value through `scePthreadAttrSetsolosched`, returning `EINVAL` (22) for a null or uninitialized attribute like the other POSIX attribute setters. Only the name is public (aerolib `2+pVfgiEd7A`); the signature and behaviour follow the SCE twin, which [KytyPS5](https://github.com/KytyPS5/KytyPS5/blob/947627d10d4ef4b68ba3c0189aab6c368e70a8d2/src/kernel/pthread.cpp#L2188-L2199) and [sharpemu](https://github.com/sharpemu/sharpemu/blob/a2983692930564815a77f81e74c151268f5b935f/src/SharpEmu.Libs/Kernel/KernelPthreadExtendedCompatExports.cs#L891-L913) store as an `int` without a range check, and [PS5PCEM](https://github.com/iStark/PS5PCEM/blob/71de7681f06c5db59a1120a3bb554c86780c3f5f/src/hle/libs/kernel_threading.zig#L1396-L1398) implements this alias over it. On a PS5 (firmware 13.60) only 0 and 16 are accepted; every other value returns `ENOTSUP` (45, `0x8002002D` from the SCE call) and keeps the stored one, and the SCE calls return `EINVAL` for a null or uninitialized attribute. PPSA15878 passes 16. Threads created from the attribute are not scheduled differently; what solo scheduling does on the console is unknown. Returnal (PPSA01285 v03.000.005) stopped on it with `what(): pthread_attr_setsolosched_np_nid_postfix not implemented` (#2872, #1155); LEGO Horizon Adventures (PPSA14632, #734) and Palworld (PPSA23126, #2598) import it +- [pthread_main_np](../../../core/libs/prx/libkernel/Pthread/src/Thread.cpp) (libkernel_sys) - console behaviour is unmeasured. Linux identifies the process initial thread by kernel TID/PID equality, including worker-first loading. Other hosts identify the thread that initialized libkernel; loading it first from a worker can misidentify the initial thread. The pre-initialization -1 state is not exposed. - [sceKernelMapFlexibleMemory / sceKernelMapNamedFlexibleMemoryInternal](../../../core/libs/prx/libkernel/DirectMemory/Export.cpp) (libkernel) - flag 0x8000 is accepted and ignored; its meaning is not established. KytyPS5 (`GUEST_MAP_UNKNOWN_8000`) and sharpemu accept it without reading it. Every known caller is an SDK 9 `libc.prx` heap, which passes it with read/write protection and uses the mapping as an older `libc.prx` uses `sceKernelMapNamedFlexibleMemory` with flags 0: through the Internal variant in PPSA21564, through `sceKernelMapFlexibleMemory` in PPSA22520 01.000.011 - [sceKernelMtypeprotect](../../../core/libs/prx/libkernel/DirectMemory/DirectMemory.cpp) (libkernel) - sets the memory type of the direct mappings in the page-rounded range and of the direct memory behind them, as shadPS4 and prosper do (KytyPS5 ignores the type); the type is not validated, flexible pages in the range only get the protection, and a later map of the retyped direct memory reports the type it was allocated with. `sceKernelBatchMap2` operation 4 takes the same path with the entry type - [Map hints inside a reservation](../../../core/libs/prx/libkernel/DirectMemory/DirectMemory.cpp) (libkernel) - `sceKernelMapDirectMemory` and the flexible and anonymous maps place a mapping without `MAP_FIXED` at its hint address when the whole range lies in a range still reserved by `sceKernelReserveVirtualRange`, as if `MAP_FIXED` were set. Taken from PPSA01474, which reserves 64 GiB and then maps its heaps inside it with hints and no `MAP_FIXED`, and uses the hint addresses afterwards; not measured on the console. Hints outside a reservation, or over a range that is partly mapped, stay hints - [Fixed anonymous mmap](../../../core/libs/prx/libkernel/DirectMemory/PosixMemory.cpp) (libkernel) - `MAP_PRIVATE | MAP_ANON | MAP_FIXED` replaces the requested range through the existing guest mapping machinery and zeroes the new memory. `MAP_EXCL` is checked under the allocation-registry mutation lock, including virtual reservations, and returns `ENOMEM` without changing an occupied range; without `MAP_FIXED` it is `EINVAL`. Lengths are rounded to 16 KiB and fixed addresses must be aligned. The complete rounded range must lie inside the guest arena or, for POSIX fixed anonymous `mmap` on Windows, one current or registered native thread stack; other mapping APIs do not opt into stack replacement. Native stack replacement keeps the reservation, decommits and recommits fresh pages, and rejects foreign allocations, ranges spanning reservations and host `PAGE_GUARD` pages before mutation. Current-stack ranges must end at least 64 KiB below the active host frame; callers replacing another thread's stack must coordinate with that thread. If recommitting fails, the call returns `ENOMEM` with the range still reserved; thread cleanup attempts to recommit it before restoring write access. This follows FreeBSD 11.4 [argument validation and rounding](https://github.com/freebsd/freebsd-src/blob/8c639945a44588f6cfdddfb057bb5aad88735da0/sys/vm/vm_mmap.c#L226-L299), [fixed replacement](https://github.com/freebsd/freebsd-src/blob/8c639945a44588f6cfdddfb057bb5aad88735da0/sys/vm/vm_map.c#L1455-L1464), and [collision errno](https://github.com/freebsd/freebsd-src/blob/8c639945a44588f6cfdddfb057bb5aad88735da0/sys/vm/vm_mmap.c#L1604-L1613). The console behaviour has not been measured. Linux and Windows accept addresses from 64 KiB that no host mapping occupies, such as the 0x400000 imported by PICO-8 PPSA99808; macOS keeps the 0x200000000 start. Non-fixed private anonymous mappings keep their hint; null hints still use the 8 GiB area. On Windows the host's `KUSER_SHARED_DATA` always occupies 0x7ffe0000, so Wine's shared user data page (Forever Launcher PPSA99030) cannot be placed there. The console address-space layout is unmeasured; executable placement outside the host arena is tracked in #5217. Static catalog disassembly finds `0x1012` in PPSA98001/PPSA99808 and `0x5012` in PPSA99808; these titles were not run. - [Mapping hints with no room above them](../../../core/libs/prx/libkernel/DirectMemory/DirectMemory.cpp) (libkernel) - a mapping without `MAP_FIXED` whose hint lies above the guest address space, or has no free range at or above it, is placed from the bottom of the guest arena, as FreeBSD 11.4's [`vm_mmap_object`](https://github.com/freebsd/freebsd-src/blob/8c639945a44588f6cfdddfb057bb5aad88735da0/sys/vm/vm_mmap.c#L1569) retries through [`vm_map_find_min`](https://github.com/freebsd/freebsd-src/blob/8c639945a44588f6cfdddfb057bb5aad88735da0/sys/vm/vm_map.c#L1555-L1584) from its minimum address. FreeBSD's minimum is the end of the largest possible data segment rather than the start of the arena, and the console's address-space layout is not measured. PS5CEMU-HAR (PPSA99360) gives `sceKernelReserveVirtualRange` a hint near its own code, which is a host address here because the relinked executable lies outside the guest arena, so its JIT gets memory more than 2 GiB from its code and does not start - [_sceKernelRtldThreadAtexitIncrement, _sceKernelRtldThreadAtexitDecrement](../../../core/libs/prx/libkernel/System/src/Rtld.cpp) (libkernel) - the argument is the `dso` address a title's `libc.prx` passes to `__cxa_thread_atexit` (PPSA14632), which fails when Increment returns nonzero. As in the [fpPS4](https://github.com/red-prig/fpPS4) reimplementation, Increment takes a reference on the loaded image containing the address and Decrement releases one; the variants without the leading underscore are assumed to match +- [pthread_cleanup_push, pthread_cleanup_pop](../../../core/libs/prx/libkernel/Pthread/src/Thread.cpp) (libkernel, NIDs `4ZeZWcMsAV0`, `RVxb0Ssa5t0`) share the caller-record cleanup list with `__pthread_cleanup_push_imp` and `__pthread_cleanup_pop_imp`, following [FreeBSD 11.4 thr_clean.c](https://github.com/freebsd/freebsd-src/blob/d106002967eff712894ab8b5337bbbff106ce5e0/lib/libthr/thread/thr_clean.c). The firmware body reading reported by [PR8428](https://github.com/boykopovar/AnyPS5/pull/8428) also sets the thread's unwind-disabled flag in the heap form; that flag is not modeled here, and runtime-created guest threads skip guest-frame unwinding in these exit paths. The firmware observation is attributed to that contributor, not independently reproduced. Heap records use C++ `new` here, whereas the FreeBSD reference leaves the cleanup list unchanged if `malloc` fails; console allocation-failure behavior and its interaction with unwinding remain unverified. - [tcgetattr, tcsetattr](../../../core/libs/prx/libkernel/File/src/Terminal.cpp) (libkernel) - every file and pipe descriptor is taken as not a terminal (`ENOTTY`), and a socket gets `EADDRNOTAVAIL` for `AF_INET` and `EOPNOTSUPP` otherwise, as FreeBSD's `in_control` and `pru_control_notsupp` answer a termios ioctl; what descriptors 0 to 2 of a title are on the console, and whether any of them is a terminal there, is unknown - [cfsetspeed](../../../core/libs/prx/libkernel/File/src/Terminal.cpp) (libkernel, NID `C1MQ6OaXRjo`) - console behavior and module/library versions are unverified. The prototype, uint32 speed and 44-byte termios layout (input speed at 36, output speed at 40) follow the public PS5 payload SDK [termios.h](https://github.com/ps5-payload-dev/sdk/blob/a7685ce8e97ce1f8a4f38253a41d54241c9124f1/include/freebsd/termios.h) and [sys/_termios.h](https://github.com/ps5-payload-dev/sdk/blob/a7685ce8e97ce1f8a4f38253a41d54241c9124f1/include/freebsd/sys/_termios.h). The module association follows its libkernel stub table and the NID rehashes to the aerolib name. Both speed fields accept every uint32 value and no flags or control characters change, as [FreeBSD 11.4 termios.c](https://github.com/freebsd/freebsd-src/blob/d106002967eff712894ab8b5337bbbff106ce5e0/lib/libc/gen/termios.c) does. No terminal I/O is performed. Null pointers throw where the reference dereferences them. - [select](../../../core/libs/prx/libkernel/Socket/src/Socket.cpp) (libkernel) - descriptor 0 is never reported readable and descriptors 1 and 2 are always writable, as for a console title with no input; reads from descriptor 0 still go to the host stdin. `/dev/random` and `/dev/urandom` follow `randomdev_poll` for a seeded device under [`selscan`](https://github.com/freebsd/freebsd-src/blob/release/11.4.0/sys/kern/sys_generic.c#L1178-L1236), which asks once with the flags of every set the descriptor is in: in the read set they are readable and reported in no other set, and otherwise they are reported in the write and exception sets they were asked in. A regular file, a directory or a file read from app0.zar is always readable and writable and never in the exception set, as `vop_stdpoll` answers, on every host. Guest sockets and libSceNet sockets are polled. A kqueue is readable while one of its events is triggered and is never writable or in the exception set, as FreeBSD 11.4's [`kqueue_poll`](https://github.com/freebsd/freebsd-src/blob/release/11.4.0/sys/kern/kern_event.c#L1900-L1924) answers, on every host. Other descriptors are polled through the host on Linux, while on Windows pipes are checked every millisecond with the readiness test `poll` uses and any other descriptor throws. Dungeons (PPSA16064) selects on descriptor 0, and RetroArch (PPSA99169) selects on its web server's wake-up pipe next to its listening socket -- [select](../../../core/libs/prx/libkernel/Socket/src/Socket.cpp) (libkernel) - a descriptor the socket poller reports as unknown that is below `GuestSockets::FirstDescriptor` is polled on the host instead of throwing (on Windows only a pipe, as above); an invalid host descriptor fails with `EBADF`, and mixed host and socket sets are polled in short alternating slices so neither side waits out the full slice alone. A descriptor that stops being a socket, a kqueue or a pipe during the wait fails the call with `EBADF` when it is closed and is selected again with the rest of the timeout when its number was reused, as FreeBSD 11.4's [`kern_select`](https://github.com/freebsd/freebsd-src/blob/release/11.4.0/sys/kern/sys_generic.c#L1129-L1140) looks every descriptor up again in each pass. A close that has already removed the descriptor from the guest's kqueue, pipe or file tables but not yet closed its host descriptor is seen by that new look-up as a descriptor of unknown kind, which throws on Windows and is polled through the host on Linux. Wobbly Life (PPSA29413) selects on file descriptors while streaming its bundles +- [select](../../../core/libs/prx/libkernel/Socket/src/Socket.cpp) (libkernel) - a descriptor the socket poller reports as unknown is polled on the host instead of throwing (on Windows only a pipe, as above); an invalid host descriptor fails with `EBADF`, and mixed host and socket sets are polled in short alternating slices so neither side waits out the full slice alone. A descriptor that stops being a socket, a kqueue or a pipe during the wait fails the call with `EBADF` when it is closed and is selected again with the rest of the timeout when its number was reused, as FreeBSD 11.4's [`kern_select`](https://github.com/freebsd/freebsd-src/blob/release/11.4.0/sys/kern/sys_generic.c#L1129-L1140) looks every descriptor up again in each pass. A close that has already removed the descriptor from the guest's kqueue, pipe or file tables but not yet closed its host descriptor is seen by that new look-up as a descriptor of unknown kind, which throws on Windows and is polled through the host on Linux. Wobbly Life (PPSA29413) selects on file descriptors while streaming its bundles - [__progname](../../../core/libs/prx/libkernel/System/src/Process.cpp) (libkernel) - unknown data export - [environ](../../../core/libs/prx/libkernel/System/src/Process.cpp) (libkernel) - data export pointing to a fixed empty environment so titles that import it load; it is not the environment libc's `getenv` reads, so it lists none of those variables and `setenv`/`putenv` changes do not appear in it - [seteuid, setegid, setuid, setgid, setreuid, setregid, setresuid, setresgid, setgroups, getgroups](../../../core/libs/prx/libkernel/System/src/Process.cpp) (libkernel) - the guest process is assumed to run as root, with real, effective and saved user and group ids 0. As in FreeBSD's `sys_seteuid`, `sys_setegid`, `sys_setuid`, `sys_setgid`, `sys_setreuid`, `sys_setregid`, `sys_setresuid` and `sys_setresgid`, id 0 (or -1 for an unchanged `setreuid`/`setregid`/`setresuid`/`setresgid` id) is then accepted without a privilege check and changes no credential, so 0 is returned; any other id would change an id, which is not modelled, and throws. `setgroups` keeps the supplementary group list as `kern_setgroups` does (`NGROUPS_MAX` 1023, an empty list leaves the effective group as the only entry, a first entry other than 0 would change the effective group and throws) and `getgroups` reports it. The ids and privileges a title has on a console are unverified @@ -117,8 +120,7 @@ - [qk043QPsrZU](../../../core/libs/prx/libkernel/Unimplemented.cpp) (libkernel) - unknown name, signature - [uDGXwUKqi8s](../../../core/libs/prx/libkernel/Unimplemented.cpp) (libkernel) - unknown name, signature - [sceKernelGetCpuTemperature, sceKernelGetSocSensorTemperature](../../../core/libs/prx/libkernel/System/src/ThermalSensors.cpp) (libkernel) - read the host's thermal sensors: on Linux from `/sys/class/hwmon` and `/sys/class/thermal`, on Windows from the ACPI thermal zones (`MSAcpi_ThermalZoneTemperature` over WMI) and the storage temperature property of the first physical drive. Sensor 0 is the CPU/package value, 1 the first other value and 2 an NVMe value; a host that exposes none reports every sensor as unsupported (`EINVAL`). The console's SoC channel count and meanings are hardware-dependent and differ from the host's, the host sensors are not the console's, the ACPI reading is unavailable on many machines, and the storage temperature property is numbered 52 on Windows 10 2004 and later and 22 before it, so the mapping, the values and the unsupported-input error are unverified; the storage channel was checked against the drive's own SMART composite temperature on one NVMe host (`StorageDeviceTemperatureProperty`, 36 °C on a WD_BLACK SN7100). `sceKernelGetCpuTemperature` reports sensor 0. PPSA99058 and PPSA99420 call both -- [LinuxProtFromSce](../../../core/libs/prx/libkernel/DirectMemory/DirectMemory.cpp) (libkernel) - protection bits 0x100 and 0x200 are accepted and assumed not to affect host CPU access; host protection is derived only from the read, write and execute bits -- [getdtablesize](../../../core/libs/prx/libkernel/System/src/Process.cpp) (libkernel) - returns the smaller of the `RLIMIT_NOFILE` soft limit of `getrlimit` and the host's `getdtablesize()`, capped at `INT_MAX`: FreeBSD returns the smaller of the `RLIMIT_NOFILE` soft limit and `maxfilesperproc` ([`sys_getdtablesize`](https://github.com/freebsd/freebsd-src/blob/8c639945a44588f6cfdddfb057bb5aad88735da0/sys/kern/kern_descrip.c#L338-L355)), and the host call supplies that bound on macOS, where the soft limit alone is not one (`setrlimit` accepts soft limits above `maxfilesperproc`, `RLIM_INFINITY` included); `maxfilesperproc` is not measured on the console. The guest limit is the host's soft limit, raised to the hard limit when libkernel loads only on Linux: `core/libs/prx/libkernel/File/src/OpenFileLimit.cpp` is `__linux__`-only, so on macOS the guest gets whatever soft limit the host process inherited. VLC (PPSA85300) imports it for a `closefrom` loop in the child of its spawn helper ([libc_stubs.c](https://github.com/ZiZc3/VLC/blob/d46be6a68f4244466b041c2dc1b640915ac1a983/ps5/compat/libc_stubs.c#L66-L72)), which never runs because its `fork` fails with `ENOSYS` +- [getdtablesize](../../../core/libs/prx/libkernel/System/src/Process.cpp) (libkernel) - returns the smaller of the `RLIMIT_NOFILE` soft limit of `getrlimit` and the host's `getdtablesize()`, capped at `INT_MAX`: FreeBSD returns the smaller of the `RLIMIT_NOFILE` soft limit and `maxfilesperproc` ([`sys_getdtablesize`](https://github.com/freebsd/freebsd-src/blob/8c639945a44588f6cfdddfb057bb5aad88735da0/sys/kern/kern_descrip.c#L338-L355)), and the host call supplies that bound on macOS, where the soft limit alone is not one (`setrlimit` accepts soft limits above `maxfilesperproc`, `RLIM_INFINITY` included); `maxfilesperproc` is not measured on the console. On Linux and macOS the guest limit is the host's soft limit. VLC (PPSA85300) imports it for a `closefrom` loop in the child of its spawn helper ([libc_stubs.c](https://github.com/ZiZc3/VLC/blob/d46be6a68f4244466b041c2dc1b640915ac1a983/ps5/compat/libc_stubs.c#L66-L72)), which never runs because its `fork` fails with `ENOSYS` - [close, sceKernelClose](../../../core/libs/prx/libkernel/File/src/HostStreams.cpp) (libkernel) - descriptors 0 to 2 that are open when libkernel loads belong to the host process: closing one fails with `EPERM` (`sceKernelClose`: `0x80020001`) and leaves it open, as closing the open descriptors 0 to 2 of a payload process did on a PS5 (firmware 13.60); whether a title process can close them is unverified. PPSA21703 calls `sceKernelClose(0)` repeatedly; closing the host stream let the host C runtime give descriptor 0 to the next file opened, which the next call then closed - [sceKernelPrintBacktraceWithModuleInfo](../../../core/libs/prx/libkernel/Unimplemented.cpp) (libkernel) - imported by PS4 titles, which do not load without it, and added without an implementation: declared without parameters, every call throws @@ -127,6 +129,7 @@ ### Functional - [scePthreadYield](../../../core/libs/prx/libkernel/Pthread/src/Thread.cpp) (libkernel) on Windows calls Sleep(1) after 512 consecutive yields that find no other thread ready on the current processor and arrive less than ~10,000 TSC ticks apart (so the span varies with host CPU TSC rate); FreeBSD sched_yield never sleeps. +- [__tls_get_addr](../../../core/libs/prx/libkernel/Module/src/Tls.cpp) (libkernel, NID `vNe1w4diLCs`) throws on macOS, where the relinker binds guest modules to `Aps5GuestTlsGetAddr_nid_no_patch`, which no library defines yet; it also throws for a null index, module 0 and a Windows thread without a block for the module. It reads the module word as the relinker writes it for `R_X86_64_DTPMOD64`: on Windows the address of the module's PE `_tls_index`, resolved through the thread's `ThreadLocalStoragePointer` as in [WindowsGuestStartup.cpp](../../../core/relinker/elfpatcher/src/windows/WindowsGuestStartup.cpp); on Linux the glibc module ID, passed to glibc's `__tls_get_addr`. Guest modules' imports are bound to the host resolver, so this export is reached only through a lookup by NID. - [Guest thread scheduling](../../../core/libs/prx/libkernel/Pthread/src/Thread.cpp) (libkernel) - the policies and priorities that `sched_get_priority_max`, `sched_get_priority_min`, `pthread_setschedparam` and `scePthreadSetschedparam` accept, and those a created thread takes, follow a PS5 (firmware 13.60), but they are only recorded and reported: they are not applied to host threads, so a title's priority order has no effect on host scheduling - [Linux runtime module initialization](../../../core/libs/prx/libkernel/Module/src/DynamicLoader.cpp) (libkernel) - modules in explicit runtime directories can be mapped for bindings before an explicit guest load runs their entry and init array once with the caller arguments. Finalizers run only after initialization completed. Console dependency-start and finalization ordering are unmeasured. Windows and macOS use their existing lifecycle paths. @@ -149,7 +152,7 @@ - On Linux, [direct memory](../../../core/libs/prx/libkernel/DirectMemory/DirectMemory.cpp) lives in one sparse memfd at file offset = physical address, so the [GPU imports](../../../core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp) can share one udmabuf buffer object per 64 MiB of it. Released direct memory is not punched out of the file, because a live import of its chunk pins the pages and the GPU would keep reading the old ones: its pages stay committed (the process keeps the high-water mark of the direct memory it used) and are zeroed when the range is allocated again. - [system](../../../core/libs/prx/libkernel/System/src/Process.cpp) (libkernel) runs no command. It follows FreeBSD 11's `lib/libc/stdlib/system.c` for a sandbox without `/bin/sh`: a null command returns 1 unconditionally, as that version does, and any command returns the wait status of a child that could not exec the shell and called `_exit(127)` (`0x7f00`). Whether the console's application sandbox has no shell, and whether `vfork` succeeds there (FreeBSD returns -1 when it fails), is unverified - [sceKernelWriteThrottlingStatus](../../../core/libs/prx/libkernel/File/src/Stdio.cpp) (libkernel) reports no write throttling: the host SSD has no write budget, so the first qword of the 32-byte status is set to `UINT32_MAX` and the rest is zeroed; returns `EFAULT` (`0x8002000e`) when passed a null status buffer pointer. PPSA17221 reads only that qword: it multiplies it by 64 KiB and compares the product with byte thresholds up to 0x4AF00000 to pick one of five tiers. When the call fails the title assumes 0x4B000001 bytes, which selects the same top tier as `UINT32_MAX`. What the value measures on hardware (a remaining budget or a rate) and the meaning of the other three qwords are unknown -- [Windows directory descriptors](../../../core/libs/prx/libkernel/File/src/DirectoryDescriptor.cpp) (libkernel) take one snapshot of the directory, on the first `getdents`, `getdirentries` or non-zero `lseek` (`SEEK_SET` or `SEEK_CUR`), and keep it until it is discarded; `lseek` to offset 0 only discards the snapshot, and the next read lists the directory again, so every rewind costs O(entries) on the next read. `lseek` takes the offset as an entry index and `SEEK_CUR` with offset 0 only reports the index. `SEEK_END` throws because FreeBSD defines it relative to the directory size, which is not modelled. A negative result returns `EINVAL` and a `SEEK_CUR` offset that overflows returns `EOVERFLOW`, as FreeBSD `vn_seek` reports them. Names whose UTF-8 encoding exceeds the one-byte `d_namlen` limit are not representable in this guest directory-record layout: `getdents` returns `ENAMETOOLONG` without consuming the entry. Repeated calls therefore report the same error and entries after that name cannot be reached through this descriptor; FreeBSD's `getdents` behavior for host filenames that exceed its `MAXNAMLEN` is not verified. `getdirentries` still reports 0 through `basep` instead of the position of the block it read, so only 0 and values returned by `lseek` are valid offsets; FreeBSD offsets are filesystem cookies. Descriptors retain the opened directory's native handle across renames. Enumeration reloads and `*at` operations resolve its current path, so a concurrent rename between resolution and the operation is not atomic. Enumeration of a removed directory and network-share path queries have not been verified +- [Windows directory descriptors](../../../core/libs/prx/libkernel/File/src/DirectoryDescriptor.cpp) (libkernel) take one snapshot of the directory, on the first `getdents`, `getdirentries` or non-zero `lseek` (`SEEK_SET` or `SEEK_CUR`), and keep it until it is discarded; `lseek` to offset 0 only discards the snapshot, and the next read lists the directory again, so every rewind costs O(entries) on the next read. `lseek` takes the offset as an entry index and `SEEK_CUR` with offset 0 only reports the index. `SEEK_END` throws because FreeBSD defines it relative to the directory size, which is not modelled. A negative result returns `EINVAL` and a `SEEK_CUR` offset that overflows returns `EOVERFLOW`, as FreeBSD `vn_seek` reports them. Names whose UTF-8 encoding exceeds the one-byte `d_namlen` limit are not representable in this guest directory-record layout, so `getdents` and `getdirentries` throw when they reach one; FreeBSD's behavior for host filenames that exceed its `MAXNAMLEN` is not verified. `getdirentries` reports through `basep` the entry index its block starts at, so only 0 and the values from `basep` or `lseek` are valid offsets; FreeBSD offsets are filesystem cookies. Descriptors retain the opened directory's native handle across renames. Enumeration reloads and `*at` operations resolve its current path, so a concurrent rename between resolution and the operation is not atomic. Enumeration of a removed directory and network-share path queries have not been verified - [Linux directory entry types](../../../core/libs/prx/libkernel/File/src/Stdio.cpp) (libkernel) - `sceKernelGetdirentries` reports a host symlink inside the app0 tree as the type of its target (directory or regular file), since a console app0 has no links and links there come from how the title was unpacked; a link elsewhere, or a dangling one, stays a link. A directory opened through an app0 link resolves to its target's host path, so links nested inside that target keep the link type. - [ftruncate, truncate, sceKernelFtruncate](../../../core/libs/prx/libkernel/File/src/Stdio.cpp) (libkernel) extend a file on Windows with `SetFileInformationByHandle` (`FileEndOfFileInfo`), which reserves the clusters but writes no zero bytes, and report `EFBIG` for a length the volume cannot hold (`ERROR_INVALID_PARAMETER` on a disk file; seen with a length of `INT64_MAX`, the size from which NTFS refuses it was not measured) and `ENOSPC` when the free space is smaller. FreeBSD 11.4 makes the extension a hole on a file system that has them ([`ffs_truncate`](https://github.com/freebsd/freebsd-src/blob/release/11.4.0/sys/ufs/ffs/ffs_inode.c) writes only the last block), so a length above the free space succeeds there. A write behind the end of the file still makes NTFS write zero bytes over the gap, as the file is not sparse. None of this was measured on a console. - [readv, writev, preadv, pwritev and their sceKernel forms](../../../core/libs/prx/libkernel/File/src/Stdio.cpp) (libkernel) - unreadable iovec-table errors follow FreeBSD 11.4's [`copyinuio`](https://github.com/freebsd/freebsd-src/blob/release/11.4.0/sys/kern/subr_uio.c#L401-L434), not console measurements. The table is copied before inspecting its entries; payload-buffer validation is unchanged. A Linux `process_vm_readv` failure other than `EFAULT` throws, including when the host denies that API. @@ -160,7 +163,7 @@ - [sceKernelAddReadEvent and sceKernelAddWriteEvent](../../../core/libs/prx/libkernel/Equeue/Equeue.cpp) (libkernel): a read event on a listening socket, here and in `kevent`, reports the number of completed connections waiting to be accepted in `data`, as FreeBSD 11.4's [`filt_solisten`](https://github.com/freebsd/freebsd-src/blob/release/11.4.0/sys/kern/uipc_socket.c#L3384-L3392) reports `so_qlen`: on Linux a TCP listener's accept queue from `TCP_INFO` (`tcpi_unacked`, which Linux fills with the accept backlog for a listening socket), and elsewhere, or for a listener that is not TCP, 1 while a connection is waiting, as no host call reports that count. A write event reports the free space of the socket's send buffer in `data`, as FreeBSD 11.4's [`filt_sowrite`](https://github.com/freebsd/freebsd-src/blob/release/11.4.0/sys/kern/uipc_socket.c#L3358-L3382) reports `sbspace`: on Linux the host's `SO_SNDBUF` less the bytes `SIOCOUTQ` counts as queued, which include the host's per-packet overhead, so the space shrinks by somewhat more than the bytes sent. Windows has no query for that space and macOS is not wired up, so both report the whole `SO_SNDBUF`, which does not shrink as data is queued. Only guest sockets are supported; other descriptors and a low watermark above 1 throw - [sceKernelAddReadEvent on pipes](../../../core/libs/prx/libkernel/Equeue/Equeue.cpp) (libkernel) is an exception to the sockets-only rule above: it also takes the read end of a pipe, as `kevent` does through FreeBSD's `filt_piperead`, and ignores the size argument there. Host streams, other descriptors and a write event on a pipe throw - [sceKernelAddReadEvent and sceKernelAddWriteEvent on regular files](../../../core/libs/prx/libkernel/Equeue/Equeue.cpp) (libkernel) are the other exception: a size argument above 1, directories and other vnode types throw, and whether the console's file systems answer as `vfs_kqfilter` does was not measured. A wait holding one of these events polls it every millisecond, as no host call reports every file change, so a write through another descriptor shows up to 1 ms late. Unlike FreeBSD, a seek can make a read event fire again: FreeBSD 11.4's [`kqueue_scan`](https://github.com/freebsd/freebsd-src/blob/release/11.4.0/sys/kern/kern_event.c) deactivates a level-triggered read knote once `filt_vfsread` reports `data` 0, and only a vnode `KNOTE` (a write, an extend or a truncate) activates it again; `lseek` posts none, so after a file read to its end is seeked back, the 1 ms poll here reports the new `data` (10 for a 10-byte file seeked to 0) where FreeBSD keeps waiting until the file changes. Otherwise they follow FreeBSD 11.4's [`filt_vfsread` and `filt_vfswrite`](https://github.com/freebsd/freebsd-src/blob/release/11.4.0/sys/kern/vfs_subr.c#L5122-L5168): a read event reports the size less the descriptor's offset in `data` and fires while that is not 0; a write event always fires with `data` 0 -- [close](../../../core/libs/prx/libkernel/File/src/Stdio.cpp) and [setsockopt](../../../core/libs/prx/libkernel/Socket/src/Udp.cpp) (libkernel) reach a [libSceNet](../../../core/libs/prx/libSceNet/Export.cpp) socket through hooks libSceNet registers, as `select` polls them; the other libkernel socket calls do not. libSceNet numbers its sockets from 32 in its own table, so a CRT file descriptor and a socket can share a number; `close` then closes the socket. On the console both are one kernel descriptor space +- [close](../../../core/libs/prx/libkernel/File/src/Stdio.cpp) and [setsockopt](../../../core/libs/prx/libkernel/Socket/src/Udp.cpp) (libkernel) reach a [libSceNet](../../../core/libs/prx/libSceNet/Export.cpp) socket through hooks libSceNet registers, as `select` and `poll` poll them and `fcntl` answers `F_GETFL` and `F_SETFL`, failing other commands with `EINVAL`; the other libkernel socket calls do not. libSceNet numbers its sockets from 32 in its own table, so a CRT file descriptor and a socket can share a number; `close` then closes the socket. On the console both are one kernel descriptor space - [sceKernelPread, sceKernelPwrite, sceKernelPreadv, sceKernelPwritev](../../../core/libs/prx/libkernel/File/src/Stdio.cpp) (libkernel) on Windows transfer with an overlapped `ReadFile`/`WriteFile` and restore the descriptor's file pointer afterwards. Guest scalar transfers, positioned transfers, vectored transfers and seeks share a position lock across duplicated descriptors; a vector holds it for the whole operation. Independently opened descriptors and other processes do not share that lock, so vector transfers over their overlapping file ranges are not coordinated. Handles that are not disk files return `ESPIPE`. A pipe or console `readv` can return a short read when no more input is available; each iovec is transferred separately, so a failure after the first transfer returns the bytes already done - [sceKernelAioSubmitReadCommands, sceKernelAioSubmitWriteCommands and their Multiple variants](../../../core/libs/prx/libkernel/Aio/src/Aio.cpp) (libkernel) on Windows transfer through the same positioned path as `sceKernelPread`/`sceKernelPwrite` and restore the descriptor's file pointer afterwards; positioned transfers, plain transfers and seeks of one descriptor are serialized per descriptor (shared across duplicated descriptors), so a concurrent transfer observes a stable file pointer - [sceKernelAioSetParam](../../../core/libs/prx/libkernel/Aio/src/Aio.cpp) (libkernel) - the limits and `sceKernelAioInitializeParam`'s defaults (three 20-byte scheduling structs, the last without split) are measured on a PS5 (firmware 13.60), where a null struct crashes both calls; here both throw. The scheduling settings are not used: `sceKernelAioInitializeImpl` ignores the struct and requests run synchronously on submit @@ -178,7 +181,7 @@ - [sceKernelRaiseException](../../../core/libs/prx/libkernel/System/src/Exception.cpp) on Windows suspends the target and redirects it to the handler. A target running host code (any module other than the executable and the `*.guest.prx` modules, so libkernel, libc and the other HLE modules count too) is resumed and sampled again until it is back in guest code, since a handler that waits there would keep the host locks that code holds. The raising thread spins for 20 µs before each new host-code sample: suspended again at once, the target could stay at the same instruction for every sample until the 50 ms below ran out (on a 16-core Ryzen 9 5950X, `guest_raise_in_host_code` then raised into `fwrite` and deadlocked on its stream lock), and the 20 µs is a measured choice, not a console value; a target blocked in an ntdll wait is redirected in place, as are NtContinue and winpthreads after their retry limit. A target that stays in host code without waiting for 50 ms after the raise began, such as a long HLE or driver call, is then redirected in host code anyway, with the same hazard. A target seen right after a `syscall` instruction in ntdll, inside a system call that is not a wait such as the `NtWriteFile` of an `fwrite` holding its stream lock, restarts those 50 ms, so a raise can cost the raising thread up to the 1 s retry limit. While the target is suspended only `VirtualQuery` and a lock-free cache of image bases are consulted; an image not yet in the cache is classified with `GetModuleFileNameW` after the target is resumed. An APC queued at the first host-code sample, which an alertable guest wait would run sooner, is not implemented - [sceKernelRaiseException](../../../core/libs/prx/libkernel/System/src/Exception.cpp) builds the handler's `ucontext` with FreeBSD's amd64 layout (16-byte sigmask, `mcontext` at 0x40, `mc_rsp` at 0xf8); the console's layout is not verified beyond the fields PS5Util reads - [sceKernelRaiseException](../../../core/libs/prx/libkernel/System/src/Exception.cpp) does not consult the target thread's signal mask -- [pthread_sigmask](../../../core/libs/prx/libkernel/System/src/Signals.cpp) (libkernel) shares the process-wide mask of `sigprocmask` and `_sigprocmask`, which keeps only the first 32 signals; FreeBSD keeps a mask per thread +- [pthread_sigmask](../../../core/libs/prx/libkernel/System/src/Signals.cpp) (libkernel) shares the process-wide mask of `sigprocmask` and `_sigprocmask`; FreeBSD keeps a mask per thread - [sceKernelRaiseException](../../../core/libs/prx/libkernel/System/src/Exception.cpp) reaches a thread that waits in an alertable `TimedWait` wait through an APC. A thread blocked anywhere else, including all waits under `APS5_COARSE_TIMED_WAITS` and host waits inside the emulator, is redirected and runs the handler only when that wait returns - [sceKernelRaiseException](../../../core/libs/prx/libkernel/System/src/Exception.cpp) on Windows runs the handler wherever the target thread was interrupted. It waits only while the thread is inside winpthreads or restoring a context through `NtContinue`, and throws if that lasts 1 s, so a handler that calls into other host code the thread was interrupted in, such as the C runtime's heap or a lock of the emulator, can deadlock on it or reenter it. A thread that holds the address-wait lock of `sceKernelSyncOnAddressWait`, `sceKernelSyncOnAddressWake` and `_umtx_op`, or the park queue lock of the guest mutexes, gets the raise as an APC instead, which runs once it has released the lock or while it waits; the other locks of the emulator are not deferred this way - [sigaltstack](../../../core/libs/prx/libkernel/System/src/Signals.cpp) (libkernel) records each thread's alternate signal stack and reports it back, following FreeBSD's `kern_sigaltstack` (`EINVAL` for flags other than `SS_DISABLE`, `ENOMEM` below `MINSIGSTKSZ` 2048), but handlers never run on it, so `SS_ONSTACK` and `EPERM` are never reported @@ -205,10 +208,11 @@ - [sceKernelGetSystemExVersion, sysKernelGetLowerLimitSysexVersion, sysKernelGetLowerLimitUpdVersion](../../../core/libs/prx/libkernel/System/src/SystemConfiguration.cpp) (libkernel) and [sceKernelGetTraceMemoryStats](../../../core/libs/prx/libkernel/DirectMemory/Export.cpp) (libkernel) - follow libkernel.sprx, libkernel_sys.sprx and libkernel_web.sprx of firmware 13.42, read from disassembly and not measured on a console. None of them asks the kernel: the first writes an empty string to both outputs and returns a plain 22, not `SCE_KERNEL_ERROR_EINVAL`, when either is null; the lower limits write an empty string and a 32-bit 0; the trace memory statistics write 0 to each output that is not null. The meaning of the outputs is not known - [machdep.tsc_freq](../../../core/libs/prx/libkernel/System/src/SystemConfiguration.cpp) (libkernel) reports the host TSC frequency that `sceKernelGetTscFrequency` measures, as a 64-bit value like FreeBSD 11's [`sysctl_machdep_tsc_freq`](https://github.com/freebsd/freebsd-src/blob/release/11.0.0/sys/x86/x86/tsc.c#L658-L676). FreeBSD lets root write it to change the TSC timecounter's frequency; a write here returns -1 with `EPERM`. PPSA99203 reads it at start-up and measures the TSC itself when the value is 100 MHz or less - [getrlimit](../../../core/libs/prx/libkernel/System/src/Process.cpp) (libkernel) - `RLIMIT_CPU`, `RLIMIT_FSIZE`, `RLIMIT_CORE`, `RLIMIT_SBSIZE`, `RLIMIT_VMEM`/`AS`, `RLIMIT_NPTS`, `RLIMIT_SWAP`, `RLIMIT_KQUEUES` and `RLIMIT_UMTXP` report infinity as in FreeBSD's process-0 defaults, and `RLIMIT_DATA` mirrors the host limit; a payload process on a PS5 (firmware 12.70) reads 0x800000000 for both limits. `RLIMIT_NOFILE` reports, as both soft and hard limit, the number of descriptors after which AnyPS5 itself fails with `EMFILE`: on Windows the C runtime's 8192 low-level descriptors, which guest files, pipes and sockets all take, and as many stdio streams, which libkernel raises from 512 at load with [`_setmaxstdio`](https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/setmaxstdio), on Linux the host's `RLIMIT_NOFILE`, whose soft limit libkernel raises to the hard limit at load, and on macOS the smaller of the host's hard limit and `kern.maxfilesperproc`, which libkernel sets as both limits at load, since macOS fails with `EMFILE` at `kern.maxfilesperproc` whatever the soft limit. A payload process on a PS5 (firmware 12.70) reads 13952 for both limits, while `getdtablesize` returns 12555 and the process can open descriptors up to 12554. XPSemu (PPSA97358) reads `RLIMIT_NOFILE` in QEMU's `os_setup_limits` and raises the soft limit to the hard one when they differ. `RLIMIT_STACK` (0x200000), `RLIMIT_RSS` and `RLIMIT_MEMLOCK` (infinity) and `RLIMIT_NPROC` (1604) report the soft and hard limits a payload process reads on a PS5 (firmware 12.70). Guest locking still follows the host: `mlock` and `sceKernelMlock` fail at the host's hard `RLIMIT_MEMLOCK` on Linux, and on Windows when the process working set cannot grow, although `RLIMIT_MEMLOCK` reports infinity. There the main thread's stack is 0x200000 as well (`pthread_attr_get_np`); here the main thread runs on the host thread's stack, whose size can differ. Whether a title process reads the same limits is unverified. +- [EVFILT_TIMER modify with data 0](../../../core/libs/prx/libkernel/Equeue/src/Kqueue.cpp) (libkernel) - a timer change with `EV_ADD`, `data` and `fflags` unset keeps the note's period instead of taking FreeBSD's zero default, which would fire without delay; whether the console keeps or zeroes the period is unverified. `EV_ENABLE` on a disabled timer reports the expiries it missed while disabled, as FreeBSD 11's `filt_timerexpire` counts a disabled note and keeps its phase: the missed count is summed in one step at the first wait and the next expiry keeps the note's phase, which `TimerDisableEnableRearm` pins; not measured on a console. A change that sets `EV_ADD`, `data` or `fflags` still throws, waiting for the measured re-add rules: FreeBSD 11's `kqueue_register` copies `data` and `fflags` onto the note and the new period applies at the next expiry. - [setrlimit](../../../core/libs/prx/libkernel/System/src/Process.cpp) (libkernel) validates the resource and input in FreeBSD order, maps negative limits to infinity, and lowers a soft limit above the hard limit. A request other than `RLIMIT_NPROC` succeeds when its normalized values match `getrlimit`, or, for `RLIMIT_NOFILE`, when `rlim_max` does not exceed the current hard limit and `rlim_cur` does not exceed `rlim_max`, storing the updated limits for subsequent `getrlimit` queries; descriptor allocation enforcement of the lowered soft limit is not implemented, and changing other limits throws because guest limit state is not stored. In a payload process on a PS5 (firmware 12.70), `setrlimit(RLIMIT_NOFILE)` lowers a requested 13952 to 12555, as the hard and as the soft limit; here a request within the current hard limit is stored as given and one above it throws; setting `RLIMIT_STACK`, `RLIMIT_RSS` and `RLIMIT_MEMLOCK` to their current values succeeds and changes nothing, as here; setting `RLIMIT_NPROC` to its current 1604 also succeeds but leaves 1443. `RLIMIT_NPROC` follows FreeBSD 11 by clamping both values to 1 through `maxprocperuid`, stores the result and returns it from `getrlimit`. The initial 1604 and `maxprocperuid` 1443 follow that measurement: process 0's limit starts at `maxproc` ([`init_main.c`](https://github.com/freebsd/freebsd-src/blob/release/11.0.0/sys/kern/init_main.c#L550-L551)), `maxprocperuid` starts at nine tenths of it ([`subr_param.c`](https://github.com/freebsd/freebsd-src/blob/release/11.0.0/sys/kern/subr_param.c#L258)), and `setrlimit` applies that bound ([`kern_resource.c`](https://github.com/freebsd/freebsd-src/blob/release/11.0.0/sys/kern/kern_resource.c#L714-L718)). `kern.maxproc` fails with `ENOENT` in the payload process, so the values cannot be queried independently, and process creation does not enforce the stored limit. Java 25 LAN / DNS (PPSA99869) sets `rlim_cur = MIN(0x100000, rlim_max)` during VM initialization - [execvp](../../../core/libs/prx/libkernel/System/src/Process.cpp) (libkernel) throws: replacing the process image is not supported. PPSA85300 imports it and fails to load without it; its `fork` and `vfork` fail with `ENOSYS` ([libc_missing.c](https://github.com/ZiZc3/VLC/blob/f3253020a64368153233ede29183014c0b6c8979/ps5/compat/libc_missing.c#L290-L292)), so the child process that would call it is never created. - [nmount](../../../core/libs/prx/libkernel/File/src/Stdio.cpp) (libkernel) throws: mounting file systems is not supported. Prospero Themes (PPSA90210) imports it and fails to load without it; it opens its theme library without calling it, and its strings (`/dev/ssd0.system_ex`, `/system_ex`, `exfatfs`, `fstype`, `fspath`, `from`, `ignoreacl`) point to remounting the console's `/system_ex` partition to write theme files there. -- [socketpair](../../../core/libs/prx/libkernel/Socket/src/Udp.cpp) (libkernel) - the pair is the host's `AF_UNIX` pair on Linux and macOS and, on Windows, a loopback TCP connection for `SOCK_STREAM` or two connected UDP sockets for `SOCK_DGRAM`; `SOCK_SEQPACKET` throws on Windows and macOS, which has no such `AF_UNIX` pair. A datagram sent to a full receiver gets `ENOBUFS` on the console, waits or gets `EAGAIN` on Linux and is dropped on Windows, and on Windows a datagram `recv` after the peer closed reports `ECONNRESET` instead of the console's `ENOTCONN`, and the first stream `send` after the peer closed succeeds on the loopback connection, where the console returns `EPIPE`; the sends after it report `EPIPE`. `read` and `write` on a pair end go to the host like on every guest socket. `getpeername` on a pair end succeeds after the peer closed, where the console returns `ENOTCONN`, and `connect`, `bind` and `sendto` with an address on a pair end report an address-family error instead of the console's `EISCONN`. On Windows `poll` on a stream end reports `POLLIN` after the peer's `shutdown(SHUT_WR)` or `close`, as the console does after a `shutdown(SHUT_WR)`; after the peer's `close` the console reports `POLLIN` with `POLLHUP`, because `unp_drop` disconnects the other end, and the loopback connection cannot tell that from a shutdown, so no `POLLHUP` is reported +- [socketpair](../../../core/libs/prx/libkernel/Socket/src/Udp.cpp) (libkernel) - the pair is the host's `AF_UNIX` pair on Linux and macOS and, on Windows, a loopback TCP connection for `SOCK_STREAM` or two connected UDP sockets for `SOCK_DGRAM`; `SOCK_SEQPACKET` throws on Windows and macOS, which has no such `AF_UNIX` pair. A datagram sent to a full receiver gets `ENOBUFS` on the console, waits or gets `EAGAIN` on Linux and is dropped on Windows, and on Windows a datagram `recv` after the peer closed reports `ECONNRESET` instead of the console's `ENOTCONN`, and the first stream `send` after the peer closed succeeds on the loopback connection, where the console returns `EPIPE`; the sends after it report `EPIPE`. `read` and `write` on a pair end go to the host as on every guest socket. `connect`, `bind` and `sendto` with an address on a pair end report an address-family error instead of the console's `EISCONN`. On Windows `poll` on a stream end reports `POLLIN` after the peer's `shutdown(SHUT_WR)` or `close`, as the console does after a `shutdown(SHUT_WR)`; after the peer's `close` the console reports `POLLIN` with `POLLHUP`, because `unp_drop` disconnects the other end, and the loopback connection cannot tell that from a shutdown, so no `POLLHUP` is reported - Guest sockets on macOS ([the equeue wait, 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; `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 @@ -216,9 +220,10 @@ - [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 - [recv and recvfrom after `shutdown(SHUT_RD)`](../../../core/libs/prx/libkernel/Socket/src/Udp.cpp) (libkernel) return 0 on Windows ([`soreceive_generic`](https://github.com/freebsd/freebsd-src/blob/release/11.4.0/sys/kern/uipc_socket.c#L1556-L1562)) where Winsock fails with `EPIPE`; Linux and macOS still return data buffered before it, which the console discards. - [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) check a socket address length as FreeBSD 11.4's [`getsockaddr`](https://github.com/freebsd/freebsd-src/blob/release/11.4.0/sys/kern/uipc_syscalls.c) and the `sa_len` test of `tcp_usr_connect` and `in_pcbconnect` do: below 2 or an `AF_INET` address below 16 or an `AF_INET6` address below 28 bytes fails with `EINVAL`, above 255 with `ENAMETOOLONG`. `sendto` does not check an address longer than `sockaddr_in` on an `AF_INET` datagram socket, where `udp_output` answers `EINVAL` unless the socket has a local address and port and the destination is neither `INADDR_ANY` nor `INADDR_BROADCAST`, nor on an unconnected stream socket, which FreeBSD connects implicitly through `tcp_connect` and its length test. An address of another family still fails with `EAFNOSUPPORT`, as the console's behaviour for it is not known. None of this was measured on a console. +- [bind, connect, sendto](../../../core/libs/prx/libkernel/Socket/src/Udp.cpp) (libkernel) check a socket address as a payload process on a PS5 (firmware 13.60) did on datagram sockets: a length below 2 fails with `EINVAL` and above 255 with `ENAMETOOLONG`; an `AF_INET` socket needs exactly 16 bytes and an `AF_INET6` socket 28, or `EINVAL`; another family fails with `EAFNOSUPPORT`; `sendto` on an `AF_INET` socket, and all three on an `AF_INET6` socket, check the length first. Unmeasured: `bind` and `connect` on an `AF_INET` socket check the family first, where FreeBSD 11.4's `tcp_usr_bind` and `tcp_usr_connect` check the length first; stream sockets follow the datagram order; `AF_UNSPEC` with `INADDR_ANY`, which FreeBSD's `bind` accepts, fails; `connect` on a listening stream socket fails with `EOPNOTSUPP` first, as `soconnect` does. A connected stream socket's `sendto` ignores the address once its length passes, as `tcp_usr_send` does +- [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 - [read, write and vector I/O](../../../core/libs/prx/libkernel/File/src/Stdio.cpp) (libkernel) on a guest socket use `recv` and `send` without flags; `sceKernelReadv` and `sceKernelWritev` gather or scatter through one socket operation, preserving stream short reads and datagram boundaries. The positioned `pread`, `pwrite`, `preadv` and `pwritev` forms, and their `sceKernel` forms, return `ESPIPE` for an open guest socket and `EBADF` for a closed one. `EPIPE` from a write raises the host's `SIGPIPE` on Linux unless the socket has `SO_NOSIGPIPE` set, and the guest cannot ignore it: `signal(SIGPIPE, SIG_IGN)` and `sigaction` record the disposition, as they do for every number from 1 to 128, but only the six signals with host equivalents (2, 4, 6, 8, 11 and 15) take effect on the host or are delivered, so the host `SIGPIPE` is not stopped; nothing is raised on Windows; a `write` longer than `INT_MAX` bytes is `EMSGSIZE` where the console sends it. AIO on a guest socket still goes to the host, which has no such descriptor -- [Socket descriptor numbers](../../../core/libs/prx/libkernel/Socket/src/Udp.cpp) (libkernel, libSceNet) - `socket`, `accept`, `socketpair`, `dup`, `sceNetSocket` and `sceNetAccept` take the lowest free number of the host descriptor table that files use, as FreeBSD 11.4 `fdalloc` takes the lowest free entry of the one process table (`kern_descrip.c`), so every number stays below `FD_SETSIZE` (1024) while fewer than 1024 descriptors are open. The number holds a zero-access `NUL` handle on Windows and a duplicate of the host socket on Linux, and the socket tables map it to the socket. The host table also holds the runtime's own files, so the numbers differ from the console's; the first number `socket` and `sceNetSocket` return on a console and its `getdtablesize` are not measured. Paths that bypass the socket tables see the placeholder: libc `fdopen` on a socket opens it, and libkernel `close` of a libSceNet socket releases the number but leaves the libSceNet socket open. Palworld (PPSA23126), The Mound (PPSA26223) and Dying Light 2 (PPSA02262) set socket bits in a 1024-bit `fd_set` +- [Socket descriptor numbers](../../../core/libs/prx/libkernel/Socket/src/Udp.cpp) (libkernel, libSceNet) - `socket`, `accept`, `socketpair`, `dup`, `sceNetSocket` and `sceNetAccept` take the lowest free number of the host descriptor table that files use, as FreeBSD 11.4 `fdalloc` takes the lowest free entry of the one process table (`kern_descrip.c`), so every number stays below `FD_SETSIZE` (1024) while fewer than 1024 descriptors are open. The number holds a zero-access `NUL` handle on Windows and a duplicate of the host socket on Linux, and the socket tables map it to the socket. The host table also holds the runtime's own files, so the numbers differ from the console's; the first number `socket` and `sceNetSocket` return on a console and its `getdtablesize` are not measured. Paths that bypass the socket tables see the placeholder: libc `fdopen` on a socket opens it, and libkernel `sceKernelClose` of a libSceNet socket releases the number but leaves the libSceNet socket open. Palworld (PPSA23126), The Mound (PPSA26223) and Dying Light 2 (PPSA02262) set socket bits in a 1024-bit `fd_set` - [fstat on a guest socket](../../../core/libs/prx/libkernel/Socket/src/Udp.cpp) (libkernel) fills the fields FreeBSD 11's soo_stat and pru_sense_null fill and zeroes the rest: S_IFSOCK, the read bits while the receive side is open or data is queued, the write bits while the send side is open, st_size and st_blksize. Only this process's shutdown closes a side here; a peer's shutdown, close or reset does not clear the bits as FreeBSD's socantrcvmore and socantsendmore do. st_size is the host's FIONREAD, which for a Linux datagram socket is the size of the next datagram where FreeBSD counts every queued byte, and st_blksize is the host's SO_SNDBUF, which Linux reports as twice the size that was set. A socketpair end reports st_dev and st_ino 0, where FreeBSD's uipc_sense reports NODEV and a per-socket number - [poll](../../../core/libs/prx/libkernel/Socket/src/Udp.cpp) (libkernel) waits on guest sockets and pipes, through `WSAPoll` on Windows and `poll` on Linux; the `pollfd` layout and flag values are FreeBSD's. A libSceNet socket joins the same host wait through the native socket libSceNet lends to libkernel. `WSAPoll` rejects `POLLPRI`, so on Windows a socket's `POLLPRI` is asked as `POLLRDBAND` and `POLLIN` as `POLLRDNORM`; Winsock reports urgent data until it is read with `MSG_OOB`, where FreeBSD 11.4's `sopoll_generic` stops once the normal stream passes the mark. Guest `send` and `recv` refuse `MSG_OOB` with `EOPNOTSUPP`, so urgent data can only come from an outside peer and Windows keeps reporting `POLLPRI` after the stream passes the mark. A pipe follows FreeBSD's `pipe_poll`: the read end is readable when data is buffered, either end reports `POLLHUP` once the other end is closed, with the requested `POLLIN` and `POLLRDNORM` bits and without `POLLOUT`, which `pollscan` clears, and the write end is writable when `PIPE_BUF` (512) bytes are free on Windows, or when the host kernel says so on Linux. `POLLOUT` on a read end throws: FreeBSD opens both ends for reading and writing and reports it writable, and host pipes are one-way. Windows pipes cannot be waited on, so while a pipe is polled `poll` checks it with `NtQueryInformationFile` and waits on the sockets in slices of 1 ms. A kqueue is ready for `POLLIN` and `POLLRDNORM` while one of its events is triggered and for no other event, as FreeBSD 11.4's [`kqueue_poll`](https://github.com/freebsd/freebsd-src/blob/release/11.4.0/sys/kern/kern_event.c#L1900-L1924) answers. A kqueue cannot be waited on either, so on every host `poll` checks it every millisecond and waits on the other descriptors in slices of 1 ms. A kqueue closed during the wait reports `POLLNVAL`, and one whose number was reused is polled again with the rest of the timeout, as FreeBSD 11.4's [`pollrescan`](https://github.com/freebsd/freebsd-src/blob/release/11.4.0/sys/kern/sys_generic.c#L1499-L1519) looks the descriptor up again. A close that has already removed the kqueue but not yet closed its host descriptor is seen as a descriptor of unknown kind, which throws. A regular file, a directory or a file read from app0.zar is always ready for `POLLIN`, `POLLRDNORM` and `POLLOUT` and never for `POLLPRI`, `POLLRDBAND` or `POLLWRBAND`, as FreeBSD 11.4's [`vop_stdpoll`](https://github.com/freebsd/freebsd-src/blob/release/11.4.0/sys/kern/vfs_default.c#L563-L574) and `vop_nopoll` answer every event `poll` accepts; which of the two the console's filesystems use is not known, and they agree on these events. `/dev/random` and `/dev/urandom` follow FreeBSD 11.4's [`randomdev_poll`](https://github.com/freebsd/freebsd-src/blob/release/11.4.0/sys/dev/random/randomdev.c#L274-L285) for a seeded device: a request with `POLLIN` or `POLLRDNORM` gets only those bits back, and any other request gets every requested bit. Open descriptors 0 to 2 follow the console model `select` uses: descriptor 0 never reports an event and descriptors 1 and 2 report `POLLOUT`, whatever the host attaches to them. A closed descriptor reports `POLLNVAL`, and an open descriptor that is neither a guest socket, a libSceNet socket, a pipe, a file, a directory, the random device nor descriptor 0 to 2 (other devices) throws, as do event bits other than `POLLIN`, `POLLPRI`, `POLLOUT`, `POLLRDNORM`, `POLLRDBAND` and `POLLWRBAND` (the `POLLERR`, `POLLHUP` and `POLLNVAL` bits are ignored in `events`), an infinite timeout with no socket, pipe or kqueue to wait on. A closed socket descriptor reports `POLLNVAL`; the console's limit on the descriptor count is unknown and not checked - [poll](../../../core/libs/prx/libkernel/Socket/src/Udp.cpp) (libkernel) on Windows reports a guest stream socket whose peer closed as readable and adds `POLLHUP` only once the socket has shut its own sending side, as FreeBSD 11.4's [`sopoll_generic`](https://github.com/freebsd/freebsd-src/blob/release/11.4.0/sys/kern/uipc_socket.c#L3080-L3086) does; `WSAPoll` reports `POLLHUP` alone in both cases. A reset or refused connection (`POLLHUP` with `POLLERR`) keeps `WSAPoll`'s flags, a libSceNet socket keeps them too, and a call that asks for no event still returns early on the peer's close with nothing reported. Not measured on a console. @@ -226,7 +231,8 @@ - [kevent on a pipe](../../../core/libs/prx/libkernel/Equeue/src/Kqueue.cpp) (libkernel) - host pipes are one-way, where FreeBSD's [`kern_pipe`](https://github.com/freebsd/freebsd-src/blob/release/11.0.0/sys/kern/sys_pipe.c#L422) opens both ends for reading and writing, so `EVFILT_READ` on the write end and `EVFILT_WRITE` on the read end throw; on macOS `EVFILT_WRITE` on a pipe throws, as the host has no call for a pipe's capacity. `EVFILT_WRITE` reports the free space of the host buffer, not of FreeBSD's 16 KiB one, and on Linux fires when the host says the pipe is writable rather than at `PIPE_BUF` (512) free bytes. Windows pipes cannot be waited on, so a kqueue waiting on one checks it every 1 ms. Otherwise [`filt_piperead`](https://github.com/freebsd/freebsd-src/blob/release/11.0.0/sys/kern/sys_pipe.c#L1787-L1828) and `filt_pipewrite` are followed: `EV_EOF` once the other end closes, `EPIPE` for a write event added after the read end closed, and `NOTE_LOWAT` ignored. On Windows `fcntl` cannot make a pipe write end non-blocking, so the full-pipe and drain case of `EVFILT_WRITE` is tested on Linux only and the `NtQueryInformationFile` write quota is checked there only for the free space, `EV_EOF` and `EPIPE`. - [kevent on a kqueue](../../../core/libs/prx/libkernel/Equeue/src/Kqueue.cpp) (libkernel) - `EVFILT_READ` on a kqueue counts the watched queue's enabled notes that are ready when it is evaluated, where [`filt_kqueue`](https://github.com/freebsd/freebsd-src/blob/5ed7eb0d97ba4436218e810f61bd059acba984c2/sys/kern/kern_event.c#L363-L370) reports `kq_count`, the queued notes: a queued note counts until that kqueue is scanned, even once disabled or no longer ready (a socket or pipe read empty, a user note cleared, a watched kqueue drained), so FreeBSD can report it readable where this reports nothing. A queued `EV_ONESHOT` note is reported there with its last count and deleted; here it is evaluated again and, if the watched queue is empty by then, neither reported nor deleted. `EV_CLEAR` throws, as FreeBSD re-arms it only when the watched kqueue queues a note. A cycle of watches throws; a note on the queue itself is `EINVAL`. Not measured on a console - [Socket error numbers](../../../core/libs/prx/libkernel/Socket/include/SocketError.hpp) (libkernel) - a host socket error becomes the FreeBSD 11 `errno.h` number of the same name; the numbers are not checked on the console. Winsock `WSAESHUTDOWN` becomes `EPIPE`, as a send after `shutdown` does on FreeBSD, and a host error with no FreeBSD socket counterpart becomes `EIO`. On Windows a refused nonblocking `connect` is never reported (`SO_ERROR` is unsupported), so a repeated one keeps reporting `EALREADY` where FreeBSD reports `ECONNREFUSED`. A receive after `shutdown(SHUT_RD)` reports `EPIPE` on Windows where FreeBSD returns 0 -- [getsockopt, setsockopt](../../../core/libs/prx/libkernel/Socket/src/SocketOptions.cpp) (libkernel) - a guest socket has the SOL_SOCKET level, five `IPPROTO_TCP` options, `IPV6_V6ONLY` and seven `IPPROTO_IP` options. `TCP_NOPUSH`, `TCP_NOOPT` and `TCP_KEEPINIT` fail with `ENOPROTOOPT` (42), where a payload process on a PS5 (firmware 13.60) read them as 0, and so does `SO_ACCEPTFILTER` (0x1000), which the console fails with `EINVAL` for a set and a get on a non-listening socket, as FreeBSD 11.4 does; the other options of these levels fail with `ENOPROTOOPT` and were not all measured. `SO_KEEPALIVE`, `SO_DONTROUTE`, `SO_BROADCAST`, `SO_OOBINLINE` and `SO_LINGER` act on the host socket, and a boolean one reads back as its own bit, as there. Winsock does not clear a pending error when `SO_ERROR` reads it, so on Windows a pending error is reported once and again only after a new `connect`; a second failure with the same code without a `connect` in between is hidden +- [getsockopt, setsockopt](../../../core/libs/prx/libkernel/Socket/src/SocketOptions.cpp) (libkernel) - a guest socket has the SOL_SOCKET level, eight `IPPROTO_TCP` options, `IPV6_V6ONLY` and ten `IPPROTO_IP` options. `SO_ACCEPTFILTER` (0x1000) fails with `ENOPROTOOPT` (42), where a payload process on a PS5 (firmware 13.60) failed it with `EINVAL` for a set and a get on a non-listening socket, as FreeBSD 11.4 does; the other options of these levels fail with `ENOPROTOOPT` and were not all measured. `SO_KEEPALIVE`, `SO_DONTROUTE`, `SO_BROADCAST`, `SO_OOBINLINE` and `SO_LINGER` act on the host socket, and a boolean one reads back as its own bit, as there. Winsock does not clear a pending error when `SO_ERROR` reads it, so on Windows a pending error is reported once and again only after a new `connect`; a second failure with the same code without a `connect` in between is hidden +- [TCP_NOPUSH, TCP_NOOPT, TCP option 0x80, IP_RECVDSTADDR, IP_RECVIF, IP_RECVTTL](../../../core/libs/prx/libkernel/Socket/src/SocketOptions.cpp) (libkernel) - kept and read back as a payload process on a PS5 (firmware 13.60) did: the TCP ones as the bits 0x1000, 0x8 and 0x10000 (so 0x80 is not FreeBSD's `TCP_KEEPINIT` there), the IP ones as 0 or 1. None of them changes what the socket does: `TCP_NOPUSH` does not hold back sends, and the IP ones add no control message to `recvmsg`. `IP_RECVTTL` was only read, never set, on the console, and an accepted socket takes `TCP_NOPUSH` from its listener as FreeBSD 11.4's `syncache_socket` does, which was not measured - [SO_DEBUG, SO_REUSEADDR, SO_USELOOPBACK, SO_REUSEPORT, SO_TIMESTAMP, SO_BINTIME and option 0x10000](../../../core/libs/prx/libkernel/Socket/src/SocketOptions.cpp) (libkernel) - kept as bits that read back as on a PS5 (firmware 13.60, payload process), and options 0x4000 and 0x8000 are accepted and cannot be read, as there; only `SO_REUSEADDR` and `SO_REUSEPORT` change what the socket does. Both are set on the host, `SO_REUSEPORT` as `SO_REUSEADDR` on Windows, which has no `SO_REUSEPORT` and there also lets the socket bind over one that did not set it; Linux spreads unicast datagrams across the sockets, where FreeBSD gives each to one. Option 0x10000 is only kept: if the console treats it as FreeBSD 12's `SO_REUSEPORT_LB`, two sockets that set it share a port there, where the second `bind` here fails with `EADDRINUSE`. An accepted socket takes the bits from its listener, as FreeBSD 11.4's `sonewconn` copies `so_options`; that was not measured - [IP_ADD_MEMBERSHIP, IP_DROP_MEMBERSHIP, IP_MULTICAST_IF](../../../core/libs/prx/libkernel/Socket/src/SocketOptions.cpp) (libkernel) - set on the host socket after the checks a PS5 (firmware 13.60, payload process) showed: `EOPNOTSUPP` on a stream socket, `EINVAL` for a short value or a group outside 224.0.0.0/4, `EADDRINUSE` for a group joined twice and `EADDRNOTAVAIL` for one not joined, tracked per socket. An interface the host lacks fails with the host's error (`EADDRNOTAVAIL` on the console). A group joined through `INADDR_ANY` and through that interface's address counts as two here. Not measured, after FreeBSD 11.4: a drop through `INADDR_ANY` leaves the first such group on any interface (`inp_leave_group`), and the other multicast options fail with `EOPNOTSUPP` on a stream socket (`inp_setmoptions`). An `ip_mreqn` with a non-zero index or address throws, as only a zeroed one was measured, and so does reading `IP_MULTICAST_IF` into 12 bytes, where FreeBSD returns an `ip_mreqn` - [TCP_MAXSEG](../../../core/libs/prx/libkernel/Socket/src/SocketOptions.cpp) (libkernel) - kept per stream socket, read as 536 at first and failing with `EINVAL` for 1000, 70000 and 100, as a payload process on a PS5 (firmware 13.60) did. No segment set succeeded there, so the rule here, `EINVAL` above the current segment or below 176 and any segment between accepted, follows FreeBSD 11.4's `tcp_default_ctloutput` (`optval + 40 >= V_tcp_minmss`) and is not measured. An `AF_INET6` socket also starts at 536 here, where FreeBSD's `tcp_newtcpcb` uses 1220; not measured. The segment is not set on the host socket, so the host's segment size is its own, and a connected socket still reads the segment it was given instead of the negotiated one @@ -237,12 +243,12 @@ - [SO_SNDTIMEO, SO_RCVTIMEO](../../../core/libs/prx/libkernel/Socket/src/SocketOptions.cpp) (libkernel) - the value checks and the 32.32 fixed-point read-back follow [`sosetopt`](https://github.com/freebsd/freebsd-src/blob/8c639945a44588f6cfdddfb057bb5aad88735da0/sys/kern/uipc_socket.c#L2657-L2689), as a payload process on a PS5 (firmware 13.60) answered them. A receive or send on a blocking socket waits that long for the host to report the socket readable or writable and fails with `EWOULDBLOCK`, but only before the first transfer: once writable the host send has no limit, where FreeBSD returns the bytes sent so far, and a receive whose data another thread takes after the wait blocks again. `sendfile` ignores the send timeout, the host wait has millisecond steps, and an accepted socket takes both from its listener - [IPV6_V6ONLY](../../../core/libs/prx/libkernel/Socket/src/SocketOptions.cpp) (libkernel) - the `IPPROTO_IPV6` option 27 is set on the host socket and reads back as 0 or 1, after FreeBSD's [`ip6_ctloutput`](https://github.com/freebsd/freebsd-src/blob/8c639945a44588f6cfdddfb057bb5aad88735da0/sys/netinet6/ip6_output.c#L1716-L1732): a value that is not exactly an `int` fails with `EINVAL`, as does setting it on a bound socket, which the host refuses too. `socket` turns it on for every `AF_INET6` socket, as a payload process on a PS5 (firmware 13.60) reported, and Java turns it off on the sockets it opens: Java 25 Advanced Network (PPSA99871) stops at `java.net.SocketException: Protocol not available` without it. The value checks and the bound-socket answer were not measured - [connect to AF_UNSPEC](../../../core/libs/prx/libkernel/Socket/src/Udp.cpp) (libkernel) dissolves a datagram association as FreeBSD 11.4's `udp_disconnect()` does, which resets the local address to the wildcard address and keeps the port. On Linux and on Windows a socket bound to an explicit port keeps its local address as well (`127.0.0.1:` stays `127.0.0.1:`), because a bound socket cannot be bound again, and `getsockname` reports that host address. On Windows a `sendto` to a non-loopback address from such a socket then fails with `ENETUNREACH` (Winsock 10051, measured on Windows 10), where FreeBSD sends it from the wildcard address. One bound to port 0 is bound again to the wildcard address with the port it had -- [connect](../../../core/libs/prx/libkernel/Socket/src/Udp.cpp) (libkernel) - `connect` to port 0 on an unconnected `AF_INET` or `AF_INET6` stream or datagram socket fails with `EADDRNOTAVAIL` (49), as FreeBSD 11.4's `in_pcbconnect_setup()` and `in6_pcbconnect()` do; a connected datagram socket is disconnected first, as `soconnect()` does, and then fails with 49. A connected stream socket keeps its host `EISCONN` answer. Known gap: `sendto` and `sendmsg` to port 0 on an `AF_INET` datagram socket fail with 49 unless the socket is bound to a specific address and port and the destination is neither `INADDR_ANY` nor `INADDR_BROADCAST`, which is the path where `udp_output()` skips `in_pcbconnect_setup()` and FreeBSD sends to port 0. There nothing can receive on port 0, so the call returns the length without the host, because Linux's `udp_sendmsg` refuses port 0 with `EINVAL`; an `AF_INET6` socket still goes to the host. The answers are taken from the FreeBSD source and are not measured on a console. [sceNetConnect](../../../core/libs/prx/libSceNet/Export.cpp) is not changed +- [connect](../../../core/libs/prx/libkernel/Socket/src/Udp.cpp) (libkernel) - `connect` to port 0 on an `AF_INET` or `AF_INET6` stream or datagram socket fails with `EADDRNOTAVAIL` (49), and on a connected datagram socket it disconnects first, as on a PS5 (firmware 13.60) and in FreeBSD 11.4's `soconnect()`. A connected stream socket keeps its host `EISCONN` answer. Known gap: `sendto` and `sendmsg` to port 0 on an `AF_INET` datagram socket fail with 49 (measured for an unbound socket) unless the socket is bound to a specific address and port and the destination is neither `INADDR_ANY` nor `INADDR_BROADCAST`, which is the path where `udp_output()` skips `in_pcbconnect_setup()` and FreeBSD sends to port 0. There the call returns the length without the host, as Linux's `udp_sendmsg` refuses port 0 with `EINVAL`; an `AF_INET6` socket still goes to the host. [sceNetConnect](../../../core/libs/prx/libSceNet/Export.cpp) is not changed - [msync](../../../core/libs/prx/libkernel/DirectMemory/PosixMemory.cpp) (libkernel) follows FreeBSD 11's `kern_msync` and `vm_map_sync`: the address is rounded down to the page, a range that wraps is `EINVAL`, as is `MS_ASYNC` with `MS_INVALIDATE`, and a range whose start or any page is not mapped (as `sceKernelVirtualQuery` reports it, reservations included) is `ENOMEM`; a page unmapped from inside a larger mapping still counts as mapped there, since `sceKernelVirtualQuery` keeps reporting the whole mapping. The guest has no file mappings, so a successful call writes nothing back. `MS_INVALIDATE` on a mapped range fails with `EBUSY`, as it did in a payload process on a PS5 (firmware 13.60) for anonymous memory, locked or not, also with a hole unmapped inside it; a title process, reservations, direct memory and flexible memory were not measured - [madvise](../../../core/libs/prx/libkernel/DirectMemory/PosixMemory.cpp) (libkernel) accepts `MADV_PROTECT` (10) as a no-op hint without modifying process protection. FreeBSD 11's `kern_madvise` (`sys/vm/vm_mmap.c`) handles it before the address check, ignores the address and length, and calls `kern_procctl(..., PROC_SPROTECT, PPROT_SET)`, which requires `PRIV_VM_MADV_PROTECT` and fails with `EPERM` without it. Returning 0 unconditionally assumes the calling process is privileged. Console behaviour is unverified - [mincore](../../../core/libs/prx/libkernel/DirectMemory/PosixMemory.cpp) (libkernel) follows FreeBSD 11's `sys_mincore` (`sys/vm/vm_mmap.c`), not measured on the console: the address is rounded down to the page, length 0 returns 0, a null vector over a mapped range returns `EFAULT`, an overflowing range or any unmapped page in the range (as reported by `sceKernelVirtualQuery`) returns `ENOMEM`. For valid ranges, a page reports `MINCORE_INCORE` (0x1) when `sceKernelVirtualQuery` reports it committed and 0 when it is only reserved; actual residency, referenced and modified bits are not modelled. Length 0 returns 0 when the start page is mapped and `ENOMEM` otherwise, and the range and mapping checks come before the null vector `EFAULT`, as in `kern_mincore` Java 25 LAN / DNS (PPSA99869) imports it -- [mlockall, munlockall](../../../core/libs/prx/libkernel/DirectMemory/PosixMemory.cpp) (libkernel) - `mlockall` returns `EINVAL` for zero or unknown flags. Valid `MCL_CURRENT` throws because it would lock host stacks, heaps, modules and driver mappings along with guest memory; `MCL_FUTURE` throws because later mappings are not tracked for locking. FreeBSD 11.4's `sys_munlockall` (`sys/vm/vm_mmap.c`:1133-1165) checks `priv_check(td, PRIV_VM_MUNLOCK)` first (returning `EPERM` without it) and unwires the user map (`vm_map_unwire` over `vm_map_min`...`vm_map_max` with `VM_MAP_WIRE_HOLESOK`). Returning 0 unconditionally assumes the calling process is privileged. `munlockall` unlocks memory locked by `mlock` (`VirtualUnlock` on Windows, tolerating `ERROR_NOT_LOCKED` for pages never locked, and `munlockall` on Linux). On main, XPSemu (PPSA97358) fails to load at these imports (mlockall #4386, munlockall); their calls in QEMU `os-posix.c` execute only when `-overcommit mem-lock=on` is enabled. The call has not been observed in a run with this implementation. -- [socket](../../../core/libs/prx/libkernel/Socket/src/Udp.cpp) (libkernel) creates only `SOCK_STREAM` and `SOCK_DGRAM` sockets in `AF_INET` and `AF_INET6`. A type that FreeBSD 11.4's inet domain has no protocol for in any configuration ([`in_proto.c`](https://github.com/freebsd/freebsd-src/blob/release/11.4.0/sys/netinet/in_proto.c) has no `SOCK_RDM` entry and no unknown type) fails with `EPROTOTYPE` when the protocol is 0 and `EPROTONOSUPPORT` otherwise, as [`socreate`](https://github.com/freebsd/freebsd-src/blob/release/11.4.0/sys/kern/uipc_socket.c) does. `SOCK_RAW`, which `in_proto.c` always has (`socreate` creates it for a privileged process), and `SOCK_SEQPACKET`, which it has only in a kernel built with `SCTP`, fail with `EPROTONOSUPPORT`; whether the console allows either is not known. `SOCK_DGRAM` with `IPPROTO_UDPLITE` and `AF_UNIX` (`socketpair` supports it) fail with `EPROTONOSUPPORT` and `EAFNOSUPPORT` where FreeBSD creates the socket +- [mlockall, munlockall](../../../core/libs/prx/libkernel/DirectMemory/PosixMemory.cpp) (libkernel) - `mlockall` returns `EINVAL` for zero or unknown flags. Valid `MCL_CURRENT` throws because it would lock host stacks, heaps, modules and driver mappings along with guest memory; `MCL_FUTURE` throws because later mappings are not tracked for locking. FreeBSD 11.4's `sys_munlockall` (`sys/vm/vm_mmap.c`:1133-1165) checks `priv_check(td, PRIV_VM_MUNLOCK)` first (returning `EPERM` without it) and unwires the user map (`vm_map_unwire` over `vm_map_min`...`vm_map_max` with `VM_MAP_WIRE_HOLESOK`). Returning 0 unconditionally assumes the calling process is privileged. `munlockall` unlocks memory locked by `mlock` (`VirtualUnlock` on Windows, tolerating `ERROR_NOT_LOCKED` for pages never locked, and `munlockall` on Linux). XPSemu (PPSA97358) imports `mlockall` and `munlockall`; their calls in QEMU `os-posix.c` execute only when `-overcommit mem-lock=on` is enabled. The call has not been observed in a run with this implementation. +- [socket](../../../core/libs/prx/libkernel/Socket/src/Udp.cpp) (libkernel) creates only `SOCK_STREAM` and `SOCK_DGRAM` sockets in `AF_INET` and `AF_INET6`. In a payload process on a PS5 (firmware 13.60) `SOCK_RDM`, `SOCK_SEQPACKET` and an unknown type failed with `EPROTOTYPE` when the protocol was 0 and `EPROTONOSUPPORT` otherwise, as here, and a family other than `AF_INET`, `AF_INET6` and `AF_UNIX` with `EAFNOSUPPORT`. The console also created `SOCK_RAW` (for that payload process, which may hold privileges a title does not), `SOCK_DGRAM` with `IPPROTO_UDPLITE`, and `AF_UNIX` stream, datagram and seqpacket sockets; these fail here with `EPROTONOSUPPORT` and `EAFNOSUPPORT` (`socketpair` supports `AF_UNIX`) - [sigtimedwait](../../../core/libs/prx/libkernel/System/src/Signals.cpp) (libkernel) waits on a process-wide pending set instead of throwing: a signal raised while blocked stays pending and is taken by `sigwait`, `sigwaitinfo` or `sigtimedwait`, delivered to the handler when `_sigprocmask` unblocks it, or delivered by `pause`. The set covers all 128 signals and the lowest number that is pending and in the set is selected (FreeBSD specifies the lowest number only among real-time signals). Selection, `EAGAIN` on timeout, `EINVAL` for a `tv_nsec` outside 0 to 1000000000 while nothing is pending and `NULL` timeout blocking indefinitely follow FreeBSD's [sigtimedwait(2)](https://man.freebsd.org/cgi/man.cgi?query=sigtimedwait). `sigwait` returns 0 with the number in its output, as POSIX specifies, and `sigwaitinfo` and `sigtimedwait` return the number, as FreeBSD does. The guest `siginfo_t` follows FreeBSD 11's `sys/sys/siginfo.h`: 80 bytes, `si_signo` at 0, `si_code` at 8, `si_pid` at 12, `si_uid` at 16, `si_addr` at 24, `si_value` at 32 and `si_band` at 40; only `si_signo`, `si_code` (`SI_USER`) and `si_pid` (the guest pid) are written, `si_uid` stays 0 because no uid is modelled, and the console's layout is not verified. PPSA85300 imports `sigtimedwait` and fails to load without it; its only call site is VLC's `vlc_writev` ([filesystem.c](https://github.com/videolan/vlc/blob/6de05adcbaf2e8b85fe86aad4169393098628119/src/posix/filesystem.c#L243-L278)), which polls with a zero timeout to drain a `SIGPIPE` only after `writev` fails with `EPIPE`. The waits are not cancellation points and an unblocked caught signal does not interrupt them with `EINTR`, where FreeBSD's `sigwaitinfo` and `sigtimedwait` may return it. `SIGPIPE` has no host equivalent and is never raised by a host write here (see `read, write and vector I/O`), so VLC's drain finds nothing - [pause, sigsuspend, sigwait, sigwaitinfo](../../../core/libs/prx/libkernel/System/src/Signals.cpp) (libkernel) take the pending set of `sigtimedwait` instead of throwing. `pause` waits for a pending signal that is not blocked and whose disposition can be delivered, runs its handler on the calling thread and returns -1 with `EINTR`; an ignored signal is discarded and the wait continues, and it never returns for a signal whose handler cannot run. A signal whose registered handler has `SA_SIGINFO` still throws, and one whose disposition is the default action and that has no host equivalent (every signal except 2, 4, 6, 8, 11 and 15) is neither delivered nor discarded: it stays pending until a wait takes it, where FreeBSD runs the default action, which terminates the process for most of them. A pending `SIGALRM` with the default disposition exits the process with status 142 once it is unblocked, as FreeBSD's default action does. PPSA68091, PPSA99169, PPSA99420 and PPSA97358 import them and fail to load without them. PPSA68091 calls `pause` at one site (0x8F7266), in a loop that waits while a global holds another thread's `errno` address. PPSA99169 only stores the address of `pause` in a table of symbol addresses (0x30DB1). PPSA99420 calls `pause` at 0x3BD80F6 and 0x3C9E220, `sigwait` at 0x3C9E4C7 and `sigwaitinfo` at 0x3C9E588. PPSA97358 calls `sigwait` from QEMU's `sigwait_compat` thread ([compatfd.c](https://github.com/ZiZc3/XPSemu/blob/8eec07b4e31f66dce8e0b05c1ca1281af303e933/util/compatfd.c#L28-L53)), which `qemu_signal_init` ([main-loop.c](https://github.com/ZiZc3/XPSemu/blob/8eec07b4e31f66dce8e0b05c1ca1281af303e933/util/main-loop.c#L110-L147)) starts for `SIGIO`, `SIGALRM` and `SIGBUS` when the main loop is created, so it reaches the wait at start-up, and from the vCPU thread of the dummy accelerator ([dummy-cpus.c](https://github.com/ZiZc3/XPSemu/blob/8eec07b4e31f66dce8e0b05c1ca1281af303e933/accel/dummy-cpus.c#L48-L56)). `sigsuspend` swaps the process-wide mask of `_sigprocmask` for its argument, waits as `pause` does through the same helper, then restores the mask through `_sigprocmask`, and returns -1 with `EINTR`; a null set throws, as the console faults in libthr instead of returning `EFAULT`. All four words of the argument replace the mask and are restored afterwards, as in `_sigprocmask`. Java 25 LAN / DNS (PPSA99869, #5501) imports it and fails to load without it, after `sysctlnametomib`, `fegetenv` and `mincore`. None of the five waits is a cancellation point - [getsid, setpgid, setpgrp](../../../core/libs/prx/libkernel/System/src/Process.cpp) (libkernel) - getsid returns the calling process ID for pid 0 and the calling process, and `ESRCH` for other process IDs, assuming the single guest process is its own session leader. setpgid and setpgrp follow FreeBSD 11.4's `sys_setpgid` for the only guest process: a negative group ID fails with `EINVAL`, a process ID other than 0 or the caller's PID (including a negative PID) fails with `ESRCH`, and because the single guest process is modeled as its own session leader, `SESS_LEADER(targp)` fails with `EPERM` before normalizing the process group or reaching the same-process-group no-op. PPSA74126 imports `getsid` and fails to load without it @@ -258,7 +264,7 @@ - [_accept, _bind, _connect, _getpeername, _getsockname, _getsockopt, _listen, _recvfrom, _recvmsg, _sendmsg, _sendto, _setsockopt](../../../core/libs/prx/libkernel/Socket/src/Udp.cpp), [_getdirentries](../../../core/libs/prx/libkernel/File/src/Stdio.cpp), [_sigaction, _sigsuspend](../../../core/libs/prx/libkernel/System/src/Signals.cpp) (libkernel) are not measured on the console. They forward to the calls without the underscore, which have no libthr layer here, as FreeBSD 11.4 makes the underscore names the plain system calls. `_sigaction` and `sigaction` share one handler table, where FreeBSD's `__thr_sigaction` hands its own wrapper to the system call `_sigaction` reads back, and rejects `SIGCANCEL` (32). A null set throws in `_sigsuspend` as in `sigsuspend`, while the system call FreeBSD 11.4 exports as `_sigsuspend` ([`Symbol.map`](https://github.com/freebsd/freebsd-src/blob/8c639945a44588f6cfdddfb057bb5aad88735da0/lib/libc/sys/Symbol.map#L961)) returns `EFAULT` - [Regular file mappings](../../../core/libs/prx/libkernel/DirectMemory/PosixMemory.cpp) (libkernel) - on Linux `mmap` maps a regular file's descriptor shared or private like a shared memory object, with the same access checks; SQLite's WAL index (`-shm`) in Dusklight PPSA99305 needs it. FreeBSD 11 `mmap(2)` and shadPS4's `MemoryManager::MapFile` map regular files; the console's behaviour is not measured. Other descriptors (pipes, sockets, directories, devices) still fail with `EOPNOTSUPP`. On Windows a shared mapping is a view of a file section (`CreateFileMappingW` on the descriptor's handle, read-write when the descriptor is, otherwise read-only), so writes through the descriptor and the mapping see each other. This also maps anonymous `shm_open` objects and JIT shared memory descriptors, which are temporary files on Windows. A shared mapping may end inside the 16 KiB page that holds the end of the file, as POSIX [`mmap`](https://pubs.opengroup.org/onlinepubs/9799919799/functions/mmap.html) allows (llama.cpp in PS5LM Plus PPSA99581 maps a whole model file this way): the section keeps the file's size, so the file never grows, the view ends with the 4 KiB host page that holds the end of the file, which Windows fills with zeros past it, and the rest of the guest page is private zero pages. As POSIX requires, the bytes past the end read zero and are never written to the file; bytes written to those private pages are seen only through that mapping, not through other mappings of the file, and a file that grows later does not show its new bytes there. A shared mapping that reaches a whole page past the end of the file fails with `EOPNOTSUPP`, where POSIX maps it and delivers `SIGBUS` on access, as do `PROT_EXEC` and a write-only descriptor. A read-write alias (`GuestArenaMapAlias`) of a mapped page that holds the end of the file throws. `mprotect` above the view's protection (writing through a read-only descriptor, or adding `PROT_EXEC`) fails with `EACCES` before anything changes; FreeBSD allows `PROT_EXEC` on a readable descriptor. Shrinking the file with `ftruncate` fails with `EINVAL` while any shared mapping of it exists, even one that does not cover the removed part, because the section keeps the file's size at `mmap`; FreeBSD truncates. A read-write alias of a view (`GuestArenaMapAlias`, used when the GPU imports guest memory) of a read-only file section fails, as the alias is mapped `PAGE_READWRITE`. Views of the same file made by separate `mmap` calls are separate sections, so write tracking does not treat them as aliases of each other. A private mapping on Windows is a copy of the file read at `mmap`, which POSIX allows (later changes to the file need not show); pages wholly past the end of the file fail with `EOPNOTSUPP` instead of faulting on access, and a write-only descriptor fails with `EOPNOTSUPP`. - [File mappings on macOS](../../../core/libs/prx/libkernel/DirectMemory/PosixMemory.cpp) (libkernel) - `mmap` of a regular file, of an anonymous `shm_open` object (an unlinked temporary file on macOS) or of a JIT shared memory descriptor maps the descriptor shared or private as on Linux, with the same access checks. macOS refuses to create an executable file mapping (`EPERM`), so an executable mapping is made without execute and then given it with `mprotect`. Under Rosetta 2 (Apple M2, macOS 26), code rewritten through one view of a file after it ran from another view keeps its old translation until the executable view's protection changes. Named `shm_open` objects still throw on macOS. -- [sendfile](../../../core/libs/prx/libkernel/Socket/src/Udp.cpp) (libkernel) follows FreeBSD 11's `sendfile` for a connected stream socket: headers, the file from `offset` (to its end when `nbytes` is 0) and trailers, the file offset left unchanged, `EAGAIN` with `*sbytes` set after a partial send on a non-blocking socket. It reads the file through `sceKernelPread` in 64 KiB blocks and sends each with `send`. A socket as the file fails with `EINVAL`, as on FreeBSD, but any other descriptor `sceKernelPread` reads, such as `/dev/urandom`, is sent where FreeBSD requires a regular file or shared memory. `flags` are ignored: reads complete before sending, so `SF_NODISKIO` never fails with `EBUSY`, and `SF_SYNC` returns once the data is queued on the socket rather than sent. PS5MC (PPSA99420) imports it +- [sendfile](../../../core/libs/prx/libkernel/Socket/src/Udp.cpp) (libkernel) follows FreeBSD 11's `sendfile` for a connected stream socket: headers, the file from `offset` (to its end when `nbytes` is 0) and trailers, the file offset left unchanged, `EAGAIN` with `*sbytes` set after a partial send on a non-blocking socket. It reads the file through `sceKernelPread` in 64 KiB blocks and sends each with `send`. A file that is not a regular file or shared memory, such as a socket, `/dev/urandom` or a kqueue, fails with `EINVAL` and `*sbytes` 0, as FreeBSD's [`sendfile_getobj`](https://github.com/freebsd/freebsd-src/blob/8c639945a44588f6cfdddfb057bb5aad88735da0/sys/kern/kern_sendfile.c#L421-L463) refuses it. `flags` are ignored: reads complete before sending, so `SF_NODISKIO` never fails with `EBUSY`, and `SF_SYNC` returns once the data is queued on the socket rather than sent. PS5MC (PPSA99420) imports it - [pthread_kill](../../../core/libs/prx/libkernel/System/src/Signals.cpp) (libkernel) returns the error number like FreeBSD's `pthread_kill`: `EINVAL` for signals outside 0 to 128 and `ESRCH` for a null thread. A signal to the calling thread goes through `raise`, so it shares `raise`'s limits; a signal to another thread is left on the pending set for whichever thread waits for or unblocks it, since it is not delivered to the chosen thread, and a handle that is not a live guest thread returns `ESRCH` without touching it - [select](../../../core/libs/prx/libkernel/Socket/src/Socket.cpp) (libkernel) validates `tv_usec` but saturates a valid timeout beyond the remaining `steady_clock` range at `time_point::max()`, so the wait can continue effectively indefinitely. The console's behavior for a valid timeout outside the host clock's range is unknown. - [inet_ntop, inet_pton](../../../core/libs/prx/libkernel/Socket/src/AddressConversion.cpp) (libkernel) - an `AF_INET6` result of `inet_ntop` is followed by zero bytes up to `size`. In a payload process on a PS5 (firmware 12.70), the text forms, the order of the checks and this padding were measured through both exports. The padding was sampled at sizes from 3 to 65536, above 64 only at 65, 128, 256, 1024, 4096 and 65536; the sizes that were not sampled, sizes above 65536 and a title process are assumed to behave the same @@ -273,7 +279,7 @@ - [pthread_cond_reltimedwait_np](../../../core/libs/prx/libkernel/Pthread/Posix/Cond.cpp) (libkernel) takes `(cond, mutex, usec)`, a relative timeout in microseconds, and is `scePthreadCondTimedwait` with POSIX error numbers. FreeBSD 11.4 has no such function; the signature comes only from shadPS4, which registers one function for this NID and for `scePthreadCondTimedwait` ([`condvar.cpp`](https://github.com/shadps4-emu/shadPS4/blob/3a9f57265d28975658f1ca941daa5c879c7a74bd/src/core/libraries/kernel/threads/condvar.cpp#L229-L234)). shadPS4 reads a 64-bit count; here it is the 32-bit `SceKernelUseconds` of the SCE twin, as for `sem_reltimedwait_np`. Unverified on the console - [pthread_mutex_reltimedlock_np](../../../core/libs/prx/libkernel/Pthread/Posix/Mutex.cpp) (libkernel) takes `(mutex, usec)`, a relative timeout in microseconds, and is `scePthreadMutexTimedlock` with POSIX error numbers. FreeBSD 11.4 has no such function; the signature comes only from shadPS4, which registers one function for this NID and for `scePthreadMutexTimedlock` ([`mutex.cpp`](https://github.com/shadps4-emu/shadPS4/blob/7c960eae136b956cf4c1d72aacd2426b650330df/src/core/libraries/kernel/threads/mutex.cpp#L284-L287)). shadPS4 reads a 64-bit count; here it is the 32-bit `SceKernelUseconds` of the SCE twin, as for `pthread_cond_reltimedwait_np`, so a count of 2^32 microseconds or more would be truncated if the console reads 64 bits. Unverified on the console - [sysctl kern.arandom](../../../core/libs/prx/libkernel/System/src/SystemConfiguration.cpp) (libkernel) serves FreeBSD 11's MIB {1, 37} (CTL_KERN, KERN_ARANDOM) and the "kern.arandom" sysctlbyname lookup through std::random_device, returning min(*oldLength, 256) random bytes. Following FreeBSD's sysctl_kern_arnd, a null buffer reports min(*oldLength, 256) without writing, a null length returns 0 without writing, and requests with a new value return EPERM (1) as the node is read-only. Cryptographic quality depends on the host's random device implementation. -- [pthread_atfork](../../../core/libs/prx/libkernel/Pthread/Posix/Atfork.cpp) (libkernel) appends the three handlers to a process-wide list and returns 0, or `ENOMEM` when the entry cannot be allocated, as FreeBSD 11.4's [`_pthread_atfork`](https://github.com/freebsd/freebsd-src/blob/8c639945a44588f6cfdddfb057bb5aad88735da0/lib/libthr/thread/thr_fork.c#L78-L100) does; null handlers are accepted. The handlers never run: `fork` throws and `vfork` is absent, so no child process is created. Handlers of a module that is unloaded stay in the list, where FreeBSD's `__pthread_cxa_finalize` removes them. PPSA97358 has a source-level call from the constructor `rcu_init` ([rcu.c](https://github.com/ZiZc3/XPSemu/blob/8eec07b4e31f66dce8e0b05c1ca1281af303e933/util/rcu.c#L488-L495)), but current-main runtime reachability is unverified; XPSemu currently stops first at the unresolved `mlockall` import (#4386) +- [pthread_atfork](../../../core/libs/prx/libkernel/Pthread/Posix/Atfork.cpp) (libkernel) appends the three handlers to a process-wide list and returns 0, or `ENOMEM` when the entry cannot be allocated, as FreeBSD 11.4's [`_pthread_atfork`](https://github.com/freebsd/freebsd-src/blob/8c639945a44588f6cfdddfb057bb5aad88735da0/lib/libthr/thread/thr_fork.c#L78-L100) does; null handlers are accepted. The handlers never run: `fork` throws and `vfork` is absent, so no child process is created. Handlers of a module that is unloaded stay in the list, where FreeBSD's `__pthread_cxa_finalize` removes them. PPSA97358 has a source-level call from the constructor `rcu_init` ([rcu.c](https://github.com/ZiZc3/XPSemu/blob/8eec07b4e31f66dce8e0b05c1ca1281af303e933/util/rcu.c#L488-L495)), but current-main runtime reachability is unverified - [sceKernelGetPageTableStats](../../../core/libs/prx/libkernel/DirectMemory/Export.cpp) (libkernel) reports 8192 entries on each side and counts them as a PS5 (firmware 13.60) counted them for a payload process: one cpu entry for each 2 MiB granule that holds a committed mapping, whatever its protection (none included), and one gpu entry for each 1 GiB region that holds a GPU-accessible mapping, plus one for each 2 MiB granule of such a mapping that is not a whole granule of direct memory at a 2 MiB-aligned physical address. A granule or region shared by several mappings counts once, and reservations do not count. On the console the first GPU mapping of a process also takes three gpu entries and one cpu entry that stay after it is unmapped, which is not modelled, and only the ranges whose protection is recorded here are counted. A null pointer returns `SCE_KERNEL_ERROR_EFAULT`, where the console faults. Resonance: A Plague Tale Legacy (PPSA30601) calls it at start-up (#4067) - [clock_settime](../../../core/libs/prx/libkernel/Time/Time.cpp) (libkernel) validates like FreeBSD 11.4's [`kern_clock_settime`](https://github.com/freebsd/freebsd-src/blob/8c639945a44588f6cfdddfb057bb5aad88735da0/sys/kern/kern_time.c#L396-L412) for a root caller: `EFAULT` for a null time, `EINVAL` for any clock but `CLOCK_REALTIME`, a negative second count or a nanosecond count outside 0 to 999999999. A valid `CLOCK_REALTIME` request throws, naming the requested time, since the host clock is never set and no guest clock offset is kept. FreeBSD checks `PRIV_CLOCK_SETTIME` first, which a jailed process fails with `EPERM`; whether a title holds it on the console is unverified. PS5MC (PPSA99420) imports it; no call site is known - [Short sleeps ended by GPU and flip completions](../../../core/libs/prx/libkernel/Time/SleepWake.cpp) (libkernel) - a `sceKernelUsleep`, `usleep`, `nanosleep` or `sceKernelNanosleep` of 1 ms or less returns before the requested time, which FreeBSD and the console do not do: it ends once the AGC driver reports a completed GPU batch or batch completion action, or VideoOut completes a flip, so a title that polls a GPU label or the flip status between sleeps does not sleep the rest. A title that paces frames with such a sleep can wake up to 1 ms early. A thread returns early at most 8 times in a run of sleeps; the run restarts when the thread submits AGC work or did not sleep the requested time since its last sleep, so a loop that counts sleeps to time out still sleeps all but 8 in full. `APS5_NO_SLEEP_WAKE=1` keeps every sleep in full diff --git a/docs/dev/debt/libkernel_sys.md b/docs/dev/debt/libkernel_sys.md index a79103f587..318740aa6a 100644 --- a/docs/dev/debt/libkernel_sys.md +++ b/docs/dev/debt/libkernel_sys.md @@ -30,7 +30,7 @@ - [chroot](../../../core/libs/prx/libkernel_sys/Export.cpp) (libkernel_sys) follows FreeBSD 11.4's [`sys_chroot`](https://github.com/freebsd/freebsd-src/blob/8c639945a44588f6cfdddfb057bb5aad88735da0/sys/kern/vfs_syscalls.c#L776-L807) and [`pwd_chroot`](https://github.com/freebsd/freebsd-src/blob/8c639945a44588f6cfdddfb057bb5aad88735da0/sys/kern/kern_descrip.c#L3059-L3085) for a root caller: `EFAULT` for a null path, `ENOENT` for an empty or missing one, `ENAMETOOLONG` for a path of 1024 bytes or more or a component over 255, and `ENOTDIR` for a path that is not a directory or passes through a file. A directory that is the guest root (`/`, `/..`, or `.` after `fchdir` to a descriptor of `/`) succeeds and changes nothing, as the root stays the same directory; the guest is taken never to have changed its root, so open directory descriptors do not make it fail with `EPERM` (`kern.chroot_allow_open_directories` 1). Any other directory throws, naming the path: the guest path resolver has a fixed root and mount aliases (`/app0`, `/savedata0`) that do not move with it. On the console a title starts in a sandbox root, where `pwd_chroot` refuses with `EPERM` while a directory is open; whether that holds for titles, and whether a title holds `PRIV_VFS_CHROOT`, are unverified. Porpoise (PPSA99764) weak-imports it and calls it only as `fchdir` to its saved descriptor of `/` then `chroot(".")`, to put its sandbox root back after a jailbreak daemon replaced it ([`put_root_back`](https://github.com/elripalda/Porpoise-Dolphin-Emulator-for-PS5/blob/2ed1ab5a06995aa198f7bccd4da0f90c3fc29d39/src/porpoise_jailbreak.cpp#L303-L331)) - [fchown](../../../core/libs/prx/libkernel_sys/Export.cpp) (libkernel_sys) - ownership is not modelled: the guest's own owner and group (0) and the unchanged value (-1) are accepted, a descriptor that is not open fails with `EBADF`, and any other owner or group throws, naming it. The check reads the descriptor with `fstat`, ignoring the CRT's invalid-parameter handler on Windows as `DescriptorControl` does. The console's ownership rules are unverified. Morrowind (`mshivam019/morrowind-ps5`) imports it - [chown, lchown and fchownat](../../../core/libs/prx/libkernel_sys/Export.cpp) (libkernel_sys) - ownership is not modelled, as for `fchown`: owner and group 0 and the unchanged value (-1) are accepted, and any other owner or group throws, naming it. The path is looked up first, as in FreeBSD 11's `kern_fchownat`, with `stat`, with `lstat` for `lchown`, and with `fstatat` for `fchownat`, so a lookup error is returned before the owner is checked and nothing is changed on the host. `fchownat` flags other than `AT_SYMLINK_NOFOLLOW` (0x200) return `EINVAL`, as in FreeBSD 11. The console's ownership rules are unverified -- [linkat](../../../core/libs/prx/libkernel_sys/Export.cpp) (libkernel_sys) passes `AT_FDCWD` (-100) and absolute paths to `link`, and flags other than `AT_SYMLINK_FOLLOW` (0x400) return `EINVAL`, as in FreeBSD 11. A relative path with a directory descriptor throws, and so does a symbolic link as the source without `AT_SYMLINK_FOLLOW`, where FreeBSD links the symbolic link itself. Console behaviour is unverified +- [linkat](../../../core/libs/prx/libkernel_sys/Export.cpp) (libkernel_sys) resolves `AT_FDCWD` (-100) and absolute paths as `link` does, and flags other than `AT_SYMLINK_FOLLOW` (0x400) return `EINVAL`, as in FreeBSD 11. Any other relative path is joined to the descriptor's host directory, found the same way as for `fchdir`, so guest path aliases and case-insensitive name matching do not apply to it, and a `..` component is not kept inside the guest root. It returns `EBADF` for a descriptor that is not open and `ENOTDIR` for one that is not a directory. A symbolic link as the source without `AT_SYMLINK_FOLLOW` throws, where FreeBSD links the symbolic link itself. Console behaviour is unverified - [pthread_set_defaultstacksize_np and scePthreadSetDefaultstacksize](../../../core/libs/prx/libkernel_sys/Export.cpp) (libkernel_sys) set the stack size that `scePthreadAttrInit` and a thread created without attributes use, as [fpPS4's `pthread_set_defaultstacksize_np`](https://github.com/red-prig/fpPS4/blob/04cefd4/kernel/ps4_pthread_attr.pas#L89-L102) does: a size of 16384 bytes or less fails with `EINVAL` (`0x80020016` from the sce form) and there is no upper limit, so a default the host cannot allocate fails only when a thread is created. Attributes initialised earlier keep their size. Not checked on a PS5 - [sceKernelTitleWorkaroundIsEnabled](../../../core/libs/prx/libkernel_sys/Export.cpp) (libkernel_sys) - not measured on a console; the `{version, align, ids[2]}` layout, the bit test and the limit of 0x3A bits follow [shadPS4](https://github.com/shadps4-emu/shadPS4/blob/a808e76/src/core/libraries/kernel/kernel.cpp), which notes that the limit changes between firmwares. A negative bit is `EINVAL` here; shadPS4 compares it signed and reads outside `ids`. Titles usually pass the `title_workaround` block of `sceKernelGetAppInfo`, which does not write that block here, so the bits read are whatever the caller's memory held - [sceKernelGetProcessType](../../../core/libs/prx/libkernel_sys/Export.cpp) (libkernel_sys) - not measured on a console; as in shadPS4, the title's own pid, -1 and 0 are type 0 (big application) and any other pid is `ESRCH` diff --git a/docs/dev/debt/relinker.md b/docs/dev/debt/relinker.md index 241d10f16f..d91f5cd055 100644 --- a/docs/dev/debt/relinker.md +++ b/docs/dev/debt/relinker.md @@ -10,7 +10,7 @@ - [Runtime-loaded modules the executable needs](../../../core/relinker/relinker/src/guest/GuestModuleBuilder.cpp) (`--module-dir`) are mapped at startup on Windows and started when the title loads them with `sceKernelLoadStartModule`, with their start arguments, as a Unity player loads `mono-ps4.sprx`. A title that calls such a module before loading it finds its initializers not run; whether the console starts it earlier is not measured. A module the executable only imports from and the title never loads itself gets no `module_start` and no initializers at all under this deferral. The [entry stub](../../../core/relinker/elfpatcher/src/windows/WindowsEntryStubBuilder.cpp) prints `Deferred module ` at startup for each such module that an import of the executable names, whether or not the title loads it later; an import without a module name is not reported. macOS still starts it at startup. - The executable file that [relinker](../../../core/relinker/elfpatcher/src/windows/WindowsPeWriter.cpp) generates opens a console when launched, unless it is relinked with `--windows-gui`, which selects the GUI subsystem. A GUI build started from Explorer has no standard output or error handle; the [entry stub](../../../core/relinker/elfpatcher/src/windows/WindowsEntryStubBuilder.cpp) gives each missing one `anyps5.log` beside the executable, replacing the previous run's file (#3282). Errors about the executable path or about waiting for the previous LoadExec process are written before the log is opened and are lost when the standard error handle is missing. If the log cannot be created, output to the missing handles is lost. - [Guest import registries](../../../core/relinker/relinker/src/guest/GuestModuleBuilder.cpp) - declared host imports of bundled modules are recorded with their module name and relocation target, even when another guest module exports the same stripped NID. No-op relocations are omitted. Registries describe import bindings, not implementation correctness or runtime reachability. -- Converted Windows main executables [omit `DYNAMIC_BASE`](../../../core/relinker/elfpatcher/src/windows/WindowsPeWriter.cpp) by default, not only with `--windows-fixed-base`: on the console the executable lies inside the 40-bit window that the title's own `sceLibcMspaceCreate` checks (#3043). Relocations are kept, so if `0x140000000` is taken Windows relocates the image, possibly above that window. Verified only on Windows 10. +- Converted Windows main executables [omit `DYNAMIC_BASE`](../../../core/relinker/elfpatcher/src/windows/WindowsPeWriter.cpp) and [prefer `0x400000`](../../../core/relinker/elfpatcher/src/windows/WindowsPePatcher.cpp) for their lowest ELF load page by default, not only with `--windows-fixed-base`: on the console the executable lies inside the 40-bit window that the title's own `sceLibcMspaceCreate` checks (#3043). Where the console loads an executable that does not require an address is not measured; `0x400000` is the base that executables reading their GOT through `app0/imports.txt` assume (#4013). Relocations are kept, so if that range is taken Windows can relocate the image, possibly above that window; no run has observed this, and from this base an image cannot reach the shared user data page at `0x7ffe0000`, since Windows refuses a `SizeOfImage` above `0x77000000` (#9332). Verified on Windows 11 only. - [SDK memory-management syscall traps](../../../core/relinker/relinker/src/analysis/SyscallScanner.cpp) under `--trap-sdk-syscall-stubs` recognize three exact instruction sequences from [ps5-payload-dev SDK libc/mman.c](https://github.com/ps5-payload-dev/sdk/blob/12cf3dda40/libc/mman.c), observed in Nuvio Maxd 0.5.15 (PPSA99288): syscall 74 and the two syscall 477 paths, with their argument preparation and carry-flag error handling. Matching requires a decoded instruction boundary and the complete sequence inside the scanned code range. Other SDK/compiler output remains rejected. The matched syscall becomes `UD2`; this does not implement mmap or mprotect and a call still faults. - The [instruction decoder](../../../core/relinker/codegen/src/x86/X64InstructionDecoder.cpp) reads a 16-bit displacement for `66 E8`, `66 E9` and `66 0F 80`-`8F` without REX.W, as AMD processors, the console included, do (binutils `objdump -M amd64`; REX.W selects the 32-bit form). AMD also truncates the target of every near relative branch with that prefix, rel8, LOOP and JRCXZ forms included, to 16 bits. Instruction metadata marks these branches as truncated and reports no branch target for them, and stubs refuse to move them. Compilers do not emit these forms. - Converted Linux main executables are [placed at `0x400000`](../../../core/relinker/relinker/src/pipeline/Conversion.cpp) by default, as `ET_EXEC` without ASLR, not only with `--linux-fixed-base`: the console executable lies inside the 40-bit window that the title's own `sceLibcMspaceCreate` checks (#3043). Where the console loads an executable that does not require an address is not measured; `0x400000` is the base that executables reading their GOT through `app0/imports.txt` assume (#4013). The relinker refuses an image that spans 2 GiB or more, so the executable ends below the guest arena at `0x200000000`. With `--lazy-binding` the executable stays position independent. diff --git a/docs/dev/debt/shader.md b/docs/dev/debt/shader.md index 6919cefeed..6c372caccf 100644 --- a/docs/dev/debt/shader.md +++ b/docs/dev/debt/shader.md @@ -22,7 +22,7 @@ - [s_subvector_loop_begin and s_subvector_loop_end](../../../core/shader/recompiler/Translation/src/ControlFlowInstructions.cpp) (core/shader/recompiler) - follow AMD's RDNA 2 instruction set reference and a gfx1036 (wave64) measurement, pinned in [SubvectorLoop.cpp](../../../core/libs/prx/libSceAgcDriver/tests/execution/SubvectorLoop.cpp); `S0` in the end instruction's `elif(S0 == 0)` is read as its SGPR operand. A wave32 shader and a destination other than an SGPR throw because neither is measured. The begin instruction tests for an empty mask as `(exec_lo | exec_hi) == 0`: AMD's Windows driver (32.0.21045.5002 and 32.0.21042.62) compiled `exec_lo == 0 && exec_hi == 0` as a test of the whole 64-bit mask when guest loads use selects, as they do with `robustBufferAccess2` (#7376, #7623). Measured on PC RDNA2 (Radeon 610M), not on a PS5. The [specialization pass](../../../core/shader/recompiler/SpirvBackend/src/SpirvSpecialization.cpp) keeps a constant-condition branch whose untaken target is a loop header, since folding it removes the loop's back edge, which SPIR-V requires exactly once per loop header (SPIRV-Tools rejects the module and the NVIDIA driver 615.78.08 crashes compiling it); a loop whose back-edge block becomes unreachable in another way is not handled - [Vertex entry merged wave info](../../../core/shader/recompiler/Translation/src/InstructionTranslator.cpp) (recompiler) - `s3` of every vertex-path shader is set to `waveSize | waveSize << 8` (vertex and primitive count of a full wave, wave index 0), or to `32 | 32 << 8` for a wave64 program on a 32-lane host subgroup, which runs it at one lane per invocation and holds no lanes 32-63. On a device whose `subgroupSupportedStages` lacks the vertex stage (lavapipe, MoltenVK), vertex and local programs run as one-lane waves: `s3` is `1 | 1 << 8`, the lane id is 0, a ballot is the invocation's own bit, a shuffle or broadcast returns the invocation's value, an elect is true and a subgroup reduction is the value itself, so no `GroupNonUniform` capability is declared. Layout taken from the prologue Mesa's ACO emits for NGG vertex shaders (`s_bfe_u64 exec` from `s3`), not measured on hardware. The driver gives every graphics program user data from `s8`, so the condition does not tell NGG from legacy vertex shaders: they just never read `s3`. A draw whose last wave is partial still reports a full wave, and so does a host wave with idle invocations (an RTX 5070 ran every vertex warp of a non-indexed triangle list with 30 of its 32 invocations). - [s_barrier in vertex-path programs](../../../core/shader/recompiler/SpirvBackend/src/SpirvFlowEmitter.cpp) (recompiler) - emits no instruction when the program has no LDS or GDS access and no memory write or atomic, so no wave of the subgroup can observe another, or when the barrier runs before every memory access of the program (it is on the entry's straight-line path with no load, store, atomic, image or LDS access ahead of it), so it orders nothing; the `GS_ALLOC_REQ` such a barrier orders on NGG passthrough programs is already dropped on the vertex path. The Vertex execution model has no workgroup barrier. Other programs with LDS, GDS or memory writes throw. Not measured on hardware -- [Vertex clip and cull distances](../../../core/shader/recompiler/Translation/src/ShaderInputInfoBuilder.cpp) (libSceAgcDriver) - `PA_CL_VS_OUT_CNTL` enable bit `s` of `CLIP_DIST_ENA`/`CULL_DIST_ENA` is taken to select component `s` of the `pos1`/`pos2` exports, with the Vulkan array index counted by the enabled bits below it, and `VS_OUT_CCDIST0_VEC_ENA` as bit 22; this follows the recompiler's existing position-export mapping, not hardware or documentation. The guest clip distances share one `gl_ClipDistance` array with the all-zero clip position distance, which takes the index after them. A vertex program whose own code has no `pos1`..`pos3` export is compiled and prepared without these bits (`PositionExportLayout`), so registration and draws agree on its artifact; an export in a subroutine it calls is not seen by that scan +- [Vertex clip and cull distances](../../../core/shader/recompiler/Translation/src/ShaderInputInfoBuilder.cpp) (libSceAgcDriver) - `PA_CL_VS_OUT_CNTL` enable bit `s` of `CLIP_DIST_ENA`/`CULL_DIST_ENA` is taken to select component `s` of the `pos1`/`pos2` exports, with the Vulkan array index counted by the enabled bits below it, and `VS_OUT_CCDIST0_VEC_ENA` as bit 22; this follows the recompiler's existing position-export mapping, not hardware or documentation. The guest clip distances share one `gl_ClipDistance` array with the all-zero clip position distance, which takes the index after them. A vertex program whose own code has no `pos1`..`pos3` export is compiled and prepared without these bits (`PositionExportLayout`), so registration and draws agree on its artifact; an export in a subroutine it calls is not seen by that scan. A device without `shaderCullDistance` (MoltenVK) throws on a draw that enables a cull distance; none is emulated. - [32_AR color exports](../../../core/shader/recompiler/SpirvBackend/src/SpirvModuleEmitter.cpp) (shader recompiler) - with `SPI_SHADER_COL_FORMAT` 3 the red value is export channel 0 and the alpha is export channel 1, the GFX10 layout of Mesa's [`emit_ps_color_export`](https://gitlab.freedesktop.org/mesa/mesa/-/blob/3e32b0e1f132231b7a972c1b0b5b06c7e16cf8b9/src/amd/common/nir/ac_nir_lower_ps_late.c#L400-L411), ACO and radeonsi in Mesa 22.0 ([aco_instruction_selection.cpp](https://gitlab.freedesktop.org/mesa/mesa/-/blob/a82920af6efa4a7a66919885c6477fbd8fdc7b9d/src/amd/compiler/aco_instruction_selection.cpp#L11087-L11096), [si_shader_llvm_ps.c](https://gitlab.freedesktop.org/mesa/mesa/-/blob/a82920af6efa4a7a66919885c6477fbd8fdc7b9d/src/gallium/drivers/radeonsi/si_shader_llvm_ps.c#L323-L333)) and AMD's [LLPC](https://github.com/GPUOpen-Drivers/llpc/blob/40cb8d95ad8d6f7f1652e3fd47d39667594cce08/lgc/lowering/FragmentColorExport.cpp#L157-L168); before GFX10 the alpha was channel 3. Channels 2 and 3, which none of these compilers enables, are ignored; green and blue are 0 and the alpha of an export without channel 1 is 1.0, the defaults of the other formats, which no source gives. Not measured on hardware, neither on gfx1013 nor on a PC RDNA 2 GPU; pinned in [Pixel32ArExport.cpp](../../../core/libs/prx/libSceAgcDriver/tests/execution/Pixel32ArExport.cpp) - [GCN instructions](../../../core/shader/recompiler/RdnaDecoder/src/GcnInstructionDecoder.cpp) (shader, PS4) - PS4 (Sea Islands) instructions are re-encoded to their RDNA encodings with opcode tables built from shadPS4's `opcodes.h` and decoded by the RDNA decoder; an encoding without an RDNA counterpart throws. MIMG has no DIM field on GCN: the dimension is taken as 2D, or 2D array when DA is set, and the [materializer](../../../core/shader/recompiler/Optimization/src/ResourceMaterializer.cpp) rejects a T# whose type needs another address count. MIMG word 1 bits [31:26] are reserved on GCN (A16 and D16 on RDNA). - [GCN buffer and image descriptors](../../../core/shader/recompiler/RdnaDecoder/src/RdnaDescriptorFormat.cpp) (shader, PS4) - a GCN V# word 3 (DATA_FORMAT [18:15], NUM_FORMAT [14:12], names read from the most significant field) is rewritten to the unified format of the PS5 layout with OOB_SELECT 1 for a strided buffer and 3 otherwise, following the GFX6-7 NUM_RECORDS rules in Mesa's `ac_descriptors`; ATC, HASH, HEAP and MTYPE are dropped. The V# base is 44 bits, as in shadPS4's `AmdGpu::Buffer`: Limbo leaves 0x7 in word 1 bits [15:12]. A GCN T# is rewritten to the PS5 layout with SW_MODE linear, keeping TILING_INDEX [4:0], POW2_PAD [5] and PITCH - 1 [19:6] in word 7. None of it is checked on a console. @@ -54,7 +54,7 @@ - An [image table](../../../core/shader/recompiler/Optimization/src/ResourceMaterializer.cpp) T# of an MSAA or FMASK image, or of a color format under a depth compare, faults when selected: tables have no multisampled descriptors and no emulated color compare. - Direct [FMASK image loads](../../../core/shader/recompiler/Optimization/src/ResourceMaterializer.cpp) of 16 samples, CMASK compression (bar the 8-fragment native owner path), packed accesses and other layouts throw. Uncompressed FMASK of up to 8 samples reads a single-mip 2D or 2D-array 8-, 16- or 32-bit `UINT` snapshot with `Z_64KB_X` addressing; selectors may name X, zero or one. `Fmask32_S8_F8` returns the stored word; others expand to 4 bits per sample, an index at or past the fragment count reading 8 (unknown), samples past the count 0. Layouts follow PAL's [expanded values](https://github.com/GPUOpen-Drivers/pal/blob/c5e800072a32f68b6ccc4422936d96167c6e0728/src/core/hw/gfxip/gfx9/gfx9MaskRam.cpp#L5005) and [FMASK surfaces](https://github.com/GPUOpen-Drivers/pal/blob/c5e800072a32f68b6ccc4422936d96167c6e0728/src/core/imported/addrlib/src/core/addrlib2.cpp#L877). Console results, unused nibbles included, are unmeasured; compressed color sampling is unsupported. - A [DIM 2D read of a 2D MSAA T#](../../../core/shader/recompiler/Optimization/src/ResourceMaterializer.cpp) returns sample 0, which is not measured on the console's gfx1013, at an implicit LOD above 0, at an explicit one for texels over 16 bits except formats 22 and 56 in SW_64KB_R_X, or for other formats and swizzle modes; 64- and 128-bit SW_64KB_Z_X texels are not covered: gfx1031 does not address their samples. Such a read is an `image_load` without a mip, `image_sample`, `image_sample_lz` or `image_sample_l` of a direct sampled image; other accesses (gathers, bias, gradients, offsets, LOD clamps, depth compares, `image_load_mip`, `image_get_resinfo`, `image_get_lod`, PCK, BY2/BY4) throw, as does a depth-bits T# (16_UINT, 32_UINT or 32_SINT in a Z swizzle mode). On gfx1031 (RX 6700 XT, HIP), such reads return sample 0 at 2x, 4x and 8x for 8- to 128-bit texels in SW_64KB_R_X and 8- to 32-bit ones in SW_64KB_Z_X (formats 1, 5, 7, 11, 13, 14, 18, 22, 29, 56, 60, 64, 71, 77, 133). -- `image_store_mip`, `image_store_pck`, PCK2/PCK4 and MIMG BY2/BY4 through an [image table](../../../core/shader/recompiler/SpirvBackend/src/SpirvImageEmitter.cpp) T# fault (`unsupported operation`) when an active lane executes them; the store is dropped and the load reads zeros. 32-bit image atomics through a table lower to `OpAtomic*` on the table `AtomicView` (`Device` scope, relaxed, `AcquireRelease`/`UniformMemory` barrier, as the direct path) instead of faulting; 64-bit atomics still fault (no `Atomic64View` on the table path). +- `image_store_mip`, `image_store_pck`, PCK2/PCK4 and MIMG BY2/BY4 through an [image table](../../../core/shader/recompiler/SpirvBackend/src/SpirvImageEmitter.cpp) T# fault (`unsupported operation`) when an active lane executes them; the store is dropped and the load reads zeros. 32-bit and 64-bit image atomics through a table lower to `OpAtomic*` on the table `AtomicView`/`Atomic64View` (`Device` scope, relaxed, `AcquireRelease`/`UniformMemory` barrier as the direct path) instead of faulting; the host needs `VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT` for the view format. Packed formats and BY element counts still fault. - An [image table](../../../core/shader/recompiler/Optimization/src/ResourceMaterializer.cpp) S# with a min or max reduction or FORCE_UNNORMALIZED faults when selected, as does an integer, converted or depth-bits table T# paired with a direct min or max S# that filters between texels. - Uint and Sint [image table](../../../core/shader/recompiler/SpirvBackend/src/SpirvMemory/SpirvDescriptors.cpp) entries and direct T#s under a table S# sample through a point-filtered copy of the S#: Vulkan leaves linear filtering of integer formats undefined; the console is assumed to point-sample. - Comparison sampling of a color texture through an [image table](../../../core/shader/recompiler/Optimization/src/ResourceMaterializer.cpp) S# throws at the first dispatch or draw that binds it. @@ -86,9 +86,9 @@ - [8_SRGB and 8_8_SRGB loads](../../../core/shader/recompiler/SpirvBackend/src/SpirvImageEmitter.cpp) on a device that cannot sample R8_SRGB or R8G8_SRGB return the sRGB EOTF rounded to nearest even at bf16 precision, as adriadam10 measured on RDNA2 (gfx1035) in #866; the PS5's gfx1013 is not measured. This is the path on a device that cannot blit R8 or RG8 to RGBA8, and with `APS5_SRGB_SHADER_DECODE=1`; otherwise a load of a sampled texture reads the RGBA8 sRGB copy and gets the device's own decode. - [Samples and gathers](../../../core/shader/recompiler/SpirvBackend/src/SpirvImageEmitter.cpp) of 8_SRGB and 8_8_SRGB textures read an RGBA8 sRGB copy of the texture (libSceAgcDriver, [Texture.cpp](../../../core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp)) on a device that cannot sample R8_SRGB or R8G8_SRGB but can blit R8 or RG8 to RGBA8, so they use that device's own decode. They still throw on a device that cannot blit, and with `APS5_SRGB_SHADER_DECODE=1`. `APS5_SRGB_SHADER_DECODE=copy` also takes the copy on a device that samples these formats natively, so the copy can be tested on any device that can blit R8 or RG8 to RGBA8; on a device that cannot blit, it behaves like `APS5_SRGB_SHADER_DECODE=1`. A multisampled or depth view of these formats gets no copy. - [Bindless image table](../../../core/shader/recompiler/Optimization/src/ResourceMaterializer.cpp) entries of 8_SRGB and 8_8_SRGB textures read zeros, like converted formats, on a device that cannot sample R8_SRGB or R8G8_SRGB. -- [Shader MODE register access](../../../core/shader/recompiler/Translation/src/RoundingMode.cpp) starts from the rounding fields of `GuestContext::floatMode` and follows immediate rounding writes (`s_round_mode`, `s_setreg_imm32_b32` on MODE bits 0-3) through the control flow graph; `s_getreg_b32` of those bits returns the tracked value. Only `v_cvt_f32_i32`, `v_cvt_f32_u32`, `v_ldexp_f32`, the f16 conversions and `v_ldexp_f16` (with f16 denormals kept) and the instructions that already read `FLOAT_MODE` follow a rounding mode set at run time; any other float instruction that runs while a directed rounding mode differs from the initial one throws at that instruction. Rounding bits written from an SGPR (`s_setreg_b32`) or that differ between the paths reaching an instruction throw where they are read or used. A shader without `FLOAT_MODE` metadata throws on any rounding change. Non-rounding register reads still throw; `s_setreg_b32` writes to other hardware registers are still ignored. Tests follow the public RDNA2/LLVM contract, not console measurements. +- [Shader MODE register access](../../../core/shader/recompiler/Translation/src/RoundingMode.cpp) starts from the rounding fields of `GuestContext::floatMode` and follows immediate rounding writes (`s_round_mode`, `s_setreg_imm32_b32` on MODE bits 0-3) through the control flow graph; `s_getreg_b32` of those bits returns the tracked value. Only `v_cvt_f32_i32`, `v_cvt_f32_u32`, `v_ldexp_f32`, `v_cvt_pk_u8_f32`, the f16 conversions and `v_ldexp_f16` (with f16 denormals kept) and the instructions that already read `FLOAT_MODE` follow a rounding mode set at run time; any other float instruction that runs while a directed rounding mode differs from the initial one throws at that instruction. Rounding bits written from an SGPR (`s_setreg_b32`) or that differ between the paths reaching an instruction throw where they are read or used. A shader without `FLOAT_MODE` metadata throws on any rounding change. Non-rounding register reads still throw; `s_setreg_b32` writes to other hardware registers are still ignored. Tests follow the public RDNA2/LLVM contract, not console measurements. - [Flat scalar-read reachability](../../../core/shader/recompiler/Optimization/src/ResourceTracker.cpp) keeps both successors active for non-clean predicates and loop headers, so an inaccessible direct root on such a path still refuses capture. Skipping a read under a clean, evaluable scalar branch follows RDNA2 conditional PC semantics and synthetic fixtures; console execution and title behavior are unverified. -- [v_cvt_pk_u8_f32](../../../core/shader/recompiler/Translation/src/ConvertInstructions.cpp) throws in f32 denormal modes 1 and 2 and with a directed round mode set at run time (see the previous entry); the PS5's gfx1013 is not measured. Otherwise it rounds its source in the `FLOAT_MODE` f32 round mode (ties to even, toward +infinity, -infinity or zero), clamps it to 0..255 (a NaN gives 0) and flushes a denormal source when f32 denormals are flushed. A kept positive denormal gives 1 toward +infinity, decided on the bits, as a driver without `DenormPreserve 32` may flush it. Measured on RDNA2 (gfx1030, RX 6800, AMD Windows driver 32.0.21045.5002) over 2,133 sources (k/8 for k = -16 to 2,099, values next to 0.5 and 255.5, ±1e10, denormals, infinities, NaNs) at IEEE 0 and 1, f32 denormal modes 0 and 3 and f32 round modes 0 to 3, DX10_CLAMP=1, f16 denormals kept, f16 round to nearest even, FP16_OVFL=0. +- [v_cvt_pk_u8_f32](../../../core/shader/recompiler/Translation/src/ConvertInstructions.cpp): the PS5's gfx1013 is not measured. It rounds its source in the `FLOAT_MODE` f32 round mode (ties to even, toward +infinity, -infinity or zero), clamps it to 0..255 (a NaN gives 0) and flushes a denormal source when f32 denormals are flushed. A kept positive denormal gives 1 toward +infinity, decided on the bits, as a driver without `DenormPreserve 32` may flush it. Measured on RDNA2 (gfx1030, RX 6800, AMD Windows driver 32.0.21045.5002) over 2,133 sources (k/8 for k = -16 to 2,099, values next to 0.5 and 255.5, ±1e10, denormals, infinities, NaNs) at IEEE 0 and 1, f32 denormal modes 0 and 3 and f32 round modes 0 to 3, DX10_CLAMP=1, f16 denormals kept, f16 round to nearest even, FP16_OVFL=0. A round mode set by `s_round_mode` gives the results of the same mode in `FLOAT_MODE`, measured on RDNA2 (gfx1036) over 2,148 such sources in every f32 denormal and round mode. - A [flat SRT read](../../../core/shader/recompiler/Optimization/src/SrtWalker/SrtDescriptorEvaluation.cpp) through a null or unmapped pointer loaded from memory raises a [BDA fault](../../../core/libs/prx/libSceAgcDriver/Graphics/src/BdaResources.cpp) only if the program executes it, then stops or reads zero like a BDA read. - Repeated `s_load`s of one [flat SRT](../../../core/shader/recompiler/Optimization/src/SrtWalker/SrtDescriptorEvaluation.cpp) dword through a null or unmapped pointer report one of their pcs, and an `s_load` whose inaccessible dwords are all unused, or only address repeated loads, reports no fault of its own. - A value read through a null or unmapped pointer still throws at record time if a [uniform fill or table base](../../../core/shader/recompiler/Optimization/src/SrtWalker/SrtDescriptorEvaluation.cpp) needs it, or if the pointer comes from user data and is not null, even if the console skips the read. @@ -126,7 +126,7 @@ - [f16 unary, frexp and conversion denormals](../../../core/shader/recompiler/Translation/src/FloatInstructions.cpp) follow the `FLOAT_MODE` f16 denormal field: `v_ceil_f16`, `v_floor_f16`, `v_fract_f16`, `v_rcp_f16`, `v_rsq_f16`, `v_sqrt_f16`, `v_log_f16`, `v_exp_f16`, `v_sin_f16`, `v_frexp_mant_f16`, `v_frexp_exp_i16_f16`, `v_cvt_norm_i16_f16`, `v_cvt_norm_u16_f16` and `v_cvt_f32_f16` flush a denormal half input to its signed zero when bit 0 is clear (0 and 2), and the f16-result ones flush a denormal half result to its signed zero when bit 1 is clear (0 and 1), after the host rounds it to half. Measured on RDNA2 (gfx1036) at IEEE=0 and IEEE=1 with denorm16 0..3 over every non-NaN f16 input (63,490 rows per mode and instruction): the only mismatches are the 1-ULP driver differences of `v_exp_f16` (2 inputs) and `v_sin_f16` (14), which are the same with denormals kept. NaN inputs are not compared. `v_ldexp_f16` shares the input rule. `v_cvt_pknorm_i16_f16` and `v_cvt_pknorm_u16_f16` flush both half inputs by the same bit, measured on RDNA2 (gfx1030) over every f16 input (each half also negated in the other source) at IEEE=0 and IEEE=1 with denorm16 0..3 and at f16 rounding 1..3: every row matches. Shaders without a known float mode keep the previous lowering. - [v_div_fixup_f16](../../../core/shader/recompiler/Translation/src/FloatInstructions.cpp) flushes its src1 and src2 to a zero of the same sign when bit 0 of the `FLOAT_MODE` f16 denormal field is clear (0 and 2) and keeps a denormal src0 and result in every mode, as `v_div_fixup_f32` does with the f32 field. Measured on RDNA2 (gfx1031, Radeon RX 6700 XT, AMD Windows driver 32.0.21045.5002 through HIP) over 6859 triples of 19 halves (zeros, denormals, minimum normals, ±0.5, ±1, the largest finite value, infinities and quiet and signaling NaNs) at IEEE=0 and IEEE=1 with denorm16 0..3 and FP16_OVFL 0 and 1, also with neg and abs source modifiers and with op_sel high halves. Shaders without a known float mode keep the previous lowering. The PS5's gfx1013 is not measured. - [Packed f16 NaN results](../../../core/shader/recompiler/Translation/src/FloatInstructions.cpp) (`v_pk_add/mul/fma/min/max_f16`) follow the hardware measured on RDNA2 (gfx1035) at IEEE=0 and IEEE=1 with f16 round-to-nearest-even and f16 denormals kept: with IEEE=1 a signaling NaN input is quieted and min/max return the other operand only for a quiet NaN; with IEEE=0 NaN inputs pass through unquieted and min/max ignore signaling. In `v_pk_fma_f16` an invalid product (inf * 0) gives the default NaN even when src2 is a NaN. A shader without a known float mode is translated as IEEE=0, the mode titles use; a mode with another f16 rounding throws. In the f16 denormal modes that flush, each denormal input lane is flushed to a zero of its sign when bit 0 of the field is clear (0 and 2), so `inf * 0x0001` is an invalid product there, and when bit 1 is clear (0 and 1) a `v_pk_add_f16` result below 2^-14, or a `v_pk_mul_f16`, `v_pk_fma_f16` or `v_pk_fmac_f16` result whose exact value rounded to 11 significant bits with an unbounded exponent is below 2^-14, is flushed to a zero of its sign; `v_pk_min/max_f16` flush only their inputs. The native f16x2 add and multiply is not used while results are flushed. Measured on RDNA2 (gfx1031, Radeon RX 6700 XT, AMD Windows driver 32.0.21045.5002 through HIP) at IEEE=0 and IEEE=1 with denorm16 0..3, over 19,192 to 162,204 lanes per instruction with op_sel, op_sel_hi, neg_lo, neg_hi and clamp variants and products and sums at the 2^-14 boundary. -- [f32 denormals](../../../core/shader/recompiler/Translation/src/TranslationContext/OperandAccess.cpp) follow the shader's `FLOAT_MODE` f32 denormal field (bits 5:4) when it flushes them (0, and shaders without a known float mode, as in the 0xc0 most titles use), measured on RDNA2 (gfx1035) over 1444 rows per instruction at IEEE=0 and IEEE=1. `v_add/sub/subrev/mul/mul_legacy/mullit/fma/fmac/fmamk/fmaak/min/max/min3/max3/med3/fract/floor/ceil/frexp_mant/sin/cos_f32` flush their f32 inputs and their result to a zero of the same sign (`v_mullit_f32` measured on RDNA2 (gfx1036) over 6907 rows per mode at IEEE=0 and IEEE=1, so a positive denormal src2 counts as zero); the f32 compares, `v_cvt_i32/u32/rpi_i32/flr_i32_f32`, `v_frexp_exp_i32_f32`, `v_cvt_f64_f32`, `v_cvt_f16_f32`, `v_cvt_pkrtz_f16_f32`, `v_cvt_pknorm_i16/u16_f32` and `v_cvt_pk_u8_f32` flush their f32 inputs. `v_div_scale_f32` flushes all three inputs to signed zeros, measured on RDNA2 (gfx1036) over 2744 operand triples per mode at IEEE=0 and IEEE=1 with f32 denormals flushed and kept; its scale-down behaviour and host denormal preservation remain incomplete. `v_div_fixup_f32` flushes its src1 and src2 and keeps a denormal src0 and result, measured on RDNA2 (gfx1036) over 6859 rows per mode at IEEE=0 and IEEE=1. Tininess is detected after rounding, measured on RDNA2 (gfx1036) for `v_mul_f32` and `v_mullit_f32` at IEEE=0 and IEEE=1: a product is flushed when its value rounded to 24 bits with an unbounded exponent is below 2^-126, so `0x3f7ffffe * 0x00800001` (2^-126 * (1 - 2^-46)) gives `0x00800000` and `0x3f7fffff * 0x00800000` (2^-126 * (1 - 2^-24)) gives zero. The check rounds in the f32 round mode of `FLOAT_MODE` (bits 1:0), measured in all four modes, while the products themselves are still rounded to nearest even. This applies to `v_mul_f32`, `v_mul_legacy_f32`, `v_mullit_f32`, and to `v_fma_f32`, `v_fmac_f32`, `v_fmamk_f32`, `v_fmaak_f32` and `v_fma_mix_f32` when the addend is zero; with a nonzero addend the fused result is kept, so an exact result just below 2^-126 that rounds to it is not flushed. In the three directed modes the check is computed exactly from the significands. To nearest even (0, the mode of shaders without a known float mode) one factor is multiplied by 2^64, which is exact below 2^64, and the product with the other factor is compared with 2^-62. That multiply is a plain `OpFMul` like the product, and no f32 rounding mode is requested in the SPIR-V, so the check relies on the driver rounding f32 to nearest even by default, as the products do, and a product that rounds up to 2^-126 is the emitted product. `v_fma_mix_f32` follows this rule with mixed f16/f32 sources too, measured on RDNA2 (gfx1036) with f16 in either multiplicand slot, low and high half selection, and an f32 or f16 zero addend: f32 `0x00801002` times f16 `0x3bff` gives `0x00800000` to nearest at IEEE=0 and IEEE=1, while the neighbours `0x00801001` and `0x00801003` give zero and `0x00800001`. The tiny-product boundary was also measured for both signs in all four f32 round modes at IEEE=0; Its f16 sources are flushed to a zero of their sign when bit 0 of the f16/f64 denormal field is clear (0 and 2), whatever the f32 field, measured on RDNA2 (gfx1031, Radeon RX 6700 XT, AMD Windows driver 32.0.21045.5002 through HIP) at IEEE=0 and IEEE=1 with f32 denormal modes 0 and 3 and f16 denormal modes 0 to 3, over 2744 triples of 14 halves with all three sources f16 and 1960 rows with an f32 multiplicand. `v_fma_mixlo_f16` and `v_fma_mixhi_f16` flush their f32 sources too and keep a product below 2^-126, measured on RDNA2 (gfx1036). `v_mad_legacy_f32` and `v_mac_legacy_f32` flush their inputs, their product and their result in every mode, see its entry; their product is still checked for tininess on its exact value, so one below 2^-126 gives zero even when it rounds to 2^-126, as the console's separately rounded encoding is not measured at this boundary. Denormal modes 1 and 2 throw for the other instructions except the f32 compares. Not covered, and not measurable on RDNA2 (no such opcodes) or not measured: `v_mac_f32`, `v_mad_f32`, `v_madak_f32` and `v_madmk_f32` (rounded separately), `v_dot2_f32_f16` and `v_div_fmas_f32` (on hardware `v_div_fmas_f32` flushes only its result), f32 interpolation and `ds_add_f32` keep the previous lowering; `ds_min/max/cmpst_f32` and the image, buffer, global and flat `fmin/fmax/fcmpswap` flush both operands by the field, see the float atomics entries. With f32 denormals kept (3) the results depend on the driver's default denormal behaviour, as no `DenormPreserve` execution mode is requested; `v_ldexp_f32` and the f32 compares are the exceptions. `v_cmp_X_f32` and `v_cmpx_X_f32` compare the operands as sign-magnitude integers with the NaN cases handled apart, so a denormal is not read as zero, measured on RDNA2 (gfx1036) over 256 operand pairs per opcode at IEEE=0 and IEEE=1 with f32 denormals kept and flushed. `v_ldexp_f32` preserves subnormal inputs and rounds a subnormal result in the f32 round mode of `FLOAT_MODE`, measured on RDNA2 (gfx1036) over 2163 rows in each of the four round modes at IEEE=0 and IEEE=1. An overflow rounds like any other result (infinity, or the largest finite value when the mode rounds that sign toward zero). With f32 denormals flushed it flushes a subnormal input and result, measured over the same rows in each round mode at IEEE=0 only. A device whose driver splits `Fma` into a multiply and an add flushes a product below 2^-126 before adding a non-zero addend in `v_fma_f32` and `v_fmac_f32`: `0x1fffffff * 0x1fffffff + 0x00800000` gives `0x00800000` instead of the fused `0x00ffffff` on RADV RENOIR (Mesa 26.2.4), whose compiled shader has `v_mad_f32` and no `v_fma_f32`. [F32DenormalFlush](../../../core/libs/prx/libSceAgcDriver/tests/execution/F32DenormalFlush.cpp) accepts that sum on such a device. +- [f32 denormals](../../../core/shader/recompiler/Translation/src/TranslationContext/OperandAccess.cpp) follow the shader's `FLOAT_MODE` f32 denormal field (bits 5:4) when it flushes them (0, and shaders without a known float mode, as in the 0xc0 most titles use), measured on RDNA2 (gfx1035) over 1444 rows per instruction at IEEE=0 and IEEE=1. `v_add/sub/subrev/mul/mul_legacy/mullit/fma/fmac/fmamk/fmaak/min/max/min3/max3/med3/fract/floor/ceil/frexp_mant/sin/cos_f32` flush their f32 inputs and their result to a zero of the same sign (`v_mullit_f32` measured on RDNA2 (gfx1036) over 6907 rows per mode at IEEE=0 and IEEE=1, so a positive denormal src2 counts as zero); the f32 compares, `v_cvt_i32/u32/rpi_i32/flr_i32_f32`, `v_frexp_exp_i32_f32`, `v_cvt_f64_f32`, `v_cvt_f16_f32`, `v_cvt_pkrtz_f16_f32`, `v_cvt_pknorm_i16/u16_f32` and `v_cvt_pk_u8_f32` flush their f32 inputs. `v_div_scale_f32` flushes all three inputs to signed zeros, measured on RDNA2 (gfx1036) over 2744 operand triples per mode at IEEE=0 and IEEE=1 with f32 denormals flushed and kept; its scale-down behaviour and host denormal preservation remain incomplete. `v_div_fixup_f32` flushes its src1 and src2 and keeps a denormal src0 and result, measured on RDNA2 (gfx1036) over 6859 rows per mode at IEEE=0 and IEEE=1. Tininess is detected after rounding, measured on RDNA2 (gfx1036) for `v_mul_f32` and `v_mullit_f32` at IEEE=0 and IEEE=1: a product is flushed when its value rounded to 24 bits with an unbounded exponent is below 2^-126, so `0x3f7ffffe * 0x00800001` (2^-126 * (1 - 2^-46)) gives `0x00800000` and `0x3f7fffff * 0x00800000` (2^-126 * (1 - 2^-24)) gives zero. The check rounds in the f32 round mode of `FLOAT_MODE` (bits 1:0), measured in all four modes, while the products themselves are still rounded to nearest even. This applies to `v_mul_f32`, `v_mul_legacy_f32`, `v_mullit_f32`, and to `v_fma_f32`, `v_fmac_f32`, `v_fmamk_f32`, `v_fmaak_f32` and `v_fma_mix_f32` when the addend is zero; with a nonzero addend the fused result is kept, so an exact result just below 2^-126 that rounds to it is not flushed. In the three directed modes the check is computed exactly from the significands. To nearest even (0, the mode of shaders without a known float mode) one factor is multiplied by 2^64, which is exact below 2^64, and the product with the other factor is compared with 2^-62. That multiply is a plain `OpFMul` like the product, and no f32 rounding mode is requested in the SPIR-V, so the check relies on the driver rounding f32 to nearest even by default, as the products do, and a product that rounds up to 2^-126 is the emitted product. `v_fma_mix_f32` follows this rule with mixed f16/f32 sources too, measured on RDNA2 (gfx1036) with f16 in either multiplicand slot, low and high half selection, and an f32 or f16 zero addend: f32 `0x00801002` times f16 `0x3bff` gives `0x00800000` to nearest at IEEE=0 and IEEE=1, while the neighbours `0x00801001` and `0x00801003` give zero and `0x00800001`. The tiny-product boundary was also measured for both signs in all four f32 round modes at IEEE=0; Its f16 sources are flushed to a zero of their sign when bit 0 of the f16/f64 denormal field is clear (0 and 2), whatever the f32 field, measured on RDNA2 (gfx1031, Radeon RX 6700 XT, AMD Windows driver 32.0.21045.5002 through HIP) at IEEE=0 and IEEE=1 with f32 denormal modes 0 and 3 and f16 denormal modes 0 to 3, over 2744 triples of 14 halves with all three sources f16 and 1960 rows with an f32 multiplicand. `v_fma_mixlo_f16` and `v_fma_mixhi_f16` flush their f32 sources too and keep a product below 2^-126, measured on RDNA2 (gfx1036). `v_mad_legacy_f32` and `v_mac_legacy_f32` flush their inputs, their product and their result in every mode, see its entry; their product is still checked for tininess on its exact value, so one below 2^-126 gives zero even when it rounds to 2^-126, as the console's separately rounded encoding is not measured at this boundary. Denormal modes 1 and 2 throw for the other instructions except the f32 compares and the f32 conversions in their entries. Not covered, and not measurable on RDNA2 (no such opcodes) or not measured: `v_mac_f32`, `v_mad_f32`, `v_madak_f32` and `v_madmk_f32` (rounded separately), `v_dot2_f32_f16` and `v_div_fmas_f32` (on hardware `v_div_fmas_f32` flushes only its result), f32 interpolation and `ds_add_f32` keep the previous lowering; `ds_min/max/cmpst_f32` and the image, buffer, global and flat `fmin/fmax/fcmpswap` flush both operands by the field, see the float atomics entries. With f32 denormals kept (3) the results depend on the driver's default denormal behaviour, as no `DenormPreserve` execution mode is requested; `v_ldexp_f32` and the f32 compares are the exceptions. `v_cmp_X_f32` and `v_cmpx_X_f32` compare the operands as sign-magnitude integers with the NaN cases handled apart, so a denormal is not read as zero, measured on RDNA2 (gfx1036) over 256 operand pairs per opcode at IEEE=0 and IEEE=1 with f32 denormals kept and flushed. `v_ldexp_f32` preserves subnormal inputs and rounds a subnormal result in the f32 round mode of `FLOAT_MODE`, measured on RDNA2 (gfx1036) over 2163 rows in each of the four round modes at IEEE=0 and IEEE=1. An overflow rounds like any other result (infinity, or the largest finite value when the mode rounds that sign toward zero). With f32 denormals flushed it flushes a subnormal input and result, measured over the same rows in each round mode at IEEE=0 only. A device whose driver splits `Fma` into a multiply and an add flushes a product below 2^-126 before adding a non-zero addend in `v_fma_f32` and `v_fmac_f32`: `0x1fffffff * 0x1fffffff + 0x00800000` gives `0x00800000` instead of the fused `0x00ffffff` on RADV RENOIR (Mesa 26.2.4), whose compiled shader has `v_mad_f32` and no `v_fma_f32`. [F32DenormalFlush](../../../core/libs/prx/libSceAgcDriver/tests/execution/F32DenormalFlush.cpp) accepts that sum on such a device. - [v_rcp, v_rsq, v_sqrt, v_log, v_exp, v_sin and v_cos](../../../core/shader/recompiler/Translation/src/FloatInstructions.cpp) (f32 and f16) use the driver's approximation for finite results, not the console's: the low bits can differ. Only NaN, invalid, zero and infinite results and the exact sin/cos zeros are chosen on the bits. Measured on RDNA2 (gfx1036) over every f16 input and 32,832 f32 inputs: RADV returns the hardware's bits for every input of rcp, rsq, sqrt and log and all but one of exp (f16 0x11c5, 1 ULP); NVIDIA (615.71.09) stays within 2 ULP except `v_log_f32` near 1.0 (next entry). [v_sin and v_cos](../../../core/shader/recompiler/SpirvBackend/src/SpirvAlu/SpirvAluEmitterMath.cpp) take the driver's sine or cosine of the radians of the exact cycle, except within 2^-12 of a turn from a zero of the function, where the result is the linear term of the exact distance to the zero: the hardware's constant 6.2831826 (0x40c90fd5) at the integers, which the hardware applies exactly to inputs below 2^-12 of a turn, and the f32 2π at the half and quarter turns, where the hardware is within 7 ULP of it. Outside those bands, a driver result more than 4 ULP from a Taylor series in turns of the exact cycle is replaced by the series, which is within 2 ULP of the true sine and cosine; the hardware is up to 9 ULP from them (gfx1035, 243,092 f32 inputs), so results stay within 13 ULP of the hardware on any driver. RADV returns the hardware's bits for every f16 input and for 32,422 sine and 32,486 cosine results of the 32,832 f32 inputs; the rest are 1 ULP off, except up to 14 ULP on either side of non-zero integers and up to 15 ULP beyond ±256 cycles, where the hardware's own reduction differs from the exact fraction, and up to 6 ULP inside the half- and quarter-turn bands. NVIDIA's own sine is within 1 ULP on 93% of the f32 inputs and up to 1,166 ULP off just outside the bands, its cosine within 163 ULP; the series replaces those results. A denormal f32 input with f32 denormals kept gives the hardware the input times 6.2831826; both hosts flush it. - [v_rcp_f32 and v_rcp_iflag_f32 with `APS5_EXACT_RCP`](../../../core/shader/recompiler/SpirvBackend/src/SpirvAlu/SpirvAluEmitterReciprocal.cpp) return the hardware reciprocal for normal inputs with normal results: a cubic over 32 mantissa segments, the linear term rounded to nearest even, plus 2,761 one-ULP corrections. It matches all 2^23 mantissas of an RDNA2 (gfx1031) sweep; inputs or results that are not normal keep the driver's 1/x. It is off by default because the coefficient and correction tables add about 13k SPIR-V words to each shader that uses it. The switch also reaches v_rcp_f16 (rounded from the f32 reciprocal) and the pixel shader's position W input. - [v_ldexp_f32 in denormal modes 1 and 2](../../../core/shader/recompiler/Translation/src/FloatInstructions.cpp) follows the `FLOAT_MODE` f32 denormal field: mode 1 keeps a subnormal input and flushes a result below 2^-126 to a zero of its sign in every f32 round mode, also one that rounds to 2^-126 at subnormal precision (`0x3fffffff` scaled by 2^-127); mode 2 flushes a subnormal input to a zero of its sign and rounds a subnormal result in the f32 round mode of `FLOAT_MODE`, as mode 3 does. Measured on RDNA2 (gfx1030, Radeon RX 6800, AMD Windows driver 32.0.21045.5002 through HIP) over 10,260 rows (54 inputs of both signs: zeros, subnormals, normals near 2^-126 and 1.0, the largest finite value, infinities and NaNs, each scaled by 190 exponents from -2^31 to 2^31-1) at IEEE=0 and IEEE=1 with each f32 denormal mode 0 to 3 and f32 round mode 0 to 3, DX10_CLAMP=1, f16 denormals kept, f16 round to nearest even and FP16_OVFL=0; with the `clamp` modifier the result is clamped as in the other modes. The PS5's gfx1013 is not measured. @@ -137,6 +137,7 @@ - [Ordered not-equal, less-than and greater-than compares](../../../core/shader/recompiler/SpirvBackend/src/SpirvAlu/SpirvAluEmitterMath.cpp) (shader recompiler) - `FPOrdNotEqual32` is emitted as `OpFUnordNotEqual`, and `FPOrdLessThan32` and `FPOrdGreaterThan32` as their ordered forms, each with both operands checked for NaN on their bits; the results are the same for every input. The AMD Windows driver 32.0.13058.8001 (Radeon 860M, RDNA 3.5) returns 1 for a NaN operand when any float form of not-equal feeds a ballot on a 32-wide subgroup (#825), and so does a less-than or greater-than against an infinity the driver sees as a constant (#3536), presumably rewritten into a not-equal by its compiler - [16-bit integer multiplies](../../../core/shader/recompiler/Translation/src/IntegerInstructions.cpp) (`v_mul_lo_u16`, `v_pk_mul_lo_u16`) (shader recompiler) - a factor taken from the low half of its source is read as the low 24 bits of the register, not the low 16; the low 16 bits of the product are the same for every input. The AMD Windows driver 32.0.21045.5002 (RX 6700 XT, RDNA 2) stores the full 32-bit product when two values it knows fit in 16 bits are multiplied, the product is reduced to 16 bits and nothing else is merged into the stored value: `v_mul_lo_u16` into a register whose high half is zero, also with factors masked to 16 bits by the program, and `v_pk_mul_lo_u16` whose high lanes are zero wrote 0xfffe0001 for 0xffff * 0xffff where the GPU writes 0x00000001. Reducing the product with `v_and_b32`, `v_bfe_u32` or a shift pair loses the same bits; factors read as 24-bit fields do not. The [constant folder](../../../core/shader/recompiler/Optimization/src/ConstantFolder.cpp) keeps a field read that a multiply uses, even when the program already masked the factor to 16 bits, since folding it away brings the full product back (#8271). Measured against the same instructions run through the [hardware oracle](../HW_ORACLE.md) on that GPU; other drivers are not checked - [f32 compares in denormal modes 1 and 2](../../../core/shader/recompiler/Translation/src/VectorInstructions.cpp) (`v_cmp_X_f32` and `v_cmpx_X_f32` with X = eq, ge, gt, le, lg, lt, neq, nge, ngt, nle, nlg, nlt) flush their f32 denormal inputs by bit 0 of the `FLOAT_MODE` f32 denormal field: mode 1 keeps them as mode 3 does, and mode 2 flushes them as mode 0 does. Measured on RDNA2 (gfx1030, Radeon RX 6800, AMD Windows driver 32.0.21045.5002 through HIP) over 484 operand pairs of zeros, denormals, minimum normals, ones, the largest finite value, infinities and quiet and signaling NaNs of both signs, in VOPC form, at IEEE=0 and IEEE=1 with each f32 denormal mode 0 to 3, f32 round to nearest even, DX10_CLAMP=1, f16 denormals kept, f16 round to nearest even and FP16_OVFL=0. The PS5's gfx1013 is not measured. +- [f32 conversions in denormal modes 1 and 2](../../../core/shader/recompiler/Translation/src/VectorInstructions.cpp) (`v_cvt_i32/u32/rpi_i32/flr_i32_f32`, `v_frexp_exp_i32_f32`, `v_cvt_f64_f32`, `v_cvt_pknorm_i16/u16_f32`, `v_cvt_pk_u8_f32`, `v_cvt_pkrtz_f16_f32` and `v_cvt_f16_f32`) flush their f32 denormal inputs by bit 0 of the `FLOAT_MODE` f32 denormal field: mode 1 keeps them as mode 3 does, and mode 2 flushes them as mode 0 does. Measured on RDNA2 (gfx1036, ROCm 7.1.1, Linux 7.2) over 148 sources and 484 operand pairs (zeros, denormals, minimum normals, f16 limits, the largest finite value, infinities, NaNs) at IEEE=0 and IEEE=1 in every f32 denormal and round mode, and for the f16 and f64 results in every f16/f64 denormal and round mode. `v_div_scale_f32` and `v_div_fixup_f32` do not follow this rule and still throw in modes 1 and 2, as do `v_mad_mixlo/mixhi_f16`, which RDNA2 lacks. The PS5's gfx1013 is not measured. - [f16 compares](../../../core/shader/recompiler/Translation/src/CompareInstructions.cpp) (`v_cmp_X_f16` and `v_cmpx_X_f16` with X = eq, ge, gt, le, lg, lt, neq, nge, ngt, nle, nlg, nlt) flush their f16 denormal inputs to a zero of the same sign by bit 0 of the `FLOAT_MODE` f16 denormal field: modes 0 and 2 flush them, 1 and 3 keep them. Measured on RDNA2 (gfx1031, Radeon RX 6700 XT, AMD Windows driver 32.0.21045.5002 through HIP) over 256 operand pairs of zeros, denormals, minimum normals, ones, the largest finite value, infinities and quiet and signaling NaNs of both signs, in VOPC form, at IEEE=0 and IEEE=1 with each f16 denormal mode 0 to 3, f16 round to nearest even, DX10_CLAMP=1, f32 denormals kept and FP16_OVFL=0. Shaders without a known float mode keep the previous lowering. The PS5's gfx1013 is not measured. - [DB_SHADER_CONTROL.PRIMITIVE_ORDERED_PIXEL_SHADER](../../../core/shader/recompiler/SpirvBackend/src/SpirvModuleEmitter.cpp) (shader recompiler) - the host pixel interlock spans the whole shader, not only up to `s_sendmsg` ORDERED_PS_DONE. - [POPS collision SGPRs](../../../core/shader/recompiler/SpirvBackend/src/SpirvModuleEmitter.cpp) (shader recompiler) - the collision wave ID and intrawave collision mask read 0, so a title skips its POPS wait and runs its per-collision loop once. diff --git a/docs/user/USAGE.md b/docs/user/USAGE.md index 3a4dc187ee..6029ff3898 100644 --- a/docs/user/USAGE.md +++ b/docs/user/USAGE.md @@ -29,6 +29,8 @@ relinker [options] An explicit `--module-dir` also works when the module parent has no `sce_module`, `sce_modules` or `prx` directory. For a homebrew bundle with shared libraries beside its executable, use `--module-dir .`; no empty standard directory is required. Without an explicit module directory, the standard-directory requirement remains. +A module the executable needs that is not converted is looked for under the module parent directory, outside the module directories. Each SELF container or `ET_SCE_DYNAMIC` ELF found there whose name matches, up to the `.prx`, `.sprx`, `.suprx` or `.debug_prx` suffix (ignoring case with `--windows`, as the guest module match does), is reported after the conversion with the `--module-dir` that would include it; the output still refers to a host library of that name. A file that cannot be read is not reported. + Linux output: ```sh @@ -64,7 +66,7 @@ All switches are disabled by default. `unused-filter` defaults to `0`; `--rpath` | `--macos` | Produce an x86-64 Mach-O executable, with bundled modules as Mach-O libraries in `app0/sce_module`. Conflicts with `--windows`. | | `--windows-diagnostics` | Include startup dependency diagnostics. Requires `--windows`. | | `--windows-gui` | Select the Windows GUI subsystem instead of the console subsystem. Requires `--windows`. | -| `--windows-fixed-base
` | Map the lowest ELF load page at this fixed Windows address, given in decimal or hexadecimal (`0x`). Requires `--windows`, a 64 KiB-aligned address from `0x20000` through `0x7fffffff0000`, and a complete image fitting in the user address space. The main executable has no ASLR or base relocations; an occupied address fails to load. Bundled modules keep their normal placement. | +| `--windows-fixed-base
` | Map the lowest ELF load page at this fixed Windows address instead of the preferred `0x400000`, given in decimal or hexadecimal (`0x`). Requires `--windows`, a 64 KiB-aligned address from `0x20000` through `0x7fffffff0000`, and a complete image fitting in the user address space. The main executable has no ASLR or base relocations; an occupied address fails to load. Bundled modules keep their normal placement. | | `--trace-imports` | Pass each function import through the libc.prx call tracer, see [tracing system library calls](#tracing-system-library-calls). Windows and Linux output only; conflicts with `--lazy-binding`. | | `--linux-fixed-base
` | Load the Linux executable at this fixed address instead of the default `0x400000`, given in decimal or hexadecimal (`0x`): every virtual address of the image is offset by it, so virtual address 0 is placed at the address, as the console places an executable. Requires a 64 KiB-aligned address from `0x10000` through `0x7fffffff0000` that is a multiple of every `PT_LOAD` alignment, and an image that ends in the user address space. The executable is written as `ET_EXEC`, without ASLR, as it is at the default address. Bundled modules keep their normal placement. Conflicts with `--windows`, `--macos` and `--lazy-binding`. | | `--macos-fixed-base
` | Map the lowest ELF load page of the macOS executable at this fixed address, given in decimal or hexadecimal (`0x`). Requires `--macos`, a 64 KiB-aligned address from `0x20000` through `0x7fffffff0000`, and an image that ends in the macOS user address space. `__PAGEZERO` ends 64 KiB below the address and the Mach-O header occupies those 64 KiB. The executable has no ASLR; an address the process cannot map fails to load. Bundled modules keep their normal placement. | @@ -176,7 +178,7 @@ Verify mode rejects the conversion options (`--windows`, `--macos`, `--to-intel` ## Runtime layout -For an executable that assumes its image starts at `0x400000`, use `relinker --windows --windows-fixed-base 0x400000 source/input.elf app.exe`. This maps its lowest ELF load page there; the PE headers occupy the preceding 64 KiB. Use this option only when the executable requires an exact address. Without it, the Windows executable has no `DYNAMIC_BASE` and loads at its preferred base `0x140000000`; relocations are kept, so Windows relocates it if that range is taken. Modules keep `DYNAMIC_BASE`. This option does not change macOS output. +The Windows executable has no `DYNAMIC_BASE` and prefers to load with its lowest ELF load page at `0x400000`, where Ruffle (PPSA68091), VLC (PPSA85300) and XPSemu (PPSA97358) expect their image when they read their `app0/imports.txt`; the PE headers occupy the preceding 64 KiB (preferred base `0x3f0000`). Relocations are kept, so Windows can relocate it if that range is taken. When the executable requires an exact address, use `relinker --windows --windows-fixed-base
source/input.elf app.exe`, which maps the lowest ELF load page at that address without relocations, so an occupied address fails to load. Modules keep `DYNAMIC_BASE`. This option does not change macOS output. For an executable that assumes its image starts at `0x400000`, as Ruffle (PPSA68091), VLC (PPSA85300) and XPSemu (PPSA97358) do when they read their `app0/imports.txt`, use `relinker --macos --macos-fixed-base 0x400000 source/input.elf app` on macOS. Use this option only when the executable requires a fixed address; without it, macOS output places the lowest ELF load page at `0x140010000`. Linux output places virtual address 0 at `0x400000` without an option, inside the 40-bit window that a title's own `sceLibcMspaceCreate` checks; `--linux-fixed-base` selects another address, and with `--lazy-binding` the executable stays position independent. @@ -201,7 +203,7 @@ Some applications also need their original `app0/sce_sys/param.json` at runtime. Resources can also be packed into `app0.zar` beside `app0/`, a [ZArchive](https://github.com/Exzap/ZArchive) whose root is the `app0/` directory. A file present in `app0/` is read from there and any other file from the archive; the executable, `sce_module/` and `sce_sys/` stay in `app0/`. The archive is read only through `sceKernelOpen`/`open`, the read, seek and stat calls on its descriptors and `sceKernelStat`; other calls on an archived path, listing a directory that the archive also contains and opening a file in it for writing fail as described in [technical debt](../dev/debt/libkernel.md). An archive that cannot be opened stops the title at its first file access. -Use the generated files printed as `Guest module:` for bundled title modules. `libs/` is for AnyPS5 system libraries, not the original PS5 `.prx` files. Placing an original PS5 module in `libs/` on Windows makes Windows try to load it as a DLL and can fail with error 193 (not a valid Win32 application). A module the title loads while it runs that was not relinked, such as one in a directory not given to `--module-dir`, is not loaded either: the title gets an error and continues, and the runtime prints `[module] dlopen: was not relinked: ...` once for each file. Relink that module's directory with `--module-dir `. +For bundled title modules, use the `.guest.prx` files the relinker writes into `app0/` and lists in the layout it prints. `libs/` is for AnyPS5 system libraries, not the original PS5 `.prx` files. Placing an original PS5 module in `libs/` on Windows makes Windows try to load it as a DLL and can fail with error 193 (not a valid Win32 application). A module the title loads while it runs that was not relinked, such as one in a directory not given to `--module-dir`, is not loaded either: the title gets an error and continues, and the runtime prints `[module] dlopen: was not relinked: ...` once for each file. Relink that module's directory with `--module-dir `. On Windows, a self-built `libs/` also needs `libgcc_s_seh-1.dll`, `libstdc++-6.dll` and `libwinpthread-1.dll` from the `mingw64/bin` directory of the toolchain that built the libraries; the release archives already contain them. The libraries are loaded without searching `PATH`, so a copy elsewhere on the system is not used, and a library that needs one of them fails with error 126 (the specified module could not be found) although its `.prx` file is present. With `APS5_MIMALLOC` set, the title loads `mimalloc.dll` and `mimalloc-redirect.dll` from `libs/` and allocates through mimalloc. Copy both from `build/core/libs/libs`; the release archives contain them. Without them the title keeps the C runtime's heap and prints nothing. diff --git a/tools/build_web.py b/tools/build_web.py index 8a5e555bf0..4127eaf9a0 100644 --- a/tools/build_web.py +++ b/tools/build_web.py @@ -71,7 +71,8 @@ def publish_libraries(output, release=None): raise ValueError("Invalid library archive") names = {} for file in files: - if not file.filename.startswith("libs/") or any(part in ("..", ".", "") for part in file.filename.rstrip("/").split("/")) or "\\" in file.filename: + if (file.orig_filename != file.filename or not file.filename.startswith("libs/") + or any(part in ("..", ".", "") for part in file.filename.rstrip("/").split("/")) or "\\" in file.filename): raise ValueError("Invalid library archive layout") name = file.filename.rstrip("/").lower() if name in names: @@ -90,6 +91,8 @@ def publish_libraries(output, release=None): path = f"libraries/{platform}-{checksum}.zip" temporary.replace(output / path) manifest["platforms"][platform] = {"path": path, "size": size, "expandedBytes": expanded, "sha256": checksum} + except zipfile.BadZipFile as error: + raise ValueError(f"Invalid release archive {asset['name']}: {error}") from error finally: temporary.unlink(missing_ok=True) (output / "release.json").write_text(json.dumps(manifest, indent=2) + "\n", encoding="utf-8") @@ -158,6 +161,8 @@ def publish_release(output): raise RuntimeError(f"Could not restore release output. Previous site is preserved at {previous}") from error raise published = True + except zipfile.BadZipFile as error: + raise ValueError(f"Invalid release archive {asset['name']}: {error}") from error finally: if published or not previous.exists(): shutil.rmtree(temporary) diff --git a/tools/check_compile.py b/tools/check_compile.py index c2c0befc3a..32934f8fb3 100644 --- a/tools/check_compile.py +++ b/tools/check_compile.py @@ -11,8 +11,18 @@ from contextlib import nullcontext from pathlib import Path CPP = (".cpp", ".cc", ".cxx", ".c") -DROP = ("-c", "-MD", "-MMD", "-MP") +DROP = ("-c", "-MD", "-MMD", "-MP", "-fsyntax-only", "-fno-syntax-only") DROP_WITH_VALUE = ("-o", "-MT", "-MF", "-MQ", "-MJ") +PREPROCESSING = ("-E", "--preprocess", "-M", "--dependencies", "-MM", "--user-dependencies", + "-MG", "--print-missing-file-dependencies", "-P", "--no-line-commands", + "-C", "-CC", "-dM", "-dD", "-dI") +WITH_VALUE = ("-I", "-L", "-F", "-B", "-D", "-U", "-x", "-include", "--include", "-imacros", "--imacros", + "--define-macro", "--undefine-macro", "-iquote", "-isystem", "-idirafter", "-iprefix", + "-iwithprefix", "-iwithprefixbefore", "-isysroot", "--sysroot", "-target", "--target", + "-arch", "-std", "-T", "-u", "-e", "--param", "-Xclang", "-Xpreprocessor", "-Xassembler", "-Xlinker") +WITHOUT_VALUE = (*DROP, *PREPROCESSING, "-S", "-fsyntax-only", "-Werror", "-Wall", "-Wextra", + "-pedantic", "-pedantic-errors", "-pthread", "-pipe", "-v") +JOINED_OPTIONS = ("-I", "-L", "-F", "-B", "-D", "-U", "-O", "-g", "-W") def capture(command, cwd=None, encoding="utf-8"): @@ -149,32 +159,73 @@ def syntax_only(entry, source): return syntax_arguments(arguments, directory, source) +def validate_preprocessor_arguments(argument): + forwarded = argument[4:].split(",") + if any(option.startswith("@") for option in forwarded): + raise ValueError(f"unsupported forwarded compiler option response file in {argument}") + options = iter(forwarded) + for option in options: + if option in ("-D", "-U", "-I", "-F", "-include", "--include", "-imacros", "--imacros", + "-isystem", "-iquote", "-idirafter", "-isysroot"): + if not next(options, None): + raise ValueError(f"missing operand for {option} in {argument}") + elif not (option.startswith(("-D", "-U", "-I", "-F")) and len(option) > 2): + raise ValueError(f"unsupported forwarded compiler option {option} in {argument}") + + def syntax_arguments(arguments, directory, source): validate_arguments(arguments) for argument in arguments[1:]: if argument.startswith("@"): raise ValueError(f"unexpanded response file {argument[1:]}; provide expanded compile arguments before checking syntax") wanted = source.resolve() - trimmed = [] - index = 0 + trimmed = [arguments[0]] + index = 1 + positional = False + syntax_added = False while index < len(arguments): argument = arguments[index] - if argument in DROP_WITH_VALUE: - index += 2 - continue - if argument in DROP or argument.startswith(("-MT", "-MF", "-MQ", "-MJ")): + if not syntax_added and argument.startswith("-"): + trimmed.append("-fsyntax-only") + syntax_added = True + if not positional and argument == "--": + positional = True + trimmed.append(argument) index += 1 continue - if not argument.startswith("-"): + if not positional and (argument in ("-Xclang", "-Xpreprocessor") or argument.startswith(("-Xclang=", "-Xpreprocessor="))): + raise ValueError(f"unsupported forwarded compiler option {argument}") + if not positional and argument in (*DROP_WITH_VALUE, *WITH_VALUE): + if index + 1 == len(arguments): + raise ValueError(f"missing operand for {argument}") + if argument in WITH_VALUE: + trimmed.extend(arguments[index:index + 2]) + index += 2 + continue + if not positional and argument.startswith("-Wp,"): + validate_preprocessor_arguments(argument) + if not positional and (argument in (*DROP, *PREPROCESSING) or argument.startswith(("-MT", "-MF", "-MQ", "-MJ"))): + index += 1 + continue + if positional or not argument.startswith("-"): candidate = Path(argument) if not candidate.is_absolute(): candidate = directory / candidate if candidate.resolve() == wanted: index += 1 continue + if positional: + trimmed.append(str(candidate.resolve())) + index += 1 + continue + elif (argument not in WITHOUT_VALUE and not argument.startswith(JOINED_OPTIONS) and "=" not in argument and index + 1 < len(arguments) + and arguments[index + 1] in PREPROCESSING): + raise ValueError(f"unknown operand count for {argument} before {arguments[index + 1]}") trimmed.append(argument) index += 1 - trimmed += ["-fsyntax-only", str(wanted)] + if not syntax_added: + trimmed.append("-fsyntax-only") + trimmed.append(str(wanted)) return trimmed diff --git a/tools/check_conventions.py b/tools/check_conventions.py index fb378cda0d..9e95eb4bf6 100644 --- a/tools/check_conventions.py +++ b/tools/check_conventions.py @@ -1,5 +1,6 @@ import argparse import io +import itertools import json import os import posixpath @@ -24,6 +25,7 @@ RULES = { "system-dependency": ("error", "CONTRIBUTING.md#code", "Third-party code is a submodule under 3rdparty/ built from source, not found on the system"), "title-specific": ("error", "CONTRIBUTING.md#code", "Implement the general behaviour, not what one title needs; title-specific code belongs in its sce_module"), "extension": ("error", "CONTRIBUTING.md#code", "Avoid non-standard extensions where standard C++ is enough"), + "alignment": ("error", "CONTRIBUTING.md#code", "MinGW GCC rejects static objects aligned above 8192 bytes; align a larger block at run time inside a bigger buffer"), "notes-file": ("error", "CONTRIBUTING.md#branches-and-pull-requests", "Notes, investigation and agent files go in the pull request, not in the repository; only the root AGENTS.md is allowed"), "binary": ("error", "docs/dev/CONVENTIONS.md", "Only UTF-8 text files in the repository; images go in the gist comments"), "ci-gate": ("error", "CONTRIBUTING.md#build-and-test", "A job that runs for pull requests needs a file filter: paths on the pull_request trigger, or needs eligibility and an if on its outputs"), @@ -59,6 +61,12 @@ STUB_BODY = re.compile(r"^(?:\(void\)\s*\w+\s*;|static_cast\(\s*\w+\s*\)\s SYSTEM_DEPENDENCY = re.compile(r"\b(find_package\s*\((?!\s*(Python3|Threads|Git)\b)|pkg_check_modules\b|pkg_search_module\b|find_(library|path|program|file)\b)", re.I) TITLE = re.compile(r"\b(PPSA|CUSA)\d{5}\b") EXTENSION = re.compile(r"__attribute__|__declspec|#\s*pragma\s+(?!once\b)") +INTEGER = r"(0[xX][0-9a-fA-F']+|0[bB][01']+|[0-9][0-9']*)[uUlLzZ]*" +ALIGNAS = re.compile(rf"\balignas\s*\(\s*(?:{INTEGER}|([A-Za-z_][A-Za-z0-9_]*))\s*\)") +CONSTANT = re.compile(rf"\bconstexpr\b[^;=]*?\b([A-Za-z_][A-Za-z0-9_]*)\s*(?:=\s*|\{{\s*){INTEGER}\s*[;}}]") +NAMESPACE = re.compile(r"\bnamespace\s+((?:[A-Za-z_][A-Za-z0-9_]*\s*::\s*(?:inline\s+)?)*[A-Za-z_][A-Za-z0-9_]*)\s*$|\bnamespace\s*$") +LINKAGE = re.compile(r'\bextern\s*""\s*$') +ALIGNMENT_LIMIT = 8192 LINK = re.compile(r"\[[^\]]+\]\(([^)\s]+)") FENCE = re.compile(r"^ {0,3}(```|~~~).*?^ {0,3}\1[ \t]*\r?$|^ {0,3}(?:```|~~~).*\Z", re.S | re.M) INLINE = re.compile(r"`[^`\n]*`") @@ -172,12 +180,20 @@ class Check: source = self.show(path).split("\n") masked = cpp_text("\n".join(source), preserve_comments=True).split("\n") assembly = asm_exports("\n".join(source)) if core and path.startswith("core/libs/prx/") else {} + constants, starts = None, None for number, text in lines: bare = masked[number - 1] if ("//" in bare or "/*" in bare) and not ALLOWED_COMMENT.match(bare): self.report("comment", path, number) if EXTENSION.search(bare): self.report("extension", path, number, EXTENSION.search(bare).group(0)) + if "alignas" in bare: + if constants is None: + constants = named_constants(cpp_text("\n".join(source))) + starts = list(itertools.accumulate((len(line) + 1 for line in masked), initial=0)) + alignment = over_aligned(bare, constants, starts[number - 1]) + if alignment: + self.report("alignment", path, number, alignment) if core and TITLE.search(text): self.report("title-specific", path, number, TITLE.search(text).group(0)) if core and path.startswith("core/libs/prx/"): @@ -580,6 +596,68 @@ def cpp_text(text, preserve_comments=False): return CPP_TOKEN.sub(mask, text) +def integer_literal(text): + digits = text.replace("'", "").lower() + if digits.startswith(("0x", "0b")): + return int(digits, 0) + return int(digits, 8 if len(digits) > 1 and digits[0] == "0" else 10) + + +def brace_scopes(text): + stack, scopes, boundary = [], [], -1 + for index, character in enumerate(text): + if character not in "{};": + continue + if character == "{": + head = text[boundary + 1:index] + outer = next((key[1] for _, key in reversed(stack) if key and key[0] == "namespace"), "") + match = NAMESPACE.search(head) + if match and re.search(r"\binline\s+namespace\b", head): + key = ("namespace", outer) + elif match: + key = ("namespace", outer + "::" + re.sub(r"\binline\b|\s+", "", match.group(1) or "{anonymous}")) + else: + key = None if LINKAGE.search(head) else ("block", index) + stack.append((index, key)) + elif character == "}" and stack: + start, key = stack.pop() + scopes.append((start, index, key)) + boundary = index + return scopes + + +def scope_chain(scopes, position): + chain = [] + for _, _, key in sorted((scope for scope in scopes if scope[0] < position < scope[1]), reverse=True): + if key and key[0] == "namespace": + parts = key[1].split("::") + chain.extend(prefix for prefix in (("namespace", "::".join(parts[:count])) for count in range(len(parts), 1, -1)) if prefix not in chain) + elif key: + chain.append(key) + return chain + [("namespace", "")] + + +def named_constants(text): + scopes = brace_scopes(text) + definitions = [(match.group(1), integer_literal(match.group(2)), match.start(), scope_chain(scopes, match.start())[0]) for match in CONSTANT.finditer(text)] + return definitions, scopes + + +def constant_value(constants, name, position): + definitions, scopes = constants + chain = scope_chain(scopes, position) + visible = [(-chain.index(scope), start, value) for found, value, start, scope in definitions if found == name and start < position and scope in chain] + return max(visible)[2] if visible else 0 + + +def over_aligned(text, constants=((), ()), offset=0): + for match in ALIGNAS.finditer(text): + value = integer_literal(match.group(1)) if match.group(1) else constant_value(constants, match.group(2), offset + match.start()) + if value > ALIGNMENT_LIMIT: + return match.group(0) + return None + + def function_body(lines, start): text = cpp_text("\n".join(lines[start:start + 400])) brace, semicolon = text.find("{"), text.find(";") diff --git a/tools/check_main_sync.py b/tools/check_main_sync.py index f6d7532082..0fdfbdfc79 100644 --- a/tools/check_main_sync.py +++ b/tools/check_main_sync.py @@ -54,8 +54,10 @@ def merged_pull_requests(repo, mergebase, base, paths): def report(repo, base, head): repo = git(repo, "rev-parse", "--show-toplevel").stdout.strip() found = git(repo, "merge-base", base, head, check=False) - if found.returncode: + if found.returncode == 1: raise RuntimeError(f"{head} and {base} have no common ancestor") + if found.returncode: + raise RuntimeError(f"git merge-base failed: {found.stderr.strip()}") mergebase = found.stdout.strip() behind = int(git(repo, "rev-list", "--count", f"{head}..{base}").stdout) ahead = int(git(repo, "rev-list", "--count", f"{base}..{head}").stdout) diff --git a/tools/check_skips.py b/tools/check_skips.py index d29c91b065..e2f8f246f0 100644 --- a/tools/check_skips.py +++ b/tools/check_skips.py @@ -11,16 +11,22 @@ NO_DISPLAY = re.compile(r"skipped,.*no display", re.IGNORECASE) NO_VULKAN_DEVICE = re.compile(r"skipped,.*no usable Vulkan device", re.IGNORECASE) HIGH_REFRESH_LIMITATION = re.compile(r"current display does not provide 120 Hz", re.IGNORECASE) +CTEST_SKIP_STATUS = re.compile(r"SKIP_RETURN_CODE=\d+|SKIP_REGULAR_EXPRESSION_MATCHED", re.IGNORECASE) WINDOWS_PREFIX = "agc" +def device_limitations(output, patterns): + reasons = [match.group(0) for line in output.splitlines() if (match := re.search(r"skipped,.*", line, re.IGNORECASE))] + return bool(reasons) and all(any(pattern.search(reason) for pattern in patterns) for reason in reasons) + + def high_refresh_limitation(output): reasons = [] for line in output.splitlines(): reason = line.strip() - if reason.lower().startswith("skipped,"): - reason = reason[len("skipped,"):].strip() + if match := re.search(r"skipped,", reason, re.IGNORECASE): + reason = reason[match.end():].strip() if reason: reasons.append(reason) return bool(reasons) and all(HIGH_REFRESH_LIMITATION.fullmatch(reason) for reason in reasons) @@ -39,7 +45,8 @@ def skips(path): name = case.get("name") if not name: raise ValueError(f"{path}: skipped testcase has no name") - output = ["skipped, " + reason.strip() for reason in (skipped.get("message", ""), skipped.text or "") if reason.strip()] + output = ["skipped, " + reason.strip() for reason in (skipped.get("message", ""), skipped.text or "") + if reason.strip() and not CTEST_SKIP_STATUS.fullmatch(reason.strip())] output += [case.findtext(channel) or "" for channel in ("system-out", "system-err")] yield name, "\n".join(output) @@ -59,14 +66,15 @@ def main(argv=None): parser.error(str(error)) if args.list: for name, output in found: - reason = next((line.strip() for line in output.splitlines() if line.strip().lower().startswith("skipped")), "") + reason = next((match.group(0) for line in output.splitlines() + if (match := re.search(r"skipped,.*", line, re.IGNORECASE))), "") print(f"{name}: {reason}") return 0 if args.job == "windows": - unexpected = [name for name, output in found if not name.startswith(WINDOWS_PREFIX) and not NO_DISPLAY.search(output) and not NO_VULKAN_DEVICE.search(output) and not high_refresh_limitation(output)] + unexpected = [name for name, output in found if not name.startswith(WINDOWS_PREFIX) and not device_limitations(output, (NO_DISPLAY, NO_VULKAN_DEVICE)) and not high_refresh_limitation(output)] expected = f"any {WINDOWS_PREFIX}* test, which the runner has no Vulkan driver for, or a test that reports no display or Vulkan device or a display without a 120 Hz mode" else: - unexpected = [name for name, output in found if not DEVICE_LIMITATION.search(output) and not high_refresh_limitation(output)] + unexpected = [name for name, output in found if not device_limitations(output, (DEVICE_LIMITATION,)) and not high_refresh_limitation(output)] expected = "any test that reports the device limitation it needs, such as narrow subgroups, a missing extension, no display for a Vulkan window or a display without a 120 Hz mode" for name in unexpected: print(f"error: {name} skipped") diff --git a/tools/check_test_registration.py b/tools/check_test_registration.py index e74e2f72e6..d29473a451 100644 --- a/tools/check_test_registration.py +++ b/tools/check_test_registration.py @@ -11,7 +11,7 @@ LEXICAL = re.compile(r'\\.|"(?:\\.|[^"\\])*"|\[(?P=*)\[.*?\](?P= r'|(?P\#\[(?P=*)\[.*?\](?P=comment_equals)\]|\#[^\n]*)', re.S) KNOWN_UNRUN = set() -SCRIPT = re.compile(r"(?:[\w.-]+/)*test_\w+\.py") +SCRIPT = re.compile(r"(? BRANCH_VARIANT_LIMIT: + raise AuditError(f"more than {BRANCH_VARIANT_LIMIT} preprocessor branch combinations in one function") + return variants + + return expand(root) + + +def variant_calls(body): + return [unconditional_calls(variant) for variant in branch_variants(body)] + + +def unconditional_calls(body): + names = set() + for offset, statement in top_level_statements(body): + block = statement.strip() + if block.startswith("{") and block.endswith("}"): + names |= unconditional_calls(block) + elif not (CONDITIONAL.match(block) or BRANCHING.search(statement)): + for call in progress.CALL.finditer(statement): + before = statement[:call.start()] + if before.count("{") == before.count("}") and not progress.QUALIFIED.search(body, 0, offset + call.start()): + names.add(call.group(1)) + if EXIT.search(statement): + break + return names + + +def always_stub_calls(text): + helpers = {} + for match in progress.STUB_WRAPPER.finditer(text): + body = text[match.end() - 1:progress.body_end(text, match.end() - 1) + 1] + helpers.setdefault(match.group(1), []).extend(variant_calls(body)) + calls = {progress.STUB} + while True: + found = {name for name, bodies in helpers.items() if name not in calls and all(targets & calls for targets in bodies)} + if not found: + return calls + calls |= found + + +def conditional_stubs(library): + conditional = set() + for source in library.rglob("*.cpp"): + if "tests" in source.relative_to(library).parts: + continue + text = progress.code(source.read_text(errors="ignore")) + calls = always_stub_calls(text) + for match in progress.DEFINITION.finditer(text): + body = text[match.end() - 1:progress.body_end(text, match.end() - 1) + 1] + if not all(targets & calls for targets in variant_calls(body)): + conditional.add(match.group(1)) + return conditional + + def source_stubs(source): + return source_stub_classes(source)[0] + + +def source_stub_classes(source): if not Path(source).is_dir(): raise AuditError(f"{source}: not a directory") stubs = {} + partial = set() shared = {} for library in sorted(item for item in Path(source).iterdir() if item.is_dir()): aliases = {} for file in nid_names.source_files(library): - for nid, name in nid_names.source_aliases(file.read_text(errors="ignore")): + for nid, name in nid_names.source_aliases(file.read_text(encoding="utf-8-sig", errors="ignore")): aliases.setdefault(name, set()).add(nid) group = progress.scan_library(library) if "shared_sources" in group: shared[library.name] = group["shared_sources"] done = {nid for name in group["done_names"] for nid in nids_of(name, aliases)} + conditional = conditional_stubs(library) if group["todo_names"] else set() for name in group["todo_names"]: for nid in nids_of(name, aliases) - done: stubs.setdefault((library.name + ".prx", nid), name) + if name in conditional: + partial.add((library.name + ".prx", nid)) for library, owner in shared.items(): chain = [library] while owner in shared: @@ -498,7 +625,9 @@ def source_stubs(source): for (provider, nid), name in list(stubs.items()): if provider == owner + ".prx": stubs[(library + ".prx", nid)] = name - return stubs + if (provider, nid) in partial: + partial.add((library + ".prx", nid)) + return stubs, partial def read_registry(path): @@ -569,17 +698,17 @@ class ModuleNames(set): return isinstance(library, str) and module_stem(library, self.fold) in self.stems -def classify(nid, library, providers, stubs, modules): +def classify(nid, library, providers, stubs, modules, partial=frozenset()): if library and library in modules: return "module" if not providers: return "absent" if all((provider, nid) in stubs for provider in providers): - return "stub" + return "partial" if any((provider, nid) in partial for provider in providers) else "stub" return "implemented" -def audit(imports, exports, stubs, libraries, modules, module_imports=None, module_exports=None, *, needed_libraries=(), windows_libraries=()): +def audit(imports, exports, stubs, libraries, modules, module_imports=None, module_exports=None, *, needed_libraries=(), windows_libraries=(), partial=frozenset()): windows_names = {} for library in windows_libraries: windows_names.setdefault(library.casefold(), set()).add(library) @@ -622,11 +751,11 @@ def audit(imports, exports, stubs, libraries, modules, module_imports=None, modu record["symbol_mismatch"] = bool(library) and library not in modules and bool(providers) and resolved_nid != nid if not library: providers = sorted(set(providers) | set((module_exports or {}).get(resolved_nid, []))) - kind = classify(resolved_nid, library, providers, stubs, modules) + kind = classify(resolved_nid, library, providers, stubs, modules, partial) record["class"] = kind record["providers"] = providers - record["library_mismatch"] = kind in ("implemented", "stub") and bool(library) and system_library(library) not in providers and "libc.prx" not in providers - record["name"] = next((stubs[(provider, resolved_nid)] for provider in providers if (provider, resolved_nid) in stubs), None) if kind == "stub" else None + record["library_mismatch"] = kind in ("implemented", "partial", "stub") and bool(library) and system_library(library) not in providers and "libc.prx" not in providers + record["name"] = next((stubs[(provider, resolved_nid)] for provider in providers if (provider, resolved_nid) in stubs), None) if kind in ("partial", "stub") else None ordered = sorted(records.values(), key=lambda record: (record["class"], record["library"] or "", record.get("module") or "", record["nid"])) check_conservation(len(imports) + sum(len(symbols) for symbols, _ in (module_imports or {}).values()), ordered) missing = defaultdict(int) @@ -747,7 +876,8 @@ def render(summary, records, missing, stops, missing_hosts=(), located=None): lines = [f"{summary['references']} references, {summary['unique_imports']} unique imports"] for kind in CLASSES: lines.append(f" {kind:<12}{summary['unique_by_class'][kind]:>6} imports {summary['references_by_class'][kind]:>6} references") - for title, kind in (("Absent: no built library exports these", "absent"), ("Stub: exported but throws when called", "stub")): + for title, kind in (("Absent: no built library exports these", "absent"), ("Stub: exported but throws when called", "stub"), + ("Partial: exported, throws only for inputs whose behaviour is unknown", "partial")): selected = [record for record in records if record["class"] == kind] if selected: lines.append("") @@ -787,6 +917,10 @@ def render(summary, records, missing, stops, missing_hosts=(), located=None): def main(argv=None): + if hasattr(sys.stdout, "reconfigure"): + sys.stdout.reconfigure(encoding="utf-8", errors="backslashreplace") + if hasattr(sys.stderr, "reconfigure"): + sys.stderr.reconfigure(encoding="utf-8", errors="backslashreplace") parser = argparse.ArgumentParser(description="classify the imports of a converted game against the built system libraries") parser.add_argument("registries", nargs="+", type=Path, help="JSON written by 'relinker --registry'") parser.add_argument("--libs", action="append", required=True, help="directory of built .prx files; repeat for several") @@ -819,7 +953,8 @@ def main(argv=None): modules = set(module_imports) modules |= {name.removesuffix(".guest.prx") for name in modules if name.endswith(".guest.prx")} modules = ModuleNames(modules, fold=bool(windows)) - records, missing = audit(imports, exports, source_stubs(args.source), libraries, modules, module_imports, module_exports, needed_libraries=needed, windows_libraries=windows) + stubs, partial = source_stub_classes(args.source) + records, missing = audit(imports, exports, stubs, libraries, modules, module_imports, module_exports, needed_libraries=needed, windows_libraries=windows, partial=partial) missing_hosts = audit_host_dependencies(host_dependencies, libraries, modules, windows) if args.names: attach_names(records, load_names(args.names)) @@ -845,7 +980,4 @@ def main(argv=None): if __name__ == "__main__": - for stream in (sys.stdout, sys.stderr): - if hasattr(stream, "reconfigure"): - stream.reconfigure(encoding="utf-8", errors="replace") raise SystemExit(main()) diff --git a/tools/progress.py b/tools/progress.py index a3c38e1e83..aaef552f7b 100644 --- a/tools/progress.py +++ b/tools/progress.py @@ -520,6 +520,10 @@ def validate_snapshot(snapshot): def main(argv=None): + if hasattr(sys.stdout, "reconfigure"): + sys.stdout.reconfigure(encoding="utf-8", errors="backslashreplace") + if hasattr(sys.stderr, "reconfigure"): + sys.stderr.reconfigure(encoding="utf-8", errors="backslashreplace") global PRX, OPCODES previous = PRX, OPCODES parser = argparse.ArgumentParser() @@ -539,7 +543,7 @@ def main(argv=None): snapshots = [] for path in args.compare: try: - snapshots.append(json.loads(path.read_text(encoding="utf-8"))) + snapshots.append(json.loads(path.read_text(encoding="utf-8-sig"))) except (OSError, ValueError) as error: parser.error(f"{path}: {error}") for path, snapshot in zip(args.compare, snapshots): @@ -579,6 +583,4 @@ def main(argv=None): if __name__ == "__main__": - if hasattr(sys.stdout, "reconfigure"): - sys.stdout.reconfigure(encoding="utf-8") raise SystemExit(main()) diff --git a/tools/progress_history.py b/tools/progress_history.py index b223ab7c58..e98eaa5df8 100644 --- a/tools/progress_history.py +++ b/tools/progress_history.py @@ -25,8 +25,13 @@ def git(*args): def daily_commits(ref): + try: + log = git("log", "--first-parent", "--format=%H %ct", ref) + except subprocess.CalledProcessError as error: + reason = error.stderr.decode("utf-8", errors="replace").strip() + raise ValueError(f"cannot read the history of {ref}: {reason}") from error seen = {} - for line in git("log", "--first-parent", "--format=%H %ct", ref).decode("utf-8").splitlines(): + for line in log.decode("utf-8").splitlines(): sha, timestamp = line.split() seen.setdefault(datetime.fromtimestamp(int(timestamp), timezone.utc).date().isoformat(), sha) return sorted(seen.items()) diff --git a/tools/run_job_manager_reference.py b/tools/run_job_manager_reference.py index d804f3e573..705d0e1228 100644 --- a/tools/run_job_manager_reference.py +++ b/tools/run_job_manager_reference.py @@ -3,24 +3,27 @@ import hashlib import json import os import shutil +import struct import subprocess import sys import tempfile from pathlib import Path from import_audit import read_host_imports -from unwrap_self import unwrap +from unwrap_self import Refused, unwrap ROOT = Path(__file__).resolve().parent.parent sys.path.insert(0, str(ROOT / "core/relinker/relinker/tests")) from guest_import_fixtures import executable -CASES = ("memory", "validation", "dispatch", "ordering", "nested", "limits", "node_pool", "priority", "shutdown", "worker_policy", "worker_wake", "worker_wait", "worker_count", "worker_spin") +CASES = ("memory", "owned_state", "concurrent_wait", "validation", "dispatch", "ordering", "nested", "limits", "node_pool", "priority", "shutdown", "worker_policy", "worker_wake", "worker_wait", "worker_count", "worker_spin") +PARITY_CASES = tuple(case for case in CASES if case not in ("node_pool", "worker_wait")) def stage_libraries(directory, build, toolchain, dependencies): providers = {path.name.lower(): path for path in (build / "core/libs/libs").glob("*.prx")} - providers.update({path.name.lower(): path for path in toolchain.glob("*.dll")}) + if toolchain is not None: + providers.update({path.name.lower(): path for path in toolchain.glob("*.dll")}) pending = list(dependencies) staged = set() while pending: @@ -44,7 +47,8 @@ def run(args, directory): if not helper.is_file(): raise RuntimeError("Build the job_manager_reference target first") shutil.copy2(helper, libraries / "jobref.prx") - subprocess.run([str(args.build / "core/libs/nid_patcher.exe"), "jobref", "--preserve-export-list", + suffix = ".exe" if sys.platform == "win32" else "" + subprocess.run([str(args.build / f"core/libs/nid_patcher{suffix}"), "jobref", "--preserve-export-list", str(args.build / "core/libs/libc.exports"), str(libraries / "jobref.prx")], check=True, capture_output=True) module_hash = None if args.module: @@ -58,14 +62,19 @@ def run(args, directory): else: unwrap(args.module, target) source = directory / "input.elf" - source.write_bytes(executable("jobref.prx", symbol="Run_nid_no_patch")) - output = directory / "reference.exe" + entry = executable("jobref.prx", symbol="Run_nid_no_patch") + entry[0x4000:0x400f] = b"\x48\x83\xec\x08\xff\x15" + struct.pack(" 30: parser.error("--timeout must be greater than zero and at most 30 seconds") try: @@ -124,7 +144,7 @@ def main(): directory.mkdir(parents=True, exist_ok=False) print(f"Artifacts: {directory}", flush=True) return run(args, directory) - except (OSError, RuntimeError, subprocess.SubprocessError) as error: + except (OSError, Refused, RuntimeError, subprocess.SubprocessError) as error: print(str(error), file=sys.stderr) if isinstance(error, subprocess.CalledProcessError) and error.stderr: print(error.stderr.decode(errors="replace"), file=sys.stderr) diff --git a/tools/suggest_patches.py b/tools/suggest_patches.py index 51d91d85a1..ead6b408e7 100644 --- a/tools/suggest_patches.py +++ b/tools/suggest_patches.py @@ -69,6 +69,9 @@ def validate_entry(directory, entry): def main(argv=None): + for stream in (sys.stdout, sys.stderr): + if hasattr(stream, "reconfigure"): + stream.reconfigure(encoding="utf-8", errors="backslashreplace") parser = argparse.ArgumentParser(description="Recommend a local patch only after metadata, hashes and relinker verification match") parser.add_argument("--catalog", required=True, type=Path, help="directory containing index.json and patch files") parser.add_argument("--param-json", required=True, type=Path, help="title metadata file") @@ -135,7 +138,8 @@ def main(argv=None): command.extend(("--executable", executable)) command.append(str(args.input)) try: - result = subprocess.run(command, capture_output=True, text=True, timeout=args.timeout_seconds) + result = subprocess.run(command, capture_output=True, text=True, encoding="utf-8", errors="replace", + timeout=args.timeout_seconds) except subprocess.TimeoutExpired: print(f"{label}: rejected: relinker verification exceeded {args.timeout_seconds} seconds") continue diff --git a/tools/tests/test_build_web.py b/tools/tests/test_build_web.py index 11c38bfdd4..78cdb95d0e 100644 --- a/tools/tests/test_build_web.py +++ b/tools/tests/test_build_web.py @@ -5,12 +5,14 @@ import io import json from pathlib import Path import subprocess +import struct import sys import tempfile import unittest from unittest.mock import patch import warnings import zipfile +import zlib sys.path.insert(0, str(Path(__file__).resolve().parents[1])) import build_web @@ -26,6 +28,60 @@ def library_zip(entries): class LibraryPublicationTests(unittest.TestCase): + def test_unicode_path_rewrite_is_rejected_before_decompression(self): + original = "libs/../libc.prx" + rewritten = "libs/libc.prx" + entry = zipfile.ZipInfo(original) + unicode_path = b"\x01" + struct.pack(" Texels{};", "alignas(65536)"), + ("alignas(16384) static char block[16];", "alignas(16384)"), + ("alignas( 0x10000 ) char block[16];", "alignas( 0x10000 )"), + ("alignas(0X4000u) char block[16];", "alignas(0X4000u)"), + ("alignas(65'536) char block[16];", "alignas(65'536)"), + ("alignas(040000) char block[16];", "alignas(040000)"), + ("alignas(0b100000000000000) char block[16];", "alignas(0b100000000000000)"), + ("alignas(256) char small[4]; alignas(32768) char large[4];", "alignas(32768)"), + ): + with self.subTest(line=line): + self.assertEqual(over_aligned(line), match) + + def test_alignments_within_the_limit(self): + for line in ( + "alignas(8192) char block[16];", + "alignas(0x2000) char block[16];", + "alignas(256) std::array Input{};", + "alignas(4096) char page[4096];", + "alignas(std::max_align_t) char storage[16];", + "alignas(Shader) char storage[sizeof(Shader)];", + "realignas(65536)", + "constexpr std::size_t TexelAlignment = 65536;", + ): + with self.subTest(line=line): + self.assertIsNone(over_aligned(line)) + + def test_named_constants_of_the_file(self): + self.assertEqual(reported("constexpr std::size_t BlockBytes = 65536;\n" + "static constexpr std::uint32_t PageBytes{0x1000u};\n" + "constexpr auto Large = 0x10000;\n" + "constexpr std::size_t Texels = 4u << 20u;\n" + "alignas(BlockBytes) std::array Block{};\n" + "alignas( Large ) char block[16];\n" + "alignas(PageBytes) char page[4096];\n" + "alignas(Texels) char texels[16];\n" + "alignas(inotify_event) char buffer[16384];\n"), [5, 6]) + self.assertEqual(reported("alignas(BlockBytes) char block[16];\n" + "constexpr std::size_t BlockBytes = 65536;\n"), []) + + def test_constants_in_separate_scopes(self): + self.assertEqual(reported(SMALL + LARGE), [7]) + self.assertEqual(reported(LARGE + SMALL), [3]) + + def test_constants_in_nested_scopes(self): + for outer, inner, expected in ((64, 16384, [6]), (16384, 64, [3, 8])): + text = ("void Nested() {\n" + f" constexpr std::size_t Alignment = {outer};\n" + " alignas(Alignment) static char before[4];\n" + " {\n" + f" constexpr std::size_t Alignment = {inner};\n" + " alignas(Alignment) static char inside[4];\n" + " }\n" + " alignas(Alignment) static char after[4];\n" + "}\n") + with self.subTest(outer=outer, inner=inner): + self.assertEqual(reported(text), expected) + + def test_constants_in_reopened_namespaces(self): + large = "constexpr std::size_t Alignment = 16384;" + use = "alignas(Alignment) static char data[4];" + for text, expected in ( + (f"namespace N {{ {large} }}\nnamespace N {{ {use} }}\n", [2]), + (f"namespace N {{ {large} }}\nnamespace M {{ {use} }}\n", []), + (f"namespace {{ {large} }}\nnamespace {{ {use} }}\n", [2]), + (f"namespace A::B {{ {large} }}\nnamespace A {{ namespace B {{ {use} }} }}\n", [2]), + (f"namespace A {{ {large} }}\nnamespace A::B {{ {use} }}\n", [2]), + (f"namespace A {{ inline namespace V1 {{ {large} }} }}\nnamespace A {{ {use} }}\n", [2]), + (f"namespace A {{ inline namespace V1 {{ {large} }} }}\nnamespace B {{ {use} }}\n", []), + (f"namespace N {{ {large} }}\nnamespace N {{ void F() {{ constexpr std::size_t Alignment = 64; {use} }} }}\n", []), + (f'extern "C" {{ {large} }}\n{use}\n', [2]), + ): + with self.subTest(text=text): + self.assertEqual(reported(text), expected) + + +class AlignmentRuleTests(unittest.TestCase): + def findings(self, after): + with tempfile.TemporaryDirectory() as directory: + root = Path(directory) + + def git(*args): + return subprocess.run(["git", "-c", f"safe.directory={root}", "-c", "user.name=Conventions Test", + "-c", "user.email=test@example.com", "-c", "commit.gpgsign=false", *args], + cwd=root, capture_output=True, check=True, encoding="utf-8").stdout + + source = root / SOURCE + source.parent.mkdir(parents=True) + source.write_text("alignas(65536) char existing[16];\n", encoding="utf-8") + git("init", "-q") + git("add", ".") + git("commit", "-qm", "test: add fixture") + source.write_text("alignas(65536) char existing[16];\n" + after, encoding="utf-8") + git("commit", "-qam", "test: add over-aligned blocks") + original = Path.cwd() + try: + os.chdir(root) + check = Check("HEAD~1", "HEAD") + check.code() + finally: + os.chdir(original) + return check.findings + + def test_only_added_code_is_reported(self): + self.assertEqual(self.findings("alignas(256) char small[16];\n" + "const char* text = \"alignas(65536)\";\n" + "alignas(0x10000) char added[16];\n" + "constexpr std::size_t BlockBytes = 65536;\n" + "alignas(BlockBytes) std::array Block{};\n"), + [("alignment", SOURCE, 4, "alignas(0x10000)"), ("alignment", SOURCE, 6, "alignas(BlockBytes)")]) + + def test_constants_are_resolved_in_their_scope(self): + self.assertEqual(self.findings("namespace First {\n" + SMALL + LARGE + "}\nnamespace Second {\n" + LARGE + SMALL + "}\n"), + [("alignment", SOURCE, 9, "alignas(Alignment)"), ("alignment", SOURCE, 15, "alignas(Alignment)")]) + + def test_reopened_namespace_keeps_its_constants(self): + self.assertEqual(self.findings("namespace N {\n" + " constexpr std::size_t Alignment = 16384;\n" + "}\n" + "namespace N {\n" + " alignas(Alignment) static char data[4];\n" + "}\n"), + [("alignment", SOURCE, 6, "alignas(Alignment)")]) + + +if __name__ == "__main__": + unittest.main() diff --git a/tools/tests/test_check_conventions_env_reference.py b/tools/tests/test_check_conventions_env_reference.py index d8fe70da63..ce341ce439 100644 --- a/tools/tests/test_check_conventions_env_reference.py +++ b/tools/tests/test_check_conventions_env_reference.py @@ -58,11 +58,15 @@ def findings_of(root, base, head, ref="base", directory="."): class EnvReferenceDiffTests(unittest.TestCase): - def run_case(self, base, head, target=None, directory="."): + def create_repository(self, base, head, target=None): temporary = tempfile.TemporaryDirectory() self.addCleanup(temporary.cleanup) root = Path(temporary.name) repository(root, base, head, target) + return root + + def run_case(self, base, head, target=None, directory="."): + root = self.create_repository(base, head, target) return findings_of(root, base, head, "base" if target is None else "target", directory) def test_a_check_from_a_subdirectory_reports_the_same_findings(self): @@ -80,10 +84,10 @@ class EnvReferenceDiffTests(unittest.TestCase): other: None, } expected = [("env-reference", SAMPLE, 2, f"APS5_NEW_READ is read here but has no row in {DOC}")] - self.assertEqual(self.run_case(base, head, target), expected) - for directory in ("core", "core/libs/prx/libSceExample", "docs/dev"): + root = self.create_repository(base, head, target) + for directory in (".", "core", "core/libs/prx/libSceExample", "docs/dev"): with self.subTest(directory=directory): - self.assertEqual(self.run_case(base, head, target, directory), expected) + self.assertEqual(findings_of(root, base, head, "target", directory), expected) def test_a_new_spaced_read_is_reported_at_its_line(self): base = {DOC: DOC_TEXT, SAMPLE: "int unrelated;\n"} diff --git a/tools/tests/test_check_main_sync.py b/tools/tests/test_check_main_sync.py index a82463563e..15d1e5c287 100644 --- a/tools/tests/test_check_main_sync.py +++ b/tools/tests/test_check_main_sync.py @@ -166,6 +166,15 @@ class CheckMainSyncTests(unittest.TestCase): result = run_tool(self.repo.path, "--head", "island") self.assertEqual(result.returncode, 2) self.assertIn("no common ancestor", result.stderr) + result = run_tool(self.repo.path, "--head", "missing") + expected = subprocess.run( + ["git", "-C", str(self.repo.path), "merge-base", "main", "missing"], + capture_output=True, + encoding="utf-8", + ).stderr.strip() + self.assertEqual(result.returncode, 2) + self.assertIn(f"git merge-base failed: {expected}", result.stderr) + self.assertNotIn("no common ancestor", result.stderr) def check_unicode_output(self, conflict): name = "sp ace \u00e9 \u6e2c \U0001f680.txt" diff --git a/tools/tests/test_check_skips.py b/tools/tests/test_check_skips.py index 6e3871733b..9c708417ee 100644 --- a/tools/tests/test_check_skips.py +++ b/tools/tests/test_check_skips.py @@ -37,6 +37,102 @@ OTHER = [ class CheckSkipsTests(unittest.TestCase): + def test_ctest_status_and_prefixed_device_reasons_are_expected(self): + reports = ( + ('skipped, the device lacks geometryShader', "linux"), + ('f16 native: skipped, the device has no native f16 with RTE rounding and kept denormals', "linux"), + ('video: skipped, no display or Vulkan device: ErrorInitializationFailed', "windows"), + ('skipped, no usable Vulkan device: none', "windows"), + ) + with tempfile.TemporaryDirectory() as directory: + junit = Path(directory) / "junit.xml" + for report, job in reports: + with self.subTest(job=job, report=report): + junit.write_text(f'{report}', encoding="utf-8") + result = subprocess.run([sys.executable, "-I", str(TOOL), str(junit), "--job", job], + capture_output=True, text=True) + self.assertEqual(result.returncode, 0, result.stdout + result.stderr) + self.assertIn("all expected", result.stdout) + + def test_ctest_status_does_not_allow_missing_or_unexpected_reasons(self): + reports = ( + '', + '', + 'skipped, flaky\nskipped, the device lacks geometryShader', + ) + with tempfile.TemporaryDirectory() as directory: + junit = Path(directory) / "junit.xml" + for report in reports: + for job in ("linux", "windows"): + with self.subTest(job=job, report=report): + junit.write_text(f'{report}', encoding="utf-8") + result = subprocess.run([sys.executable, "-I", str(TOOL), str(junit), "--job", job], + capture_output=True, text=True) + self.assertEqual(result.returncode, 1, result.stdout + result.stderr) + self.assertIn("error: guest_probe skipped", result.stdout) + + def test_ctest_status_preserves_high_refresh_policy(self): + reason = "skipped, current display does not provide 120 Hz" + reports = ( + (f'{reason}', 0), + (f'{reason}', 0), + (f'{reason}\nunexpected failure detail', 1), + (f'{reason}\nskipped, flaky', 1), + (f'skipped, no display\n{reason}', 1), + ) + with tempfile.TemporaryDirectory() as directory: + junit = Path(directory) / "junit.xml" + for report, expected_code in reports: + for job in ("linux", "windows"): + with self.subTest(job=job, report=report): + junit.write_text(f'{report}', encoding="utf-8") + result = subprocess.run([sys.executable, "-I", str(TOOL), str(junit), "--job", job], + capture_output=True, text=True) + self.assertEqual(result.returncode, expected_code, result.stdout + result.stderr) + + def test_list_reports_device_reason_after_ctest_status(self): + xml = ('' + 'f16 native: skipped, the device has no native f16') + with tempfile.TemporaryDirectory() as directory: + junit = Path(directory) / "junit.xml" + junit.write_text(xml, encoding="utf-8") + result = subprocess.run([sys.executable, "-I", str(TOOL), str(junit), "--list"], + capture_output=True, text=True) + self.assertEqual(result.returncode, 0, result.stdout + result.stderr) + self.assertIn("guest_probe: skipped, the device has no native f16", result.stdout) + self.assertNotIn("SKIP_RETURN_CODE", result.stdout) + + def test_unexpected_skip_reason_cannot_hide_behind_a_device_limitation(self): + reports = ( + ('skipped, the device lacks geometryShader', "linux"), + ('skipped, no display', "windows"), + ('flakyskipped, no usable Vulkan device', "windows"), + ('skipped, flaky\nskipped, the device lacks geometryShader', "linux"), + ) + with tempfile.TemporaryDirectory() as directory: + junit = Path(directory) / "junit.xml" + for report, job in reports: + with self.subTest(job=job, report=report): + junit.write_text(f'{report}', encoding="utf-8") + result = subprocess.run([sys.executable, "-I", str(TOOL), str(junit), "--job", job], + capture_output=True, text=True) + self.assertEqual(result.returncode, 1, result.stdout + result.stderr) + self.assertIn("error: guest_probe skipped", result.stdout) + + def test_multiple_allowed_skip_reasons_remain_expected(self): + reports = ( + ('skipped, no display', "linux"), + ('skipped, no usable Vulkan device', "windows"), + ) + with tempfile.TemporaryDirectory() as directory: + junit = Path(directory) / "junit.xml" + for report, job in reports: + with self.subTest(job=job, report=report): + junit.write_text(f'{report}', encoding="utf-8") + result = subprocess.run([sys.executable, "-I", str(TOOL), str(junit), "--job", job], + capture_output=True, text=True) + self.assertEqual(result.returncode, 0, result.stdout + result.stderr) + def test_non_junit_xml_fails_in_every_cli_mode(self): reports = ('', 'coverage') with tempfile.TemporaryDirectory() as directory: diff --git a/tools/tests/test_debt_split.py b/tools/tests/test_debt_split.py index 1f2cf31775..ae68754774 100644 --- a/tools/tests/test_debt_split.py +++ b/tools/tests/test_debt_split.py @@ -44,15 +44,14 @@ class DebtSplitTests(unittest.TestCase): self.root = Path(self.directory.name) self.git("init", "-q", "-b", "main") self.write(INDEX, ORIGINAL) - self.git("add", ".") - self.git("commit", "-qm", "docs: record technical debt") def tearDown(self): self.directory.cleanup() def git(self, *args, check=True): return subprocess.run( - ["git", "-c", "user.name=Debt Test", "-c", "user.email=test@example.com", "-c", "commit.gpgsign=false", *args], + ["git", "-c", "user.name=Debt Test", "-c", "user.email=test@example.com", "-c", "commit.gpgsign=false", + "-c", "maintenance.auto=false", *args], cwd=self.root, capture_output=True, text=True, check=check, env={**os.environ, "GIT_EDITOR": "true"}, ) @@ -68,10 +67,19 @@ class DebtSplitTests(unittest.TestCase): return subprocess.run([sys.executable, str(TOOL), command], cwd=self.root, capture_output=True, text=True, timeout=20) def split(self): - result = self.tool("split") - self.assertEqual(result.returncode, 0, result.stdout + result.stderr) + directory, streams = os.getcwd(), (sys.stdout, sys.stderr) + os.chdir(self.root) + try: + with open(os.devnull, "w", encoding="utf-8") as sink: + sys.stdout = sys.stderr = sink + debt_split.main(["split"]) + finally: + os.chdir(directory) + sys.stdout, sys.stderr = streams + + def commit(self, message): self.git("add", "-A") - self.git("commit", "-qm", "docs: split technical debt") + self.git("commit", "-qm", message) def test_split_preserves_external_urls_and_rewrites_local_links(self): links = ["HTTPS://example.test/guide#intro", "//example.test/guide#intro", @@ -114,11 +122,13 @@ class DebtSplitTests(unittest.TestCase): self.assertEqual(self.read(INDEX).count("[debt](debt/)"), 1) def rebase(self, stubs, functional): + self.commit("docs: record technical debt") self.git("checkout", "-qb", "change") self.write(INDEX, index(stubs, functional)) self.git("commit", "-qam", "feat: change debt") self.git("checkout", "-q", "main") self.split() + self.commit("docs: split technical debt") self.git("checkout", "-q", "change") rebase = self.git("rebase", "main", check=False) self.assertNotEqual(rebase.returncode, 0, rebase.stdout + rebase.stderr) @@ -170,11 +180,13 @@ class DebtSplitTests(unittest.TestCase): self.assertIn("<<<<<<<", self.read(INDEX)) def test_resolve_refuses_an_entry_main_changed_too(self): + self.commit("docs: record technical debt") self.git("checkout", "-qb", "change") self.write(INDEX, index([A_STUB, B_STUB + " here", C_STUB], [A_FUNCTIONAL, SHADER, SHARED])) self.git("commit", "-qam", "feat: change b") self.git("checkout", "-q", "main") self.split() + self.commit("docs: split technical debt") path = "docs/dev/debt/libSceB.md" self.write(path, self.read(path).replace("returns 0", "returns 1")) self.git("commit", "-qam", "docs: change b") @@ -185,6 +197,7 @@ class DebtSplitTests(unittest.TestCase): self.assertIn("entry not found", result.stderr) def test_resolve_needs_a_conflict(self): + self.commit("docs: record technical debt") result = self.tool("resolve") self.assertNotEqual(result.returncode, 0) self.assertIn("not in a three-way conflict", result.stderr) diff --git a/tools/tests/test_import_audit.py b/tools/tests/test_import_audit.py index c1acc164c6..7035c0615c 100644 --- a/tools/tests/test_import_audit.py +++ b/tools/tests/test_import_audit.py @@ -172,7 +172,7 @@ def build_pe_with_imports(dlls, names=()): def write_source(root, library, text): directory = Path(root) / library directory.mkdir(parents=True, exist_ok=True) - (directory / "Export.cpp").write_text(text) + (directory / "Export.cpp").write_text(text, encoding="utf-8") def write_registry(path, entries, encoding="utf-8"): @@ -323,7 +323,7 @@ class ImportAuditTests(unittest.TestCase): data = json.loads(report.read_text(encoding="utf-8")) records = {record["nid"]: record for record in data["imports"]} self.assertEqual(data["references"], 5) - self.assertEqual(data["unique_by_class"], {"implemented": 3, "stub": 0, "absent": 1, "module": 0}) + self.assertEqual(data["unique_by_class"], {"implemented": 3, "partial": 0, "stub": 0, "absent": 1, "module": 0}) self.assertEqual(records["strcmp"]["references"], 2) self.assertEqual(records["strcmp"]["providers"], ["libc.prx"]) self.assertTrue(records["missing_function"]["weak"]) @@ -614,8 +614,8 @@ class ImportAuditTests(unittest.TestCase): data = json.loads(result.read_text()) self.assertEqual(data["references"], 10) self.assertEqual(data["unique_imports"], 9) - self.assertEqual(data["unique_by_class"], {"implemented": 3, "stub": 2, "absent": 3, "module": 1}) - self.assertEqual(data["references_by_class"], {"implemented": 3, "stub": 3, "absent": 3, "module": 1}) + self.assertEqual(data["unique_by_class"], {"implemented": 3, "partial": 0, "stub": 2, "absent": 3, "module": 1}) + self.assertEqual(data["references_by_class"], {"implemented": 3, "partial": 0, "stub": 3, "absent": 3, "module": 1}) self.assertEqual(data["missing_libraries"], {"libSceFoo.prx": 1, "libSceOther.prx": 1}) self.assertEqual(data["library_mismatch"], 1) kinds = {(record["nid"], record["library"]): record["class"] for record in data["imports"]} @@ -644,7 +644,7 @@ class ImportAuditTests(unittest.TestCase): self.assertEqual((code, err), (1, "")) data = json.loads(result.read_text()) self.assertEqual(data["references"], 4) - self.assertEqual(data["unique_by_class"], {"implemented": 2, "stub": 1, "absent": 1, "module": 0}) + self.assertEqual(data["unique_by_class"], {"implemented": 2, "partial": 0, "stub": 1, "absent": 1, "module": 0}) self.assertEqual(data["missing_libraries"], {}) records = {(record["nid"], record["module"]): record for record in data["imports"]} self.assertEqual(records[("AAAAAAAAAAA", "main.prx")]["class"], "implemented") @@ -720,7 +720,7 @@ class ImportAuditTests(unittest.TestCase): self.assertEqual((code, err), (0, "")) data = json.loads(result.read_text()) self.assertEqual(data["references"], 3) - self.assertEqual(data["unique_by_class"], {"implemented": 2, "stub": 0, "absent": 0, "module": 1}) + self.assertEqual(data["unique_by_class"], {"implemented": 2, "partial": 0, "stub": 0, "absent": 0, "module": 1}) self.assertEqual(data["missing_libraries"], {}) records = {(record["nid"], record.get("module")): record for record in data["imports"]} self.assertEqual(records[("AAAAAAAAAAA", "provider.data")]["providers"], ["libSceA.prx"]) @@ -765,7 +765,7 @@ class ImportAuditTests(unittest.TestCase): self.assertEqual((code, err), (0, "")) data = json.loads(report.read_text(encoding="utf-8")) self.assertEqual(data["missing_libraries"], {}) - self.assertEqual(data["unique_by_class"], {"implemented": 0, "stub": 0, "absent": 0, "module": 1}) + self.assertEqual(data["unique_by_class"], {"implemented": 0, "partial": 0, "stub": 0, "absent": 0, "module": 1}) self.assertEqual(data["references"], 1) self.assertEqual(data["imports"][0]["library"], needed) finally: @@ -784,7 +784,7 @@ class ImportAuditTests(unittest.TestCase): self.assertEqual((code, err), (1, "")) data = json.loads(report.read_text(encoding="utf-8")) self.assertEqual(data["missing_libraries"], {needed: 1}) - self.assertEqual(data["unique_by_class"], {"implemented": 0, "stub": 0, "absent": 1, "module": 0}) + self.assertEqual(data["unique_by_class"], {"implemented": 0, "partial": 0, "stub": 0, "absent": 1, "module": 0}) def test_converted_module_matches_imports_of_its_base_name(self): work = self.work @@ -932,7 +932,7 @@ class ImportAuditTests(unittest.TestCase): self.assertEqual((code, err), (1, "")) data = json.loads(result.read_text()) self.assertEqual((data["references"], data["unique_imports"]), (2, 2)) - self.assertEqual(data["unique_by_class"], {"implemented": 1, "stub": 0, "absent": 1, "module": 0}) + self.assertEqual(data["unique_by_class"], {"implemented": 1, "partial": 0, "stub": 0, "absent": 1, "module": 0}) self.assertEqual(data["references_by_class"], data["unique_by_class"]) self.assertEqual(data["missing_libraries"], {"libSceMissing.prx": 1}) records = {record["nid"]: record for record in data["imports"]} @@ -1077,7 +1077,7 @@ class ImportAuditTests(unittest.TestCase): code, out, err = work.run(registry, "--json", str(result)) self.assertEqual((code, err), (0, "")) data = json.loads(result.read_text()) - self.assertEqual(data["unique_by_class"], {"implemented": 1, "stub": 0, "absent": 0, "module": 0}) + self.assertEqual(data["unique_by_class"], {"implemented": 1, "partial": 0, "stub": 0, "absent": 0, "module": 0}) self.assertEqual(data["references"], 1) def test_module_export_suffix_is_stripped_with_and_without_sections(self): @@ -1129,7 +1129,7 @@ class ImportAuditTests(unittest.TestCase): data = json.loads(result.read_text()) self.assertEqual(data["references"], 4 + int(unresolved)) self.assertEqual(data["unique_by_class"], - {"implemented": 3, "stub": 0, "absent": int(unresolved), "module": 0}) + {"implemented": 3, "partial": 0, "stub": 0, "absent": int(unresolved), "module": 0}) records = {record["nid"]: record for record in data["imports"]} for symbol in (MESSAGE_NID, MESSAGE_NAME, "strlen"): self.assertEqual(records[symbol]["providers"], [provider.name]) @@ -1308,6 +1308,27 @@ class ImportAuditTests(unittest.TestCase): self.assertNotIn(("libSceTwin.native.prx", twin), stubs) self.assertNotEqual(nid_names.compute_nid("printf"), nid_names.compute_nid("printf_nid_postfix")) + def test_source_stubs_decodes_source_with_utf8_bom(self): + source = self.work.source + write_source(source, "libSceBom", "\ufeff" + STUB_SOURCE.format(name="sceBomPending")) + stubs = import_audit.source_stubs(source) + self.assertEqual(stubs.get(("libSceBom.prx", nid_names.compute_nid("sceBomPending"))), "sceBomPending") + + def test_source_stubs_passes_decoded_text_without_bom_to_alias_scanner(self): + source = self.work.source + write_source(source, "libSceBomAlias", "\ufeff" + 'APS5_EXPORT("AAAAAAAAAAA", sceBomAlias);\n' + STUB_SOURCE.format(name="sceBomAlias")) + seen = [] + real = nid_names.source_aliases + + def spy(text): + seen.append(text) + return real(text) + + with patch.object(nid_names, "source_aliases", spy): + import_audit.source_stubs(source) + self.assertTrue(seen) + self.assertTrue(all(text.startswith("APS5_EXPORT(") for text in seen)) + def test_disambiguated_stubs_use_the_nid_of_their_symbol(self): source = self.work.source write_source(source, "libkernel", STUB_SOURCE.format(name="fstat_nid_disambig1_nid_postfix") @@ -1377,6 +1398,77 @@ class ImportAuditTests(unittest.TestCase): self.assertEqual(import_audit.source_stubs(source), { (library + ".prx", nid): "scePending" for library in ("libA", "libB", "libZOwner")}) + def test_guarded_exports_are_partial_and_unconditional_ones_are_stubs(self): + source = self.work.source + write_source(source, "libGuard", + "void Fail() { NotImplemented_nid_no_patch(__func__); }\n" + "void Check(int value) { if (value) NotImplemented_nid_no_patch(__func__); }\n" + "int APS5_VABI sceDirect(int value) { NotImplemented_nid_no_patch(__func__); return 0; }\n" + "int APS5_VABI sceReturned(int value) { return NotImplemented_nid_no_patch(__func__); }\n" + "int APS5_VABI sceWrapped(int value) { value += 1; Fail(); return value; }\n" + "int APS5_VABI sceIf(int value) { if (value > 1) NotImplemented_nid_no_patch(__func__); return value; }\n" + "int APS5_VABI sceBlock(int value) { if (value) { NotImplemented_nid_no_patch(__func__); } return 0; }\n" + "int APS5_VABI sceElse(int value) { if (value) return 1; else Fail(); return 0; }\n" + "int APS5_VABI sceGuarded(int value) { Check(value); return value; }\n" + "int APS5_VABI sceLoop(int value) { for (int i = 0; i < value; ++i) Fail(); return 0; }\n" + "int APS5_VABI sceSwitch(int value) { switch (value) { case 0: return 0; default: Fail(); } return 1; }\n" + "int APS5_VABI sceTernary(int value) { return value ? value : NotImplemented_nid_no_patch(__func__); }\n" + "int APS5_VABI sceShort(int value) { return value && NotImplemented_nid_no_patch(__func__); }\n" + "int APS5_VABI sceLambda(int value) { auto f = [&]() { Fail(); }; return value; }\n" + "int APS5_VABI sceMember(int value) { if (value) Fail(); other.Fail(); return value; }\n" + "int APS5_VABI sceHost(int value) {\n#if defined(_WIN32)\n return value;\n#elif defined(__linux__)\n" + " return value + 1;\n#else\n NotImplemented_nid_no_patch(__func__);\n return 0;\n#endif\n}\n" + "int APS5_VABI sceHostHelper(int value) {\n#ifdef HOST_WITHOUT_IT\n Fail();\n#endif\n return value;\n}\n" + "#ifdef ONLY_HERE\nint APS5_VABI sceOuter(int value) { NotImplemented_nid_no_patch(__func__); return 0; }\n#endif\n" + "int APS5_VABI sceEveryHost(int value) {\n#if defined(_WIN32)\n NotImplemented_nid_no_patch(__func__);\n#else\n" + " NotImplemented_nid_no_patch(__func__);\n#endif\n return 0;\n}\n" + "int APS5_VABI sceEveryElif(int value) {\n#if defined(HOST_A)\n Fail();\n#elif defined(HOST_B)\n" + " NotImplemented_nid_no_patch(__func__);\n#else\n Fail();\n#endif\n return 0;\n}\n" + "int APS5_VABI sceNested(int value) {\n#if defined(HOST_A)\n#ifdef FEATURE\n return value;\n#else\n Fail();\n#endif\n" + "#else\n Fail();\n#endif\n return 0;\n}\n" + "void SoftFail(int value) { if (value == 0) return; NotImplemented_nid_no_patch(__func__); }\n" + "void HardFail(int value) { if (value == 0) throw std::invalid_argument(\"zero\"); NotImplemented_nid_no_patch(__func__); }\n" + "int APS5_VABI sceGuardReturn(int value) { if (value == 0) return 0; NotImplemented_nid_no_patch(__func__); return 1; }\n" + "int APS5_VABI sceGuardThrow(int value) { if (value == 0) throw std::invalid_argument(\"zero\"); " + "NotImplemented_nid_no_patch(__func__); return 1; }\n" + "int APS5_VABI sceGuardBlock(int value) { { if (value == 0) return 0; } Fail(); return 1; }\n" + "int APS5_VABI sceGuardGoto(int value) { if (value == 0) goto done; Fail(); done: return 0; }\n" + "int APS5_VABI sceGuardHost(int value) {\n#ifdef HOST_A\n if (value == 0) return 0;\n#endif\n Fail();\n return 1;\n}\n" + "int APS5_VABI sceSoftHelper(int value) { SoftFail(value); return 0; }\n" + "int APS5_VABI sceHardHelper(int value) { HardFail(value); return 0; }\n" + "int APS5_VABI scePlainBlock(int value) { { NotImplemented_nid_no_patch(__func__); } return 0; }\n" + "int APS5_VABI sceNestedBlock(int value) { value += 1; { { Fail(); } } return value; }\n" + "int APS5_VABI sceBlockThenGuard(int value) { { if (value == 0) return 0; NotImplemented_nid_no_patch(__func__); } return 1; }\n") + write_source(source, "libShared", '#include "prx/libGuard/Export.cpp"\n') + stubs, partial = import_audit.source_stub_classes(source) + names = ("sceDirect", "sceReturned", "sceWrapped", "sceIf", "sceBlock", "sceElse", "sceGuarded", + "sceLoop", "sceSwitch", "sceTernary", "sceShort", "sceLambda", "sceMember", "sceHost", "sceHostHelper", + "sceOuter", "sceEveryHost", "sceEveryElif", "sceNested", "sceGuardReturn", "sceGuardThrow", + "sceGuardBlock", "sceGuardGoto", "sceGuardHost", "sceSoftHelper", "sceHardHelper", + "scePlainBlock", "sceNestedBlock", "sceBlockThenGuard") + kinds = {name: "partial" if ("libGuard.prx", nid_names.compute_nid(name)) in partial else "stub" for name in names} + self.assertEqual({name for name, kind in kinds.items() if kind == "stub"}, + {"sceDirect", "sceReturned", "sceWrapped", "sceOuter", "sceEveryHost", "sceEveryElif", + "sceGuardThrow", "sceHardHelper", "scePlainBlock", "sceNestedBlock"}) + self.assertEqual(set(stubs), {(library, nid_names.compute_nid(name)) for library in ("libGuard.prx", "libShared.prx") for name in names}) + self.assertEqual(partial, {(library, nid_names.compute_nid(name)) for library in ("libGuard.prx", "libShared.prx") + for name, kind in kinds.items() if kind == "partial"}) + + def test_partial_import_is_its_own_class(self): + direct, guarded = nid_names.compute_nid("sceDirect"), nid_names.compute_nid("sceGuarded") + stubs = {("libA.prx", direct): "sceDirect", ("libA.prx", guarded): "sceGuarded", ("libB.prx", guarded): "sceGuarded"} + partial = {("libB.prx", guarded)} + exports = {direct: ["libA.prx"], guarded: ["libA.prx", "libB.prx"]} + imports = [(direct, "libA.prx", False), (guarded, "libA.prx", False), (guarded, "libA.prx", False)] + records, _ = import_audit.audit(imports, exports, stubs, {"libA.prx", "libB.prx"}, set(), partial=partial) + self.assertEqual({record["nid"]: (record["class"], record["name"]) for record in records}, + {direct: ("stub", "sceDirect"), guarded: ("partial", "sceGuarded")}) + summary = import_audit.summarize(records, 3, {}) + self.assertEqual(summary["references_by_class"], {"implemented": 0, "partial": 2, "stub": 1, "absent": 0, "module": 0}) + text = import_audit.render(summary, records, {}, []) + self.assertIn("Stub: exported but throws when called (1)", text) + self.assertIn("Partial: exported, throws only for inputs whose behaviour is unknown (1)", text) + def test_shared_source_cycle_fails(self): source = self.work.source for library, owner in (("libA", "libB"), ("libB", "libA")): @@ -2046,7 +2138,7 @@ class ImportAuditTests(unittest.TestCase): data = json.loads(report.read_text(encoding="utf-8")) self.assertEqual(data["source_commit"], commit) self.assertIsNone(data["source_dirty"]) - self.assertEqual(data["unique_by_class"], {"implemented": 1, "stub": 0, "absent": 0, "module": 0}) + self.assertEqual(data["unique_by_class"], {"implemented": 1, "partial": 0, "stub": 0, "absent": 0, "module": 0}) def test_git_stamp_keeps_commit_when_status_cannot_start(self): completed = subprocess.CompletedProcess([], 0, stdout="abcdef\n") @@ -2144,15 +2236,17 @@ class ImportAuditTests(unittest.TestCase): registry = self.work.root / "game.json" output = self.work.root / "audit.json" (self.work.libs / "libSceExample.prx").write_bytes(exporting(nid)) - write_source(self.work.source, "libSceExample", STUB_SOURCE.format(name=name)) - for weak in (False, True): - with self.subTest(weak=weak): - write_registry(registry, [(nid, "libSceExample.prx", weak)]) - self.assertEqual(self.work.run(registry)[0], 0) - code, out, err = self.work.run(registry, "--strict-stubs", "--json", str(output)) - self.assertEqual((code, err), (1, "")) - self.assertIn("stub", out) - self.assertEqual(json.loads(output.read_text(encoding="utf-8"))["unique_by_class"]["stub"], 1) + block = "int APS5_VABI {name}(int value) {{ {{ NotImplemented_nid_no_patch(__func__); }} return 0; }}\n" + for form in (STUB_SOURCE, block): + write_source(self.work.source, "libSceExample", form.format(name=name)) + for weak in (False, True): + with self.subTest(form=form, weak=weak): + write_registry(registry, [(nid, "libSceExample.prx", weak)]) + self.assertEqual(self.work.run(registry)[0], 0) + code, out, err = self.work.run(registry, "--strict-stubs", "--json", str(output)) + self.assertEqual((code, err), (1, "")) + self.assertIn("stub", out) + self.assertEqual(json.loads(output.read_text(encoding="utf-8"))["unique_by_class"]["stub"], 1) write_source(self.work.source, "libSceExample", DONE_SOURCE.format(name=name) + STUB_SOURCE.format(name="sceUnreferencedPending")) self.assertEqual(self.work.run(registry, "--strict-stubs")[0], 0) @@ -2201,6 +2295,33 @@ class StrictProviderTests(unittest.TestCase): write_registry(registry, [("AAAAAAAAAAA", "libSceMissing.prx")]) self.assertEqual(work.run(registry, "--strict-providers")[0], 1) + def test_main_reconfigures_streams(self): + class Stream: + def __init__(self): + self.encoding = None + self.errors = None + + def reconfigure(self, encoding=None, errors=None): + self.encoding = encoding + self.errors = errors + + def write(self, text): + pass + + def flush(self): + pass + + out, err = Stream(), Stream() + with patch.object(import_audit.sys, "stdout", out), patch.object(import_audit.sys, "stderr", err): + try: + import_audit.main([]) + except SystemExit: + pass + self.assertEqual(out.encoding, "utf-8") + self.assertEqual(out.errors, "backslashreplace") + self.assertEqual(err.encoding, "utf-8") + self.assertEqual(err.errors, "backslashreplace") + if __name__ == "__main__": unittest.main() diff --git a/tools/tests/test_nid_names.py b/tools/tests/test_nid_names.py index f5ccf2945d..f14b4be874 100644 --- a/tools/tests/test_nid_names.py +++ b/tools/tests/test_nid_names.py @@ -41,8 +41,13 @@ class DatabaseCacheTests(unittest.TestCase): database.write_text(f"{nid} sceExample\n", encoding="utf-8") scratch = str(Path(directory) / "scratch") Path(scratch).mkdir() + tree = Path(directory) / "tree" + (tree / "core" / "libs" / "prx").mkdir(parents=True) + (tree / "tools").mkdir() + tool = tree / "tools" / "nid_names.py" + tool.write_bytes(Path(script).read_bytes()) environment = {**os.environ, "ANYPS5_NID_DB": str(database), "TEMP": scratch, "TMP": scratch, "TMPDIR": scratch} - result = subprocess.run([sys.executable, script, "--nid", nid, "--json"], capture_output=True, text=True, + result = subprocess.run([sys.executable, str(tool), "--nid", nid, "--json"], capture_output=True, text=True, env=environment, timeout=20) self.assertEqual(list(Path(scratch).iterdir()), []) self.assertEqual(result.returncode, 0, result.stderr) diff --git a/tools/tests/test_progress.py b/tools/tests/test_progress.py index 397f8494dd..c7f305b811 100644 --- a/tools/tests/test_progress.py +++ b/tools/tests/test_progress.py @@ -622,5 +622,50 @@ class ProgressTests(unittest.TestCase): self.assertIn("is not a source tree", stderr.getvalue()) self.assertIn(str(path), stderr.getvalue()) + def test_compare_accepts_snapshots_with_utf8_bom(self): + def snapshot(names): + return {"libraries": progress.summarize([ + {"name": "libScePad", "label": "Pad", "done": len(names), "todo": 0, + "done_names": names, "todo_names": [], "inert_names": []}]), + "shaders": {"done": 0, "total": 0, "percent": 0, "groups": [], "extra": []}} + with tempfile.TemporaryDirectory() as directory: + base = Path(directory) / "base.json" + head = Path(directory) / "head.json" + base.write_text("\ufeff" + json.dumps(snapshot([])), encoding="utf-8") + head.write_text("\ufeff" + json.dumps(snapshot(["Ready"])), encoding="utf-8") + stdout = io.StringIO() + with patch("sys.stdout", stdout): + code = progress.main(["--compare", str(base), str(head)]) + self.assertEqual(code, 0) + self.assertIn("implemented", stdout.getvalue()) + + def test_main_reconfigures_streams(self): + class Stream: + def __init__(self): + self.encoding = None + self.errors = None + + def reconfigure(self, encoding=None, errors=None): + self.encoding = encoding + self.errors = errors + + def write(self, text): + pass + + def flush(self): + pass + + out, err = Stream(), Stream() + with patch.object(progress.sys, "stdout", out), patch.object(progress.sys, "stderr", err): + try: + progress.main([]) + except SystemExit: + pass + self.assertEqual(out.encoding, "utf-8") + self.assertEqual(out.errors, "backslashreplace") + self.assertEqual(err.encoding, "utf-8") + self.assertEqual(err.errors, "backslashreplace") + + if __name__ == "__main__": unittest.main() diff --git a/tools/tests/test_progress_history.py b/tools/tests/test_progress_history.py index 38b9f5de86..7dbec9aa67 100644 --- a/tools/tests/test_progress_history.py +++ b/tools/tests/test_progress_history.py @@ -99,6 +99,17 @@ class ProgressHistoryTests(unittest.TestCase): self.assertIn(" [--verbose] """ import argparse +import io import math import secrets import struct @@ -217,7 +218,7 @@ def place_segments(data, headers, records): for header in headers: if header["type"] == PT_LOAD and header["size"] == 0: continue - if header["source"] > len(data) or header["size"] > len(data) - header["source"]: + if header["source"] < 0 or header["source"] > len(data) or header["size"] > len(data) - header["source"]: raise Refused("segment %d does not fit the file" % header["index"]) @@ -329,7 +330,7 @@ def unwrap(path, output, verbose=False): destination.parent.mkdir(parents=True, exist_ok=True) temporary_path = destination.parent / (".unwrap-self-" + secrets.token_hex(16)) - temporary = temporary_path.open("xb") + temporary = io.open(temporary_path, "xb") try: with temporary: temporary.write(result)