From 716d81186192809af67a78a2c79cfc43bfe20f7f Mon Sep 17 00:00:00 2001 From: SandstromPL Date: Thu, 15 Oct 2026 20:30:06 +0530 Subject: [PATCH] feat(libSceDiscMap): report no disc bitmap from the two disc map queries Until Dawn (CUSA02636) bundles a libSceFios2.prx that imports two libSceDiscMap functions, sceDiscMapIsRequestOnHDD (lbQKqsERhtE) and ioKMruft1ek, and no host library exported them. Both now return SCE_DISC_MAP_ERROR_NO_BITMAP_INFO (0x81100004) and write nothing, as shadPS4 and fpPS4 do. That is the error the console library returns while it has no disc bitmap loaded. Co-Authored-By: Claude Opus 5.5 --- core/libs/prx/libSceDiscMap/CMakeLists.txt | 15 +++++++++ core/libs/prx/libSceDiscMap/Export.cpp | 32 +++++++++++++++++++ core/libs/tests/GuestDiscMap.cpp | 36 ++++++++++++++++++++++ docs/dev/debt/libSceDiscMap.md | 9 ++++++ 4 files changed, 92 insertions(+) create mode 100644 core/libs/prx/libSceDiscMap/CMakeLists.txt create mode 100644 core/libs/prx/libSceDiscMap/Export.cpp create mode 100644 core/libs/tests/GuestDiscMap.cpp create mode 100644 docs/dev/debt/libSceDiscMap.md diff --git a/core/libs/prx/libSceDiscMap/CMakeLists.txt b/core/libs/prx/libSceDiscMap/CMakeLists.txt new file mode 100644 index 0000000000..fa84f65ac2 --- /dev/null +++ b/core/libs/prx/libSceDiscMap/CMakeLists.txt @@ -0,0 +1,15 @@ +add_library(libSceDiscMap SHARED EXCLUDE_FROM_ALL Export.cpp) +target_include_directories(libSceDiscMap PRIVATE ${LIBS_INCLUDE_DIR}) +configure_windows_unwind(libSceDiscMap) + +if(BUILD_TESTING) + add_test_executable(guest_disc_map_tests ${LIBS_INCLUDE_DIR}/tests/GuestDiscMap.cpp) + target_include_directories(guest_disc_map_tests PRIVATE ${LIBS_INCLUDE_DIR}) + target_link_libraries(guest_disc_map_tests PRIVATE libSceDiscMap libc) + configure_windows_unwind(guest_disc_map_tests) + add_test(NAME guest_disc_map COMMAND guest_disc_map_tests) + if(WIN32) + set_tests_properties(guest_disc_map PROPERTIES ENVIRONMENT_MODIFICATION + "PATH=path_list_prepend:$") + endif() +endif() diff --git a/core/libs/prx/libSceDiscMap/Export.cpp b/core/libs/prx/libSceDiscMap/Export.cpp new file mode 100644 index 0000000000..e1f2638a83 --- /dev/null +++ b/core/libs/prx/libSceDiscMap/Export.cpp @@ -0,0 +1,32 @@ +#include +#include "SceTypes.hpp" +#include "prx/libc/include/General.hpp" + +namespace { + +constexpr std::int32_t SCE_DISC_MAP_ERROR_NO_BITMAP_INFO = static_cast(0x81100004); + +} + +extern "C" { + +std::int32_t APS5_VABI sceDiscMapIsRequestOnHDD(const char* path, std::int64_t offset, std::int64_t size, std::int32_t* result) { + (void)path; + (void)offset; + (void)size; + (void)result; + return SCE_DISC_MAP_ERROR_NO_BITMAP_INFO; +} + +APS5_EXPORT("ioKMruft1ek", sceDiscMapUnknown_ioKMruft1ek); +std::int32_t APS5_VABI sceDiscMapUnknown_ioKMruft1ek(const char* path, std::int64_t offset, std::int64_t size, void* flags, void* out1, void* out2) { + (void)path; + (void)offset; + (void)size; + (void)flags; + (void)out1; + (void)out2; + return SCE_DISC_MAP_ERROR_NO_BITMAP_INFO; +} + +} diff --git a/core/libs/tests/GuestDiscMap.cpp b/core/libs/tests/GuestDiscMap.cpp new file mode 100644 index 0000000000..41f711baff --- /dev/null +++ b/core/libs/tests/GuestDiscMap.cpp @@ -0,0 +1,36 @@ +#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, void* flags, void* out1, void* out2); +} + +namespace { + +constexpr std::int32_t noBitmapInfo = static_cast(0x81100004); + +void Require(bool condition, const char* message) { + if (!condition) { + std::fprintf(stderr, "DiscMap: %s\n", message); + std::abort(); + } +} + +} + +int main() { + std::int32_t result = 0x5a5a5a5a; + Require(sceDiscMapIsRequestOnHDD("/app0/data.bin", 0, 0x10000, &result) == noBitmapInfo, "sceDiscMapIsRequestOnHDD did not report the missing bitmap"); + Require(result == 0x5a5a5a5a, "sceDiscMapIsRequestOnHDD wrote its result"); + std::uint64_t flags = ~0ull; + std::uint64_t out1 = ~0ull; + std::uint64_t out2 = ~0ull; + Require(sceDiscMapUnknown_ioKMruft1ek("/app0/data.bin", 0x8000, 0x10000, &flags, &out1, &out2) == noBitmapInfo, "ioKMruft1ek did not report the missing bitmap"); + Require(flags == ~0ull && out1 == ~0ull && out2 == ~0ull, "ioKMruft1ek wrote an output"); + std::puts("DiscMap tests passed"); + return 0; +} diff --git a/docs/dev/debt/libSceDiscMap.md b/docs/dev/debt/libSceDiscMap.md new file mode 100644 index 0000000000..29814e4aa3 --- /dev/null +++ b/docs/dev/debt/libSceDiscMap.md @@ -0,0 +1,9 @@ +# libSceDiscMap technical debt + +### Silent stubs + +- [libSceDiscMap](../../../core/libs/prx/libSceDiscMap/Export.cpp) implements only the state with no disc bitmap: `sceDiscMapIsRequestOnHDD` and `ioKMruft1ek` return `SCE_DISC_MAP_ERROR_NO_BITMAP_INFO` (0x81100004) for every request and write nothing. CUSA02636's bundled `libSceFios2.prx` imports both; what it does with the error is not known (shadPS4 returns the same, and [shadps4-game-compatibility #617](https://github.com/shadps4-compatibility/shadps4-game-compatibility/issues/617) lists CUSA02636 as in-game) + +### Unknown function info + +- [sceDiscMapIsRequestOnHDD, sceDiscMapUnknown_ioKMruft1ek](../../../core/libs/prx/libSceDiscMap/Export.cpp) (libSceDiscMap, NIDs `lbQKqsERhtE` and `ioKMruft1ek`) - `ioKMruft1ek` has no known name. The `(path, offset, size, result)` and `(path, offset, size, flags, out1, out2)` signatures follow [shadPS4 disc_map.cpp](https://github.com/shadps4-emu/shadPS4/blob/b2d7ec7d31f9ad9426db93afe079db8679b3e1e0/src/core/libraries/disc_map/disc_map.cpp); the widths of the `ioKMruft1ek` outputs are unknown (shadPS4 `int*`, [fpPS4](https://github.com/red-prig/fpPS4/blob/04cefd43e6fddd1ab033e7980cd356d14c964905/src/ps4_libscediscmap.pas) `PInt64`), so they are `void*`. The error code is the one both return; [shadPS4 #2686](https://github.com/shadps4-emu/shadPS4/pull/2686) reads the console library as checking an initialisation global first in each call and returning it while the global is clear. Not measured on a console