Merge pull request #3823 from xXPBSXx/fix/rudp-exports-ppsa03490-v3

fix(rudp): provide the calls PPSA03490 still lacks
This commit is contained in:
Adrià 2026-10-12 00:07:39 +02:00 committed by GitHub
commit 01b7bb68be
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 79 additions and 0 deletions

View File

@ -219,6 +219,16 @@ if(BUILD_TESTING)
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libSceRudp>")
endif()
add_test_executable(guest_rudp_pump_tests tests/GuestRudpPump.cpp)
target_include_directories(guest_rudp_pump_tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(guest_rudp_pump_tests PRIVATE libSceRudp libc)
configure_windows_unwind(guest_rudp_pump_tests)
add_test(NAME guest_rudp_pump COMMAND guest_rudp_pump_tests)
if(WIN32)
set_tests_properties(guest_rudp_pump PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libSceRudp>")
endif()
add_test_executable(guest_memory_pool_stats_tests tests/GuestMemoryPoolStats.cpp)
target_include_directories(guest_memory_pool_stats_tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(guest_memory_pool_stats_tests PRIVATE libSceSsl libSceHttp2 libSceNet libkernel libc)

View File

@ -242,4 +242,25 @@ int APS5_VABI sceRudpRead(int ctx_id, void* data, uint32_t len, int flags, void*
}
return valid_ctx(ctx_id) ? RUDP_ERROR_CONN_RESET : RUDP_ERROR_INVALID_CONTEXT_ID;
}
int APS5_VABI sceRudpNetFlush(void) {
std::lock_guard<std::mutex> lk(g_mutex);
return g_inited ? 0 : RUDP_ERROR_NOT_INITIALIZED;
}
int APS5_VABI sceRudpProcessEvents(void) {
std::lock_guard<std::mutex> lk(g_mutex);
return g_inited ? 0 : RUDP_ERROR_NOT_INITIALIZED;
}
int APS5_VABI sceRudpNetReceived(void) {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI sceRudpGetMaxSegmentSize(void) {
NotImplemented_nid_no_patch(__func__);
return 0;
}
}

View File

@ -0,0 +1,47 @@
#include "prx/libc/include/general/VabiMacros.hpp"
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <stdexcept>
#include <string>
extern "C" {
int APS5_VABI sceRudpInit_nid_postfix(void*, int);
int APS5_VABI sceRudpTerminate();
int APS5_VABI sceRudpProcessEvents();
int APS5_VABI sceRudpNetFlush();
int APS5_VABI sceRudpGetMaxSegmentSize();
int APS5_VABI sceRudpNetReceived();
}
static void Require(bool value, int line) {
if (!value) {
std::fprintf(stderr, "rudp check failed at line %d\n", line);
std::abort();
}
}
#define CHECK(value) Require((value), __LINE__)
int main() {
constexpr int notInitialized = static_cast<int>(0x80770001);
CHECK(sceRudpProcessEvents() == notInitialized);
CHECK(sceRudpNetFlush() == notInitialized);
alignas(8) static unsigned char pool[0xC58];
CHECK(sceRudpInit_nid_postfix(pool, sizeof(pool)) == 0);
CHECK(sceRudpProcessEvents() == 0);
CHECK(sceRudpNetFlush() == 0);
CHECK(sceRudpTerminate() == 0);
for (const auto call : {&sceRudpNetReceived, &sceRudpGetMaxSegmentSize}) {
bool threw = false;
try {
call();
} catch (const std::runtime_error&) {
threw = true;
}
CHECK(threw);
}
return 0;
}

View File

@ -40,6 +40,7 @@ Throughout the project, every function at every stage either **does exactly what
- [libSceHttp2](../../core/libs/prx/libSceHttp2/Export.cpp) - no request reaches the network, so `sceHttp2SetMinSslVersion` has no TLS connection to restrict and its value is ignored, as for `sceHttp2SslEnableOption` and `sceHttp2SslDisableOption`. The three setters validate `id` against the live handle registry and return `SCE_HTTP2_ERROR_INVALID_ID` (`0x817B1100`) for a handle that was never allocated, was deleted, or belonged to a terminated context, following [prosper](https://github.com/mattias800/prosper). Whether the console restricts the object kind these setters accept, and what it does with an id from a previous init/term cycle, is unverified, so any live handle kind is accepted and ids are never reused. `sceHttp2Term`, `sceHttp2DeleteTemplate`, `sceHttp2DeleteRequest`, `sceHttp2CreateTemplate`, `sceHttp2CreateRequestWithURL`, `sceHttp2CreateCookieBox` and `sceHttp2SendRequestAsync` also return the invalid-id error for a handle of the wrong kind or no longer live, following prosper (not measured on a console)
- [libSceNpTrophy2](../../core/libs/prx/libSceNpTrophy2/src/GameInfo.cpp): `sceNpTrophy2RegisterUnlockCallback` accepts a callback that is never called, as no trophy is ever unlocked, `sceNpTrophy2UnregisterUnlockCallback` only returns success, and `sceNpTrophy2ShowTrophyList` returns success without showing a list (there is no system trophy UI; seen on PPSA15552).
- [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.
- [sceRudpProcessEvents and sceRudpNetFlush](../../core/libs/prx/libSceRudp/Export.cpp) (libSceRudp) - there is no reliable-UDP stack on the host, and every `sceRudpWrite`, `sceRudpRead` and `sceRudpGetStatus` call here reports a reset or idle context without queueing data, so no context ever holds pending data to process or send; both calls return success after `sceRudpInit` and `RUDP_ERROR_NOT_INITIALIZED` before it, as [shadPS4](https://github.com/shadps4-emu/shadPS4/blob/main/src/core/libraries/rudp/rudp.cpp) returns OK from its stubs. PPSA03490 calls `sceRudpProcessEvents(0)` followed by `sceRudpNetFlush()` from its P2P service thread and ignores the first result; whether the real calls take parameters is unknown
- [sceRudpActivate](../../core/libs/prx/libSceRudp/Export.cpp) (libSceRudp) - there is no reliable-UDP stack on the host to activate, so it returns success without doing anything, as [shadPS4](https://github.com/shadps4-emu/shadPS4/blob/main/src/core/libraries/rudp/rudp.cpp) does for its own `sceRudpActivate`. PPSA01325 calls it with no arguments during start-up; what the console activates, and whether it reports an error before `sceRudpInit`, is unverified
- [ulobjmgr](../../core/libs/prx/ulobjmgr/Export.cpp) registers no object: `_sceUlobjmgrRegisterObject` always hands out id 0 and `_sceUlobjmgrUnregisterObject` releases nothing, as shadPS4 does
- [libSceHttp](../../core/libs/prx/libSceHttp/Export.cpp) - no request reaches the network, so `sceHttpSetResponseHeaderMaxSize` has no response header to limit, `sceHttpSetRecvBlockSize` (`(int id, u32 blockSize)` as in [shadPS4](https://github.com/shadps4-emu/shadPS4/blob/main/src/core/libraries/network/http.h)) no response body to read in blocks and `sceHttpRedirectCacheFlush` no redirect to forget; `sceHttpsUnloadCert` returns success like `sceHttpsLoadCert`, which keeps no certificate; `sceHttpSetRedirectCallback` and `sceHttpSetCookieRecvCallback` accept callbacks that are never called, `sceHttpsSetSslVersion` has no TLS connection to configure and `sceHttpsGetSslError` reports error 0 with detail 0; `sceHttpSetAuthInfoCallback` accepts a callback that is never called, as no server asks for authentication; `sceHttpsGetCaList` and `sceHttpsFreeCaList` report an empty CA list (`certs` null, `certsNum` 0) and return 0, as no CA store is kept, and a null list returns `ERROR_INVALID_VALUE`; unlike shadPS4 they do not check that `http_ctx_id` is a live context nor that the library is initialised, and `sceHttpsFreeCaList` also nulls `certs`, which shadPS4 leaves untouched. The signatures and the `{ void* certs; int certsNum; }` layout follow [shadPS4](https://github.com/shadps4-emu/shadPS4/blob/main/src/core/libraries/network/http.h) (PS4), not confirmed on a PS5 title