From ce0915e83471dd6c0264f7484a7f563221234c36 Mon Sep 17 00:00:00 2001 From: gookie <36005381+gookie-dev@users.noreply.github.com> Date: Sun, 11 Oct 2026 20:12:34 +0200 Subject: [PATCH] feat(libSceHttp2): implement sceHttp2DeleteCookieBox PPSA35943 (Graveyard Keeper 2) imports sceHttp2DeleteCookieBox, which no library exported. On current main the loader stops the title there: ./eboot.elf: symbol lookup error: ./eboot.elf: undefined symbol: O9ync3F-JVI sceHttp2DeleteCookieBox(cookieBoxId) erases the box from the handle registry sceHttp2CreateCookieBox adds it to and returns 0, or the library's invalid-id error (0x817B1100) for an id that is not a live cookie box. The signature follows SharpProspero and the behaviour prosper's sceHttp2DeleteCookieBox; the error code is listed in TechnicalDebt as not measured on a console. guest_http2 deletes a box twice, a context id, a box whose context was terminated, and the two boxes it uses before sceHttp2Term. With this change the title loads and runs into its asset loading. --- core/libs/prx/libSceHttp2/Export.cpp | 7 +++++++ core/libs/tests/GuestHttp2.cpp | 8 ++++++++ docs/dev/TechnicalDebt.md | 1 + 3 files changed, 16 insertions(+) diff --git a/core/libs/prx/libSceHttp2/Export.cpp b/core/libs/prx/libSceHttp2/Export.cpp index f037bf7f9..786bf3099 100644 --- a/core/libs/prx/libSceHttp2/Export.cpp +++ b/core/libs/prx/libSceHttp2/Export.cpp @@ -356,6 +356,13 @@ int APS5_VABI sceHttp2CreateCookieBox(int lib_http2_ctx_id) { return id; } +int APS5_VABI sceHttp2DeleteCookieBox(int cookie_box_id) { + std::lock_guard lock(g_handlesMutex); + if (FindHandle(cookie_box_id, Http2Kind::CookieBox) == nullptr) return ERROR_INVALID_ID; + g_handles.erase(cookie_box_id); + return 0; +} + int APS5_VABI sceHttp2SetCookieBox(int id, int cookie_box_id) { (void)id; (void)cookie_box_id; diff --git a/core/libs/tests/GuestHttp2.cpp b/core/libs/tests/GuestHttp2.cpp index e64d3053f..ffce322a3 100644 --- a/core/libs/tests/GuestHttp2.cpp +++ b/core/libs/tests/GuestHttp2.cpp @@ -8,6 +8,7 @@ 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(int); +int APS5_VABI sceHttp2DeleteCookieBox(int); int APS5_VABI sceHttp2SetCookieBox(int, int); int APS5_VABI sceHttp2CookieFlush(int); int APS5_VABI sceHttp2SetRequestNoContentLength(int); @@ -71,6 +72,11 @@ int main() { const int box = sceHttp2CreateCookieBox(context); const int other = sceHttp2CreateCookieBox(context); Require(box > 0 && other > 0 && box != other && box != context); + const int discarded = sceHttp2CreateCookieBox(context); + Require(discarded > 0 && discarded != box && discarded != other); + Require(sceHttp2DeleteCookieBox(discarded) == 0); + Require(sceHttp2DeleteCookieBox(discarded) == InvalidId); + Require(sceHttp2DeleteCookieBox(context) == InvalidId); const int tmpl = sceHttp2CreateTemplate(context, "agent", 2, 0); Require(tmpl > 0 && tmpl != box && tmpl != other); Require(sceHttp2SetResolveRetry(tmpl, 3) == 0); @@ -119,6 +125,7 @@ int main() { Require(sceHttp2Term(doomedContext) == 0); RequireSslSetters(doomedContext, InvalidId); RequireSslSetters(doomedContextBox, InvalidId); + Require(sceHttp2DeleteCookieBox(doomedContextBox) == InvalidId); RequireSslSetters(doomedContextTemplate, InvalidId); RequireSslSetters(doomedContextRequest, InvalidId); Require(sceHttp2Term(doomedContext) == InvalidId); @@ -153,6 +160,7 @@ int main() { Require(Throws([&] { sceHttp2WaitAsync(request, &result, nullptr, nullptr); })); Require(sceHttp2DeleteRequest(request) == 0); Require(sceKernelDeleteEqueue(eq) == 0); + Require(sceHttp2DeleteCookieBox(box) == 0 && sceHttp2DeleteCookieBox(other) == 0); Require(sceHttp2Term(context) == 0); KernelEqueue templateEqueue = 0; diff --git a/docs/dev/TechnicalDebt.md b/docs/dev/TechnicalDebt.md index 446bdd0bc..1b0998b11 100644 --- a/docs/dev/TechnicalDebt.md +++ b/docs/dev/TechnicalDebt.md @@ -68,6 +68,7 @@ Throughout the project, every function at every stage either **does exactly what - [sceVoiceQoSSetConnectionAttribute](../../core/libs/prx/libSceVoiceQoS/Export.cpp) (libSceVoiceQoS, NID `KCGOxg8iX7s`) is a throwing stub declared without parameters, like the other endpoint calls of the library: PPSA04159 fails to load without it and its signature is unknown. The name hashes to the imported NID (`tools/nid_names.py`) - [sceVideoOutGetOutputStatusWithVrr](../../core/libs/prx/libSceVideoOut/Unimplemented.cpp) (libSceVideoOut, NID `gWT7X8H0bYs`) - the name hashes to the imported NID. PPSA26344 version 02.002.000 passes a VideoOut handle and an output pointer at three call sites. It compares a 32-bit value at byte 4 with 2, tests bit 0x10 at byte 16, and, when set, compares low 16-bit values at bytes 48, 50 and 52 with 48, 60 and 120. The full output layout, size, field meanings and console errors are unknown. Every call throws without reading or writing caller memory. - [sceHttp2WebSocketSetPingInterval](../../core/libs/prx/libSceHttp2/Export.cpp) (libSceHttp2, NID `YfaXPnc8PJE`) - imported by `libdiscord_partner_sdk.prx` of PPSA23126 (issue 2648). The parameters, the unit of the interval and the console errors are unknown. Every call throws. +- [sceHttp2DeleteCookieBox](../../core/libs/prx/libSceHttp2/Export.cpp) (libSceHttp2) - imported by PPSA35943's Unity player. The `(int cookieBoxId)` signature follows [SharpProspero](https://github.com/SvenGDK/SharpProspero/blob/5dfdb4b0b166e83dc9ae275001afb695f12c7174/src/SharpProspero/Interop/Net/Http2.cs#L215-L217). A box `sceHttp2CreateCookieBox` returned is discarded; an unknown or already deleted id returns the library's invalid-id error (0x817B1100), as [prosper](https://github.com/mattias800/prosper/blob/b1bec57186a0/prosper/src/hle/net/hle_http2.cpp#L512-L523) does; not measured on a console - [sceKernelGetProsperoSystemSwVersion](../../core/libs/prx/libkernel/System/src/SoftwareVersion.cpp) (libkernel) reports system software version `0x01000000` ("01.000.000"); the console's firmware version is not modeled. The 0x28-byte block (a 64-bit size at 0, the version string at 8 and the packed version at 0x24) follows [SharpProspero](https://github.com/SvenGDK/SharpProspero/blob/main/src/SharpProspero/Interop/Kernel/KernelSystem.cs), which Prospero Multi Tools (PPSA99110) and Prospero Explorer (PPSA99109) are built with and which sets the size to 40, and the same fields in [etaHEN](https://github.com/etaHEN/etaHEN/blob/main/Source%20Code/daemon/include/ipc.hpp) and [shsrv](https://github.com/ps5-payload-dev/shsrv/blob/master/sh.c). A size other than 0x28 returns `SCE_KERNEL_ERROR_EINVAL` without writing; whether the console checks the size is unverified, since etaHEN and shsrv declare a 0x30-byte block and do not set it - [sceKernelGetAllowedSdkVersionOnSystem](../../core/libs/prx/libkernel/System/src/SoftwareVersion.cpp) (libkernel) reports the system software version with the 12 patch bits set, `0x01000fff`, as [shadPS4](https://github.com/shadps4-emu/shadPS4/blob/98fd0689/src/core/libraries/kernel/kernel.cpp) does on the PS4 and as [SharpProspero](https://github.com/SvenGDK/SharpProspero/blob/main/src/SharpProspero/Interop/Kernel/KernelSystem.cs) describes it, which Prospero Explorer (PPSA99109) reads it through; a null pointer returns `SCE_KERNEL_ERROR_EINVAL`. The console's value and its errors are unverified - [sceSystemServiceLaunchApp](../../core/libs/prx/libSceSystemService/Export.cpp) (libSceSystemService) - AnyPS5 runs one title and cannot start another, so every call throws without reading its arguments. The (title ID, null-terminated argv, launch parameters) signature follows [SharpProspero](https://github.com/SvenGDK/SharpProspero/blob/5dfdb4b0b166e83dc9ae275001afb695f12c7174/src/SharpProspero/Interop/SystemService/SystemService.cs#L141-L148), whose `AppLauncher` Prospero Explorer (PPSA99109) and Prospero Multi Tools (PPSA99110) import it through and which passes a 0x20-byte launch context or null; the console's argument checks and errors are unknown