A static recompilation of Perfect Dark Remaster (2010, Xbox 360, Title ID 584109C2) to native Windows x86-64, built on the ReXGlue SDK.
Static recompilation translates the Xbox 360 PowerPC code inside the game's default.xex into native C++ that compiles and runs on a PC. There is no emulator and no interpreter in the loop; file I/O, GPU commands, audio and threading go through the ReXGlue runtime.
This project is not affiliated with Microsoft/Rare/4J. It contains no game files: you need your own legally owned copy of the game.
- Working build. The project compiles cleanly and the executable boots to real Direct3D 12 rendering with audio, controller support, and the texture-noise fix applied.
- Codegen runs clean. Analysis of
assets/default.xexproduces 0 errors; the code range0x820C0000-0x825BB934(≈ 4.8 MB) comes out as 15 032 recompiled functions. - Both graphics backends compiled in. The SDK is built from source with
REXGLUE_USE_D3D12andREXGLUE_USE_VULKANboth enabled, so--graphics_backend=d3d12|vulkancan be switched at runtime. - SDK built from source. Unlike projects that vendor a prebuilt SDK archive, this repo pulls the ReXGlue SDK as a git submodule at
thirdparty/rexglue-sdkand builds it together with the game, so Tracy profiling and the SDK's perf counters (on in every non-Release build) come with it. - Debug instrumentation wired up.
win-amd64-relwithdebinfobuilds enableREXGLUE_ENABLE_PERF_COUNTERSand linkTracyClientrd.dll, so per-frame CSV metrics and Tracy profiling both work out of the box. Seetools/benchmark.ps1andtools/analyze_benchmark.py.
- Native Windows build — no emulator, no interpreter; the game's own PowerPC code is compiled to x86-64.
- Third-person camera mod — camera behind Joanna, her animated body with the gun she holds, reload animation, wall collision; toggle with
V. Solo play. How it was made:src/mod/third_person/README.md. - No hang on mission restart — the N64 audio library's event queue can run empty, and its voice handlers then spin forever holding the sound lock (black screen); an empty queue now yields a short delay instead (
src/audio/event_queue.cpp). - Optional Xbox LIVE prompt skip —
pdr_skip_live_prompt = trueanswers the startup "Gamer Profile not online" box with "Continue playing offline" instead of showing it (headlesswould pick "Connect to Xbox LIVE" and hang). - Dual graphics backend — pick Direct3D 12 or Vulkan at runtime via
--graphics_backendorsettings/hardware.toml. - Build optimizations — Release builds use
-O3with ThinLTO (and-march=x86-64-v2on x86-64), RelWithDebInfo-O2 -g; seecmake/build_optimizations.cmake. - Texture noise fix — ported from the community xenia-canary
game-patchesfor Perfect Dark (584109C2), applied as a direct guest-memory write insrc/game_patches.h. Enabled by default insettings/hardware.toml. - Runtime debug tools — stub sweep and missing-function scan gated behind the
dev_debug_runtimecvar; produceslogs/stub_sweep.txtandlogs/missed_functions.txtfor ongoing work on unregistered addresses. A thread sampler (pdr_sample_threads_after_s/pdr_sample_threads_duration_s) logs the busiest threads' hottest functions once,pdr_log_gpu_waitlogs render-thread GPU waits, andtools/thread_cpu.ps1prints per-thread CPU use of a running game. - Performance benchmarking —
tools/benchmark.ps1runs the game on both backends for a fixed duration and prints a side-by-side comparison;tools/analyze_benchmark.pycomputes FPS / frame-time percentiles from the CSV. - SDL gamepad support —
settings/gamecontrollerdb.txtis staged next to the exe so controllers SDL doesn't already recognize still work.
- CMake 3.25+
- Ninja
- Clang / LLVM (clang-cl works too) — MSVC alone will not build this
- Windows SDK (for D3D12) and Vulkan SDK (for Vulkan)
- Git with submodule support (the SDK is a submodule)
- Your own legally-owned copy of Perfect Dark Remaster, extracted from the Xbox One disc/ISO
The SDK is a git submodule at thirdparty/rexglue-sdk. After cloning:
git submodule update --init --recursiveThat's it — CMakeLists.txt already points REXSDK_DIR at the submodule, so the build picks it up automatically.
- Extract the Xbox One ISO with XBLA-Extract (or a similar tool such as xplorer360 / extract-xiso).
- Copy the extracted contents into
assets/, so it looks like:assets/ default.xex DataFiles/ ... assets/is gitignored (assets/*in.gitignore) — nothing from the disc is, or should be, committed to this repo.
cmake --preset win-amd64-relwithdebinfo
cmake --build out/build/win-amd64-relwithdebinfoOther available presets: win-amd64-debug, win-amd64-release, win-arm64-*, linux-amd64-*, mac-amd64-*, mac-arm64-*.
Codegen (translating assets/default.xex into generated/default/*.cpp) runs automatically as a build step (perfectdarkremasterrecomp_codegen CMake target) whenever perfectdarkremasterrecomp_manifest.toml, default_functions.toml, function_names.toml, or the .xex itself changes.
function_names.toml is generated, don't edit it by hand.
cd out\build\win-amd64-relwithdebinfo
.\perfectdarkremasterrecomp.exeBoth --game_data_root and --gpu_plugin are optional: OnConfigurePaths() in src/perfectdarkremasterrecomp_app.h defaults game_data_root to <repo_root>/assets (found by walking up from the exe folder) when it isn't set via flag/env var, and gpu_plugin = "xenos" already lives in settings/hardware.toml. Pass either flag to override.
Useful flags/env vars while developing:
| Flag / env var | Effect |
|---|---|
--game_data_root <path> |
Overrides the default <repo_root>/assets game-files location. |
--graphics_backend d3d12|vulkan|any |
Forces the graphics API rexgpu-xenos uses. Default "any" picks D3D12 first. |
--gpu_plugin xenos |
Overrides settings/hardware.toml's gpu_plugin. |
--pdr_gpu_wait_mode 0|1|2 |
Render thread wait for the GPU: busy spin, yield (default), sleep. |
--pdr_tp_enable true |
Third-person camera on at start (or press V in game); offsets: pdr_tp_offset_x/y/z. |
--perf_log_csv=<path> |
Per-frame metrics CSV (only when built with REXGLUE_ENABLE_PERF_COUNTERS). |
Logs are written to out\build\<preset>\logs\*.log (the exe is built WIN32, so nothing prints to the console).
Rendering/window/vsync and input-backend defaults are checked in under settings/ (hardware.toml / mapping.toml), loaded automatically at startup. CLI flags and REX_* environment variables always override them — see settings/README.md for the full reference and precedence rules.
.
├── assets/ # Game data (default.xex + files) — gitignored
├── cmake/
│ ├── build_optimizations.cmake # Compiler flags per build type (O3 + ThinLTO for Release)
│ └── fix_symlinks.cmake # Fixes git symlinks on Windows (libmspack in SDK)
├── generated/ # Codegen output (gitignored) + rexglue.cmake
│ └── default/ # *.cpp / *.h per partition
├── out/ # Build output (gitignored)
├── settings/ # Checked-in hardware.toml / mapping.toml / gamecontrollerdb.txt
├── src/
│ ├── main.cpp # REX_DEFINE_APP entry point
│ ├── perfectdarkremasterrecomp_app.h # App hooks (OnPreSetup, OnPostSetup, ...)
│ ├── game_constants.h # Code-range constants (kCodeBase / kCodeEnd)
│ ├── game_cvars.h/.cpp # Project-defined cvars (graphics_backend, pdr_tp_*, ...)
│ ├── game/ # What the host code knows about the game: struct offsets
│ │ # (g_vars, player, prop, ...) and the guest functions it uses
│ ├── guest/memory.h # Big-endian guest memory access
│ ├── math/vec3.h # Vector math
│ ├── audio/event_queue.cpp # Fix: empty audio event queue no longer locks up the game
│ ├── mod/third_person/ # Third-person camera mod, one file per job
│ ├── platform/live_prompt.cpp # Optional Xbox LIVE prompt skip (continue offline)
│ ├── render/gpu_wait_hook.cpp # GPU ring-space wait: yield/sleep instead of busy spin
│ ├── game_patches.h # Texture-noise fix (guest-memory write)
│ ├── debug_tools.h # Stub sweep + missing-function scan
│ ├── thread_sampler.h/.cpp # One-shot sampler of the busiest threads (debug)
│ └── utils.h # Repo-root discovery + settings loading
├── thirdparty/rexglue-sdk/ # ReXGlue SDK (git submodule)
├── tools/
│ ├── benchmark.ps1 # D3D12 vs Vulkan benchmark runner
│ ├── benchmark.sh # Same, for Linux/macOS
│ ├── analyze_benchmark.py # FPS / frame-time statistics from CSV
│ └── thread_cpu.ps1 # Per-thread CPU use of a running game
├── CMakeLists.txt
├── CMakePresets.json # Platform presets (win/linux/mac × amd64/arm64)
├── CMakeUserPresets.json # Local presets (inherits platform presets)
├── default_functions.toml # Manual function boundaries for codegen
├── function_names.toml # Function names for codegen (generated)
└── perfectdarkremasterrecomp_manifest.toml
rexglue init --project-name perfectdarkremasterrecomp --xex-path assets/default.xexgeneratedCMakeLists.txt,CMakePresets.json,perfectdarkremasterrecomp_manifest.toml,generated/rexglue.cmake,src/main.cpp,src/perfectdarkremasterrecomp_app.h.- Added the ReXGlue SDK as a git submodule at
thirdparty/rexglue-sdkand pointedREXSDK_DIRat it inCMakeLists.txt— the SDK is built from source rather than a prebuilt archive. - Enabled both graphics backends (
REXGLUE_USE_D3D12on Windows,REXGLUE_USE_VULKANeverywhere) and set per-build-type compiler flags incmake/build_optimizations.cmake. - Added
GPU_PLUGINS xenosto therexglue_setup_target()call inCMakeLists.txtsorexgpu-xenos*.dllgets staged next to the exe. - Added
src/game_patches.hwith the texture-noise fix (ported from xenia-canarygame-patchesfor584109C2), applied inOnPostLoadXexImage(). - Added
src/debug_tools.hwith the stub sweep and missing-function scan, gated behind thedev_debug_runtimecvar so they don't run by default. - Added benchmarking tools (
tools/benchmark.ps1,tools/analyze_benchmark.py). - Named the recompiled functions from the Perfect Dark decompilation and built the third-person camera mod on top (
src/mod/third_person/README.md).
- Multiplayer / Co-op is not implemented.
- The
rexglueCLI must be invoked through the SDK source tree. Because the SDK is built from source, therexgluebinary is produced by the same build as the game; running codegen manually requires the SDK to have been built first.
- ReXGlue SDK (releases)
- xenia / xenia-canary — ReXGlue's runtime is derived from Xenia's, and the compatibility list was used to help pick this game as a recompilation target.
- mdqinc/SDL_GameControllerDB — controller mappings staged next to the exe.
- ryzendew/XBLA-Extract — used to unpack the Xbox One ISO.
- zerokilo/xexloaderwv — Ghidra plugin used to load and analyze
default.xexearly on. - n64decomp/perfect_dark (MIT, Ryan Dwyer) — the N64 decompilation; 4J's port shares its code, which gave the function names and made the third-person mod possible. Not included in this repo.