ZOYKUHot Board

sp00nznet/ps3recompDocumentazione

sp00nznet/ps3recomp open-source repository on GitHub

Nota sulla lingua:Documentazione tradotta non disponibile. Visualizzazione dell'originale ufficiale in inglese.
Installazione rapida
git clone https://github.com/sp00nznet/ps3recomp.git

ps3recomp

Because the Cell processor deserves a second life

Static recompilation runtime libraries for PlayStation 3 titles. Turn PS3 binaries into native executables. No emulator required.

Join the sp00nznet recomp Discord — the community hub for sp00nznet's recomp projects, where ps3recomp development happens in the open. Good place to ask questions, show a port you are working on, or find out what people are stuck on before you duplicate the effort.


What Is This?

ps3recomp is an open-source toolkit that provides the runtime libraries, system stubs, and analysis tools needed to statically recompile PlayStation 3 games into native PC executables.

Instead of interpreting or dynamically recompiling PowerPC/SPU instructions at runtime (what emulators like RPCS3 do brilliantly), we take the opposite approach: translate everything ahead of time into C/C++ that compiles with your favorite compiler on any modern platform.

This is the same philosophy behind:

...but for the PS3's glorious, terrifying Cell Broadband Engine.

Why PS3?

The PlayStation 3 has over 3,000 titles and some of the most beloved games ever made. RPCS3 has done heroic work making ~70% of the library playable through emulation, but static recompilation offers something different:

  • Native performance — no runtime translation overhead
  • Lower hardware requirements — runs on mid-range PCs
  • Moddability — recompiled C/C++ is infinitely more hackable than PPC binaries
  • Preservation — native ports survive long after emulators stop being maintained
  • Portability — the output is C/C++, so it can target any platform a compiler does (see platform support for where the runtime actually stands today)

Platform support

CI builds and tests every row on every pull request: Windows (clang-cl), macOS arm64, Linux (GCC and Clang), and Linux with the Vulkan backend on lavapipe under the validation layer. A green check means the runtime built and the tests passed. It does not mean a game ran; the last row is the only one that claims that.

Windows macOS (arm64) Linux
Runtime library builds yes yes yes
Lifter test suites + C unit tests yes yes yes
Render backend D3D12 Metal Vulkan (opt-in); null (headless, CI)
Runs a recompiled game, in this tree yes no no

The POSIX boot path runs in CI, but not yet with a retail title in this tree. ps3recomp_boot_smoke loads a synthetic PPU ELF through ppu_loader.cpp, the HLE dispatch, guest threads, the frame clock and the renderer. CI also builds and boots that ELF through templates/project on macOS and Linux. That proves the per-game scaffold runs on both hosts; it is not a compatibility claim for a retail game.

The renderers are further along than that. ps3recomp_host drives cellGcm → RSX → backend end to end with no game. With guest programs on, Metal and Vulkan both run the title's own shaders on the shared register-file draw engine. Every ps3recomp_host scene passes on both, including render-to-texture, MRT, depth textures, cube maps and stencil. Linux's default stays the headless null backend, a CPU triangle filler that CI draws with.

Downstream, people are already past this. Twisted Metal's menus run on Linux/Vulkan, inFamous on macOS, and Killzone 3 under Proton (see In the community). Those ports carry patches that are still on their way upstream, which is why the table still says "no".

The Challenge

The PS3's Cell processor is a beast unlike anything else:

Component What It Is Why It's Hard
PPU PowerPC 64-bit main CPU Custom ISA extensions, VMX/AltiVec SIMD
6x SPU 128-bit SIMD vector processors Proprietary ISA, 256KB local store, explicit DMA
Memory 256MB XDR RAM 128-byte alignment requirements, split bus
LV2 Kernel Proprietary OS layer ~300+ system calls, complex threading model
PRX Modules Dynamic libraries 100+ system libraries with intricate interdependencies

We don't shy away from hard problems. We just break them into smaller ones.

Architecture

ps3recomp/
├── tools/                    # Binary analysis & recompilation pipeline
│   ├── elf_parser.py         # Parse PS3 ELF/SELF/PRX binaries
│   ├── ppu_disasm.py         # PowerPC disassembler with PS3 extensions
│   ├── ppu_lifter.py         # PPU assembly -> C code lifter
│   ├── spu_disasm.py         # SPU instruction set disassembler
│   ├── spu_lifter.py         # SPU assembly -> C code lifter
│   ├── extract_spu_images.py # Extract embedded SPU images from PRX/ELF
│   ├── find_spu_functions.py # SPU function boundary detection
│   ├── wrap_spu_elf.py       # Wrap a raw SPU blob as a loadable ELF
│   ├── prx_analyzer.py       # Analyze PRX imports/exports and NIDs
│   ├── nid_database.py       # Function Name ID (NID) resolver
│   ├── find_functions.py     # Function boundary detection
│   └── generate_stubs.py     # Generate HLE stub skeletons from a NID list
│
├── runtime/                  # Core runtime for recompiled executables
│   ├── ppu/                  # PPU execution context
│   │   ├── ppu_context.h     # Register file, CR, LR, CTR, FPSCR
│   │   ├── ppu_memory.h      # Memory access macros (loads, stores, byte-swap)
│   │   └── ppu_ops.h         # Instruction operation macros
│   ├── spu/                  # SPU execution context
│   │   ├── spu_context.h     # 128×128-bit register file, 256KB local store, image_id
│   │   ├── spu_channels.c    # Channel ops + per-image function-table dispatch
│   │   ├── spu_helpers.h     # SPU intrinsics (incl. float conversions)
│   │   ├── spu_dma.h         # DMA (MFC) transfer engine
│   │   └── tests/            # Self-contained SPU runtime tests
│   ├── memory/               # Memory subsystem
│   │   └── vm.h              # Virtual memory manager (256MB address space)
│   └── syscalls/             # LV2 kernel system call implementations
│       ├── sys_ppu_thread.h  # Thread creation/management
│       ├── sys_mutex.h       # Mutex/cond synchronization
│       ├── sys_memory.h      # Memory allocation/mapping
│       ├── sys_fs.h          # Filesystem operations
│       └── lv2_syscall_table.h # Full syscall dispatch table
│
├── libs/                     # HLE library implementations
│   ├── audio/                # cellAudio, cellAdec, libmixer, libsnd3, libsynth2
│   ├── video/                # cellGcmSys, cellResc, cellVideoOut, cellVpost, cellVdec
│   ├── input/                # cellPad, cellKb, cellMouse
│   ├── hardware/             # cellGem, cellCamera, cellUsbd
│   ├── network/              # cellNetCtl, cellHttp, cellHttps, cellSsl, sceNp*
│   ├── filesystem/           # cellFs, cellGame, cellSaveData, cellStorage
│   ├── system/               # cellSysutil, cellSysmodule, cellRtc, sysPrxForUser
│   ├── spurs/                # cellSpurs, cellFiber, cellSpursJq, cellDaisy (SPU task management)
│   ├── sync/                 # cellSync, cellSync2 (cross-PPU/SPU synchronization)
│   ├── codec/                # cellJpgDec, cellPngDec, cellGifDec, cellPamf, cellDmux, cellAdecAtrac3p, cellAdecCelp8, cellVdecDivx
│   ├── font/                 # cellFont, cellFontFT, cellFreeType, cellL10n
│   └── misc/                 # cellScreenshot, cellSubdisplay, cellImeJp, cellVideoExport, cellMusicExport, cellGameRecording, etc.
│
├── include/ps3emu/           # Public API headers
│   ├── ps3types.h            # Fundamental PS3 types (u8-u128, s8-s64, be_t<>)
│   ├── endian.h              # Big-endian <-> little-endian conversion
│   ├── nid.h                 # NID hashing and lookup
│   ├── module.h              # Module registration framework
│   └── error_codes.h         # PS3 system error codes (CELL_OK, CELL_E*)
│
├── templates/project/        # Starter template for new game ports
│   ├── CMakeLists.txt        # Build system
│   ├── main.cpp              # Application entry point
│   ├── stubs.cpp             # Game-specific function overrides
│   └── config.toml           # Recompiler configuration
│
├── config/                   # Reference configurations
│   └── example.toml          # Example recompilation config
│
└── docs/                     # See the Documentation table below

How It Works

The pipeline follows the same proven approach as our burnout3 project, adapted for the Cell architecture:

   PS3 Game Disc / PKG
         │
         ▼
   ┌─────────────┐
   │  SELF/EBOOT  │  Encrypted PS3 executable
   │  Decryption  │  (requires keys / fSELF)
   └──────┬──────┘
          │
          ▼
   ┌─────────────┐
   │  ELF Parser  │  Extract sections, segments, relocations
   │  + PRX Scan  │  Identify imported NIDs & library deps
   └──────┬──────┘
          │
          ▼
   ┌─────────────┐
   │  PPU Disasm  │  Disassemble PowerPC 64-bit + VMX
   │  + Analysis  │  Function boundaries, jump tables, ABI
   └──────┬──────┘
          │
          ▼
   ┌─────────────┐
   │  PPU Lifter  │  PowerPC → C code generation
   │  + SPU Lift  │  SPU programs → C code generation
   └──────┬──────┘
          │
          ▼
   ┌─────────────┐
   │  Link with   │  ps3recomp runtime + HLE libs
   │  Runtime     │  Provides all PS3 OS services
   └──────┬──────┘
          │
          ▼
   ┌─────────────┐
   │  Compile &   │  MSVC / GCC / Clang
   │  Ship!       │  Native x86-64 executable
   └─────────────┘

SPU Strategy

The SPU is the elephant in the room. Each SPU has its own instruction set, its own 256KB memory, and communicates with the PPU via DMA and mailbox channels. Our approach:

  1. SPU programs are self-contained — they live in ELF segments loaded to local store (extract_spu_images.py pulls them out of PRX/ELF)
  2. Recompile each SPU program separately — dedicated spu_disasm.py + spu_lifter.py handle the SPU ISA
  3. SPU local store becomes an array — 256KB per "virtual SPU"
  4. DMA operations become memcpy — via the MFC engine (spu_dma.h)
  5. Channels become cross-thread message queues — preserving ordering guarantees
  6. Per-image function-table dispatch — image_id lets multiple SPU programs (e.g. a SPURS kernel, a policy module, and a job) coexist at overlapping local-store addresses

This mirrors how RPCS3 handles SPU but at compile time rather than runtime. The disassembler, lifter, and runtime are functional and covered by self-contained tests (runtime/spu/tests/: sum, shufb, DMA, brsl-return).

Module Status

HLE implementations of the PS3 system libraries, written for this project. RPCS3 is a behavioural reference, not a code source. Most modules are complete. The ones still marked Partial are the media decoders (cellVdec, cellAdec, cellDmux, cellAtrac, cellAdecAtrac3p) and cellSpurs. docs/MODULE_STATUS.md has one row per module and is the source for the counts.

Category Modules Status
Kernel Threading sys_ppu_thread, sys_mutex, sys_cond, sys_semaphore, sys_rwlock ✅ Complete
Kernel Events sys_event (queues, ports, flags), sys_timer ✅ Complete
Kernel Memory sys_memory, sys_mmapper (containers, shared mem) ✅ Complete
Kernel Filesystem sys_fs (path mapping, real I/O) ✅ Complete
Filesystem cellFs (real file I/O, dir ops, stat, path translation) ✅ Complete
Save System cellSaveData (callback-driven, PARAM.SFO), cellGame ✅ Complete
Input cellPad (XInput/SDL2), cellKb, cellMouse ✅ Complete
Audio cellAudio (WASAPI/SDL2, mixing thread, multi-port) ✅ Complete
Video Output cellVideoOut (resolution config, 720p default) ✅ Complete
Codecs cellPngDec, cellJpgDec, cellGifDec (stb_image) ✅ Complete
Font cellFont (stb_truetype backend + fallback metrics) ✅ Complete
Network sys_net (BSD sockets, P2P), cellNet, cellNetCtl, cellHttpUtil, cellSsl, sceNp*, sceNpTrophy, sceNpMatching2 + Score over psnr ✅ Complete
Hardware cellUsbd (USB), cellCamera (PS Eye), cellGem (PS Move) — stub, no devices ✅ Complete
Sync cellSync (atomic spinlocks, LF queue), cellSync2 (OS-backed) ✅ Complete
System cellRtc, cellMsgDialog, cellOskDialog, cellUserInfo, cellGameExec ✅ Complete
Localization cellL10n (UTF-8/16/32/UCS-2, ISO-8859-1, generic converter) ✅ Complete
Resolution cellResc (display modes, scaling, interlace, aspect ratio) ✅ Complete
Fibers cellFiber (PPU fiber scheduler via Windows Fibers/ucontext) ✅ Complete
AV Config cellAvconfExt (audio output info, gamma, sound availability) ✅ Complete
Input Util cellKey2char (HID scancode → Unicode, US-101 layout) ✅ Complete
Graphics cellGcmSys (cmd buffer, IO mapping, tile/zcull, flip handlers, timestamps, FIFO walker + ring recycle), RSX command processor (NV47xx parsing, state tracking, backend callbacks), live D3D12 backend (executes the title's real NV4097 vertex/fragment programs — indexed draws, per-draw VP constants + textures, render-to-texture, MRT, FP predication), null backend (Win32 window) ✅ Complete
SPURS cellSpurs (management APIs, event flags, task/workload tracking), cellSpursJq (job queues with wait/signal), cellDaisy (real ring buffer FIFO) ✅ Complete
Core Runtime cellSysutil (BGM, cache, disc), cellSysmodule, sysPrxForUser (real lwmutex/lwcond/threads) ✅ Complete
Media Pipeline cellPamf (PAMF header + stream descriptors), cellDmux (callback sequencing), cellVdec (H.264/MPEG-2 through FFmpeg loaded at run time, opt-in), cellAtrac (ATRAC3plus, all-in-memory), cellAdec (callbacks, no decode yet), cellSail (state machine) 🔨 Partial
HTTP/HTTPS cellHttp (real HTTP/1.1 via native sockets), cellHttps (TLS stub with cert management) ✅ Complete
Misc/Export cellSubdisplay, cellImeJp, cellVideoExport, cellMusicExport, cellPhotoExport/Import, cellGameRecording, cellPrint, cellRemotePlay ✅ Complete

Full status tracking: docs/MODULE_STATUS.md

Documentation

We've written extensive docs covering every aspect of the project. Whether you're contributing, porting a game, or just trying to understand how PS3 static recompilation works, there's a doc for you.

Document What It Covers
Getting Started Prerequisites, installation, first recompilation walkthrough
Architecture Cell processor overview, recomp pipeline stages, memory model, comparison with RPCS3
Building CMake build system, compiler support, platform-specific notes, troubleshooting
Game Porting Guide Full 12-phase walkthrough for porting a PS3 game — with flOw case study
Custom Modules Step-by-step tutorial for writing new HLE modules — NID system, calling convention bridge, patterns
FAQ & Troubleshooting Common questions, build errors, runtime crashes, lifter issues, performance tips
Contributing Development setup, code style, PR guidelines, ways to contribute
Runtime Reference Virtual memory manager, PPU/SPU execution contexts, type system, endianness, syscall dispatch, DMA engine
Syscall Reference All LV2 kernel syscalls: threading, sync, events, timers, memory, filesystem
NID System How PS3 function linking works, NID computation, module registration framework
Module Reference Detailed documentation for every HLE module — what they do and how they're implemented
Module Status Quick-reference status table for all modules
RSX Graphics RSX GPU translation architecture: command processor, D3D12 and Metal backends, shader strategy
Tools Reference Every recompiler pipeline tool documented: ELF parser, disassembler, lifter, NID database
SPU Lifter SPU ISA decoding/lifting, the runtime model (local store, channels, DMA, per-image dispatch), and the SPU tests
Platform Abstraction How we handle Win32 vs POSIX: threading, sockets, timers, audio, memory, fibers
SPU Fallback The PPU-side fallback registry — a hand-written replacement for an SPU job, or a bring-up shim before an image is lifted
Debug Console Ask a title that is already running what it is doing, without a rebuild
Runtime Diagnostics Generated index of every diagnostic environment variable the runtime reads
Prototype & Debug Builds Why unencrypted, symbol-bearing prototype builds are the pipeline's ground truth
Online Play Matchmaking, leaderboards and P2P play through a psnr server — --psnr host --username NAME
Regression Gate How five ports are checked against recorded goldens before a shared-runtime change lands — and how to tell a real red from the four kinds of measurement artefact

Getting Started

Downloads: each release includes a prebuilt SDK bundle per platform (ps3recomp-<version>-win-x64.zip, -mac-arm64.zip, -linux-x64.zip) plus SHA256SUMS.txt. A bundle contains the runtime library, its headers and the Python pipeline. VERSION.txt inside it says what that platform can and cannot do yet.

Prerequisites (building from source): Python 3.10+ (CI uses 3.12), CMake 3.20+, Ninja, and a C17/C++20 compiler: clang-cl with Visual Studio 2022 on Windows (plain MSVC builds the runtime library, but lifted game code needs clang-cl), GCC or Clang on Linux, Apple Clang (Xcode) on macOS. SDL2 is required on Linux and macOS. On macOS, install the command-line dependencies with brew install cmake ninja [email protected] sdl2. CI builds with the compilers on GitHub's windows-latest, ubuntu-latest and macos-14 runner images; no older compiler version is tested.

git clone https://github.com/sp00nznet/ps3recomp.git
cd ps3recomp
# macOS (on Linux, use: python3 -m venv .venv)
"$(brew --prefix [email protected])/bin/python3.12" -m venv .venv
source .venv/bin/activate
python -m pip install -r requirements.txt

# Stage 1: image, OPD function table, TOC and firmware imports
python tools/ppu_loader.py /path/to/EBOOT.ELF -o out/

# Stage 2: lift to C++. --hle-stubs turns each firmware import stub into
# ps3_hle_call(nid); leave it out and the first import call crashes the port.
python tools/ppu_lifter.py /path/to/EBOOT.ELF \
    --functions out/EBOOT.functions.json \
    --hle-stubs out/EBOOT.imports.json \
    --output templates/project/recompiled/

# Stage 3: the NID -> HLE handler table, next to the lifted code
python tools/gen_hle_nids.py --all --out templates/project/recompiled/ppu_hle_nids.cpp

# Build the port from the template (RECOMP_DIR defaults to ./recompiled)
cd templates/project
cmake -B build -G Ninja
cmake --build build

See docs/GETTING_STARTED.md for the full walkthrough.

Game Ports Using ps3recomp

Status as of 2026-10-12. Each port's own README carries the live detail and the run recipe.

In game

Game Title ID Status Repo
The Simpsons Arcade Game (Konami) NPUB30563 Playable, and playable online. Boots through the Konami intro and character select into Stage 1, Downtown Springfield, with its ATRAC3plus music (#186) and correct flashes and glyphs (#185). Two players meet over psnr and play a match together: lobby, character select, the host's game setup, then Stage 1 in sync on both machines with each player's input moving their character on both screens — including with one player behind a NAT, through psnr's relay (#200, see docs/ONLINE.md). A Konami arcade emulator EBOOT: the 1991 coin-op ROM lives in SIMPSONS.SR and the binary emulates the hardware around it sp00nznet/simpsonsarcade-ps3
Tornado Outbreak (Loose Cannon / Konami) BLUS30371 In game, rendering correctly with no per-title overrides. Logos and Bink intro, title, main menu, New Game (the save is created), the story intro and dialogue, then the first level under stick control at ~10–16 fps. The runtime fixes it needed — raw-SPU proxy DMA, vertex-program flow control, GPU resolve copies — are shared (#189) sp00nznet/tornado

The Simpsons Arcade Game, Stage 1 Tornado Outbreak in the farmers' market

Earlier ports

Not under active development; they are where much of the runtime was first proven, and several stay in the regression gate.

Game Title ID Where it got to Repo
Virtua Fighter 5 (Sega AM2) BLUS30020 Renders its NOW LOADING, CRIWARE and AM2 screens; zero SPURS and zero PSN imports sp00nznet/vf5
Tokyo Jungle (Crispy's/SCE Japan) NPUA80523 Data install, SPURS jobs, title screen and the main menus sp00nznet/tokyojungle
You Don't Know Jack (Jellyvision/THQ) BLUS30569 Menus and answerable quiz questions; movie-backed screens still draw noise sp00nznet/youdontknowjack
Twisted Metal (Eat Sleep Play) BCUS98106 Drove the live NV4097 engine (#113); boots real game code and its asset install sp00nznet/twistedmetal
flOw (thatgamecompany) NPUA80001 First draws with the real libsre.prx; assets load sp00nznet/flow
Rubber Ducky (Sony E3 2006 demo) NPEA00003 A debug build with full symbols — the lifter's ground truth, not a game target sp00nznet/rubberducky

In the community

Ports other people are running on ps3recomp, whose fixes come back upstream:

  • inFamous (@NoahBPeterson): in game on macOS/arm64 at around 13 fps, booting on Sony's own liblv2 and libsre (LLE). Its exact SPU float and VMX work landed in v0.15.0 (#286, #287), and @erikomis's inFAMOUS 2 bring-up on the same branch sent six fixes (#311-#316).
  • Twisted Metal (@Kurtisone): menus on Linux/Vulkan, the deferred renderer's lighting and post-FX included. Most of v0.14.0's draw-engine and Vulkan work came out of this port.
  • Killzone 3 (@undecuple): all nine chapters load and run five minutes of scripted play, and one chapter has been played by hand to its end (Windows build, run under Proton). Its general fixes went upstream through #214 and the PRs that followed it.
  • LittleBigPlanet (@sagemono), Yakuza: Dead Souls (@canersaka), God of War II HD and Ben 10 Omniverse (@andrebrumdev), and DBZ Budokai HD (@gnome41).

Ask in the Discord to get yours listed.

Want to port a game? Start with the Getting Started section, check docs/MODULE_STATUS.md for system library coverage, and see the Game Porting Guide for a real-world walkthrough.

Relationship to Other Projects

Project Role
RPCS3 Our primary reference for HLE module behavior and system call semantics. Standing on the shoulders of giants.
XenonRecomp PowerPC recompiler for Xbox 360. Same ISA family and the same approach; our lifter is our own.
N64Recomp Pioneered the modern static recomp approach. Our architecture follows the same "recompile to C, link with runtime" philosophy.
PS2Recomp Sibling project for PS2. Different ISA (MIPS vs PowerPC) but same spirit.
ReXGlue The closest sibling this project has: a static recompilation SDK for the Xbox 360, turning PowerPC into portable C++ compiled ahead of time rather than interpreted. Same shape as ps3recomp — a toolkit plus a runtime, with game ports built on top — and a generation of Xenon hardware away from Cell. Their release engineering covers five platforms from one reusable build workflow, with nightlies and tagged releases that publish artifacts.
pcrecomp Our PC recompilation toolkit. Shared philosophy of "analyze → disassemble → lift → link → ship".

Building Blocks We Leverage

  • RPCS3: a behavioural reference for HLE modules and syscalls. We read what it does and then write our own. No RPCS3 (GPL) code belongs in this tree.
  • Direct3D 12 / Metal / Vulkan: RSX graphics translation. D3D12 is the backend that runs games in this tree today. Metal (macOS) and Vulkan (Linux, opt-in, see docs/BUILDING.md) run guest shaders on the shared draw engine. CI draws with the headless null backend.
  • SDL2: input and audio off Windows. cellPad and cellAudio always use their SDL2 backends on non-Windows hosts, so SDL2 is required there; on Windows they use XInput and WASAPI. SDL2 does no windowing here; each graphics backend makes its own.
  • FFmpeg (optional, loaded at run time): video decode for cellVdec and ATRAC3plus for cellAtrac. It is never linked and never vendored.

Contributing

This is a massive undertaking and we need help. Here's how to get involved:

  • HLE Module Authors — Fill in the partial modules (media decode, SPURS edge cases) from documented behaviour
  • PPU/SPU Experts — Improve the disassembler and lifter accuracy
  • Graphics Engineers — Bring Metal and Vulkan to D3D12 parity, then run a title on them
  • Game Testers — Try recompiling titles and report what breaks
  • Documentation — Help us map out the PS3's system library landscape

See CONTRIBUTING.md for guidelines.

Not sure where to start, or want to sanity-check an idea first? Ask in the Discord — several of the people working on ports and on the lifter are there.

This project does not contain any proprietary Sony code, firmware, encryption keys, or copyrighted material (docs/FIRMWARE_LLE.md explains how LLE works without shipping firmware). It provides clean-room implementations of system library interfaces based on publicly documented behavior. You must provide your own legally obtained PS3 game files.

Contributors are credited in CONTRIBUTORS.md.

License

MIT License. See LICENSE for details.

ps3recomp was created by Ned Heller (@sp00nznet). Ports, videos and write-ups built on it are welcome. Please name ps3recomp and link this repository, and keep the copyright notice in LICENSE, which the MIT licence requires.

Changelog

v0.19.0 — "Eighty-One" (November 2026)

81 pull requests from fourteen contributors, merged in #696. Six of them are here for the first time. Most of the batch comes from ports in progress: God of War HD and Ascension drive the SPURS, GCM and SPU work, a SoulCalibur II HD port drives the main-memory tiles and the macOS window, and a lv2 conformance pass brings the sync, event, file and SPU-group syscalls closer to the SDK.

RSX and graphics

  • Tiles over main memory (@n0madic, #569): a tile bound with location MAIN is now tiled for every RSX access, as on the hardware, rather than read and written linearly. Block-compressed (DXT) 3D textures go up as volumes, in NVIDIA's VTC slice order (#585), and a recreated depth target's snapshot is released once (#604).
  • GCM (@rigaz29): GCM_FIFO_SEGMENT=<bytes> hands the command ring out in segments, as libgcm does, so the walker can start on a frame while the title is still writing it (#566; unset, nothing changes). Offset tables follow later maps and unmaps, a report is held until the SPU task round it signals has caught up, FP helpers are emitted on branched programs, and X16 and DDX/DDY are handled (#635). The FIFO walker decodes the new-style JUMP (@undecuple, #675), and the tile and zcull call lines print only in verbose mode (#676). The context end sits at the wrap JUMP slot, begin + size - 4 (@MatRanc, new, #648), and GCM_HANDLER_THREAD=1 delivers handlers from a dedicated thread (#647). cellGcmGetConfiguration reports 249 MiB of local memory, which fits a 28-bit heap size field (@StepanovGV2021, new, #660).
  • D3D12 (@DriifterSelf, new): descriptor ranges cover all 16 texture units, the offscreen target limit goes from 16 to 64, linear texture row pitch is tracked, and D3D12_NO_DBG turns off the debug layer (#600). QUAD_STRIP and POLYGON draw (#617), and unnormalized texture scaling reaches the fragment-program pipeline (#618). Both renderers pick the high-performance adapter, with a WARP fallback (@undecuple, #669), and a frame with no RSX commands presents the CPU-blit scanout (@xuxinsss, #695).
  • Metal: PS3_AA=smaa (SMAA 1x), PS3_VIBRANCE and PS3_CONTRAST in the present pass, all off by default (@erikomis, #470). The depth-bounds test is emulated where the backend has none (#694), and the MSL cache names the translator by a hash of its sources (@n0madic, #609).
  • Vulkan (@tekulvw): R32F and RGBA32F colour targets (#681), and stale engine releases kept off live objects (#682).
  • Draw engine and decompilers: SET_ZMIN_MAX_CONTROL's depth clamp is honoured (@erikomis, #693), explicit current vertex colours are preserved (@tekulvw, #658), missing vertex attribute components expand with w = 1.0 (@DriifterSelf, #597), and fragment programs honour the per-source input precision modifiers (@undecuple, #670).

SPU and SPURS

  • SPURS (@rigaz29, #629): CellSpurs2 with 32 workloads, cellSpursInitializeWithAttribute2, Taskset2 and Task2, and tasks an SPU creates. These were faked as CELL_OK or stopped at 16 workloads before. argTaskset is carried through the taskset attribute (@MatRanc, #643), maxContention is clamped and cellSpursRequestIdleSpu implemented (#649), and SPURS_IDLE_MAX caps the kernel's idle back-off, default unchanged (@MaChInEgUn3, #659).
  • Relocatable lifts (@MaChInEgUn3, #636): spu_lifter.py --reloc lifts position-independent SPU code once and runs it wherever a title copies it in local store.
  • Faster paths: quadword LS access as one load or store plus a word-swap pshufb on SSSE3 x86 (SPU_LS_VEC, #637); MFC parameter channel writes latch without a mfc_for lookup (#626); the lock-line spin sleeps after about 1 ms (#666), and the holder list is a contiguous, prefetched array (#672) (all @MaChInEgUn3). NEON fi and cflts on ARM64 (@tekulvw, #677) and a four-lane SSE4.1 form of the single-precision helpers (#683). The interpreter decodes through one 2048-entry table indexed by insn >> 21, generated by tools/gen_spu_interp.py (@mmkzer0, new, #688).
  • Channels (@MaxLeiter, new, #619): ordered wakeups, a masked RdEventStat, a word-sized SRR0 and an aligned atomic LSA. Address-only overlay registries reject unrelated large GETs (@tekulvw, #654).

PPU and lv2

  • Conformance (@MaxLeiter): sync primitives — trylock EDEADLK, timeouts, rwlock timed locks and destroy rules, lwmutex EBUSY (#621); event queue destroy honours its mode, and a timed receive runs to an absolute deadline (#622); the Windows join no longer frees the slot under the exiting thread (#623); SPU thread group destroy, start state and error returns (#624); HLE heap delete_heap and bounds, and the boot window's close quits through ps3_host_quit (#625). A contended sys_lwmutex_trylock returns CELL_EBUSY (@ohkora, new, #684).
  • Threads (@tekulvw): the executable's primary thread priority is honoured (#651), and completed callbacks are told apart from missing dispatch (#652). The main thread's stack address and size are filled in after it registers (@xuxinsss, #596).
  • Lifter and loader: the module TOC is recovered from the OPD majority when there is no .got section name (@xuxinsss, #691). Per-thread caches for HLE NID lookups, profiler breadcrumbs and indirect-call targets, and exact VMX converts (@rigaz29, #634). vmaddfp/vnmsubfp without a libm call per lane (@undecuple, #674).
  • sys_memory_container_get_size returns the right value, and syscall 350 is registered (@MatRanc, #644).

HLE libraries

  • Files: SDK open flags and error codes in sys_fs, and EBADF/EMFILE/EINVAL, file times and dot entries in cellFs (@MaxLeiter, #620). cellFsAioWrite (@MatRanc, #641) and cellFsFtruncate on the active fd table (#645). PS3_DEV_FLASH may name several roots (@n0madic, #605).
  • Audio and media: cellAdec decodes AC3 through the run-time FFmpeg loader (@undecuple, #671); cellAudio's AUDIO_WAV and AUDIO_PEAK work on the POSIX mix thread, and AUDIO_RATE has no holes (@n0madic, #606); PS3RECOMP_ATRAC_LGPL=OFF links a stub in place of the LGPL decoder (#611). cellPamf reader calls on an uninitialised reader return INVALID_ARG (@ohkora, #685), and Sail keeps its allocator argument (@tekulvw, #653).
  • System and network: cellGame reports 40 GiB − 256 KiB free above 4 GiB, so hddFreeSizeKB * 1024 cannot wrap (@erikomis, #692). cellVideoOut reports stereoscopic 3D resolutions unavailable (@MatRanc, #642). cellSysutilNpEulaCheck legacy stub (@DriifterSelf, #616). sceNp answers presence details and entitlement lists offline (@tekulvw, #679); sceNpSignaling gives connections for Matching2 room members, with context ids from 1 and ActivateConnection (@undecuple, #690); cellSysutilAvc2 exports Load, Unload and the setters (#689). cellVoice's port functions cite their SDK references (@tekulvw, #487).
  • Input: the keyboard fallback on pad port 0 works on macOS and with SDL (@n0madic, #612).

Platforms and build

  • macOS (@n0madic): a Quit item in the app menu and no alert sound on a key press (#613); a resizable window that keeps the aspect ratio, and PS3RECOMP_FULLSCREEN (#614). Apple Silicon setup docs match CI (@Tzeentchnet, #656), walker profiling is bounded by elapsed time (#657), and CI runs on macos-15 (@tekulvw, #680).
  • MinGW: ppu_loader builds with GCC (@n0madic, #610); header-defined shared data uses selectany, and timespec_get works on msvcrt (@undecuple, #668).
  • Linux: the templates use the Vulkan backend when it is built (@MatRanc, #640).
  • The runtime exports its probed SSE4.1 requirement to consumers (@tekulvw, #678).

Tooling and tests

  • ps3_env_once() looks an environment switch up once per name, and replaces the getenv calls on the SPURS job, workload dispatch and cellFs paths (@erikomis, #515).
  • test_trophy_registration (#607) and test_gcm_flip_status (#608) link and run in CI again (@n0madic). sync_stress takes tick differences modulo 2^32, so it passes after 24.8 days of host uptime (@undecuple, #627).

Known issue

  • You Don't Know Jack's boot hang from v0.18.0 is unchanged: v0.18.0 and this release reach the same point on the regression gate. The other four gate ports match v0.18.0 too.

v0.18.0 — "One Hundred Fifty-Five" (October 2026)

155 pull requests, 152 of them from ten contributors, merged in #594. The biggest batch so far, and a different shape from the last few: less of it comes from one port and more of it is platform work that every port gets. D3D12 and Metal both grow a real pipeline cache, raw SPUs run on macOS and Linux, the SPU helpers gain SSE4.1/AVX2 and exact NEON paths, and the diagnostics that had crept into the hot loops are now all behind gates.

RSX and graphics

  • D3D12 (@rigaz29, new): indexed triangle lists are drawn with their own indices (#530); guest depth/stencil state and samplers are folded into the guest-FP pipelines (#558), with depth surfaces per zeta offset that are readable as textures and FP depth export (#559). Guest textures stage through a shared upload ring with least-recently-used slots (#579), vertices are converted once per draw (#518), and a small batch can be held back across two flips (#583). The texture-slot SRVs that were overwriting the SRV heap are gone (#557). New D3D12_VSYNC=0 (#575) and on-demand RenderDoc capture with resources named in guest terms (#561). Duplicate clear-presented flips are skipped, and only those (@Tzeentchnet, new, #486).
  • Metal (@erikomis unless noted): HLSL→MSL translations are cached in memory and optionally on disk (#511), a vertex program's position invariant compiles (#563), SET_TEXTURE_BORDER_COLOR is honoured in the sampler (#476), and the staging arena records into a pooled MTLBuffer (@tekulvw, #440) with one reused buffer for depth readback (#461).
  • Vulkan: per-target colour mask and blend enable for MRT sets (#516); VK_DRAW_BATCH=1 records engine draws, snapshots, uploads and clears into a single submission (@MaChInEgUn3, #532), with readback staging reused and changed textures refreshed in place (#552).
  • Draw engine: a scissored CLEAR_SURFACE clears only the scissor (#560), user clip planes are honoured (#537), and so is the polygon offset (#562). A depth read as a texture converts on the GPU, with eviction from full surface/zeta tables (@n0madic, #499); a depth snapshot is the region the texture names (#507) and a stale one is released (#502). A compressed texture is never a render target's output (#508). A larger surface is reused only on the same sample grid (@tekulvw, #422), each texture key remembers where it was last found (#438), engine-rewritten textures upload without a full hash (#439), the per-draw pipeline key is cheaper (#459), index runs append in one pass (#465), and the depth-to-guest row conversion vectorizes (#460).
  • Decompilers and vertex fetch: shadow compare is depth FUNC reference, not the reverse (@n0madic, #424); 3D texel coordinates divide by depth (#482); the vertex program branches on the transform branch bits, with leaders up to slot 544 (#485); WPOS counts pixels on antialiased targets (#446) and follows the RSX's own window convention — SET_SHADER_WINDOW origin and pixel centres (@MaChInEgUn3, #589). Vertex array addresses wrap at 28 bits (#504), frequency 1 under a modulo divider bit is one element for the whole draw (@n0madic, #547), CMP (11-11-10) attributes decode (@rigaz29, #529), and a draw's vertices are fetched attribute by attribute (@tekulvw, #458). rsx_dispatch emits an immediate vertex for every completing ATTR0 encoding (#463). Linear A8R8G8B8 decodes with one rotation per texel (#432), the depth formats present their one channel on every crossbar source (@n0madic, #501), and the swizzled decode steps the offset instead of re-interleaving each texel (@rigaz29, #578).
  • GCM FIFO walker (@rigaz29 unless noted): NOP runs are passed over and 3D method runs decoded a command at a time (#554), vertex-program methods are taken first with one diagnostic gate per FIFO word (#548), the drain's own ring recycle counts as the JUMP to begin (#553), GCM_PARK_GRACE_MS bounds how long a park may stand (#531), a park is forgotten once the walker has left it (@erikomis, #541), and a resync replays the label releases it skips (#513). GCM handlers run from blocked semaphore waits on Windows (#576). A flip in the FIFO restores ZSTENCIL_CLEAR_VALUE, and a 0 clear value is the near plane (@n0madic, #526). rsx_state is handed only the methods with outside effects under the draw engine (@tekulvw, #466), and the EA→IO lookup behind the SPU put hook is bounded (#449).

SPU, SPURS and threads

  • Raw SPUs run on macOS and Linux (@erikomis, #473), each with its own program; SPU_RunCntl = 0 stops a running one (#505), and raw-SPU images can carry a parameter area the loader fills in (#538).
  • Dispatch and residency (@tekulvw): streamed code regions are verified once per load and then dispatched by residency (#420), with resident-code ownership honoured when the interpreter rejoins lifted code (#419) and a per-thread dispatch cache in front of spu_lifted_lookup, on by default (#481). The interpreter rejoins inside resident regions (@rigaz29, #525). Indirect-dispatch registry lookups are memoized per thread (#436), as is the per-thread MFC engine lookup (#421), and an image's fingerprint is reused while its bytes are unchanged (#433).
  • Exact float: NEON float ops without scalar fix-up lanes (@tekulvw, #445), and opt-in SPU_FLOAT_RZ running single precision natively under a round-toward-zero FPCR (#479). SSE4.1 and AVX2 forms of the per-lane integer and quadword helpers (@erikomis, #512), and AVX2 estimates, interpolation and float/int conversions four lanes at a time (@Kurtisone, #500).
  • DMA, reservations and coherency (@tekulvw): GETLLAR without the lock-line lock for registered holders (#441), only the reserved lines of a PUT copied under it (#484), a brief spin before parking on the POSIX lock-line lock (#443), DMA event producers serialized with reservation-lost notifications (#418), a yield before sleeping when a job re-issues the same transfer (#448), the overlay-source scan skipped for small GETs no source can match (#455), and the parked-task scan bounded on every committed lock line (#450). event_status updates atomically (@erikomis, #492).
  • SPURS: WAIT_SIGNAL wakes on coherent guest writes to the signal bitset (#423) and the coordinator wakes when an SPU commits the request line (#478).
  • Interpreter and lifter: interrupt enable/disable bits are honoured on every taken indirect branch (#417); pending interrupts are delivered at merged chunk entries (#435); lifted known-target branches tail-call their target under SPU_DIRECT (@erikomis, #510); lifter coverage now verifies job-module regions and embedded SPU programs, reports dispatch misses loudly, and handles spilled PPU jump tables (#444). The drain shares checkpoints and skips calls to inactive guards (#434), resolves its thread-local transfer slot once per drain (#452), and runs the per-hop hooks' common case inline (@rigaz29, #533). Straight quadword load/store sequences run in the SMC microstep on a tight loop (@MaChInEgUn3, #571), and halt and iret longjmp without unwinding on 64-bit Windows (#572). The decrementer uses the raw monotonic clock on Apple (#451).

Runtime, HLE and syscalls

  • New module surface: cellVoiceResetPort, cellVoiceUpdatePort and cellVoiceGetSignalState (@tekulvw, #487); cellSysconfOpen and cellSysconfAbort (@erikomis, #564); the licence area as system parameter 0x0122 (@undecuple, #429); cellPadInfoSensorMode and cellPadSetSensorMode (#565); ps3_host_quit, so the window's close button and Cmd+Q reach the guest (#544).
  • Offline answers: cellSysutilNpEula answers the PSN terms check through its callback (#542), sceNp answers tickets, account region and network time as OFFLINE (#543), and the cellNetCtl net-start dialog ends cancelled (#503).
  • Threads and sync: a thread that has exited is gone, and its id is not reused at once (@undecuple, #415); a thread made above its creator's priority runs until it blocks under PS3_PRIO_START=1 (@n0madic, #416); the main thread's stack information is no longer 0 + 0 (#469); each host thread runs HLE→guest callbacks on a stack of its own (#489); sys_mutex destroy refuses a mutex that is held or has waiters (#490), and MUTEX_WATCH names the owner of a lock a thread is stuck on (#474). sysPrxForUser lwmutex moves to an atomic lock word, with a fast path for leaf HLE imports (@rigaz29, #577). The runtime's host threads have names (#567). lv2 syscall 22 is registered as _sys_process_exit (@xuxinsss, new, #587).
  • Files, audio and media: cellFs repositions the stream when a fd switches between read and write (@feanor-noldorin, new, #456); ppu_fs serializes the fd table and reads each slot once (@tekulvw, #430); cellAudio's WASAPI path keeps 60 ms queued with the mixing thread ahead of the guest (#514); cellVdec drains the decoder when a sequence goes idle with pictures owed (#471) and never hands out handle 0 (@undecuple, #495). stdout and stderr are buffered and flushed on a timer (#524).
  • cellPad: a controller switched off and on again reopens (#472), XInput loads at run time rather than being imported (@undecuple, #494), a port with no controller reports centred sticks rather than zero (@Kurtisone, #496), PAD_FILE holds survive empty drain reads (@tekulvw, #570), and an empty XInput slot is polled once a second instead of every frame (@rigaz29, #581).
  • Clocks and error codes: one host clock backs mftb, system time and timers, via mach_absolute_time on macOS (#540). GCM error codes move to base 0x80210000 and SPURS task codes onto their own 0x80410900 (@undecuple, #414).
  • PPU lifter and loader (@rigaz29): guest stores inline, to match the inline loads (#573), on a cheaper access sequence — memory-model copy, one compare, a branch hint (#574); the SPU reserved-line bitmap is tested inline on guest stores (#534); the reservation is re-checked once the lock-line lock is held (#522).

Platforms and build

  • macOS: one window survives an exitspawn, via tools/host_window and a Metal host-surface mode (@erikomis, #509); the guest runs off the main thread (#477).
  • POSIX: the project template backs the whole 32-bit guest space, as on Windows (#475).
  • Windows: the runtime builds with plain MSVC (cl), not only clang-cl (@xuxinsss, #588).
  • CMake: a build configured without CMAKE_BUILD_TYPE is optimised rather than left at -O0 (#506), and the SPU program build can lift with --merge-chunks (@rigaz29, #549).

Diagnostics — all of it now gated

  • The hot paths stop reading the environment: the GCM FIFO walker no longer calls getenv per packet (@tekulvw, #437), SPU_PCSAMPLE is read once rather than per DMA (@Kurtisone, #243), and the remaining hot debug switches are read once (@rigaz29, #519, #527).
  • Logs and scans become opt-in: the SPURS module-poll log is capped per process (#431), the PUT poison scan runs only when it can be reported (#454), the closed policy-module DMA trace counter stops advancing (#453), two per-event log lines in cellVdec and spu_channels are opt-in (@rigaz29, #521), and the guest load/store watch hooks are gated behind one inlined load (@tekulvw, #483).
  • New samplers and reports: PS3_TPROF for SPU and PPU threads (#480), RSX_WALKER_PROF for the FIFO walker thread (#467), SPU_IRQWAIT_DIAG for an SPU waiting on an interrupt that never comes (@erikomis, #491), SPU_INTERP_STATS now listing where the interpreter was entered (@rigaz29, #523), PS3_SAMPLE_DRAIN=1 to sample only the RSX drain thread (#520) with exact attribution under PS3_SAMPLE_RVAS and a one-thread fast path (#568), and an ftrace span per HLE import call with its own report section (#580).

Tooling and docs

  • lift_jobmods lifts each job module at the link base its header names (@erikomis, #488); ppu_lifter --insn-patches lifts patched instructions as run-time switches (#539); the twistedmetal regression run removes its FIOS file cache first (@Kurtisone, #498).
  • Docs (@undecuple): SPU_LIFTER.md refreshed (#425), the SPU workflow added to GETTING_STARTED and the porting guide's Phase 11 (#426), prerequisites made to agree across README, GETTING_STARTED, BUILDING, TOOLS and the porting guide (#427), and template paths made to match the CMake with config.toml marked reference-only (#428). CITATION.cff added (#535).

Housekeeping

  • The five third-party GitHub Actions are pinned to commit SHAs (#590), the release.yml write token is scoped to the job that publishes rather than held by the job that compiles the tree and runs every test script (#592), and .github/CODEOWNERS records the paths that execute (#593).
  • CMakeLists.txt said VERSION 0.11.0, six releases stale, so every configure printed ps3recomp runtime v0.11.0. It says 0.18.0 now.
  • runtime/spu/tests/test_spu_int_neon.c and test_spu_float_neon.c run on the macOS arm64 job. The integer one had never been compiled by any workflow on any platform; neither had been built for NEON on an arm64 host.

Known issue

  • You Don't Know Jack can hang at boot in a SPURS EventFlagWait that no workload ever sets. The race is on v0.17.0 too (1 run in 4), but this release hits it far more often (4 in 4 on the regression gate). It climbs across several merges rather than coming from one PR, and is being chased separately.

v0.17.0 — "Thirty-Three" (October 2026)

33 pull requests from seven contributors, merged in #413. Most of them come from two new God of War ports (HD and Ascension), plus Killzone 3, Twisted Metal and SoulCalibur II HD.

RSX and graphics

  • God of War HD on D3D12 (@rigaz29, new): depth/stencil-only clears no longer wipe the scene (#393). Indexed strips keep their winding (#391). The guest-FP pipeline cache is keyed on the code, not the address, which removed a full recompile per draw for programs uploaded to a ring (#392). The FP decompiler is told the draw's export width (#396). A wrapped command ring no longer overwrites commands the RSX hasn't read (#390). initguid.h is included in the right place (#389), and new FP_DUMP=<n> (#398), PS3_HLE_TOP=<s> (#397) and SPU_INTERP_STATS=<s> (#394) diagnostics.
  • God of War: Ascension (@MaChInEgUn3, new): X16 textures present like B8, so the font atlas shows (#384). A smaller clip on the same rows reuses the surface (#382). The Vulkan pipeline table is as large as the engine's (#378).
  • Killzone 3 (@undecuple): texture offsets are 31 bits (#408). A texture smaller than the surface it aliases samples the surface's top-left (#395). get is published past a semaphore RELEASE before its label (#401). Main-memory maps take the first free IO pages, and are refused before cellGcmInit (#410).

SPU, SPURS and threads

  • The Twisted Metal bring-up runtime is on master, so that port links again (@Kurtisone, #381).
  • Taskset bitsets are updated atomically on task create and exit (#388). cellSpursQueueSize is answered (#411), and non-joinable PPU threads free their slot when they end (#409) (@undecuple).
  • The identical-transfer DMA halt also waits for wall time and backs off, so a job polling an RSX label isn't killed (@MaChInEgUn3, #383).
  • cellFiber is the SDK's scheduler API, replacing the made-up one (@n0madic, #400, closes #365).

Memory, codecs and system

  • LV2 user allocations and mapper reservations are separate domains, and loaded ELF segments are never handed out (@tekulvw, #296).
  • cellVdec: QueryAttrEx/OpenEx (#379), and time stamps and frame rate for MPEG-2 pictures (#380). WASAPI shared mode converts the 48 kHz stream, so a 44.1 kHz or 5.1 device isn't silent (#385) (@MaChInEgUn3).
  • Log caps stop at their limit (PS3_LOG_FIRST) instead of wrapping and printing on every call (@n0madic, #399, closes #364). MinGW builds the tests and reads the time zone from the system (#402).
  • Lifter: jump-table bounds compares are found beyond the 30-instruction window (@undecuple, #387). lift_jobmods --merge-chunks is passed through (#386).
  • The project template maps the guest arena with mmap on POSIX, so vm_commit can mprotect it (@arnaudaprahamian, new, #412).
  • Docs: stale module counts removed (#405), Killzone 3 entry updated (#407).

Older releases: CHANGELOG.md.

Mirror archiviato dal repository ufficiale GitHub · Visita su GitHub
Data snapshot: 2026-11-08