A static ahead-of-time (AOT) recompiler that translates PlayStation 4 (x86-64 ELF) binaries into native Apple Silicon (ARM64 macOS) executables without JIT compilation, virtual machines, or MoltenVK overhead.
===================================================================
PS4Recomp: PlayStation 4 x86-64 to Native ARM64 AOT Recompiler
===================================================================
[ps4-recomp] [1/4] Loading ELF: tools/OpenOrbis/PS4Toolchain/samples/graphics/graphics/x64/Debug/graphics.elf
Entry point: 0xcb238 | Segments: 4 | Relocations: 3057 | Time: 6ms
[ps4-recomp] [2/4] Analyzing CFG and discovering reachable code...
Discovered 5264 functions, 29181 basic blocks, 207565 instructions | Time: 140ms
[ps4-recomp] [3/4] Emitting C source files to 'output_graphics/'...
Emitted 32 C source files | Time: 332ms
[ps4-recomp] [4/4] Compiling native ARM64 binary with clang (-O2, 8 workers)...
Compiled binary: output_graphics/ps4_app | Time: 33.72s
[ps4-recomp] All tasks completed successfully in 34.198s
===================================================================
[ps4-recomp] Running output_graphics/ps4_app (watchdog timeout: 4s)...
[ps4-recomp] Initializing runtime...
[ps4-recomp] Loading guest memory image (1277952 bytes), allocated dynamic address space (1090.0 MB)
[ps4-recomp] Executing _start (0xcb238)...
main: Creating a scene
main: Entering draw loop...
[videoout] Presenting frame 0 (buffer 0, 1920x1080)
[videoout] Presenting frame 1 (buffer 1, 1920x1080)
[videoout] Presenting frame 2 (buffer 0, 1920x1080)
[ps4-recomp] Watchdog timeout of 4s reached. Terminated cleanly.
The recompiler statically parses guest PlayStation 4 x86-64 ELF binaries, recovers complete control flow graphs (CFGs) and function boundaries, lifts AMD64/SIMD/AVX instructions into clean C code, and compiles the result into a native Mach-O executable using Apple Clang.
The graphics and kernel subsystems are architected natively from first principles: direct Apple Silicon Metal rendering with zero Vulkan/MoltenVK translation layers, unified memory architecture (UMA) emulation for PS4 direct video memory, and hardware VSync synchronization via native event queues.
- Native macOS
.appBundling & Clean GUI Lifecycle (pkg/cli/cli.go&pkg/runtime/ps4_metal_screen.m):- Automatically packages compiled binaries into self-contained macOS Application bundles (
<AppName>.app). - Embeds full resources (
Contents/Resources/assets,guest_image.bin,sce_sys), auto-generatesAppIcon.icns, and producesInfo.plist. - Seamless standalone execution via Finder or
open <app>.app. Clean, immediate termination via Cmd+Q, Cmd+W, Esc, or the window close button with zero lingering background processes.
- Automatically packages compiled binaries into self-contained macOS Application bundles (
- Direct Apple Silicon Metal Presentation (
pkg/runtime/ps4_metal_screen.m):- High-performance native macOS windowing (
NSWindow) and display layer (CAMetalLayer). - Native
MTLPixelFormatBGRA8Unormpipeline matching PlayStation 4 32-bit framebuffer memory layout with zero color distortion. - Zero-copy pixel presentation pipeline using
MTLCommandQueueand blit encoding.
- High-performance native macOS windowing (
- Guest VFS Path Virtualization Layer (
pkg/runtime/ps4_vfs.c):- Transparently maps PS4 guest file paths (
/app0/...,/data/...) to bundled application resources. - Supports
--app-dirCLI parameter,PS4_APP_DIRenvironment variable, or automatic executable-relative resolution.
- Transparently maps PS4 guest file paths (
- Subsystem Lifecycle Teardowns & Zero-Leak Memory Management:
- Strict resource tracking and teardowns for Direct Memory, Event Queues, VideoOut handles, Synchronization Mutex maps, and Metal display layers.
- Guest thread stack extent reclamation (
recomp_free_thread_context) on thread termination and join. - Full AddressSanitizer and LeakSanitizer (
--asan) verification.
- Direct Video Memory Manager (
pkg/runtime/ps4_direct_mem.c):- Simulates the PS4 Unified Memory Architecture (UMA) direct physical memory space.
- Implements physical block allocation (
sceKernelAllocateDirectMemory,sceKernelGetDirectMemorySize,sceKernelReleaseDirectMemory). - Page-aligned guest virtual mapping (
sceKernelMapDirectMemory) backed by the recompiler's unified address space.
- Display Output & VideoOut Subsystem (
pkg/runtime/ps4_videoout.c):- Full
libSceVideoOut.soimplementation (sceVideoOutOpen,sceVideoOutSetBufferAttribute,sceVideoOutRegisterBuffers,sceVideoOutSetFlipRate,sceVideoOutAddFlipEvent,sceVideoOutSubmitFlip,sceVideoOutGetFlipStatus). - Double and multi-buffering with hardware-synchronized flip events.
- Full
- Event Queue Subsystem (
pkg/runtime/ps4_equeue.c):- Native kernel event queue mechanism (
sceKernelCreateEqueue,sceKernelDeleteEqueue,sceKernelWaitEqueue). - Condition-variable event signaling with support for
ORBIS_KERNEL_EVFILT_VIDEO_OUTand timed waits.
- Native kernel event queue mechanism (
- ELF Loader (
pkg/elfloader): Loads ELF segments into a contiguous guest memory image, extracts static and dynamic symbols, parses.init_array, and processes ELF64 relocations (.rela.dynand.rela.plt). - Disassembler & CFG (
pkg/disasm): Recovers functions, basic blocks, indirect jump tables from.rodata, and performs backward flag liveness analysis for dead flag elimination (DFE). Function extents come from.eh_framewhenPT_GNU_EH_FRAMEis present, so a stripped RX segment that also holds unwind data and constants is not decoded as code. A user-mode-illegal opcode (IN/OUT/HLT/CLI/STI) ends that block.ps4-recomp analyzemeasures lifter coverage on this reachable CFG (the same seeds the recompiler uses), not a linear scan of RX padding, and reports unwind extents, decode-cap hits, and privileged stops. AOT also writeshle_report.txt: imported JUMP_SLOT/GLOB_DAT symbols classified against host shims and linked PRX exports, plus syscall numbers recovered from immediates in reachable code (syscall()inrdi,SYSCALLinrax). Runtimedlsymnames and register-computed syscall numbers are out of reach of this pass. - Instruction Lifter (
pkg/lifter): Modular instruction lifter translating x86-64 instructions into clean C:- 100% instruction coverage verified across all 17 OpenOrbis SDK samples (>500,000 instructions):
alu.go: Integer arithmetic, logic, bit manipulation (BSWAP,BT,BTS,BTR,BTC,POPCNT,LZCNT,TZCNT,SHLD,SHRD), CPU feature discovery (CPUID,XGETBV), and atomic hardware synchronization (LOCK XADD,CMPXCHG).simd.go: Packed SIMD arithmetic (PSUB*,PMULLW,PMULHW,PMADDWD), packing/unpacking (PACK*,PUNPCK*), element insertion/shuffling (PINSR*,PSHUF*), vector shifts (PSLL*,PSRL*,PSRA*), scalar/packed floats (ADDSD,MULSD,COMISD,COMISS,MINSD,MAXSD,SQRTSS,SQRTSD), and comprehensive 2/3/4-operand AVX/VEX instruction support.fpu.go: IEEE 754 80-bit x87 FPU stack emulation with hardware status/control words.control_flow.go: Branch prediction hints, condition code evaluation, and DWARF exception recovery.lifter.go: Core instruction dispatch loop, opcode support registry, and operand decode/read/write primitives.
- Exception Handling & Unwinding (
pkg/runtime&pkg/emitter):- Full C++ exception handling (
try,catch,throw) support without JIT. - Guest
libunwindandlibcxxabiexecute natively to parse DWARF.eh_frameunwind tables and locate landing pads. - Functions that can throw or catch register lightweight
_setjmp/_longjmpunwind frames (UnwindFrame). - Low-level resume points (
Registers_x86_64::jumpto/unw_resume) transfer control to the enclosing landing pad with proper stack pointer restoration (RSP += 8), adhering to System V AMD64 ABI conventions.
- Full C++ exception handling (
- Multi-Threading & Synchronization (
pkg/runtime/ps4_threading.c&pkg/runtime/ps4_sync.c):- Full POSIX and Orbis multi-threading runtime support with dedicated 4 MB stacks per guest thread.
- Thread lifecycle management (
pthread_create,pthread_join,pthread_detach,pthread_self,pthread_equal). - Dynamic TLS key support (
pthread_key_create,pthread_setspecific,pthread_getspecific). - Synchronization primitives: hash-table mutex map with recursive mutex support, condition variables (
wait,timedwait,signal,broadcast), reader-writer locks, and thread-safe one-time initialization (pthread_once).
- Virtual Memory Extent Allocator (
pkg/runtime/recomp_runtime.c):- Extent-based virtual memory manager for guest
mmap,munmap, andmadvise. - Page-aligned allocations, best-fit search, extent splitting, bidirectional coalescing on free, and physical host page purging via
madvise(MADV_DONTNEED).
- Extent-based virtual memory manager for guest
- System Call & Kernel ABI (
pkg/runtime/ps4_syscalls.c):- Genuine implementations replacing stubs:
fstat: Full 128-byte FreeBSD 64-bitstruct ps4_stattranslation (st_dev,st_ino,st_mode,st_nlink,st_uid,st_gid,st_rdev, timestamps,st_size,st_blocks,st_blksize).poll: Direct translation ofstruct pollfdarrays forwarded to hostpoll().ioctl: Kernel request forwarding with proper error propagation.raise&sigprocmask: Direct POSIX signal raising and 128-bitsigset_ttranslation.- Strict
errnosynchronization: All failing syscalls and shims syncerrnodirectly to guest TLS (ctx->fs_base + 0x100). - Unknown syscalls strictly return
-1witherrno = ENOSYS.
- Genuine implementations replacing stubs:
- Optimized C Emitter (
pkg/emitter):- Emits partitioned C source files for multi-threaded Clang compilation with instruction budget balancing (~15,000 instructions per chunk) to eliminate single-core compilation bottlenecks.
- Fast-path function entry: Direct fallthrough on normal function entry (
ctx->rip == addr), bypassing basic block switches. - Selective unwinding: Leaf functions skip
UnwindFrameand_setjmpoverhead completely. - Optimized flag computation: Hot integer ALU operations prune auxiliary (
af) and parity (pf) calculations.
- Audio Subsystem (
libSceAudioOutinpkg/runtime/ps4_audioout.c):- Native macOS
AudioToolbox/AudioQueuestreaming architecture for Linear PCM audio output (sceAudioOutOpen,sceAudioOutOutput,sceAudioOutClose). - Sample-accurate timing and pacing synchronized with hardware audio frames via
mach_absolute_time(), eliminating buffer underrun/overrun.
- Native macOS
- Gamepad & Input Subsystem (
libScePadinpkg/runtime/ps4_pad.m):- Native
GameController.frameworksupport for physical controllers (DualShock 4, DualSense, Xbox, Switch Pro, MFi). - Comprehensive ergonomic keyboard mapping for all controller components: Left/Right analog sticks, digital D-pad, face buttons (Cross, Circle, Square, Triangle), analog triggers (L2/R2), bumpers (L1/R1), stick clicks (L3/R3), touchpad click, and Options/Restart button (R).
- Native
- Keyboard Subsystem (
libSceKeyboardinpkg/runtime/ps4_keyboard.m):- Full
libSceKeyboardimplementation (sceKeyboardInit,sceKeyboardOpen,sceKeyboardReadState,sceKeyboardGetKey2Char,sceKeyboardGetHandle). - Hardware USB HID keycode translation and modifier state handling for PS4 guest applications.
- Full
- Bit Manipulation Instruction Sets (BMI1 / BMI2 in
pkg/lifter/bmi.go):- Full support for x86-64 BMI1 and BMI2 extensions:
BEXTR,BZHI,ANDN,BLSR,BLSMSK,BLSI,SHLX,SHRX,SARX,RORX,MULX. - Vendored and extended disassembler (
vendor/golang.org/x/arch/x86/x86asm/bmi.go) ensuring out-of-the-box decoding of modern compiler output.
- Full support for x86-64 BMI1 and BMI2 extensions:
- System Dialog Subsystem (
libSceCommonDialog&libSceMsgDialoginpkg/runtime/ps4_dialog.m):- Native Cocoa
NSAlertmodal presentation for PS4 system and user dialogs (OK,Yes/No,OK/Cancel, and custom dual-button choices). - Synchronous and asynchronous status polling (
sceMsgDialogUpdateStatus,sceMsgDialogGetResult), with automatic headless fallback for headless/CI environments.
- Native Cocoa
- Trophy Subsystem (
libSceNpTrophyinpkg/runtime/ps4_trophy.c):- Full PS4 trophy lifecycle management (
sceNpTrophyInit,sceNpTrophyCreateContext,sceNpTrophyCreateHandle,sceNpTrophyRegisterContext,sceNpTrophyUnlockTrophy). - Bitmask tracking for up to 256 trophies, platinum unlock detection, and system notifications for unlocked trophies.
- Full PS4 trophy lifecycle management (
- Dynamic PRX Module Loading (
pkg/runtime/ps4_sysmodule.c):- Implementation of
sceKernelLoadStartModuleandsceKernelDlsymsupporting runtime loading and dynamic symbol binding for external modules and libraries (.prx).
- Implementation of
- PS4 PKG Container & SFO Metadata Engine (
pkg/ps4pkg):- Full container parser for Sony
\x7fCNTformat: header decoding, entry table descriptor parsing (MetaEntry), and filename resolution viaENTRY_NAMES. - Native Sony PSF /
param.sfoparser: UTF-8 strings, 32-bit integers, and binary attributes (TITLE,TITLE_ID,APP_VER,CATEGORY,CONTENT_ID,SYSTEM_VER). - Multi-PKG Manager: recursive folder scanning, Title ID grouping (
CUSAxxxxx), automated categorization (Base Game, Patches/Updates, Add-on Content / DLCs), and overlay/patch hierarchy resolution. - Subcommands:
ps4-recomp pkg info <pkg | dir>,ps4-recomp pkg list <pkg>, andps4-recomp pkg extract <pkg> -o <out_dir>. - Extract writes
eboot.bin, PRX/SPRX modules,sce_sys, andsce_moduleby default. Pass--resources(or--all) to also dump remaining inner PFS files.
- Full container parser for Sony
- macOS running on Apple Silicon (ARM64)
- Go 1.22 or newer (the module is built with Go 1.27)
- Xcode Command Line Tools (
clang) - FreeType 2 headers and library for samples that rasterize fonts (
font,system,SDL2,threading)
go test -v ./...
golangci-lint run --no-config ./...The CLI compiles PlayStation 4 ELF binaries into native macOS .app bundles, optionally executing them with a watchdog timer (-r -t <seconds>):
Renders a high-resolution Mandelbrot fractal directly onto a native Metal window using PS4 direct video memory and flip event synchronization:
go run . tools/OpenOrbis/PS4Toolchain/samples/graphics/graphics/x64/Debug/graphics.elf -o output_graphics -r -t 4Loads /app0/assets/images/logo.png from the .app bundle via VFS, decodes compressed PNG textures, and presents frames to Metal:
go run . tools/OpenOrbis/PS4Toolchain/samples/pngdec/pngdec/x64/Debug/pngdec.elf -o output_pngdec -r -t 4Renders the DualShock 4 controller interface on Metal, receiving live button, stick, and trigger inputs from physical controllers via GameController.framework (DualShock 4, DualSense, Xbox, Switch Pro, MFi) or keyboard fallback:
go run . tools/OpenOrbis/PS4Toolchain/samples/input/input/x64/Debug/input.elf --app-dir tools/OpenOrbis/PS4Toolchain/samples/input -o output_input -r -t 4Loads /app0/assets/fonts/Gontserrat-Regular.ttf via VFS, rasterizes TrueType vector fonts at multiple sizes with FreeType 2, and renders multi-line antialiased text to Metal:
go run . tools/OpenOrbis/PS4Toolchain/samples/font/font/x64/Debug/font.elf --app-dir tools/OpenOrbis/PS4Toolchain/samples/font -o output_font -r -t 4Recompiled applications are packaged as standalone .app bundles that can be launched directly:
# Launch the native macOS app bundle directly
open output_pngdec/pngdec.app
# Or execute the binary directly from a terminal
./output_pngdec/pngdec.app/Contents/MacOS/pngdec- Quit Application: Press Cmd + Q or select Quit from the application menu.
- Close Window: Press Cmd + W, Esc, or click the red close button ⨉. The app terminates cleanly with zero lingering background processes.
Loads /app0/sce_module/libExample.prx through sceKernelLoadStartModule, resolves _Z19testLibraryFunctionPcmi with sceKernelDlsym, and prints a std::ostringstream string built inside the PRX. The PRX must live in the app's sce_module directory (map guest /app0 with --app-dir):
go run . tools/OpenOrbis/PS4Toolchain/samples/using_library/using_library/x64/Debug/using_library.elf \
--app-dir tools/OpenOrbis/PS4Toolchain/samples/using_library -o output_using_library -r -t 4
# Opened exampleLib: 1 | Jumping to 0x20020
# test string: Hi I'm from the library! You passed: 13371338 | rv = 0x00000000- Multi-Threading & Atomicity (
threading_test.elf):go run . tests/threading_test/threading_test.elf -o output_thread --asan -r -t 3 # Result: Multi-worker std::thread join, atomic LOCK XADD, 0 ASan/LSan leaks.
- C++ Exceptions & DWARF Unwinding (
exceptions.elf):go run . exceptions.elf -o output_exc -r -t 3 # Result: try/catch/throw, .eh_frame table evaluation, and landing pad dispatch.
- Memory & Compute Stress Test (
memory_stress_test.elf):go run . tests/memory_stress_test/memory_stress_test.elf -o output_mem -r -t 5 # Result: 1M prime sieve, 128x128 matrix mult, 400MB mmap extent churn.
pkg/lifter/coverage_test.go checks that every opcode in the built samples has a lifter. Live runs below used go run . <elf> -o <dir> -r -t 3..5 after the PRX / jump-table / DT_INIT stack work.
| Binary | Live run |
|---|---|
hello_world.elf |
Prints Hello world! then waits |
exceptions.elf |
C++ throw / catch, prints Testcase PASS |
tests/threading_test.elf |
Two workers, atomic counter 100 |
tests/memory_stress_test.elf |
Sieve, matmul, qsort, mmap churn |
using_library.elf |
Loads libExample.prx, prints the full library string |
graphics.elf |
Metal present loop |
pngdec.elf |
VFS PNG + Metal present loop |
input.elf |
Controller UI + Metal present loop |
keyboard.elf |
Keyboard UI + Metal present loop |
font.elf |
FreeType text + Metal present loop |
system.elf |
User service + FreeType + Metal present loop |
threading.elf |
std::thread sample + Metal present loop |
audio-wav.elf |
AudioQueue playback (watchdog clean) |
SDL2.elf |
SDL window, TTF, pad, Metal present loop |
trophies.elf |
Unlocks trophy ID 1 |
dialogs.elf |
Starts; Cocoa alert if a display is attached |
networking.elf and net_http.elf still abort (sceNet is unimplemented). piglet.elf aborts because libScePigletv2VSH.sprx / precompiled shaders are not AOT-linked.
You can customize the guest virtual address space size by setting PS4_RECOMP_MEM:
# Allocate 2 GB of guest virtual address space
PS4_RECOMP_MEM=2G perl -e 'alarm 4; exec "./output_graphics/ps4_app"'├── cmd/
│ └── ps4-recomp/ # CLI tool entry point
├── images/
│ ├── graphics_test_01.png # Initial graphics render
│ └── graphics_test_02.png # Authentic blue Metal render
├── pkg/
│ ├── cli/ # CLI driver, macOS .app packager, watchdog orchestration
│ ├── disasm/ # Disassembly, CFG recovery, indirect jump tables, flag liveness
│ ├── elfloader/ # ELF64 segment loader, symbol table parser, relocation engine
│ ├── emitter/ # Partitioned C emission, shims, parallel Clang compiler driver
│ ├── lifter/ # Modular AMD64 instruction lifter
│ │ ├── alu.go # Integer ALU, bit operations, CPUID, atomic synchronization
│ │ ├── control_flow.go # Branching, setcc, cmovcc, exception unwinding frames
│ │ ├── fpu.go # IEEE 754 80-bit x87 FPU stack emulation
│ │ ├── simd.go # Packed SIMD, vector arithmetic, AVX/VEX instructions
│ │ └── lifter.go # Instruction decoder and opcode registry
│ └── runtime/ # Native host runtime and PS4 kernel ABI
│ ├── recomp_runtime.h # Guest context, SIMD unions, extent tracking
│ ├── recomp_runtime.c # Virtual memory extent manager, flat address space
│ ├── ps4_metal_screen.h/m # Native Apple Metal CAMetalLayer & Cocoa window renderer
│ ├── ps4_direct_mem.h/c # PS4 direct physical memory allocation & UMA mapping
│ ├── ps4_videoout.h/c # libSceVideoOut buffer registration & flip events
│ ├── ps4_equeue.h/c # Kernel event queue mechanism
│ ├── ps4_vfs.h/c # Guest VFS path virtualization (/app0/ resolution)
│ ├── ps4_syscalls.c # FreeBSD/PS4 syscall shims, signals, errno sync
│ ├── ps4_threading.c # Guest thread lifecycle, stacks, TLS keys
│ └── ps4_sync.c # Mutexes, condition variables, rwlocks, pthread_once
├── tests/
│ ├── threading_test/ # Multi-threaded C++ testcase
│ └── memory_stress_test/ # Compute and virtual memory stress testcase
├── hello_world.elf # Testcase 1: Standard I/O, usleep, global initializers
└── exceptions.elf # Testcase 2: C++ throw/catch, DWARF unwinding, stringstream
This project is licensed under the GNU General Public License version 2. See LICENSE.
Work on the loader, NID hashing, and sample binaries follows formats and tools published by other projects:
- OpenOrbis PS4 Toolchain — SDK samples used as live test binaries,
create-fself, and the Sony NID hash (SHA-1(name ‖ 518D64A635DED8C1E6B039B1C3E55230)). - golang.org/x/arch — x86-64 decoder; BMI1/BMI2 opcodes are extended in
vendor/golang.org/x/arch/x86/x86asm. - musl and LLVM libc++ — the C and C++ runtimes statically linked into OpenOrbis ELF/PRX images that the recompiler executes as guest code.
- FreeType — host rasterizer behind the
FT_*shims for font samples. - Apple Metal, Cocoa, GameController, and AudioToolbox — native presentation, input, and audio used by the runtime instead of a Vulkan translation layer.
- Community documentation of Sony
\x7fCNTPKG, PFS/PFSC, SELF (0x1D3D154F), andPT_SCE_*program headers, as implemented inpkg/ps4pkgandpkg/elfloader.
