feat(ulobjmgr): register and unregister object

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Adrià Franch 2026-10-05 19:25:46 +02:00
parent 0518f0e021
commit 4136a04ba7
4 changed files with 66 additions and 6 deletions

View File

@ -0,0 +1,20 @@
add_library(ulobjmgr SHARED EXCLUDE_FROM_ALL Export.cpp)
target_include_directories(ulobjmgr PRIVATE ${LIBS_INCLUDE_DIR})
configure_windows_unwind(ulobjmgr)
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_ulobjmgr_tests ${LIBS_INCLUDE_DIR}/tests/GuestUlobjmgr.cpp)
target_include_directories(guest_ulobjmgr_tests PRIVATE ${LIBS_INCLUDE_DIR})
target_link_libraries(guest_ulobjmgr_tests PRIVATE ulobjmgr)
add_test(NAME guest_ulobjmgr COMMAND guest_ulobjmgr_tests)
if(WIN32)
set_tests_properties(guest_ulobjmgr PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<TARGET_FILE_DIR:ulobjmgr>")
endif()
endif()

View File

@ -3,17 +3,23 @@
#include "SceTypes.hpp"
#include "prx/libc/include/General.hpp"
namespace {
constexpr int ULOBJMGR_EINVAL = 22;
constexpr std::uint32_t ULOBJMGR_ID_LIMIT = 0x4000;
}
extern "C" {
int APS5_VABI _sceUlobjmgrRegisterObject(void* object) {
(void)object;
NotImplemented_nid_no_patch(__func__);
int APS5_VABI _sceUlobjmgrRegisterObject(std::uint64_t object, std::int32_t kind, std::uint32_t* id) {
if (object == 0 || kind == 0 || id == nullptr) return ULOBJMGR_EINVAL;
*id = 0;
return 0;
}
int APS5_VABI _sceUlobjmgrUnregisterObject(void* object) {
(void)object;
NotImplemented_nid_no_patch(__func__);
int APS5_VABI _sceUlobjmgrUnregisterObject(std::uint32_t id) {
if (id >= ULOBJMGR_ID_LIMIT) return ULOBJMGR_EINVAL;
return 0;
}

View File

@ -0,0 +1,32 @@
#include "prx/libc/include/general/VabiMacros.hpp"
#include <cstdint>
#include <cstdlib>
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;
void Require(bool value) { if (!value) std::abort(); }
}
int main() {
std::uint32_t id = 0xffffffffu;
Require(_sceUlobjmgrRegisterObject(0, 1, &id) == einval);
Require(id == 0xffffffffu);
Require(_sceUlobjmgrRegisterObject(0x1000, 0, &id) == einval);
Require(id == 0xffffffffu);
Require(_sceUlobjmgrRegisterObject(0x1000, 1, nullptr) == einval);
Require(_sceUlobjmgrRegisterObject(0x1000, -1, &id) == 0);
Require(id == 0);
Require(_sceUlobjmgrUnregisterObject(id) == 0);
Require(_sceUlobjmgrUnregisterObject(0x3fff) == 0);
Require(_sceUlobjmgrUnregisterObject(0x4000) == einval);
Require(_sceUlobjmgrUnregisterObject(0xffffffffu) == einval);
}

View File

@ -21,6 +21,7 @@ Throughout the project, every function at every stage either **does exactly what
- The shader recompiler [skips baryctric coordinates](../../core/shader/recompiler/Recompiler.cpp) (is not even passed to SpirvTargetOptions at row 212).
- [libSceAvPlayer](../../core/libs/prx/libSceAvPlayer/Export.cpp): `sceAvPlayerSetLogCallback` accepts a callback that is never called, as the player produces no log messages, and `sceAvPlayerSetAvailableBandwidth` has no effect, as it governs HLS sources, which `sceAvPlayerAddSource` does not implement.
- [sceAvPlayerSetTrickSpeed](../../core/libs/prx/libSceAvPlayer/src/Source.cpp) (libSceAvPlayer) with a negative speed runs the clock backwards but delivers no frames; when a forward speed is set again, playback resumes from the rewound time.
- [ulobjmgr](../../core/libs/prx/ulobjmgr/Export.cpp) registers no object: `_sceUlobjmgrRegisterObject` always hands out id 0 and `_sceUlobjmgrUnregisterObject` releases nothing, as shadPS4 does
### Unknown function info
@ -80,6 +81,7 @@ Throughout the project, every function at every stage either **does exactly what
- [sceVoiceSetMuteFlag](../../core/libs/prx/libSceVoice/Export.cpp) (libSceVoice) - unknown signature
- [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: `set_constraint_handler_s` is not exported 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`
- [libSceUlt queues](../../core/libs/prx/libSceUlt/Export.cpp) - the added `sceUltQueuePop`, `sceUltQueueTryPush`, `sceUltQueueDestroy` and `sceUltQueueDataResourcePoolDestroy` signatures are inferred from the existing push/pop and object APIs. Queue destruction is assumed to reject blocked callers with `ULT_ERROR_BUSY` and otherwise discard queued data; pool exhaustion returns `ULT_ERROR_AGAIN`. These rules, alignment checks and shared slot limits have not been confirmed on PS5 hardware or a title. Non-null queue and data-pool option parameters throw because their layouts are unknown.
- [_sceUlobjmgrRegisterObject](../../core/libs/prx/ulobjmgr/Export.cpp) (ulobjmgr) - parameters taken from shadPS4 (PS4): a nonzero 64-bit object, a nonzero 32-bit kind and a 32-bit id output; the meaning of the first two and the PS5 signature are unverified. The id bound of `_sceUlobjmgrUnregisterObject` (below 0x4000) and the raw `EINVAL` (22) return also come from shadPS4
### Functional