
# Ninja Gaiden Black Recompiled
**A PC port of Ninja Gaiden Black by static recompilation.**
A native Linux and Windows version of *Ninja Gaiden Black* (Xbox, 2005), with an experimental Android
one, made by statically
recompiling the game's own code to run directly on a PC — not an emulator. It draws with its own
Vulkan renderer, which takes over the game's Direct3D calls instead of emulating the Xbox GPU. It
plays at a steady 60 fps on modest hardware (including the Steam Deck) and adds PC options: higher
resolutions, widescreen and ultrawide, keyboard and mouse, rebindable controls and more.
**You need your own copy of the game.** This project contains none of the game's data (graphics,
sound, movies, text): on first start it asks for your disc image and installs the game from it. It is made for the **retail USA
release** (NTSC-U, title ID `5443000D`) and checks for it.
## Screenshots
 |
| 21:9 at 6x render resolution |
 |
 |
| 16:9 at 6x render resolution |
HUD hidden |
## Features
- Native Linux (AppImage) and Windows (x64) builds; Steam Deck friendly
- Android (arm64), **experimental**, with Xbox 360 touch controls
- Render resolution up to 10x, anisotropic filtering, MSAA, sharper shadows
- 16:9, 16:10, 21:9 and 32:9 as well as 4:3: the 3D fills the screen, the HUD goes to the screen's
corners, optional HUD-free view, menus keep the game's own 16:19
- Keyboard and mouse with key prompts in the game, Xbox, PlayStation and Nintendo button prompts,
rebindable controls for keyboard, mouse and controller (Ninpo and Wind Run on any two buttons),
mouse support in the menus
- Mods: replacement game files in a `mods` folder, without touching the installed game
- Skippable intros, movies and cutscenes (an option), unlock-all options for difficulties and costumes, optional cheats
- The arcade Ninja Gaiden on the Han's Bar cabinet and the main menu, recompiled as well
- Sound mixed on the PC: positional 3D sound, the console's room reverb, and 5.1 surround on a 5.1 or
7.1 output
- Smooth frame pacing and low input latency; shaders prepared in the background
## Getting started
On every system, the first start after installing takes longer to load (the shaders are prepared then and
kept); later starts are quicker.
### Linux and Steam Deck
1. Download `NinjaGaidenBlack-x86_64.AppImage` from the releases page and make it executable
(`chmod +x`, or Properties → Allow executing).
2. Run it. On the first start a window asks for your copy of the game: a disc image (`.iso`, a full
Redump dump, or the `.7z`/`.zip` it came in) or a folder of extracted files with `default.xbe`.
The game is installed once (about 6 GB).
3. On a Steam Deck, add the AppImage to Steam (Add a Non-Steam Game) to play it in Game Mode, and
choose 16:10 in the settings.
If it closes as soon as you press Play in Game Mode, that's a bug in the current stable Steam
client with non-Steam games (fixed in the Steam Beta). Until the next stable release, either
switch Steam to the Beta, or set the game's Launch Options in Steam to
`APPIMAGE_EXTRACT_AND_RUN=1 %command%` (#11).
Needs a 64-bit Linux with glibc 2.35 or newer and a GPU with Vulkan 1.3 drivers (or older drivers that
have its dynamic rendering and synchronization2 as extensions).
### Windows
1. Download `NinjaGaidenBlack-windows-x64.zip` and extract it anywhere.
2. Run `NinjaGaidenBlack.exe` and choose your disc image as above.
Needs Windows 10 or 11 (64-bit) and a GPU with Vulkan 1.3 drivers (or older drivers that have its dynamic
rendering and synchronization2 as extensions).
**Antivirus warnings:** the program isn't code-signed, and a new unsigned program is sometimes
flagged by one antivirus's heuristics (McAfee quarantined it in #88; VirusTotal shows no other
detections). That's a false positive. Each release lists the SHA-256 hash of both downloads in its
notes and in `SHA256SUMS.txt`, so you can check that your download is the one published here: in
PowerShell, `Get-FileHash NinjaGaidenBlack-windows-x64.zip`; on Linux, `sha256sum -c SHA256SUMS.txt`.
If you'd rather not run a prebuilt program, you can build it yourself from your own disc
([Building from source](#building-from-source)).
### Android (experimental)
The Android version is new and has only been tested on one phone (a Pixel 9a, where it plays at 60 fps).
Expect problems on other phones, and please report them (below).
**Install:**
1. Download `NinjaGaidenBlack-android-arm64.apk` from the releases page and open it on the phone.
Allow installing apps from your browser or file manager when Android asks.
2. Copy your disc image (`.iso`, from the retail USA disc) to the phone or its SD card, anywhere. A `.7z`
or `.zip` has to be unpacked on a computer first: the phone has no unpacker.
3. Start the game. The first time, it asks you to choose the image with Android's file picker, then
installs the game into its own folder (about 6 GB, a minute or two; with an SD card in, it asks
whether to put it on the phone or on the card). It needs no storage permission. You can delete the
image afterwards.
Plays with the on-screen touch controls (an Xbox 360 pad), or with any controller the phone supports:
the touch controls hide while one is connected. Needs Android 10 or newer (13 or newer for full speed:
the game tells the system how long its frames take, which keeps the CPU clocks up), a GPU with Vulkan
1.3, or an older Vulkan with its dynamic rendering and synchronization2 as extensions
(on Adreno, Turnip has them).
On Adreno GPUs (Snapdragon phones) whose own driver lacks what the game needs, it uses Turnip, Mesa's
open driver for Adreno, built into the app; otherwise the phone's own.
Not there yet on Android: the arcade Ninja Gaiden, and "Return to Main Menu" from the pause menu (it
closes the game instead).
**Reporting a problem:** open an issue and give the phone's model, its chip (Snapdragon, Tensor,
Dimensity, Exynos...), the Android version, what happened, and the log: `log.txt` in
`Android/data/io.github.gamboozino.ngbrecomp/files` on the phone's storage. Some file managers can't
open that folder on recent Android; a computer can, over USB (or `adb pull
/sdcard/Android/data/io.github.gamboozino.ngbrecomp/files/log.txt`).
### macOS (unsupported)
The macOS code is a community contribution (#49) that I can't build or test, so there are no
official macOS packages and macOS bugs may go unfixed. Build the Apple Silicon app using the commands below, extract the resulting zip, and open
`Ninja Gaiden Black.app`. Choose your own disc image or extracted game folder on first start.
Current dependencies require macOS 26. Intel Macs and the xemu renderer are unsupported;
packages are signed ad hoc, without Developer ID signing or notarization.
### Where things are kept
| | Linux | Windows | macOS | Android |
|---|---|---|---|---|
| Installed game, saves | `~/.local/share/NinjaGaidenBlack` | `%LOCALAPPDATA%\NinjaGaidenBlack` | `~/Library/Application Support/NinjaGaidenBlack/saves` | `Android/data/io.github.gamboozino.ngbrecomp/files` |
| Settings (`settings.ini`, `controls.ini`) | `~/.config/NinjaGaidenBlack` | `%APPDATA%\NinjaGaidenBlack` | `~/Library/Application Support/NinjaGaidenBlack/config` | `config` in the folder above |
| Shader cache | `~/.cache/NinjaGaidenBlack` | `%LOCALAPPDATA%\NinjaGaidenBlack\shaders` | `~/Library/Application Support/NinjaGaidenBlack/cache/NinjaGaidenBlack/shaders` | `cache` in the folder above |
| Log | the terminal, or `log.txt` beside the saves when started without one | `log.txt` beside the saves (or the console it was started from) | `log.txt` beside the saves | `log.txt` beside the saves |
**Portable mode:** with a file named `portable.txt` next to `NinjaGaidenBlack.exe` (or the AppImage or Mac app),
all of these go into a `userdata` folder next to it instead. The first-run setup offers this as a
checkbox. The folder must be writable, so not inside Program Files. Delete `portable.txt` to go back.
### Mods
Files placed in a `mods` folder beside the saves (the first row above; `userdata/mods` in portable
mode) are read instead of the game's own: textures, models, sounds, movies, anything the game loads
from its files. Use the same path the file has in the game's folder, for example
`mods/movie/cre.sfd` for `movie/cre.sfd`. A mod replaces a whole file (no patches or scripts), the
installed game is never changed, and deleting the file goes back to the original. The log lists
each file taken from `mods` (`[MODS]`).
## Settings
Everything is in the game's own menus: **RECOMP SETTINGS** on the main menu, and the **Settings** tab
of the pause menu. Changes apply at once and are saved.
 |
 |
- **Graphics**: render resolution (1x–10x), texture filtering (the console's, or 2x–16x
anisotropic), anti-aliasing (MSAA), shadow resolution, Smoother Glow (a softer, fainter glow on
bright lights; off is the console's look), Lower Detail Under Load, Multithreaded Renderer (drawing on a
thread of its own, for slower CPUs; on by default on Android, off unless chosen on a PC)
- **Display**: aspect ratio (4:3, 16:9, 16:10, 21:9, 32:9), window size, windowed / fullscreen /
borderless, V-Sync (Off, Mailbox, FIFO, Adaptive), frame-rate counter, the HUD on or off, skip the
warnings and intro movies
- **Sound**: Positional Audio (3D sounds placed left and right: Mixed, the default, half the sound chip's
filters and half panned by direction, the easiest to place; Clear, by level only; Console, through the sound
chip's filters as on the Xbox, duller; Off, centred), Audio Output (Auto, Stereo
or 5.1; Auto is 5.1 on a 5.1 or 7.1 output; a change needs a restart of the game)
- **Gameplay** (each off unless chosen): the Quick Menu, an NG2-style d-pad menu for weapons, Ninpo
and items, and whether the game pauses while it is open; **Intercept** (Black or Hurricane), the Hurricane
Pack's guard counter Black left out: tap guard as an attack lands to turn it aside; **Essence-Only
Charging**, Ultimate Techniques charged only by absorbing essence, not by holding attack (#120); **Skip Any
Cutscene**, Start skipping movies and in-game cutscenes not yet watched (#139); **Responsive Menus**, Start
taken at once at the title, in a cutscene's opening wait and in the pause menu after equipping, where the game
ignores it for a while (#116)
- **Cheats** (for the session only): infinite health, ninpo, essence, items, projectiles; golden scarabs; one
hit kill (any hit that hurts an enemy or a boss kills it).
Its **Unlocks** page: all difficulties from the start, all costumes, and the main menu's Missions (with every
mission), Arcade Ninja Gaiden and Movie Theater without earning them (saved); All Weapons (every melee and
projectile weapon at its highest level), All Armlets (the armlets and bands) and All Scrolls (the Izuna Drop,
Counter Attack and Guillotine Throw technique scrolls; the story's own can still be picked up while it is on),
for the session: turned off, each takes back what it gave and puts back your own pickups; a save made while one
is on keeps what it gave
- **Controls**: rebind every action (two keys or mouse buttons and a controller button each; Ninpo
and Wind Run can take two controller buttons pressed together); camera inversion; start in third
person; Camera Sensitivity; Button Prompts; Toggle HUD (not bound unless chosen). The page shows
each binding as its key or button picture. A key or button bound to an action is taken from the
one that had it (Pause always keeps a controller button). The bindings follow the game's own
Button Settings: an action keeps its key or button whatever the game's Options assign
The game's own Options (sound, movie aspect, controller vibration and so on) are where they always
were.
## Controls
On Android, an Xbox 360 pad is drawn over the screen: the two sticks, the d-pad, A B X Y, the bumpers
and triggers, Back, Start and the stick clicks. It hides while a controller is connected.
A controller works as on the Xbox. The keyboard and mouse can be used at any time — the game follows
whichever was touched last, and its button prompts change to match (or stay on one set: "Button
Prompts" on the "Controls" page, Auto, Xbox, PlayStation, Nintendo or PC).
On a Nintendo controller the buttons work by position, as on an Xbox pad: the bottom face button
(marked B) jumps, and two-button moves sit where the game puts them; the prompts show its own letters. On Android a Nintendo controller works by label instead (the button marked A jumps).
To bind Ninpo or Wind Run to two buttons, choose its controller slot and hold the first button, then
press the second; letting go of a single button binds just that one. Moved to other buttons, the
game's own pair for it (Y + B, X + A) no longer does it.
| Action | Keys | | Action | Keys |
|---|---|---|---|---|
| Move | W A S D | | Camera | mouse (numpad 8 4 5 6) |
| Attack | left mouse, J | | Special attack | right mouse, K |
| Jump | Space | | Projectile | E |
| Ninpo | F | | Wind run | C |
| Guard / roll | Shift | | Center camera | Q, middle mouse |
| Map | Tab | | Karma window | R |
| Pause | Esc, Enter | | First-person view | Z |
After loading, the right stick (or the mouse) turns the third-person camera; click it (V) to look around
in first person. Turn off **Start in Third Person** (RECOMP SETTINGS → Controls) to start each load in
first person, as on the Xbox. **Invert Camera X / Y**
flips the stick and mouse for the third-person camera, **Invert First-Person X** first-person left and
right; first-person up and down is the game's own Options → Controller Settings → 1st Person Camera
Control. **Camera Sensitivity** (25%–300%) sets how fast the mouse, the right stick and the camera keys
turn it; over 100% the camera turns faster than the game's own top speed (the third-person camera's
left and right; its up and down stays the game's). Holding Start and Back (Select) is the game's own reset to
the title screen; turn off **Start+Back Reset** (Controls) if another program uses that combination.
With the **Quick Menu** on (RECOMP SETTINGS → Gameplay), Up and Down on the d-pad (or the Up / Down
arrows, 1 / 2) open it on the melee weapons or the items, and Left and Right on the previous or next
melee weapon; Up and Down then change category, Left and Right choose, A / Enter equips or uses, B /
Escape closes. Its keys are in Controls.
In the menus the mouse points and clicks, Esc goes back and Q / E switch the pause menu's tabs.
With Skip Any Cutscene (Gameplay), movies and in-game cutscenes can be skipped with Start (or
its key), watched before or not.
Other keys: **F10** frame-rate counter, **F11** or **Alt+Enter** fullscreen.
## The arcade Ninja Gaiden
The 1988 arcade Ninja Gaiden is a separate program on the disc (`NinjaTrilogy.xbe`, and
`NinjaTomoe.xbe` for the Japanese version) that the Xbox switches to. It is recompiled too: the
packages carry `NinjaTrilogy` and `NinjaTomoe` next to the game, and the game hands over to them from
the main menu's **ARCADE NINJA GAIDEN** and the cabinet in Han's Bar. In the arcade, Back pauses:
**B** quits back to Ninja Gaiden Black, **Y** goes to the arcade's title. It opens in the window mode
the game was in.
## Known issues
- Above 1x render resolution, a faint light line can show across the dagger in the pause menu (#83).
- The Windows build has been tested under Proton and in a Windows 11 virtual machine; reports from
real Windows PCs are especially welcome.
When reporting a graphics glitch, pressing **F7** while it is on screen records the next few seconds of
drawing to `~/ngb-trace-` on Linux, or `C:\Users\\ngb-trace-` on Windows — attach that
folder (zipped), it shows exactly what went wrong.
## Building from source
The build needs the game's code, so it starts from your own disc image.
Requirements: clang, CMake, Ninja, Python 3, git, SDL2, GLib, glslang and SPIRV-Tools (Qt 6
Widgets for the setup window, optional). The recompiler and Xbox runtime,
[xboxrecomp](https://github.com/sp00nznet/xboxrecomp) with this port's changes, is included in
`xboxrecomp/`.
```sh
xboxrecomp/third_party/fetch.sh # once: Vulkan headers, volk, VMA and the like
tools/pipeline.sh /path/to/your/ngb.iso # extract, disassemble and lift to C (a few minutes)
cmake -S . -B build/linux -G Ninja -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++
ninja -C build/linux
build/linux/NinjaGaidenBlack
```
Packages: `packaging/appimage/build.sh` (in a Docker container, for an AppImage that runs on older
systems), `packaging/windows/build.sh` (cross-compiled from Linux with llvm-mingw),
`packaging/android/build.sh` (below), and `packaging/macos/build.sh` (native Apple Silicon). Packages
contain no game data.
For Android, after the fetch and pipeline steps above (on Linux), install the Android SDK with an NDK,
build-tools and a platform (Android Studio's SDK Manager, or `sdkmanager "ndk;27.2.12479018"
"build-tools;35.0.0" "platforms;android-35"`), and a JDK, then:
```sh
packaging/android/build.sh # ANDROID_HOME= if it is not ~/Android/Sdk
adb install -r build/android-release/NinjaGaidenBlack-android-arm64.apk
```
It builds SDL2 and glslang for the phone once (into `build/android-deps`), then the game, and signs the
APK with a key it makes there (`debug.keystore`): keep that file, as Android only installs an update
over an app signed with the same key.
On macOS, install the build dependencies below, then run the fetch and pipeline steps above
and package the app:
```sh
brew install cmake ninja sdl2-compat sdl3 libepoxy glib glslang molten-vk vulkan-loader qt
packaging/macos/build.sh
```
The zip is `build/macos-release/NinjaGaidenBlack-macos-arm64.zip`. Homebrew is needed only to
build; runtime libraries, including MoltenVK, are bundled. `NGB_MAC_PREFIX` overrides the build
dependency prefix (default: `brew --prefix`).
How it works, and the details of every feature: [docs/TECHNICAL.md](docs/TECHNICAL.md) and
[docs/renderer.md](docs/renderer.md). How to contribute: [CONTRIBUTING.md](CONTRIBUTING.md); the layout, tools
and test rules, also for coding agents: [AGENTS.md](AGENTS.md).
## Support
If you'd like to support the project: [ko-fi.com/gamboozino](https://ko-fi.com/gamboozino)
## Credits
- [xboxrecomp](https://github.com/sp00nznet/xboxrecomp) by sp00nznet: the recompiler and Xbox
runtime this is built on (MIT)
- [xemu](https://xemu.app): the NV2A GPU model and the APU's voice processor (the files used here are
LGPL-2.1-or-later, its shader generators GPL-2.0 or 3.0; xemu as a whole is GPL-2.0)
- TGP482's [SCDA-XBERecomp](https://github.com/TGP482/SCDA-XBERecomp) and
[Xbox-XBERecomp](https://github.com/TGP482/Xbox-XBERecomp): the renderer's shader, vertex and
texture code, and the sound mixer's model (MIT)
- Fonts: EB Garamond and Liberation Serif (SIL Open Font License)
- Keyboard, mouse and controller prompts (the Xbox, PlayStation and Nintendo Switch buttons), and the
touch controls' buttons: Xelu's [Free Controller & Key Prompts](https://thoseawesomeguys.com/prompts/) (CC0)
- The touch controls' sticks and d-pad: Kenney's [Mobile Controls](https://kenney.nl/assets/mobile-controls) (CC0)
- Banner lettering: Chakra Petch by Cadson Demak (SIL Open Font License)
### Contributors
Code:
- [akirahayabusa](https://github.com/akirahayabusa): the freeze in scenes with the sun (#40), folders
with non-ASCII names on Windows (#41), the Difficulty Selection highlight (#42); and the Hurricane
patch (vb-zh x2.1), whose Intercept switch showed where Black had left the mechanic out (#109, #132)
- [ManemanFTW](https://github.com/ManemanFTW) (Manuel Flores): the Windows start-up hang (#9) and the
audio crackling on Windows (#34)
- [HammerD72](https://github.com/HammerD72): the audio timing fix (#32); the two spots where the game
picks the camera view at a load, for Start in Third Person (#23); impact sparks at 21:9 (#65); Smoother
Glow (#64); the Quick Menu (#60)
- [retro-meister](https://github.com/retro-meister): the macOS port (#49), and the community macOS builds
Testing, saves and traces:
- [Radarzo](https://github.com/Radarzo), [hj-0](https://github.com/hj-0),
[hyperspeedgx](https://github.com/hyperspeedgx), [serguntchik](https://github.com/serguntchik),
[PaulAndrewClift](https://github.com/PaulAndrewClift) and
[phantuannghia95-rgb](https://github.com/phantuannghia95-rgb): seven test builds, screenshots and logs
on Nvidia cards that tracked down the banded water (#16)
- [HammerD72](https://github.com/HammerD72): testing on Nvidia across many issues (shadows #53, water
#16, menus and controls)
- [DAVID106-debug](https://github.com/DAVID106-debug): the missing particles and the Xbox comparison
(#51), the high-resolution shadow flicker (#53)
- [hyperspeedgx](https://github.com/hyperspeedgx): saves across chapters 1 to 9, traces for the torch
embers (#51) and the Chapter 5 roof (#29)
- [hj-0](https://github.com/hj-0): saves for chapters 11 to 13 and a guide to moving saves from xemu
(#61)
- [yoyooo941-sys](https://github.com/yoyooo941-sys): the save that made the volcano strip reproducible
(#55)
- [firepro1211](https://github.com/firepro1211) and
[huokunlongCHAIN](https://github.com/huokunlongCHAIN): the Chapter 5 roof, including a comparison on
the Xbox One (#29)
- [matitone71](https://github.com/matitone71): the Steam Deck Game Mode log that found the launch
problem (#11)
To report a bug, test a build or send a change, see [CONTRIBUTING.md](CONTRIBUTING.md).
*Ninja Gaiden* is a trademark of Koei Tecmo. This project is not affiliated with or endorsed by Koei
Tecmo or Team Ninja.
## License
This project's code is free software: you can redistribute it and/or modify it under the terms of
the GNU General Public License as published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version (`GPL-3.0-or-later`; the text is in [LICENSE](LICENSE)).
Up to 0.9.24 it was GPL-2.0-or-later. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
The parts it is built from keep their own licenses: see [THIRD_PARTY.md](THIRD_PARTY.md).