refactor(libs): drop replacements of modules that titles ship themselves

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Adrià Franch 2026-10-05 16:50:22 +02:00
parent 109a3281f8
commit 79057e9160
17 changed files with 1 additions and 5207 deletions

View File

@ -7,6 +7,7 @@
- A silent stub is allowed only when it unblocks a title and only affects the UI; add it to [silent stubs](docs/dev/TechnicalDebt.md#silent-stubs).
- Missing imports fail at startup with a clear error; don't replace them with fallbacks that keep running.
- 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 (NpCppWebApi over NpWebApi2). 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).
- 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.
- 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.

View File

@ -118,17 +118,6 @@ foreach(LIB_DIR ${LIBS_DIRS})
endif()
endforeach()
set(LIBCOHTML_PATCHED ${PATCHED_DIR}/libcohtml.prx)
set(LIBCOHTML_PROSPERO_PATCHED ${PATCHED_DIR}/libcohtml.Prospero.prx)
add_custom_command(
OUTPUT ${LIBCOHTML_PROSPERO_PATCHED}
COMMAND ${CMAKE_COMMAND} -E copy "${LIBCOHTML_PATCHED}" "${LIBCOHTML_PROSPERO_PATCHED}"
DEPENDS ${LIBCOHTML_PATCHED}
VERBATIM
)
add_custom_target(libcohtml_prospero DEPENDS ${LIBCOHTML_PROSPERO_PATCHED})
list(APPEND PATCHED_OUTPUTS ${LIBCOHTML_PROSPERO_PATCHED})
add_custom_target(libs DEPENDS ${PATCHED_OUTPUTS})
if(BUILD_TESTING)
@ -170,16 +159,6 @@ if(BUILD_TESTING)
add_test(NAME host_thread_local COMMAND host_thread_local_tests)
set_tests_properties(host_thread_local PROPERTIES TIMEOUT 15)
add_test_executable(guest_np_cpp_web_api_intrusive_ptr_tests tests/GuestNpCppWebApiIntrusivePtr.cpp)
target_include_directories(guest_np_cpp_web_api_intrusive_ptr_tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(guest_np_cpp_web_api_intrusive_ptr_tests PRIVATE libSceNpCppWebApi libc)
configure_windows_unwind(guest_np_cpp_web_api_intrusive_ptr_tests)
add_test(NAME guest_np_cpp_web_api_intrusive_ptr COMMAND guest_np_cpp_web_api_intrusive_ptr_tests)
if(WIN32)
set_tests_properties(guest_np_cpp_web_api_intrusive_ptr PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libSceNpCppWebApi>")
endif()
add_test_executable(savedata_core_write_replacement_tests tests/SaveDataWriteReplacement.cpp)
target_include_directories(savedata_core_write_replacement_tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(savedata_core_write_replacement_tests PRIVATE libSceSaveData)

View File

@ -1,196 +0,0 @@
#include <cstdint>
#include "SceTypes.hpp"
#include "prx/libc/include/General.hpp"
extern "C" {
// CD Projekt RED GOG Galaxy wrapper, bundled with the game as
// modules/libREDGalaxy64.prx (seen in Cyberpunk 2077 PPSA04029).
// Online Galaxy services cannot work under emulation: Init/Shutdown/
// ProcessData are accepted and ignored, interface getters return null
// (all observed engine call sites null-check the result).
// Roles below were reversed from the module's own export bodies:
// Init references clientID/clientSecret/configFilePath, Shutdown
// releases the facade singletons, ProcessData throttles facade
// ProcessData calls, GetErrorString formats Gog/Std exceptions.
APS5_EXPORT("1icN9EO2WSg", redGalaxy64Init);
std::uint64_t APS5_VABI redGalaxy64Init(const void* options) {
(void)options;
NotImplemented_nid_no_patch(__func__);
return 1;
}
APS5_EXPORT("SA7aCTRE5zg", redGalaxy64Shutdown);
void APS5_VABI redGalaxy64Shutdown(void) {
NotImplemented_nid_no_patch(__func__);
}
APS5_EXPORT("ZVPOpEqpUvo", redGalaxy64ProcessData);
void APS5_VABI redGalaxy64ProcessData(void) {
NotImplemented_nid_no_patch(__func__);
}
APS5_EXPORT("4trn+7BssaY", redGalaxy64GetErrorString);
const char* APS5_VABI redGalaxy64GetErrorString(void) {
NotImplemented_nid_no_patch(__func__);
return "";
}
APS5_EXPORT("DQAUzFVaGl8", redGalaxy64GameServerInit);
std::uint64_t APS5_VABI redGalaxy64GameServerInit(const void* options) {
(void)options;
NotImplemented_nid_no_patch(__func__);
return 1;
}
APS5_EXPORT("GKomji4WVHw", redGalaxy64ProcessGameServerData);
void APS5_VABI redGalaxy64ProcessGameServerData(void) {
NotImplemented_nid_no_patch(__func__);
}
APS5_EXPORT("36lort-kFp4", redgalaxy_stub_00);
std::uint64_t APS5_VABI redgalaxy_stub_00(std::uint64_t a0, std::uint64_t a1, std::uint64_t a2) {
(void)a0;
(void)a1;
(void)a2;
NotImplemented_nid_no_patch("36lort-kFp4");
return 0;
}
APS5_EXPORT("NgDLhCc6F7Y", redgalaxy_stub_01);
std::uint64_t APS5_VABI redgalaxy_stub_01(const void* a0, const char* a1, std::uint64_t a2) {
(void)a0;
(void)a1;
(void)a2;
NotImplemented_nid_no_patch("NgDLhCc6F7Y");
return 0;
}
APS5_EXPORT("huJ+beHcWBE", redgalaxy_stub_02);
std::uint64_t APS5_VABI redgalaxy_stub_02(void) {
NotImplemented_nid_no_patch("huJ+beHcWBE");
return 0;
}
APS5_EXPORT("sxiZFliOEDU", redgalaxy_stub_03);
std::uint64_t APS5_VABI redgalaxy_stub_03(void) {
NotImplemented_nid_no_patch("sxiZFliOEDU");
return 0;
}
APS5_EXPORT("49Bdn1OOJ90", redgalaxy_stub_04);
std::uint64_t APS5_VABI redgalaxy_stub_04(void) {
NotImplemented_nid_no_patch("49Bdn1OOJ90");
return 0;
}
APS5_EXPORT("8ahh9DUqZLY", redgalaxy_stub_05);
std::uint64_t APS5_VABI redgalaxy_stub_05(void) {
NotImplemented_nid_no_patch("8ahh9DUqZLY");
return 0;
}
APS5_EXPORT("Ard4nEfw5Vs", redgalaxy_stub_06);
std::uint64_t APS5_VABI redgalaxy_stub_06(void) {
NotImplemented_nid_no_patch("Ard4nEfw5Vs");
return 0;
}
APS5_EXPORT("AzO2fwK+MUs", redgalaxy_stub_07);
std::uint64_t APS5_VABI redgalaxy_stub_07(void) {
NotImplemented_nid_no_patch("AzO2fwK+MUs");
return 0;
}
APS5_EXPORT("HKIwQPq45o4", redgalaxy_stub_08);
std::uint64_t APS5_VABI redgalaxy_stub_08(void) {
NotImplemented_nid_no_patch("HKIwQPq45o4");
return 0;
}
APS5_EXPORT("IXRuom5imkM", redgalaxy_stub_09);
std::uint64_t APS5_VABI redgalaxy_stub_09(void) {
NotImplemented_nid_no_patch("IXRuom5imkM");
return 0;
}
APS5_EXPORT("LjDqfncevos", redgalaxy_stub_10);
std::uint64_t APS5_VABI redgalaxy_stub_10(void) {
NotImplemented_nid_no_patch("LjDqfncevos");
return 0;
}
APS5_EXPORT("Onwg0aGsFhM", redgalaxy_stub_11);
std::uint64_t APS5_VABI redgalaxy_stub_11(void) {
NotImplemented_nid_no_patch("Onwg0aGsFhM");
return 0;
}
APS5_EXPORT("oSyqfoYcK40", redgalaxy_stub_12);
std::uint64_t APS5_VABI redgalaxy_stub_12(void) {
NotImplemented_nid_no_patch("oSyqfoYcK40");
return 0;
}
APS5_EXPORT("qoS0gqW7RxI", redgalaxy_stub_13);
std::uint64_t APS5_VABI redgalaxy_stub_13(void) {
NotImplemented_nid_no_patch("qoS0gqW7RxI");
return 0;
}
APS5_EXPORT("SOtPNNwajSw", redgalaxy_stub_14);
std::uint64_t APS5_VABI redgalaxy_stub_14(void) {
NotImplemented_nid_no_patch("SOtPNNwajSw");
return 0;
}
APS5_EXPORT("udfpd9vbE+w", redgalaxy_stub_15);
std::uint64_t APS5_VABI redgalaxy_stub_15(void) {
NotImplemented_nid_no_patch("udfpd9vbE+w");
return 0;
}
APS5_EXPORT("vuGujcpcUEk", redgalaxy_stub_16);
std::uint64_t APS5_VABI redgalaxy_stub_16(void) {
NotImplemented_nid_no_patch("vuGujcpcUEk");
return 0;
}
APS5_EXPORT("VXUTdiaHbD4", redgalaxy_stub_17);
std::uint64_t APS5_VABI redgalaxy_stub_17(void) {
NotImplemented_nid_no_patch("VXUTdiaHbD4");
return 0;
}
APS5_EXPORT("w5-trCio4bQ", redgalaxy_stub_18);
std::uint64_t APS5_VABI redgalaxy_stub_18(void) {
NotImplemented_nid_no_patch("w5-trCio4bQ");
return 0;
}
APS5_EXPORT("YpZjREtZb20", redgalaxy_stub_19);
std::uint64_t APS5_VABI redgalaxy_stub_19(void) {
NotImplemented_nid_no_patch("YpZjREtZb20");
return 0;
}
APS5_EXPORT("gPJN5c9XCec", redgalaxy_stub_20);
std::uint64_t APS5_VABI redgalaxy_stub_20(void) {
NotImplemented_nid_no_patch("gPJN5c9XCec");
return 0;
}
APS5_EXPORT("z4SpWc89no8", redgalaxy_stub_21);
std::uint64_t APS5_VABI redgalaxy_stub_21(void) {
NotImplemented_nid_no_patch("z4SpWc89no8");
return 0;
}
APS5_EXPORT("zdzopKdBeU4", redgalaxy_stub_22);
std::uint64_t APS5_VABI redgalaxy_stub_22(void) {
NotImplemented_nid_no_patch("zdzopKdBeU4");
return 0;
}
}

View File

@ -1,145 +0,0 @@
#include <cstdint>
#include "SceTypes.hpp"
#include "prx/libc/include/General.hpp"
extern "C" {
APS5_EXPORT("0DsDTr534gc", renoirStub00);
uint64_t APS5_VABI renoirStub00(void) {
NotImplemented_nid_no_patch("0DsDTr534gc");
return 0;
}
APS5_EXPORT("2T56HgbPW08", renoirStub01);
uint64_t APS5_VABI renoirStub01(void) {
NotImplemented_nid_no_patch("2T56HgbPW08");
return 0;
}
APS5_EXPORT("3HnCozh8Az8", renoirStub02);
uint64_t APS5_VABI renoirStub02(void) {
NotImplemented_nid_no_patch("3HnCozh8Az8");
return 0;
}
APS5_EXPORT("5Ysce+s-CWU", renoirStub03);
uint64_t APS5_VABI renoirStub03(void) {
NotImplemented_nid_no_patch("5Ysce+s-CWU");
return 0;
}
APS5_EXPORT("AdlSqA4lGS8", renoirStub04);
uint64_t APS5_VABI renoirStub04(void) {
NotImplemented_nid_no_patch("AdlSqA4lGS8");
return 0;
}
APS5_EXPORT("bC37hk7rHqs", renoirStub05);
uint64_t APS5_VABI renoirStub05(void) {
NotImplemented_nid_no_patch("bC37hk7rHqs");
return 0;
}
APS5_EXPORT("dfPK9R6M0qM", renoirStub06);
uint64_t APS5_VABI renoirStub06(void) {
NotImplemented_nid_no_patch("dfPK9R6M0qM");
return 0;
}
APS5_EXPORT("fZiBbVa2ZDU", renoirStub07);
uint64_t APS5_VABI renoirStub07(void) {
NotImplemented_nid_no_patch("fZiBbVa2ZDU");
return 0;
}
APS5_EXPORT("hkWBH8-WfW4", renoirStub08);
uint64_t APS5_VABI renoirStub08(void) {
NotImplemented_nid_no_patch("hkWBH8-WfW4");
return 0;
}
APS5_EXPORT("hUxvGdi64Io", renoirStub09);
uint64_t APS5_VABI renoirStub09(void) {
NotImplemented_nid_no_patch("hUxvGdi64Io");
return 0;
}
APS5_EXPORT("NxqsZxGisrA", renoirStub10);
uint64_t APS5_VABI renoirStub10(void) {
NotImplemented_nid_no_patch("NxqsZxGisrA");
return 0;
}
APS5_EXPORT("OgZVIkaNmb0", renoirStub11);
uint64_t APS5_VABI renoirStub11(void) {
NotImplemented_nid_no_patch("OgZVIkaNmb0");
return 0;
}
APS5_EXPORT("ojLQdRUnVgA", renoirStub12);
uint64_t APS5_VABI renoirStub12(void) {
NotImplemented_nid_no_patch("ojLQdRUnVgA");
return 0;
}
APS5_EXPORT("s0qDfgsAgVg", renoirStub13);
uint64_t APS5_VABI renoirStub13(void) {
NotImplemented_nid_no_patch("s0qDfgsAgVg");
return 0;
}
APS5_EXPORT("sgrd-r1Nw60", renoirStub14);
uint64_t APS5_VABI renoirStub14(void) {
NotImplemented_nid_no_patch("sgrd-r1Nw60");
return 0;
}
APS5_EXPORT("sjTRb8YD7dQ", renoirStub15);
uint64_t APS5_VABI renoirStub15(void) {
NotImplemented_nid_no_patch("sjTRb8YD7dQ");
return 0;
}
APS5_EXPORT("tG86XGc2VtE", renoirStub16);
uint64_t APS5_VABI renoirStub16(void) {
NotImplemented_nid_no_patch("tG86XGc2VtE");
return 0;
}
APS5_EXPORT("umlGxOcNzgc", renoirStub17);
uint64_t APS5_VABI renoirStub17(void) {
NotImplemented_nid_no_patch("umlGxOcNzgc");
return 0;
}
APS5_EXPORT("vPxA9OFW0os", renoirStub18);
uint64_t APS5_VABI renoirStub18(void) {
NotImplemented_nid_no_patch("vPxA9OFW0os");
return 0;
}
APS5_EXPORT("X2qEBlOLkNo", renoirStub19);
uint64_t APS5_VABI renoirStub19(void) {
NotImplemented_nid_no_patch("X2qEBlOLkNo");
return 0;
}
APS5_EXPORT("ynh4E+BIaqY", renoirStub20);
uint64_t APS5_VABI renoirStub20(void) {
NotImplemented_nid_no_patch("ynh4E+BIaqY");
return 0;
}
APS5_EXPORT("YXe6ABbHZPs", renoirStub21);
uint64_t APS5_VABI renoirStub21(void) {
NotImplemented_nid_no_patch("YXe6ABbHZPs");
return 0;
}
APS5_EXPORT("z0jsXZVz75I", renoirStub22);
uint64_t APS5_VABI renoirStub22(void) {
NotImplemented_nid_no_patch("z0jsXZVz75I");
return 0;
}
}

View File

@ -1,21 +0,0 @@
add_library(libSceNpCppWebApi SHARED EXCLUDE_FROM_ALL Export.cpp)
target_include_directories(libSceNpCppWebApi PRIVATE ${LIBS_INCLUDE_DIR})
configure_windows_unwind(libSceNpCppWebApi)
if(MINGW)
foreach(runtimeLinkFlag IN ITEMS -static-libgcc -static-libstdc++ -static)
string(REPLACE "${runtimeLinkFlag}" "" CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}")
endforeach()
endif()
if(BUILD_TESTING)
add_test_executable(guest_np_cpp_web_api_string_tests ${LIBS_INCLUDE_DIR}/tests/GuestNpCppWebApiString.cpp)
target_include_directories(guest_np_cpp_web_api_string_tests PRIVATE ${LIBS_INCLUDE_DIR})
target_link_libraries(guest_np_cpp_web_api_string_tests PRIVATE libSceNpCppWebApi libc)
configure_windows_unwind(guest_np_cpp_web_api_string_tests)
add_test(NAME guest_np_cpp_web_api_string COMMAND guest_np_cpp_web_api_string_tests)
if(WIN32)
set_tests_properties(guest_np_cpp_web_api_string PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libc>")
endif()
endif()

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +0,0 @@
add_library(libcohtml SHARED EXCLUDE_FROM_ALL
${CMAKE_CURRENT_SOURCE_DIR}/Export.cpp
)
target_include_directories(libcohtml PRIVATE ${LIBS_INCLUDE_DIR})
set_target_properties(libcohtml PROPERTIES CXX_EXTENSIONS OFF)
configure_windows_unwind(libcohtml)

View File

@ -1,16 +0,0 @@
# libcohtml — deploy note
Game `DT_NEEDED` expects exactly: `libcohtml.Prospero.prx`.
Copy next to the relinked eboot (same directory):
- `build/core/libs/libs/libcohtml.Prospero.prx` (patched build output, 50 NIDs) — required.
- `libgcc_s_seh-1.dll`, `libstdc++-6.dll`, `libwinpthread-1.dll` from `winlibs-gcc15/mingw64/bin` — required on Windows (see [technical debt](../../../../docs/dev/TechnicalDebt.md)).
Do NOT deploy:
- `libcohtml.prx` (build intermediate kept for the NID-patch pipeline, wrong `DT_NEEDED` name).
- Anything under `build/core/libs/libs/unpatched/` (NIDs not patched).
- `libc.prx` / `libkernel.prx` are not runtime imports of this module (no such DLL dependency); the game may need its other modules separately (out of scope).
Scope: raw-NID stubs only; real Cohtml rendering stays out of scope.

View File

@ -1,307 +0,0 @@
#include <cstdint>
#include "SceTypes.hpp"
#include "prx/libc/include/General.hpp"
extern "C" {
APS5_EXPORT("1fOA53oGwU8", cohtml_stub_00);
std::uint64_t APS5_VABI cohtml_stub_00(void) {
NotImplemented_nid_no_patch("1fOA53oGwU8");
return 0;
}
APS5_EXPORT("2vxXHkZlhbw", cohtml_stub_01);
std::uint64_t APS5_VABI cohtml_stub_01(void) {
NotImplemented_nid_no_patch("2vxXHkZlhbw");
return 0;
}
APS5_EXPORT("3rew70M0SmY", cohtml_stub_02);
std::uint64_t APS5_VABI cohtml_stub_02(void) {
NotImplemented_nid_no_patch("3rew70M0SmY");
return 0;
}
APS5_EXPORT("4Le0SBPvnF8", cohtml_stub_03);
std::uint64_t APS5_VABI cohtml_stub_03(void) {
NotImplemented_nid_no_patch("4Le0SBPvnF8");
return 0;
}
APS5_EXPORT("53ZTBeo2a54", cohtml_stub_04);
std::uint64_t APS5_VABI cohtml_stub_04(void) {
NotImplemented_nid_no_patch("53ZTBeo2a54");
return 0;
}
APS5_EXPORT("6PaNuQipllM", cohtml_stub_05);
std::uint64_t APS5_VABI cohtml_stub_05(void) {
NotImplemented_nid_no_patch("6PaNuQipllM");
return 0;
}
APS5_EXPORT("7hn5DAs2bLk", cohtml_stub_06);
std::uint64_t APS5_VABI cohtml_stub_06(void) {
NotImplemented_nid_no_patch("7hn5DAs2bLk");
return 0;
}
APS5_EXPORT("8EYWdAM2-R0", cohtml_stub_07);
std::uint64_t APS5_VABI cohtml_stub_07(void) {
NotImplemented_nid_no_patch("8EYWdAM2-R0");
return 0;
}
APS5_EXPORT("9bGvfp1zbKo", cohtml_stub_08);
std::uint64_t APS5_VABI cohtml_stub_08(void) {
NotImplemented_nid_no_patch("9bGvfp1zbKo");
return 0;
}
APS5_EXPORT("a4E5dJh0onE", cohtml_stub_09);
std::uint64_t APS5_VABI cohtml_stub_09(void) {
NotImplemented_nid_no_patch("a4E5dJh0onE");
return 0;
}
APS5_EXPORT("BhL-ZtSHmB8", cohtml_stub_10);
std::uint64_t APS5_VABI cohtml_stub_10(void) {
NotImplemented_nid_no_patch("BhL-ZtSHmB8");
return 0;
}
APS5_EXPORT("blvwzOvsEAA", cohtml_stub_11);
std::uint64_t APS5_VABI cohtml_stub_11(void) {
NotImplemented_nid_no_patch("blvwzOvsEAA");
return 0;
}
APS5_EXPORT("dko-cMqv5yw", cohtml_stub_12);
std::uint64_t APS5_VABI cohtml_stub_12(void) {
NotImplemented_nid_no_patch("dko-cMqv5yw");
return 0;
}
APS5_EXPORT("EG4kqkxLU3Q", cohtml_stub_13);
std::uint64_t APS5_VABI cohtml_stub_13(void) {
NotImplemented_nid_no_patch("EG4kqkxLU3Q");
return 0;
}
APS5_EXPORT("-El4B0xJF2U", cohtml_stub_14);
std::uint64_t APS5_VABI cohtml_stub_14(void) {
NotImplemented_nid_no_patch("-El4B0xJF2U");
return 0;
}
APS5_EXPORT("EMhQNylkSwk", cohtml_stub_15);
std::uint64_t APS5_VABI cohtml_stub_15(void) {
NotImplemented_nid_no_patch("EMhQNylkSwk");
return 0;
}
APS5_EXPORT("-eNSKAypRz0", cohtml_stub_16);
std::uint64_t APS5_VABI cohtml_stub_16(void) {
NotImplemented_nid_no_patch("-eNSKAypRz0");
return 0;
}
APS5_EXPORT("FG9VRZfson0", cohtml_stub_17);
std::uint64_t APS5_VABI cohtml_stub_17(void) {
NotImplemented_nid_no_patch("FG9VRZfson0");
return 0;
}
APS5_EXPORT("fNvtExaHN4U", cohtml_stub_18);
std::uint64_t APS5_VABI cohtml_stub_18(void) {
NotImplemented_nid_no_patch("fNvtExaHN4U");
return 0;
}
APS5_EXPORT("g10DkPARoa8", cohtml_stub_19);
std::uint64_t APS5_VABI cohtml_stub_19(void) {
NotImplemented_nid_no_patch("g10DkPARoa8");
return 0;
}
APS5_EXPORT("gwQczxoDmG0", cohtml_stub_20);
std::uint64_t APS5_VABI cohtml_stub_20(void) {
NotImplemented_nid_no_patch("gwQczxoDmG0");
return 0;
}
APS5_EXPORT("HQF4O9D+Di4", cohtml_stub_21);
std::uint64_t APS5_VABI cohtml_stub_21(void) {
NotImplemented_nid_no_patch("HQF4O9D+Di4");
return 0;
}
APS5_EXPORT("igt3a6Q0VMc", cohtml_stub_22);
std::uint64_t APS5_VABI cohtml_stub_22(void) {
NotImplemented_nid_no_patch("igt3a6Q0VMc");
return 0;
}
APS5_EXPORT("kyApuhEHHxQ", cohtml_stub_23);
std::uint64_t APS5_VABI cohtml_stub_23(void) {
NotImplemented_nid_no_patch("kyApuhEHHxQ");
return 0;
}
APS5_EXPORT("Ljp75QXUi7s", cohtml_stub_24);
std::uint64_t APS5_VABI cohtml_stub_24(void) {
NotImplemented_nid_no_patch("Ljp75QXUi7s");
return 0;
}
APS5_EXPORT("loJ5Ef3MZrs", cohtml_stub_25);
std::uint64_t APS5_VABI cohtml_stub_25(void) {
NotImplemented_nid_no_patch("loJ5Ef3MZrs");
return 0;
}
APS5_EXPORT("LWe+u8SHKgU", cohtml_stub_26);
std::uint64_t APS5_VABI cohtml_stub_26(void) {
NotImplemented_nid_no_patch("LWe+u8SHKgU");
return 0;
}
APS5_EXPORT("nhn1ds+I2t4", cohtml_stub_27);
std::uint64_t APS5_VABI cohtml_stub_27(void) {
NotImplemented_nid_no_patch("nhn1ds+I2t4");
return 0;
}
APS5_EXPORT("NmVsRWgsKt4", cohtml_stub_28);
std::uint64_t APS5_VABI cohtml_stub_28(void) {
NotImplemented_nid_no_patch("NmVsRWgsKt4");
return 0;
}
APS5_EXPORT("ONEnhMinebs", cohtml_stub_29);
std::uint64_t APS5_VABI cohtml_stub_29(void) {
NotImplemented_nid_no_patch("ONEnhMinebs");
return 0;
}
APS5_EXPORT("PdOmR8dy1fM", cohtml_stub_30);
std::uint64_t APS5_VABI cohtml_stub_30(void) {
NotImplemented_nid_no_patch("PdOmR8dy1fM");
return 0;
}
APS5_EXPORT("PSwGBN5Icv8", cohtml_stub_31);
std::uint64_t APS5_VABI cohtml_stub_31(void) {
NotImplemented_nid_no_patch("PSwGBN5Icv8");
return 0;
}
APS5_EXPORT("RalyfwiTt8o", cohtml_stub_32);
std::uint64_t APS5_VABI cohtml_stub_32(void) {
NotImplemented_nid_no_patch("RalyfwiTt8o");
return 0;
}
APS5_EXPORT("t+OHUjVWIwU", cohtml_stub_33);
std::uint64_t APS5_VABI cohtml_stub_33(void) {
NotImplemented_nid_no_patch("t+OHUjVWIwU");
return 0;
}
APS5_EXPORT("Ter8YCVZ9tQ", cohtml_stub_34);
std::uint64_t APS5_VABI cohtml_stub_34(void) {
NotImplemented_nid_no_patch("Ter8YCVZ9tQ");
return 0;
}
APS5_EXPORT("tG3LJfAOH3k", cohtml_stub_35);
std::uint64_t APS5_VABI cohtml_stub_35(void) {
NotImplemented_nid_no_patch("tG3LJfAOH3k");
return 0;
}
APS5_EXPORT("ukSFhKPmCTg", cohtml_stub_36);
std::uint64_t APS5_VABI cohtml_stub_36(void) {
NotImplemented_nid_no_patch("ukSFhKPmCTg");
return 0;
}
APS5_EXPORT("V7KGze2XjJc", cohtml_stub_37);
std::uint64_t APS5_VABI cohtml_stub_37(void) {
NotImplemented_nid_no_patch("V7KGze2XjJc");
return 0;
}
APS5_EXPORT("vlmAvJqR7mQ", cohtml_stub_38);
std::uint64_t APS5_VABI cohtml_stub_38(void) {
NotImplemented_nid_no_patch("vlmAvJqR7mQ");
return 0;
}
APS5_EXPORT("VzhxjXDzYSI", cohtml_stub_39);
std::uint64_t APS5_VABI cohtml_stub_39(void) {
NotImplemented_nid_no_patch("VzhxjXDzYSI");
return 0;
}
APS5_EXPORT("X3FzDPzpD2Y", cohtml_stub_40);
std::uint64_t APS5_VABI cohtml_stub_40(void) {
NotImplemented_nid_no_patch("X3FzDPzpD2Y");
return 0;
}
APS5_EXPORT("x68HPh+vxsE", cohtml_stub_41);
std::uint64_t APS5_VABI cohtml_stub_41(void) {
NotImplemented_nid_no_patch("x68HPh+vxsE");
return 0;
}
APS5_EXPORT("XUe8OAKB-vQ", cohtml_stub_42);
std::uint64_t APS5_VABI cohtml_stub_42(void) {
NotImplemented_nid_no_patch("XUe8OAKB-vQ");
return 0;
}
APS5_EXPORT("y6UNQtnr0wY", cohtml_stub_43);
std::uint64_t APS5_VABI cohtml_stub_43(void) {
NotImplemented_nid_no_patch("y6UNQtnr0wY");
return 0;
}
APS5_EXPORT("YoHAXkBV06c", cohtml_stub_44);
std::uint64_t APS5_VABI cohtml_stub_44(void) {
NotImplemented_nid_no_patch("YoHAXkBV06c");
return 0;
}
APS5_EXPORT("Z9XFJCfmId4", cohtml_stub_45);
std::uint64_t APS5_VABI cohtml_stub_45(void) {
NotImplemented_nid_no_patch("Z9XFJCfmId4");
return 0;
}
APS5_EXPORT("zEniuuzG2W0", cohtml_stub_46);
std::uint64_t APS5_VABI cohtml_stub_46(void) {
NotImplemented_nid_no_patch("zEniuuzG2W0");
return 0;
}
APS5_EXPORT("zH9Z2nK1fmA", cohtml_stub_47);
std::uint64_t APS5_VABI cohtml_stub_47(void) {
NotImplemented_nid_no_patch("zH9Z2nK1fmA");
return 0;
}
APS5_EXPORT("ZHGgdWeYTo8", cohtml_stub_48);
std::uint64_t APS5_VABI cohtml_stub_48(void) {
NotImplemented_nid_no_patch("ZHGgdWeYTo8");
return 0;
}
APS5_EXPORT("ZWftPxZ4E6k", cohtml_stub_49);
std::uint64_t APS5_VABI cohtml_stub_49(void) {
NotImplemented_nid_no_patch("ZWftPxZ4E6k");
return 0;
}
}

View File

@ -1,11 +0,0 @@
add_library(libfmod SHARED EXCLUDE_FROM_ALL
${CMAKE_CURRENT_SOURCE_DIR}/Export.cpp
)
target_include_directories(libfmod PRIVATE
${LIBS_INCLUDE_DIR}
${CMAKE_SOURCE_DIR}/3rdparty/SDL2/include
)
target_link_libraries(libfmod PRIVATE libkernel libc SDL2-static)
target_compile_options(libfmod PRIVATE -fkeep-inline-functions)
configure_windows_unwind(libfmod)

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +0,0 @@
add_library(libfmodstudio SHARED EXCLUDE_FROM_ALL
${CMAKE_CURRENT_SOURCE_DIR}/Export.cpp
)
target_include_directories(libfmodstudio PRIVATE
${LIBS_INCLUDE_DIR}
)
target_link_libraries(libfmodstudio PRIVATE libkernel libc)
target_compile_options(libfmodstudio PRIVATE -fkeep-inline-functions)
configure_windows_unwind(libfmodstudio)

File diff suppressed because it is too large Load Diff

View File

@ -1,256 +0,0 @@
#include "prx/libc/include/general/VabiMacros.hpp"
#include <cstddef>
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <stdexcept>
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*);
}
static void Require(bool value) { if (!value) std::abort(); }
static constexpr std::size_t ObjectSize = 0x40;
static constexpr std::size_t VectorReferenceCountOffset = 0x30;
struct DestroyCase {
Destroy destroy;
std::size_t referenceCountOffset;
};
static void* deletedObject = nullptr;
static int deleterCalls = 0;
static void APS5_VABI RecordDelete(void* object) {
deletedObject = object;
++deleterCalls;
}
static std::int32_t ReadCount(const unsigned char* object, const std::size_t offset) {
std::int32_t value;
std::memcpy(&value, object + offset, sizeof(value));
return value;
}
static void WriteCount(unsigned char* object, const std::size_t offset, const std::int32_t value) {
std::memcpy(object + offset, &value, sizeof(value));
}
static bool OnlyCountChanged(const unsigned char* object, const std::size_t offset) {
for (std::size_t index = 0; index < ObjectSize; ++index) {
if (index >= offset && index < offset + sizeof(std::int32_t)) continue;
if (object[index] != 0x5a) return false;
}
return true;
}
static void TestConstruct(const Construct construct) {
IntrusivePtr pointer;
std::memset(&pointer, 0xa5, sizeof(pointer));
construct(&pointer);
Require(pointer.object == nullptr);
Require(pointer.deleter == nullptr);
Require(pointer.libContext == nullptr);
}
static void TestAccess(const Access access) {
int object = 0;
int context = 0;
const IntrusivePtr empty{nullptr, RecordDelete, &context};
Require(access(&empty) == nullptr);
const IntrusivePtr filled{&object, nullptr, nullptr};
Require(access(&filled) == &object);
}
static void TestCopy(const Copy copy) {
alignas(8) unsigned char object[ObjectSize];
std::memset(object, 0x5a, sizeof(object));
WriteCount(object, 0, 1);
int context = 0;
const IntrusivePtr source{object, RecordDelete, &context};
IntrusivePtr target;
std::memset(&target, 0xa5, sizeof(target));
copy(&target, &source);
Require(target.object == object);
Require(target.deleter == RecordDelete);
Require(target.libContext == &context);
Require(source.object == object);
Require(ReadCount(object, 0) == 2);
Require(OnlyCountChanged(object, 0));
const IntrusivePtr empty{nullptr, RecordDelete, &context};
std::memset(&target, 0xa5, sizeof(target));
copy(&target, &empty);
Require(target.object == nullptr);
Require(target.deleter == RecordDelete);
Require(target.libContext == &context);
}
static void TestDestroy(const DestroyCase& testCase) {
alignas(8) unsigned char object[ObjectSize];
std::memset(object, 0x5a, sizeof(object));
int context = 0;
const std::size_t offset = testCase.referenceCountOffset;
deleterCalls = 0;
deletedObject = nullptr;
IntrusivePtr empty{nullptr, RecordDelete, &context};
testCase.destroy(&empty);
Require(empty.object == nullptr);
Require(empty.deleter == RecordDelete);
Require(empty.libContext == &context);
Require(deleterCalls == 0);
WriteCount(object, offset, 2);
IntrusivePtr shared{object, RecordDelete, &context};
testCase.destroy(&shared);
Require(ReadCount(object, offset) == 1);
Require(shared.object == object);
Require(shared.deleter == RecordDelete);
Require(shared.libContext == &context);
Require(deleterCalls == 0);
IntrusivePtr last{object, RecordDelete, &context};
testCase.destroy(&last);
Require(ReadCount(object, offset) == 0);
Require(OnlyCountChanged(object, offset));
Require(deleterCalls == 1);
Require(deletedObject == object);
Require(last.object == nullptr);
Require(last.deleter == nullptr);
Require(last.libContext == &context);
WriteCount(object, offset, 1);
IntrusivePtr pooled{object, nullptr, &context};
bool thrown = false;
try {
testCase.destroy(&pooled);
} catch (const std::runtime_error&) {
thrown = true;
}
Require(thrown);
Require(deleterCalls == 1);
}
static void TestSharedOwnership() {
alignas(8) unsigned char object[ObjectSize];
std::memset(object, 0x5a, sizeof(object));
WriteCount(object, 0, 1);
deleterCalls = 0;
deletedObject = nullptr;
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);
_ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V122RecordScoreRequestBodyEED1Ev(&argument);
Require(ReadCount(object, 0) == 1);
Require(deleterCalls == 0);
_ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V122RecordScoreRequestBodyEED1Ev(&owner);
Require(ReadCount(object, 0) == 0);
Require(deleterCalls == 1);
Require(deletedObject == object);
Require(_ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V122RecordScoreRequestBodyEEptEv(&owner) == nullptr);
}
int main() {
Require(sizeof(IntrusivePtr) == 0x18);
const Construct constructors[] = {
_ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V121GetRankingRequestBodyEEC1Ev,
_ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V122GetRankingResponseBodyEEC1Ev,
_ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V122RecordScoreRequestBodyEEC1Ev,
_ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V123RecordScoreResponseBodyEEC1Ev,
_ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V130GetBoardDefinitionResponseBodyEEC1Ev,
_ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V14UserEEC1Ev,
_ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V19RecordApi26RecordScoreResponseHeadersEEC1Ev,
};
for (const auto construct : constructors) TestConstruct(construct);
const Access accessors[] = {
_ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V121GetRankingRequestBodyEEptEv,
_ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V122GetRankingResponseBodyEEptEv,
_ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V122RecordScoreRequestBodyEEptEv,
_ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V123RecordScoreResponseBodyEEptEv,
_ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V130GetBoardDefinitionResponseBodyEEptEv,
_ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V14UserEEptEv,
_ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V15EntryEEptEv,
_ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V19RecordApi26RecordScoreResponseHeadersEEptEv,
_ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6BinaryEEptEv,
_ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS3_INS1_12Leaderboards2V15EntryEEEEEEdeEv,
};
for (const auto access : accessors) TestAccess(access);
const Copy copies[] = {
_ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V121GetRankingRequestBodyEEC1ERS7_,
_ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V122RecordScoreRequestBodyEEC1ERS7_,
};
for (const auto copy : copies) TestCopy(copy);
const DestroyCase destructors[] = {
{_ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V121GetRankingRequestBodyEED1Ev, 0},
{_ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V122GetRankingResponseBodyEED1Ev, 0},
{_ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V122RecordScoreRequestBodyEED1Ev, 0},
{_ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V123RecordScoreResponseBodyEED1Ev, 0},
{_ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V130GetBoardDefinitionResponseBodyEED1Ev, 0},
{_ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V14UserEED1Ev, 0},
{_ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V19RecordApi26RecordScoreResponseHeadersEED1Ev, 0},
{_ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS3_INS1_12Leaderboards2V15EntryEEEEEED1Ev, VectorReferenceCountOffset},
};
for (const auto& testCase : destructors) TestDestroy(testCase);
TestSharedOwnership();
return 0;
}

View File

@ -1,112 +0,0 @@
#include "prx/libc/include/general/VabiMacros.hpp"
#include <cstddef>
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <stdexcept>
extern "C" {
void APS5_VABI _ZN3sce2Np9CppWebApi6Common6StringC1EPNS2_10LibContextE(void* self, void* libContext);
void APS5_VABI _ZN3sce2Np9CppWebApi6Common6StringD1Ev(void* self);
const char* APS5_VABI _ZNK3sce2Np9CppWebApi6Common6String5c_strEv(const void* self);
}
namespace {
void Require(bool value) { if (!value) std::abort(); }
constexpr std::size_t kStringSize = 0x20;
constexpr std::size_t kGuardSize = 0x10;
constexpr std::size_t kReferenceCountOffset = 0x00;
constexpr std::size_t kBufferOffset = 0x08;
constexpr std::size_t kBufferSizeOffset = 0x10;
constexpr std::size_t kLibContextOffset = 0x18;
constexpr unsigned char kFill = 0xA5;
struct Storage {
alignas(8) unsigned char bytes[kStringSize + kGuardSize];
};
template <typename TValue>
TValue Load(const Storage& storage, std::size_t offset) {
TValue value;
std::memcpy(&value, storage.bytes + offset, sizeof(value));
return value;
}
template <typename TValue>
void Store(Storage& storage, std::size_t offset, TValue value) {
std::memcpy(storage.bytes + offset, &value, sizeof(value));
}
bool GuardIntact(const Storage& storage) {
for (std::size_t i = kStringSize; i < sizeof(storage.bytes); i++) {
if (storage.bytes[i] != kFill) return false;
}
return true;
}
bool DestructorThrows(Storage& storage) {
try {
_ZN3sce2Np9CppWebApi6Common6StringD1Ev(storage.bytes);
} catch (const std::runtime_error&) {
return true;
}
return false;
}
void TestConstructedStringIsEmpty() {
std::uint64_t libContext = 1;
Storage storage;
std::memset(storage.bytes, kFill, sizeof(storage.bytes));
_ZN3sce2Np9CppWebApi6Common6StringC1EPNS2_10LibContextE(storage.bytes, &libContext);
Require(Load<std::int32_t>(storage, kReferenceCountOffset) == 0);
Require(Load<char*>(storage, kBufferOffset) == nullptr);
Require(Load<std::uint64_t>(storage, kBufferSizeOffset) == 0);
Require(Load<void*>(storage, kLibContextOffset) == &libContext);
Require(GuardIntact(storage));
const char* text = _ZNK3sce2Np9CppWebApi6Common6String5c_strEv(storage.bytes);
Require(text != nullptr && text[0] == '\0');
Storage before = storage;
_ZN3sce2Np9CppWebApi6Common6StringD1Ev(storage.bytes);
Require(std::memcmp(before.bytes, storage.bytes, sizeof(storage.bytes)) == 0);
}
void TestNullLibContextIsStored() {
Storage storage;
std::memset(storage.bytes, kFill, sizeof(storage.bytes));
_ZN3sce2Np9CppWebApi6Common6StringC1EPNS2_10LibContextE(storage.bytes, nullptr);
Require(Load<void*>(storage, kLibContextOffset) == nullptr);
Require(Load<char*>(storage, kBufferOffset) == nullptr);
Require(_ZNK3sce2Np9CppWebApi6Common6String5c_strEv(storage.bytes)[0] == '\0');
_ZN3sce2Np9CppWebApi6Common6StringD1Ev(storage.bytes);
}
void TestBufferIsReturnedAndNotDroppedSilently() {
std::uint64_t libContext = 1;
char text[] = "ranking";
Storage storage;
std::memset(storage.bytes, kFill, sizeof(storage.bytes));
_ZN3sce2Np9CppWebApi6Common6StringC1EPNS2_10LibContextE(storage.bytes, &libContext);
Store<char*>(storage, kBufferOffset, text);
Store<std::uint64_t>(storage, kBufferSizeOffset, sizeof(text));
Require(_ZNK3sce2Np9CppWebApi6Common6String5c_strEv(storage.bytes) == text);
Require(DestructorThrows(storage));
Require(std::strcmp(text, "ranking") == 0);
}
}
int main() {
TestConstructedStringIsEmpty();
TestNullLibContextIsStored();
TestBufferIsReturnedAndNotDroppedSilently();
}

View File

@ -108,10 +108,8 @@ Throughout the project, every function at every stage either **does exactly what
- [sceHttp2GetMemoryPoolStats](../../core/libs/prx/libSceHttp2/Export.cpp) (libSceHttp2) - unknown signature
- [sceNetGetMemoryPoolStats](../../core/libs/prx/libSceNet/Export.cpp) (libSceNet) - unknown signature
- [sceHttpSetRequestStatusCallback](../../core/libs/prx/libSceHttp/Export.cpp) (libSceHttp) - no reference implements it (shadPS4 only logs and returns 0); when the callback runs and what status it gets is unknown
- [sce::Np::CppWebApi::Common::IntrusivePtr](../../core/libs/prx/libSceNpCppWebApi/Export.cpp) (libSceNpCppWebApi) - the 0x18-byte layout (object, deleter, `LibContext*`) and the offset of the 32-bit reference count in the pointee (0x00, 0x30 for `Vector`) come from the module bundled with one title (PPSA21564); other SDK versions are not checked. The destructor throws on the last reference of a pointer without a deleter: destroying the object needs its destructor and the `LibContext` allocator, which are not implemented
- [sceNpSessionSignalingGetMemoryInfo](../../core/libs/prx/libSceNpSessionSignaling/Export.cpp) (libSceNpSessionSignaling) - unknown signature
- [sceNpSessionSignalingGetConnectionStatistics](../../core/libs/prx/libSceNpSessionSignaling/Export.cpp) (libSceNpSessionSignaling) - unknown signature
- [sce::Np::CppWebApi::Common::String](../../core/libs/prx/libSceNpCppWebApi/Export.cpp) (libSceNpCppWebApi) - the 0x20-byte layout (32-bit reference count, buffer at 0x08, buffer size at 0x10, `LibContext*` at 0x18) comes from the module bundled with one title (PPSA21564); other SDK versions are not checked. The destructor throws for a non-null buffer: releasing it needs the `LibContext` allocator, which is not implemented
- [sceUserServiceGetAgeLevel](../../core/libs/prx/libSceUserService/Export.cpp) (libSceUserService) - the meaning of the value is unknown; 0 is reported, as for the unset game presets. PPSA12544 (Unity) only stores it for its user profile
- [sceGameUpdateGetAddcontLatestVersion](../../core/libs/prx/libSceGameUpdate/Export.cpp) (libSceGameUpdate) - a null `entitlement_label` throws: KytyPS5 accepts it, prosper returns `0x80412803`. Bytes after `found` are zeroed as in KytyPS5; prosper leaves them untouched
- [sceSystemServiceDisableMediaPlay](../../core/libs/prx/libSceSystemService/Export.cpp) (libSceSystemService) - unknown signature

View File

@ -11,7 +11,6 @@ def package(platform, build, output, version):
raise ValueError(f"Invalid release tag for asset filenames: {version}")
libraries = sorted((build / "core/libs/libs").glob("*.prx"))
expected = {f"{directory.name}.prx" for directory in Path("core/libs/prx").iterdir() if directory.is_dir()}
expected.add("libcohtml.Prospero.prx")
missing = expected - {library.name for library in libraries}
if missing:
raise RuntimeError(f"Missing patched libraries: {', '.join(sorted(missing))}")