Repository navigation
Dying Light 2 (PPSA02262) on Windows: what stops it between conversion and its own startup #1794
Description
Summary
Dying Light 2 Stay Human (PPSA02262, Techland C-Engine, content version 01.090.000, full 73 GB dump) on Windows does not start on main (4ddbf04). Below is everything between conversion and the title's own startup code. To find each next point I added local placeholders, which are not proposed here. With all of them, the title runs its own initialisation and stops at its own assertion Net_StartUp failed (CGame.cpp(2458), CGame::Initialize).
Setup: Windows 11, MinGW GCC 15.2.0, RTX 3070. Input layout: eboot.elf as the input, sce_module/libc.prx, and the title's loose root modules (EOSSDK-PS5-Shipping, ffmpeg, libNRD, runtime_prospero, the Wwise Ak* plugins) beside it.
1. Needed module name differs from the shipped file name
The executable's needed entry is EOSSDK-PS5-Shipping.debug_prx, but the dump ships EOSSDK-PS5-Shipping.prx. The relinker matches needed names by exact filename, so it skips the module without an error. The output then fails at start-up:
Failed to load module: ...\libs\EOSSDK-PS5-Shipping.debug_prx
GetLastError: 126 - The specified module could not be found.
Renaming the file to .debug_prx makes the relinker convert it and the load succeeds.
2. libSceNpCppWebApi has no provider (same as #1033)
EOSSDK-PS5-Shipping imports from libSceNpCppWebApi.prx (first: 5f9xDKxYjbY). The dump has no copy under any name, so this is a second title for #1033.
3. Imports no built library exports
| NID | Name | Imported by |
|---|---|---|
30Rh4ixbKy4 |
sceKernelFdatasync | eboot |
9WK-vhNXimw |
sceKernelAioSetParam | eboot |
Xweb+naPZ8Y |
sceNpWebApi2GetMemoryPoolStats | eboot |
-q-vbO859Tw |
(unknown, libSceVideoOut) | eboot |
vwtVpHQKelI |
(unknown, libSceVideoOut) | eboot |
GTfJ64qFCPw |
(unknown, libSceAcm) | eboot |
tuscfitnhEo, zXvd6iNyfgc, jltWpVKtetg, iNjkt9Poblw, HJ1n138CQ2g, E4a-ahM57QQ |
sceSslCreateConnection, sceSslConnect, sceSslRead, sceSslWrite, sceSslDeleteConnection, sceSslSetVerifyCallback | ffmpeg |
None of them is on main or in an open PR (checked with the overlap tool). #1119 covers the Http2, Ssl and Net pool statistics but not NpWebApi2's.
4. sceKernelMprotect on a bundled module's image fails on Windows
libNRD (NVIDIA Real-time Denoisers, bundled) calls sceKernelMprotect on its own image with prot=0x12 and then 0x11:
[memory] protect 00007ff832970000+0x11278 prot=0x12
terminate called after throwing an instance of 'std::invalid_argument'
what(): Memory protection of a foreign image is not supported
DoMprotect (DirectMemory.cpp) accepts only the main executable's image on Windows. Linux registers the image and applies the protection.
5. Where it stops with all of the above worked around
ASRT: [Assert] | Net_StartUp failed
ASRT: [Assert] - Function: virtual int CGame::Initialize(...)
I haven't narrowed down which network call fails yet.
An earlier private fork (not upstream) got this title to rendering. The changes it needed are listed in the follow-up PRs I'll open one at a time.
AI-assisted: yes (Claude Code).
Activity
tv7 commentedon Oct 8, 2026
Update: items 1 and 5 are the same problem, and item 5 leads to a second one with guest socket descriptors.
Item 5 traced. With the title's own logging switched on (the flag at ELF
0x83e5698and its level check, set from a debugger), it reports:The executable needs
EOSSDK-PS5-Shipping.debug_prx(item 1), so I had renamed the file to get it relinked and loaded. At run time the title loads the same module by its shipped name,/app0//EOSSDK-PS5-Shipping.prx.dlopenthen looks forapp0/EOSSDK-PS5-Shipping.prx.guest.prx, which does not exist under that name, and returnsENOENT. The EOS backend fails, the lobby's start-up poll sees it, andNet::Services::StartUpreturns the error thatCGame::Initializeturns intoNet_StartUp failed.When the relinked module is reachable under both names (a hard link, locally), the title logs
[Lobby.Backend.Eos] > [StartUp] okand[Lobby] > [Initialize] all backends are up, andNet_StartUppasses. So the fix for both items is in the relinker: match a neededX.debug_prxto a shippedX.prxand keep the shipped file name for the output. I'll open a PR for that.Next stop: socket descriptors and
fd_set. Right after that, EOS'sRtcNetworkThread(WebRTC) crashes:It is
FD_SETof guest socket0x10000005into a FreeBSDfd_set(1024 bits) on its stack at0x22abfa60:0x22abfa60 + 0x10000005 / 8 = 0x24abfa60, 32 MiB past the set. The title's sockets come fromsocketin libkernel, which numbers them fromGuestSockets::FirstDescriptor(0x10000000). Any title that puts a socket into anfd_set(forselect) writes outside it like this. On the console, socket descriptors share the process descriptor table, so they are small numbers.This is a design question, because #1706, #1727 and others dispatch on
d >= FirstDescriptor, so I'm raising it here rather than in a PR. Should guest sockets get small descriptors (for example by reserving a host CRT descriptor per socket, as a private fork of mine did to get this title rendering), or is there a preferred direction?fix(relinker): match needed module names that differ only in the exte…
sktharunbalaji13-cmd commentedon Oct 10, 2026
Hi @tv7 — following up on the
sceKernelFdatasyncimport (30Rh4ixbKy4,eboot) in issue #1794.A reviewer asked whether Dying Light 2 (PPSA02262) actually stops because this import is unresolved. Could you share the exact loader/startup log line showing NID
30Rh4ixbKy4failing to resolve, and confirm that the title stops there on cleanmainwithout local placeholders?If the title proceeds past the import instead, that would also be useful to know. We want to establish the actual failure before adding the export.
fix(libkernel): reprotect bundled guest module images on Windows
fix(libkernel): reprotect bundled guest module images on Windows
tv7 commentedon Oct 10, 2026
@sktharunbalaji13-cmd Yes: on clean
mainthe title stops on this import, before any title code runs.Setup: Windows 11 Pro (10.0.26200), RTX 3070, GCC 15.2.0 UCRT (WinLibs), Release. Dying Light 2 (PPSA02262), relinked with the
mainbuild, no local placeholders.Clean
main(b5f5362): the loader stops on the first line of the log:main+ #2129 (c47f8ca,libstarget):30Rh4ixbKy4resolves, and the loader stops on the next unresolved import:So #2129 removes this stop, but the title does not start yet: 12 other imports are still unresolved on
main. In the eboot,-q-vbO859Tw,GTfJ64qFCPw,vwtVpHQKelI(no known names),sceKernelAioSetParamandsceNpWebApi2GetMemoryPoolStats.AkConvolutionReverb.prxalso needsGTfJ64qFCPw, and the bundledffmpeg.prxneeds sixsceSsl*connection functions. Whether the title depends on whatsceKernelFdatasyncdoes after start-up I can't say yet. The earlier runs in this issue had a local placeholder for it that returned 0.One merge note: #2129 merged onto current
mainbuilds, butguest_font_testsfails to compile (GuestFont.cpp:129: redefinition of 'void SetFontDirectory(...)'). That comes from the PR'stest(font)commit andmain's copy of that test, so it needs a rebase.sktharunbalaji13-cmd commentedon Oct 10, 2026
Thanks a lot, @tv7! Really appreciate you testing this against clean
mainand sharing the exact logs and side-by-side comparison. That evidence makes it much clearer whatsceKernelFdatasyncfixes and what still blocks Dying Light 2, without claiming the game is playable yet.I've also cleaned up PR #2129 to keep it focused on
sceKernelFdatasyncand its regression test, removing the unrelated font-test change. Thanks again for taking the time to investigate this thoroughly — it's genuinely helpful for contributors working on compatibility!Rohan03x commentedon Oct 10, 2026
A second title for the socket-descriptor /
selectitem: Palworld (PPSA23126, v01.102.999) hits the same crash in the EOS SDK.Setup: Windows 11 22621, RTX 3070, GCC 15.2.0 UCRT Release; main 1f0c9fe plus #1764 and local unimplemented-export declarations the title needs to bind its imports.
Crash:
unhandled exception 0xc0000005 on thread 'RtcNetworkThread', ripeossdk-ps5-shipping.prx.guest.prx+0xdea2be, write of0x221f9a0. The instruction isor QWORD PTR [rbp+rsi*8-0xb0], rdxwithrsi = fd >> 6,rdx = 1 << (fd & 63)andfd = 0x10000005, i.e.FD_SETon a 1024-bit stackfd_set(0x21fa50 + 0x400000*8 - 0xb0 = 0x221f9a0), followed by a call toselect. The descriptor comes from libkernel'ssocket(FirstDescriptor = 0x10000000).What the SDK does with descriptors (static reading of its imports and code): WebRTC builds its wake-up pair from
socket/bind/listen/connect/accept(nopipeorsocketpairimport), uses POSIXread/writeon it (covered by #1727 since), puts the sockets inselectsets, and callssceNetSetsockopt/sceNetSocketCloseon them. Its libwebsockets also appears to pass descriptor 0 toselect, because its wake-up pipe is never created.Local experiment: with libkernel sockets numbered from the host descriptor table (on Windows a zero-access CRT descriptor on
NULplus a side table, as directory descriptors already do; range tests replaced by table membership) andselectpolling libkernel sockets and host descriptors, the out-of-bounds write is gone and the title runs start-up for more than 10 s. The next stop issceHttp2WaitAsync: waiting for an operation that has not completed. ctest: 0 failed of 619 with those changes on main 292ecfb. Windows only; the non-Windows branch is not built.Questions before I propose anything:
>= FirstDescriptor?selectkeep rejecting sets that mix the two?AI-assisted: yes.
queeeef commentedon Oct 11, 2026
Palworld (PPSA23126, 01.102.999) still hits the EOS
FD_SEToverflow on currentmaina11c8f7f7(with only #3461's branch added so that every import binds):Same instruction and descriptor as reported above (
fd = 0x10000005,rsi = fd >> 6).A local experiment that gets past it (
8081a8e1, not a proposal):GuestSockets::FirstDescriptor=0x300, so libkernel sockets fit a 1024-bitfd_set;selectpasses the libkernel sockets in its sets to libkernelpollwith a zero timeout, and caps its wait at 1 ms while any are present (libSceNet sockets keep going through the poller).With it the crash is gone, the EOS threads run, and the title reaches character creation (further stops in #2648). It does not answer the two questions above:
0x300only avoids the CRT descriptors and libSceNet ids in practice, it does not keep them apart.Windows 11 Pro 26300, RTX 2080 Ti, MinGW-w64 GCC 15.2.0 (WinLibs r7), RelWithDebInfo. AI-assisted (Claude Code).
xXPBSXx commentedon Oct 11, 2026
Data for the two open questions above (
@Rohan03x,@queeeef), from readingmaina11c8f7 and FreeBSD; I have not implemented or run anything for this.0x10000000: FreeBSD 11.0.1 definesFD_SETSIZEas 1024 (sys/sys/select.h, line 59), so the guest'sfd_setis 128 bytes andFD_SETwrites at bytefd / 8. Withfd = 0x10000005that is the 32 MB write past the set that the crash shows. Any descriptor a title can put in aselectset has to be below 1024, so this applies to every title that usesselecton a socket, not only the EOS SDK.GuestSockets::FirstDescriptor(Socket/include/SocketRuntime.hpp) is compared in 27 places across 7 source files (File/src/Stdio.cpp18,File/src/Open.cpp3,Socket/src/Udp.cpp2,Equeue/Equeue.cpp,File/src/Terminal.cpp,libScePosixForWebKit/Filesystem.cpp, plus the header) and one test. Moving the base alone keeps every one of them working; replacing the range test with a table lookup, as in@Rohan03x's experiment, touches all of them.g_next_sock = 32(libSceNet/Export.cpp:293, a separate counter), and on Windows the CRT hands out the lowest free descriptor for files, so a fixed base such as0x300only avoids them while neither grows that far. Directory descriptors already avoid the CRT clash by openingNUL(File/src/DirectoryDescriptor.cpp:40) and keeping a side table, which is what the experiment generalizes to sockets; libSceNet would need the same allocator to keep the two families apart, orselecthas to reject a set that mixes them.I do not know which of these the maintainers prefer, and I have not checked what the console numbers its first socket as.
AI-assisted (Claude Code).
xXPBSXx commentedon Oct 11, 2026
The Mound (PPSA26223) on
main(0a8b1d32b, plain main, no open PRs), 120 s run: theselectstop is gone and the title stops at the same place as described here:FATAL: unhandled exception 0xc0000005 on thread 'RtcNetworkThread',rip eossdk-ps5-shipping.prx.guest.prx+0xefc6f4,rcx = 0x10000005(a socket fromGuestSockets::FirstDescriptor),rsi = 0x400000(= fd >> 6), i.e.FD_SETon the 1024-bitfd_setwith a 0x10000000-based descriptor. So the EOS SDK path described above is also what stops this title.AI-assisted (Claude Code).
feat(libkernel): implement sceKernelAioSetParam
fix(libkernel): give guest sockets ordinary descriptor numbers below …
xXPBSXx commentedon Oct 12, 2026
The descriptor design discussed here is implemented in #4391 (socket numbers reserved from the host descriptor table, so they fit
FD_SETSIZE; dispatch by table membership). On Windows, The Mound (PPSA26223) with that PR no longer stops inRtcNetworkThreadatFD_SET: 150 s without aFATAL(details and a needed rebase in #4391 (comment)). Palworld still stops earlier on an unrelated shader-recompiler abort, so it is not confirmed there. Observation only; I did not review the PR's semantics beyond building it and running its tests.AI-assisted (Claude Code).
fix(libkernel): give guest sockets ordinary descriptor numbers below …
fix(libkernel): give guest sockets ordinary descriptor numbers below …
fix(libkernel): give guest sockets ordinary descriptor numbers below …
fix(libkernel): give guest sockets ordinary descriptor numbers below …
fix(libkernel): give guest sockets ordinary descriptor numbers below …
fix(libkernel): give guest sockets ordinary descriptor numbers below …
oneandonlydean commentedon Oct 13, 2026
#3764 (kqueue) and #4391 (socket descriptors below
FD_SETSIZE) are on main. What is the first stop of PPSA02262 on plain main now?Upstream sync 7: kernel, libc and small libs (#454)
pushkarreddyy commentedon Oct 13, 2026
Working on a fix for item 4 (
sceKernelMprotecton foreign module images on Windows). Extending WindowsDoMprotectto handle registered foreign images viaVirtualProtectmatching Linux behavior, with unit tests. Will link the PR shortly.pushkarreddyy commentedon Oct 13, 2026
Implemented and opened PR for Section 4 (foreign image \sceKernelMprotect\ support on Windows unblocking Dying Light 2: Stay Human \PPSA02262): #5109
MarcZX10 commentedon Oct 14, 2026
A current-main rerun could narrow this blocker now: #2129 (sceKernelFdatasync) and #4902 (the
-q-vbO859TwVideoOut NID) are both merged. The last clean-main loader trace in this thread predates those changes. Could you rerun the Dying Light 2 conversion/startup on currentmainwith no local export placeholders and share the first remaining unresolved import or runtime stop? That will show whether one of the still-unknown VideoOut/ACM NIDs is actually next, and avoid adding exports based only on the import table.MarcZX10 commentedon Oct 15, 2026
Follow-up to my earlier current-main rerun request: the current
tools/nid_names.pyregistry now recognizes the formerly absentsceKernelFdatasync,sceKernelAioSetParam,sceNpWebApi2GetMemoryPoolStats, both VideoOut NIDs, and the six SSL NIDs; their implementations are present in currentmain(including #3305 and #4902 for the VideoOut calls). The remaining ACM NIDGTfJ64qFCPwnow resolves by name tosceAcmBatchJobPriority, but that export still throws and its callable signature/behavior is not established by the issue. A current unmodified run or import-audit result would show whether this is still the next blocker; I don't have the title dump to verify it here.tv7 commentedon Oct 16, 2026
Rerun on current
mainas asked, with no local exports or placeholders.Setup
main896e1b2b7, relinked with--module-dir . --to-intel(the title's ownprx/modules)game.exe(log flag + the "logging enabled" check); nothing in AnyPS5 changedResult
Loading, conversion and startup are no longer the problem. All imports resolve, the intro movie plays, and the game reaches the start screen at 60 FPS. After the controller is chosen it sits on a black screen with the loading spinner, without making progress (tested 20 minutes, no error in the AnyPS5 log).
The game's log shows why. It is stuck in the PSN sign-in step:
sceNpGetAccountIdAinlibSceNpManageralways returnsSCE_NP_ERROR_SIGNED_OUT(the "PSN is not emulated" policy). Dying Light 2 does not fall back to offline play when that happens; it keeps retrying the interactive sign-in. On a console that step would show the system sign-in prompt, which never appears here.EOS is not the blocker: its HTTP requests to
api.epicgames.devfail (no real network), butLobby.Backend.EosreportsCheckConnectionStatus ... ok (signed out)and the game keeps going past that.Question
Would you accept reporting the initial user as a PSN user who is signed up but offline, i.e.
sceNpGetAccountIdA(andsceUserServiceGetNpAccountId, which returns 0 today) returning a fixed local account id, while reachability and every online request still fail? On a real PS5 a user with a linked account keeps their account id while offline, so this would match the console without emulating PSN. If yes, I can open a small PR with a test. If you would rather keep "signed out" everywhere, the game needs some other way past this step and I'd like to know which one you prefer.AI-assisted: yes
pushkarreddyy commentedon Oct 16, 2026
This matches console hardware behavior: on a real PS5, a local profile with a linked account persists its 64-bit
AccountIdon storage. Even when completely offline (e.g. flight mode or disconnected network),sceNpGetAccountIdA(USER_SERVICE_INITIAL_USER_ID, &account_id)succeeds and returns that cachedaccount_id, whilesceNpGetNpReachabilityStatereportsNP_REACHABILITY_STATE_UNAVAILABLEandsceNpGetStatereportsNP_STATE_SIGNED_OUT.Titles like Dying Light 2 use the account ID to initialize local lobby/profile state and only fall back to offline play once a local identity is present. When
sceNpGetAccountIdAreturns0x80550006(SCE_NP_ERROR_SIGNED_OUT), the title assumes no account is present at all and continuously loops retrying the interactive sign-in dialog.Reporting a fixed non-zero account ID (e.g.
0x0100000000000001ull) forUSER_SERVICE_INITIAL_USER_IDinsceNpGetAccountIdA(and aligningsceUserServiceGetNpAccountId) while keeping reachability unavailable models an offline linked profile accurately without emulating online PSN infrastructure.@tv7 Since you have the title dump and repro environment ready to verify it moving past the spinner into gameplay, opening that PR with the unit test would be great!
MarcZX10 commentedon Oct 17, 2026
Opened MarcZX100 PR #6990 for the fixed emulator-local account ID shared by
sceNpGetAccountIdAandsceUserServiceGetNpAccountId. Both focused test targets compile locally; CTest aborts before assertions on this host because it lacks the PS5-required CPU extensions. The Dying Light 2 Windows runtime result remains unverified on the PR branch.MarcZX10 commentedon Oct 18, 2026
The socket-descriptor concern in the earlier follow-up is now addressed by merged PR #4391 (
fix(libkernel): give guest sockets ordinary descriptor numbers below FD_SETSIZE). Itsguest_socket_descriptorsregression test asserts created sockets are below 1024 and exercises socket readiness throughselect, mixed socket/file sets, descriptor reuse, and duplication. So the old0x10000000descriptor issue should no longer be treated as an outstanding current-main blocker. The latest Dying Light 2 run instead reaches PSN sign-in; #6990 covers the offline account-ID behavior, though title runtime on that PR head remains unverified.