Repository navigation
Grand Theft Auto: Vice City – The Definitive Edition (PPSA03530) #10520
Replies: 4 comments
|
Status update + the questions I'd like reviewed before I build more on top of this. The remap-storm blocker turned out to be a real kernel-side scalability bug — filed as #10521 with the fix direction (block-level phys index + identical-mapping no-op). With that in, the title now completes its entire arena setup and reaches UE4 init. Where it stands now — guest-internal OOM These numbers are the guest's own arena ledger, not kernel answers — it never calls Levers tested (all reproduce the same OOM)
What I'd like reviewed
Full call trace and per-blocker evidence in the top comment. Working tree carries the diagnostics + block-index/map-cover changes — nothing upstream-ready yet pending the answers above. |
|
Confirmed on our side — RTX 3070 (driver 617.42), Windows 11, With The contrast is diagnostic: our earlier runs used So: the 2.7 GiB guest OOM is not a hard blocker — it's contingent on the playgo answer. Whether the |
Controlled Resume Game A/B (2026-10-26)I ran the same existing Resume Game save in two isolated Vice City stage folders. Both used the same Machine: Windows 10.0.26300; Intel Core i5-14600K; NVIDIA GeForce RTX 5070, driver 617.42; 3840x2160. Deep tracing was enabled in both runs: all import calls, memory, GPU, draws, and draw profiling. No trace records were dropped. Baseline
Red-zone branch
Relinker report and interpretationFor this same ELF and The PlayGo setting was No PR is being opened at this point; I will wait for the overlapping red-zone PRs to settle before proposing any follow-up. |

Uh oh!
There was an error while loading. Please reload this page.
Grand Theft Auto: Vice City – The Definitive Edition (PPSA03530)
Title bring-up notes. Decrypted v01.00 dump,
APS5_PLAYGO_UNLISTED_CHUNKS=installed. Relinks cleanly (6 modules, ~8800 imports) and starts UE4 init — currently blocked during early memory setup. Sharing findings so far; work in progress.Boot chain (what works)
sceKernelOpen /app0/ue4commandline.txt→../../../Gameface/Gameface.uproject; the dump shipsgameface/(content + platforms) but noGameface.uproject— the title logsProject file not foundand continues anyway, so this is probably not fatal.memory_type=12— zero flexible-memory calls, zero anon mmaps. The whole heap lives in the direct pool.Blocker 1 — contiguous arena grab
The game's very first big call is
sceKernelAllocateDirectMemory(0, GetDirectMemorySize())— it wants the entire reported size (13.5 GiB) as one contiguous phys block. With pool == reported (13.5 GiB), the early allocs it makes first (32 KiB + ~300 MiB + a few MiB, all low phys) fragment the range → the ask fails → it bisection-probes, drains ~13.2 GiB into fragments, then its own arena OOMs on a ~5.2 GiB request (Ran out of memory allocating 5565054976).Empirical:
physical pool > reported sizelets the contiguous ask succeed (physical 14–16 GiB with reported 13.5 GiB — matching a real console's 16 GiB RAM vs ~13.5 GiB reported).Blocker 2 — guest phys-page bitmap fencepost
With pool > ~15.7 GiB the guest crashes at
read of 0x9000008000— one page past the 32 KiB block it mapped at0x9000000000. Disassembly shows libc.guest's phys-page bitmap (64 KiB granule, window addend +65 qwords): it frees the unused tail[top_alloc, ceiling)where its ceiling is ~0x3F0000000— the bitmap buffer covers exactly 4096 qwords and it accesses index 4096. A console-compatible workaround that got past it: minimum direct-alloc granule 64 KiB + remap covering the whole phys block, so the guest's own bitmap storage is 64 KiB.Blocker 3 — remap storm (performance, fixed)
The guest then builds its arena alias by re-mapping a sliding 64 KiB-stepped window: ~216k
remap fixedcalls each covering ~13.5 GiB (va_i..end ← phys_i..end). Each call is semantically a no-op for the sub-range (phys already aligned) but our per-page phys bookkeeping walked ~880kstd::mapnodes per call — O(n²), effectively a hang.Two fixes got this from ~40 calls then death → storm completes:
g_physBlocks, one entry per_commitwith split-on-partial-free) soValidatePhysicalRange/AddMappingrun O(#blocks) instead of O(#16K-pages); per-page map stays only for the Linux shared-backing paths.Current wall — guest-internal OOM
Arena builds fine now; the guest then dies inside its own sub-allocator:
Usedis constant (5.8 GiB) across pool sizes 14/15/16 GiB;Availablescales with the pool — i.e. these are the guest's internal arena numbers, not kernel answers (it never callssceKernelAvailableDirectMemorySize). The 2.7 GiB request never reaches a kernel API — its free space exists but is fragmented across the bisection-fill blocks. Under investigation: whether a different phys layout (console hands out different base addresses) or the fill pattern is what makes its largest contiguous run ≥ 2.7 GiB on real hardware.Call trace (compressed, pool=16 GiB, reported=13.5 GiB)
Working branch carries diagnostics + the block-index/map-cover changes; nothing is upstream-ready yet — the remaining question is whether the current OOM is a real guest-fragmentation limit that console layout avoids, or still a kernel-semantic gap on our side.
All reactions