espgaluda2-recomp
espgaluda2-recomp is a Linux port of Espgaluda II Black Label for Xbox 360 that reduces input lag and adds an English translation patch.
- Type: PC port
- Game: Espgaluda II Black Label
- Runs on Linux
- By cerroverb
- Latest release v1.2.1, 2026-10-31
- Source: https://github.com/cerroverb/espgaluda2-recomp
README
Espgaluda II Black Label Recomp
A Linux x86-64 and AArch64 port of the Xbox 360 version of Espgaluda II Black Label, statically recompiled with ReXGlue. It builds on the SDK copy bundled in SDOJ-Recomp.
No game data is included. You need your own dump of the game.
FAQ
Windows/macOS?
Fork it if you want that, I'm not doing it. Linux AArch64 is out now (see Releases); BSD (NetBSD) though maybe. Or if enough shmuppers ask I'll consider a Windows version BIG MAYBE THOUGH.
Is this a native port or just a glorified emulator?
Almost entirely native port. The game code (default.xex and the seven dat*.xex
modules) is recompiled ahead of time to C++, with no CPU emulation or JIT. The graphics are drawn by reNut's renderer
from the game's Direct3D calls with Vulkan, with no GPU emulation (espgaluda2_renderer=xenos for the emulated GPU).
The system calls are Xenia-derived reimplementations in C++.
The audio is the only emulated part left. The game streams its music in XMA, the Xbox 360's audio format, to the console's XMA decoder chip, and the SDK emulates that chip (FFmpeg does the decoding).
Is this AI slop?
Mostly no. The vast majority of this project is code ported and retooled from other recompilation projects, such as futari-nx (the renderer port and its input-lag work), reNut (the Direct3D-level renderer), UnleashedRecomp (frame pacing, GPU choice) and the ReXGlue SDK as bundled with SDOJ-Recomp, made to work for Espgaluda II on Linux. LLM assistance was used in the porting, but with strict instructions to simply port and retool unless bespoke changes were necessary, which were made under my direct supervision, review and testing. I am a programmer recompilation is not my specialty and is still something I am learning about, thus the LLM assistance. There is also a strict no machine generated media rule, so you will never see slop generated "art" or media in regards to any project I administer.
Does this port reduce input lag?
Yes, and this is on by default. The native renderer (the default) reads the pad as late as each frame allows and
presents right after the game's Swap: on an AMD handheld I measured 0.8-0.9 ms from pad read to present. With the
emulated renderer (espgaluda2_renderer=xenos) a patch removes about one frame: the game's Direct3D Swap saves the
GPU fence of the frame it just submitted and only waits for it at the next Swap, so the CPU runs a full frame ahead
of a GPU that flips on vblank. The patch makes Swap wait for its own frame's fence, using the game's own fence wait.
There I measured about 32 ms from pad read to present without the patch and about 16 ms with it. It can be turned
off with --latency_patch=false.
What does vsync_display_lock do?
It applies to the emulated renderer only and is off by default. Normally the game's 60 Hz vblank timer runs on
its own, so a flip can land anywhere between two display refreshes. With
--vsync_display_lock=true, the timer follows when presented frames are actually
shown on screen, using VK_KHR_present_wait, and is nudged so each flip lands
just before a refresh. It needs a Vulkan driver with present wait
(vulkan_present_wait, on by default) and a queued present mode such as FIFO or
mailbox. With immediate presentation, or without present wait, it falls back to
the plain timer.
The native renderer has its own version, on by default (futari_vblank_display_sync). It is not vsync: vsync
(renut_vsync, off by default) decides whether a finished picture waits for the display's next refresh, while this
decides when the game starts each frame. The game's 60 Hz vertical blank (where it reads the pad and starts the frame)
follows the display's real refresh on a display at a whole multiple of 60 Hz (60, 120, 180, 240 Hz), and falls back to
the 60 Hz timer where the display's timing cannot be followed (for example through Xwayland under a desktop
compositor). The game runs at 60 frames a second either way. It works with vsync off: on a 240 Hz laptop display with
vsync off the game's vertical blank stayed locked to every fourth refresh at 60 fps.
Will audio become native?
No existing project shows a native replacement yet that I could find, but let me know if one exists.
Can this help with other CAVE games?
I hope so. It could be a starting point for other CAVE games on the Xbox 360, alongside SDOJ-Recomp. How much code those games share with this one still needs checking.
What's next for this project?
Now that input latency and performance are in a good place, version 1.2.0 adds an English translation patch for the menus, messages and tutorials. The text is sourced from the official English of the Switch release. Where the Xbox 360 version has messages the Switch does not (Xbox LIVE, storage devices, Achievements), the closest official Switch lines are adapted. The tutorial's Japanese button labels are redrawn using the game's own English font. A few obvious errors in the official text are corrected, and every change is listed in a file that ships with the patch. The patch is on by default and can be turned off in the settings (translation_patch) to play with the original Japanese text.
Version 1.2.1 adds English how-to-play captions (shown after character select, before the first stage) and clearer tutorial button labels.
Status
- Boots and plays all six modes (Black Label, Arrange, Arcade, Xbox 360 and both Novice modes) with sound and working slowdown.
- The native renderer (the default) holds 60 game updates a second, locked to the display's refresh on 60, 120 and 240 Hz screens as a native Wayland window or under gamescope; through a desktop's Xwayland it keeps a 60 Hz timer. Vsync is off by default; on an AMD handheld the pad read reaches the present in 0.8-0.9 ms.
- Tested on:
- an AMD handheld (RADV) on the desktop and in Steam Game Mode;
- another AMD handheld (RADV), headless runs of every mode and of 120 and 240 Hz displays;
- a laptop with an NVIDIA GPU (driver 615) on KDE Plasma Wayland at 240 Hz. Intel GPUs should work but are untested. Please open an issue if something is wrong.
- Slowdown accuracy compared to the arcade or the original 360 still needs checking by people who know the game well. I compared them against xenia-edge and my hardmodded xbox360 with my own physical copy of the game and it seems pretty accurate, but I don't have the best eye for this kind of thing, so more eyes would be great.
- Certain things could use further testing. Two players and replays, for example, so feel free to shit up the issues section with any problems you have.
Requirements
- An x86-64 or AArch64 (ARM64) Linux system with a Vulkan GPU driver (Mesa RADV/ANV/Turnip, or NVIDIA); the AArch64 build needs glibc 2.38 or newer.
- Your own copy of Espgaluda II Black Label (Xbox 360), either as an
.isoor as extracted files (default.xex,dat00.xex...dat164.xexand theresfolder).
Install
- Download
espgaluda2-recomp-linux-amd64.tar.gz(x86-64) orespgaluda2-recomp-linux-arm64.tar.gz(AArch64) from Releases and unpack it. - Add the game, one of two ways:
- ISO: put the
.isonext toespgaluda2-recomp.sh. The first launch extracts it intogame_data(a progress window shows while it runs), after which the ISO can be deleted. - Extracted files: copy them into
game_data, or makegame_dataa symlink to the folder.
- ISO: put the
- Run
espgaluda2-recomp.sh. For Steam, add it as a non-Steam game.
Saves and settings are written to user_data beside the executable.
Settings
Press F4 in game for the settings window (search box at the top; "Save to
config" keeps them in espgaluda2_recomp.toml next to the game). Settings can
also be given on the command line, for example --fullscreen=true. Every
setting with its default is in docs/settings.md.
The ones changed by this port (native renderer, the default):
renut_vsync(off by default): off shows each picture at once, the least input lag, tearing possible; on waits for the display's refresh.futari_vblank_display_sync(on by default): the game's 60 Hz vertical blank follows the display's refresh (see the FAQ above).translation_patch(on by default): the English translation patch, the official English of the game's Switch release for the menus, messages and tutorials (seetranslation/README.txt). Off shows the original Japanese. Applies at the next launch.latency_patch(on by default): the game's swap waits for its own frame instead of running one frame ahead of the GPU.futari_fill_crop(off by default): on a 16:10 or 4:3 screen, on fills the screen by trimming only the wallpaper at the sides; off shows black bars.renut_resolution: the internal resolution, 720p (the game's own) by default.
In Steam Game Mode, turn on Allow Tearing in the quick menu (Performance) to get presentation without vsync. Without it, gamescope forces mailbox mode.
Building
You need CMake 3.25 or newer, Ninja, Clang with C++23 support (Clang 20 or newer) and git. On Debian/Ubuntu also:
sudo apt install libgtk-3-dev libx11-xcb-dev libvulkan-dev libasound2-dev libpulse-dev libpipewire-0.3-dev libcurl4-openssl-dev
On Arch:
sudo pacman -S --needed cmake ninja clang git gtk3 vulkan-headers vulkan-icd-loader alsa-lib libpulse pipewire curl
Then run:
./build.sh
The first configure downloads SDOJ-Recomp at a pinned commit and applies the
patches in sdk-patches. The build uses a lot of memory because the generated
code is large.
The recompiled code in generated is committed. To regenerate it, put the
game's .xex files in a disc folder and build the espgaluda2_recomp_codegen
target.
License
The code in this repository is under the BSD 3-Clause license (see LICENSE), except the renderer ported from
futari-nx (src/renut_engine, src/futari_*, the files marked as ported), which is GPL-3.0 (LICENSE-GPL-3.0);
a binary built with it is GPL-3.0 as a whole.
The ReXGlue SDK, Xenia and extract-xiso (bundled in tools/) carry their own licenses.
Espgaluda II is a trademark of CAVE. This project is not affiliated with CAVE.