Bringing a PS4 game demo to Windows, as a research prototype.
Recovering verifiable behaviour from a binary with no source and no documentation
Engineering research · Apr 2026 – present
At a glance
Challenge
Run a PS4 game demo on a Windows PC, although its code expects console memory, GPU commands, shader formats and system services a PC lacks.
Solution
Rehost it: the demo's x86-64 code runs directly on the CPU, system calls are reimplemented in C++, and GCN shaders are translated to SPIR-V for Vulkan.
Result
99.73% of the demo's pixel shaders translate cleanly, and one fix cut frame-present waits from up to 1.9 s to about 7 ms. Research prototype, not playable.
shadPS4 emulationWith my fix
The before/after: the same cutscene in stock emulation (hair blocked, no alpha) and with my alpha-to-coverage fix in the emulator's shader backend.
Mesh regionDrawn in-frame
The hair mesh (event 3013): its region in magenta, and its draw within the lit frame.
Mayu regionsDrawn in-frame
The mayu meshes: dedicated eyebrow, sideburn and goatee detail geometry (event 3022), and hair plus mayu drawn together.
The diagnostic overlay I built into the reference emulator (shadPS4, used as the oracle), frame 153502: frame-time budget, the live camera block read out of memory, player-position candidate scanning, and every render pass listed by its fragment shaderReference run in shadPS4, frame 50941 with passes switched off one at a time. 147 passes seen in the run; HUD elements, motion blur and a character-halo pass are marked confirmed once switching them off changed what was drawnReference run in shadPS4, frame 47819 with most full-screen work skipped, leaving the draws that still compose the scene. Draw counts and indices per draw are listed for each passReference run in shadPS4, frame 118777: the recovered view basis, projection matrix and combined view-projection alongside the live pass list, with the free camera driving the main viewThe hair fix up close: hair, mayu and eyelashes all alpha-tested. RenderDoc backbuffer, frame 1377In my patched shadPS4 build, RenderDoc: event browser, vertex buffers, mesh viewerIn my patched shadPS4 build: Lua test stage loading c_am_dummy, a real model from the gameFight scene in my patched shadPS4 build during an early experiment (bloom and lens-flare artifacts).Reference render from my patched shadPS4 build, used as the target for the native rendererPass 24 boundary, shader group 11 landing: the street renders with real materials from my own pipelineLive run 235, shader group 145 under a single-channel debug view, checking geometry and coverageFragcoord passthrough for group 147: isolating a pass to prove the plumbing before the real shader landsShader group 144 during bring-upReference target (shadPS4): group 17, event 9696, slot-0 output during shader-group bring-upReference target (shadPS4): group 58, event 10478, slot-0 outputReference target (shadPS4): group 183, event 12686, slot-0 output
The problem
The binary assumes console-specific memory, GPU commands, shader formats, synchronization and operating-system services that do not exist on a desktop host.
Approach
Simplified view of the rehosting approach. A research prototype: it does not establish playability.
Recover observable contracts from the binary and runtime evidence instead of guessing undocumented behaviour.
Translate required graphics work into desktop APIs behind narrow, versioned gates.
Separate source acceptance, build acceptance, rendered evidence and playability so partial progress is never presented as final compatibility.
Outcome
Accepted source milestones cover runtime, memory, shader and presentation work; the current state does not establish complete playability, visual correctness or general compatibility.