rood-boi is a native PC port of Vagrant Story for Linux (and Windows, built from Linux or WSL). It is built on the rood-reverse decompilation: the game's original logic is the decompiled C, compiled for x86-64 and run directly (there is no emulator and no MIPS interpreter), with a host layer that stands in for the PlayStation's GPU, GTE, SPU, CD drive, memory cards and pad. On top of that sits a modern renderer: the world is drawn from native meshes on Vulkan (or OpenGL), lit with hardware ray-traced shadows, path-traced or probe-based global illumination denoised with NVIDIA NRD, and volumetric haze, while the PS1 look (nearest-filtered textures, original geometry and 2D) is kept. A live, Unreal-style editor lets you fly a free camera and place and tune lights while the game runs.
Disclaimer. This is an unofficial fan project. It is not affiliated with,
endorsed by or sponsored by Square Enix or Sony Interactive Entertainment. It
ships no game data (no disc image, game executables, models, textures, audio
or movies); you must own Vagrant Story and supply your own disc image. (The
menu string tables under assets/ come from the upstream rood-reverse
decompilation, which needs them to rebuild the original files.) Vagrant
Story, PlayStation and all other trademarks belong to their respective owners.
- Features
- Status
- Requirements
- Getting the game data
- Build
- Run
- Tests
- Platform support
- Licence and credits
- The decompilation (upstream rood-reverse)
The detailed reference for the port (renderer, editor, settings keys,
developer RPC, test suites, architecture) is pc/README.md,
with design notes in pc/docs/.
- The original game code, natively. Main executable, title, battle/field engine, menus and effects are the decompiled C (plus translations of the remaining hand-written assembly) built for the host. The PS1 build of the same sources still matches the original binaries byte for byte.
- Renderers. Vulkan 1.3 with ray queries (64-bit build) or OpenGL 4.6/3.3. Rooms, characters, weapons, drop shadows and particles are drawn from native meshes with real depth, at up to 8x internal resolution, with perspective-correct texturing, FXAA, and frame interpolation for smooth motion above the game's 30/15 fps.
- Lighting. Ray-traced soft shadows, per-pixel path-traced indirect light (Ultra, denoised with NVIDIA NRD), DDGI probe GI (Medium/High), shadow maps where there is no ray tracing, ambient occlusion and volumetric haze. Quality presets from Original (exactly the PS1's baked lighting) to Ultra, picked automatically on first run.
- PS1 look preserved. Nearest-filtered textures, the original 2D, menus, fonts and 4:3 framing by default; post effects (depth of field, tilt-shift, fog) and 16:9 are opt-in.
- Live editor (Escape): free camera, an Outliner of the room's lights and glows, light actors from JSON prefabs (candles, torches, lanterns...), one-click lighting of the room's fixtures, Houdini-style point/edge/surface snapping, undo/redo, and a Room Browser that warps to any room of the game for lighting work (saves are blocked while warped).
- Lighting as data. Room lighting lives in layered, diff-friendly text
packs under
lighting/(generated, hand-authored, personal), so lighting can be reviewed and contributed as pull requests. A fixture catalog classifies every candle, torch, lantern and brazier type in the game once (hashes and numbers, no game data), and a generator lights every instance from it; tuning a type updates all of its instances. - Optional weapon slots. A quick weapon and shield swap on L2 + R2, ported from eremtsov's QoL mod; off by default, memory cards stay compatible with the mod and the unmodded game.
- Camera and view options. The right stick turns and zooms the game's own follow camera; optional smart cutaway walls hide only the walls actually between the camera and Ashley; optional MMPX upscaling for 2D/UI.
- Room texture animations (scrolling sigils and the like) run as GPU material effects driven by the game's own animation state.
- Audio and video. The original sound driver on a software SPU (music,
effects, reverb), the intro movie (MDEC video and XA audio), memory cards
as standard
.mcdimages that emulators also read. - Input. Keyboard and SDL 3 gamepads (Xbox, PlayStation, Switch and others), hot-plugged.
- Options in the game's own menu. Gameplay, Display, Graphics, Audio, Interface and Controls pages sit below the original rows of the Option screen, drawn in the game's style: window mode, display, fullscreen mode (asks "Keep these settings?"), vsync, frame rate cap, render quality, key and pad bindings. Plugins can add pages of their own.
- Lua plugins. Look, feel and quality-of-life changes live in Lua with hot
reload (
pc/docs/Extensions.md). Shipped:rood.options(the Option pages),rood.hud(the HUD with the modern menus) androod.classic(the classic HUD: timing words, chain count, HP/MP/RISK gauges, each checked packet for packet against the game's own drawing, which stays the fallback). - Save state slots (optional, off by default): System > Gameplay > Save states, then F5 saves, F9 loads, F6/F7 pick the slot (bindable).
- Cutscene player (developer tool, Window > Cutscene): reach a cutscene
(New Game's opening, 39 room events by warp, the ending), pause, step, go
back to any earlier frame and replay it exactly, slow motion, clean PNG
captures and repro files; the optional instant replay keeps the last 30 s
and F8 freezes it (
pc/docs/Cutscene_Player.md). - Developer tooling. A JSON-RPC control socket and Python client
(
pc/tools/rood_rpc.py) for scripted play, screenshots and memory inspection; a Lua REPL into the running game (pc/tools/rood_repl.py); the engine as a library reloaded in place (pc/run-game.sh --reload, below); save-state resume across rebuilds (--resume); headless GPU and CPU-only test suites. - Game logic moving to Zig (in progress). Battle functions are being
ported to Zig one at a time (
game/), each checked against the original C: shadow mode runs both and compares every call, a differential checker compares them on generated inputs with branch coverage, and Zig edits hot-swap into the running game. Seepc/docs/porting/.
The port is playable but unfinished. It boots, plays the intro movie, and runs New Game (the opening cutscenes, then control of Ashley) and Continue from a memory card; exploration, battles, menus, saving and loading work in the areas played so far. The automated suites cover the boot, the opening, the first rooms, a save room and long unattended soak runs. It has not been played through to the end. Known gaps:
- The ending is ported but only reached by a jump.
ENDING.PRGruns natively (credits, the MISSION COMPLETE score and rank screen, the return to the title and its clear-data save;ending_smoke, from RPCending), but no one has yet reached it by playing the final events. - Code paths that have not been translated yet stop the game with a named
[UNIMPLEMENTED]message (and a stack trace) rather than misbehaving. Rarely reached branches (some spells, effects and enemy AI routines) are less tested than the rooms the tests visit. - The game sees a digital PS1 pad: a gamepad's left stick works as a D-pad (the right stick drives the camera); there is no analog movement, button pressure or rumble.
- Widescreen (16:9) is experimental and off by default; some classic menu screens still show artifacts in 16:9 (being fixed). HDR output is not implemented.
- 32-bit Vulkan drivers have no ray tracing: the Vulkan renderer and the Ultra preset need the 64-bit build.
- Linux, and Windows through a build made on Linux or WSL (see Platform support).
- OS: Linux on x86-64. Developed and tested on Ubuntu 24.04 LTS (X11 and Wayland/XWayland sessions). Other current distributions should work with the equivalent packages but are untested. Windows 10/11 x64 runs a build made on Linux or WSL2 (see Windows); macOS is not supported.
- GPU and driver (64-bit build, recommended):
- Vulkan 1.3 with dynamic rendering, synchronization2 and geometry
shaders for the Vulkan renderer. With
VK_KHR_ray_query(NVIDIA RTX, AMD RDNA2 and later, Intel Arc, on current drivers) you get ray-traced shadows and the Ultra/High presets; tested on NVIDIA (proprietary driver) and Intel integrated graphics (Mesa). - Without ray queries Vulkan still runs, with shadow maps and the Low / Medium presets. Without usable Vulkan the game falls back to OpenGL: 4.3+ (compute shaders) for the OpenGL path tracer and probe GI, down to 3.3 core for the basic renderer.
- Vulkan 1.3 with dynamic rendering, synchronization2 and geometry
shaders for the Vulkan renderer. With
- CPU/RAM: any recent x86-64 CPU; 8 GB RAM is plenty for playing (building uses about 1-2 GB per compiler job).
- Disk: about 2.5 GB for a checkout with your disc image, the extracted data and both builds, plus about 2 GB free temporarily during the first 64-bit build (the NRD shader compiler is unpacked and then deleted).
- Network for the first build: the decompilation's
makedownloads its toolchain (old GCC builds, mkpsxiso, Python packages for splat; tens of MB). The first 64-bit build downloads NVIDIA NRD with its dependencies, including the DirectX Shader Compiler: about 500 MB, which is deleted again after NRD is built (about 40 MB stays inpc/build/nrd). Later builds work offline.
Build tools, the SDL 3 platform headers (SDL is vendored and built from source; its backends load their libraries at run time), Vulkan and the test helpers:
sudo apt install git build-essential ninja-build pkg-config python3 python3-venv \
gdb libvulkan-dev mesa-vulkan-drivers vulkan-tools \
libx11-dev libxext-dev libxi-dev libxcursor-dev libxfixes-dev libxrandr-dev \
libxrender-dev libxss-dev libxtst-dev libwayland-dev libxkbcommon-dev \
libdecor-0-dev libpipewire-0.3-dev libpulse-dev libasound2-dev \
libdbus-1-dev libudev-dev python3-numpy python3-pil xvfb- CMake 3.30 or newer. NRD's dependencies require it, and Ubuntu 24.04's
cmakepackage is 3.28: install a current CMake, for examplesudo snap install cmake --classic(or Kitware's APT repository, orpipx install cmake), and make surecmake --versionreports it. With an older CMake the build still succeeds, but without NRD (it warns once and the Vulkan path tracer uses its own denoiser). - The decompilation's toolchain, for step 3 of the build. Either
Docker (
sudo apt install docker.io, then add yourself to thedockergroup; the snap package works too), which is what this README was verified with, or install the upstream prerequisites on the host:sudo apt install binutils-mipsel-linux-gnu clang-format unzip wget(upstream lists newer minimum versions than Ubuntu 24.04 ships; see Setup). The port's own build also needsmipsel-linux-gnu-ld, and runs it from the same Docker image when it is not installed. - A graphics driver. On NVIDIA, the proprietary driver
(
nvidia-driver-*, which includes Vulkan); on AMD and Intel, Mesa (mesa-vulkan-drivers, above).vulkaninfo --summary(fromvulkan-tools) should list your GPU with apiVersion 1.3 or later. - Sound goes through SDL to PipeWire, PulseAudio or ALSA, whichever is running (Ubuntu's desktop has PipeWire).
The 32-bit build (optional, see Build) additionally needs
gcc-multilib g++-multilib and, after sudo dpkg --add-architecture i386 && sudo apt update, the 32-bit runtime libraries of the backends you use:
libx11-6:i386 libxext6:i386 libxi6:i386 libxcursor1:i386 libxfixes3:i386 libxrandr2:i386 libxss1:i386 libxrender1:i386 libpulse0:i386 libasound2t64:i386 libudev1:i386 libdbus-1-3:i386 libgl1:i386 libegl1:i386,
plus the 32-bit OpenGL driver (libgl1-mesa-dri:i386, or your NVIDIA
driver's libnvidia-gl-*:i386). Multiarch packages must match the versions
of their 64-bit counterparts; check apt's list before confirming anything it
wants to remove.
You need your own copy of Vagrant Story (USA), SLUS-01040 and a dump of it made from your own disc: a raw (2352 bytes per sector) single-track BIN image, as made by a disc-ripping tool's BIN/CUE mode. Other releases (Europe, Japan) and other formats (ISO, CHD, PBP, ECM) are not supported.
- Place the image at
disks/SLUS-01040.binin the repository (createdisks/; it is git-ignored, as is everything extracted from it). A symbolic link to an image stored elsewhere also works for the host build (Docker only sees files inside the repository, so use a copy or a hard link there). - The decompilation's
make(build step 3) extracts the disc's files intodata/with mkpsxiso'sdumpsxiso, splits the executables with splat, rebuilds them from the decompiled sources, and compares every rebuilt binary with the one from your disc.All files matchat the end is the check that your image is the right one: a bad or different dump fails there (no separate checksum is published upstream).
Never commit anything from disks/, data/, build/ or pc/build/.
The build has two parts: the upstream decompilation's make, which extracts
your disc and builds the original PS1 files (the port uses its extracted data,
symbol tables and linker maps), then the port itself
(pc/tools/build_boot.py, driven by pc/run-game.sh).
1. Clone with submodules (into your home directory if you use the Docker
snap, which cannot see /tmp):
git clone --recursive https://github.com/noprompt/rood-boi.git
cd rood-boi2. Add your disc image as disks/SLUS-01040.bin (see above).
3. Extract and build the original files (once, and again only when
src/ or the disc changes). With Docker, build the toolchain image once and
run make in it as yourself:
# The upstream Dockerfile also copies the disc into the image for CI;
# building it without that line keeps your disc out of the image.
sed '/^COPY disks/d' Dockerfile | docker build -t rood-reverse-dev:local -
docker run --rm -u "$(id -u):$(id -g)" -e HOME=/tmp -v "$PWD:/work" -w /work \
rood-reverse-dev:local make -j8(Or, with the toolchain installed on the host, just make -j8.) It ends with
✔ All files match. The image name rood-reverse-dev:local matters: the
port's build uses it to run mipsel-linux-gnu-ld when that is not installed.
4. Build and play (recommended: the 64-bit build with Vulkan):
pc/run-game.sh --vulkanpc/run-game.sh builds the port (unless --no-build), then starts the game
in a window from the repository root, with settings in pc/user/settings.cfg.
On a hybrid-graphics NVIDIA machine it renders on the NVIDIA GPU (PRIME
offload; ROOD_GPU=integrated keeps the default GPU).
| Option | Effect |
|---|---|
--vulkan |
64-bit build, Vulkan renderer (ROOD_RENDERER=vulkan). Recommended. Falls back to OpenGL if Vulkan 1.3 is not available. |
(none) or --64 |
64-bit build with the OpenGL renderer |
--32 |
32-bit build (build_boot.py --battle) with OpenGL: the original port configuration, no longer tested; needs the multilib/i386 packages above and has no Vulkan or NRD |
--reload |
64-bit development split: the engine is a library the running game reloads in place (below) |
--no-build |
skip the build step and run the existing binary |
--skip-movies |
(passed to the game) skip the intro movie |
To start at the title every time (no publisher and developer logos, no intro
movie), turn on System > Gameplay > Skip intro, or put skip_intro 1 in
pc/user/settings.cfg. It is off by default: the original start.
To shorten the wind-up before spells, items and Break Arts take effect in
battle, set System > Gameplay > Battle charging to Fast (4x) or Skip (full
speed), or put qol_skip_charging 1 (or 2) in pc/user/settings.cfg. Off
by default; the battle itself plays exactly the same, only faster to watch.
The builds go to pc/build/boot64/rood_battle_probe (64-bit) and
pc/build/boot/rood_battle_probe (32-bit). To build without running:
python3 pc/tools/build_boot.py --arch 64 (add --nrd off to skip NRD and its
download) or python3 pc/tools/build_boot.py --battle for 32-bit.
Build times (measured on a 20-thread desktop with a fast connection):
building the Docker image takes a minute or two and step 3 under a minute;
the first 64-bit build about 3 minutes (building the vendored SDL 3 and
glslang, and fetching and compiling NRD); the first 32-bit build about 2
minutes. A later build with nothing changed does nothing (well under a
second: pc/build/<tree>/build-stamp.json records every input of the last
complete build), and after a change only the units it touches recompile
(a few seconds; pc/tools/build_cache.py). build_boot.py --check says
whether a build would do anything. --no-build skips even the check.
Engine edits without a restart (Linux, 64-bit). pc/run-game.sh --reload
(with --vulkan for Vulkan) builds pc/build/dev64: rood_host, the
game and its state, and librood_engine.so, the rest of pc/ (renderers, UI,
editor, Lua, RPC). While it runs, pc/tools/dev_loop.sh --watch rebuilds only
the library after each save under pc/src or pc/shaders and the game swaps it
at its next vsync: no restart, the window, audio, settings and game state stay
(about 2.5 s from the save to the new engine on screen for a renderer edit;
dev_loop.sh --reload does it once). A change to the game itself or to what
the host is built from falls back to a rebuild and an RPC restart at the same
moment. See pc/docs/plans/2026-10-19-engine-reload.md.
pc/run-game.sh --vulkan --no-build starts the game without rebuilding. The
intro movie plays first (Start skips it), then the title: New Game, or
Continue to load from the memory card.
Keyboard
| Key | PS1 button |
|---|---|
| Arrow keys | D-pad |
| Z | Circle (confirm, attack) |
| X | Cross (cancel) |
| A | Square |
| S | Triangle |
| Q / W | L1 / R1 |
| 1 / 2 | L2 / R2 |
| Enter | Start |
| Tab | Select |
| J / L, I / K, O | camera: turn, zoom, reset (the right stick and R3 on a gamepad) |
| Escape or F1 | open/close the editor |
| F2 | free camera (opens the editor) |
| ` (backtick) | fast-forward while held (both stick clicks, L3 + R3, on a gamepad) |
Gamepads are SDL 3 gamepads (SDL's controller database; extra mappings
from SDL_GAMECONTROLLERCONFIG or a gamecontrollerdb.txt in pc/user/).
Buttons map by position, so the east face button is Circle (confirm) and the
south one Cross (cancel) on any pad; D-pad or left stick moves; shoulders,
triggers, Start/Select (Back) and the left stick click map to their PS1
equivalents. The right stick turns the camera around Ashley (left/right,
faster the further it is pushed) and zooms (up/down); R3 turns it back to
the game's 45-degree view and distance. L1/R1 still turn in 45-degree steps;
Start (or R3 with the reset turned off) is the first-person view. Settings:
the editor's Graphics > Controls (speed, dead zone, curve, invert, zoom
range, idle reset; see pc/README.md, "Right-stick camera").
PlayStation controllers, including the DualSense and DualShock 4 over USB
or Bluetooth, work as ordinary gamepads; their touchpad, motion sensors,
lightbar, rumble and adaptive triggers are not used. Gamepads can be plugged
in at any time; ROOD_CONTROLLER=none disables them. While the editor is
open the keyboard and mouse belong to the editor, but a gamepad still plays.
Saves are standard 128 KiB memory card images: slot 1 is
pc/save/card1.mcd (created on the first save), slot 2 pc/save/card2.mcd
(inserted only if the file exists). Save at a save point and load with
Continue on the title screen. The images are compatible with PS1 emulators.
Settings. Graphics and lighting settings are changed in the editor and
saved with File > Save settings (Ctrl+Shift+S) to pc/user/settings.cfg, a
plain text file (edits made outside the game apply live). Per-room lights and
lighting overrides are saved with Ctrl+S to pc/lights/. pc/save,
pc/user and pc/lights are yours and git-ignored.
Lighting quality. The editor toolbar's Lighting dropdown picks a preset:
| Preset | Shadows | Indirect light | Needs |
|---|---|---|---|
| Original | none: the PS1's own baked lighting | baked | anything |
| Low | shadow maps | baked | integrated GPUs |
| Medium | soft shadow maps | probe GI | no ray tracing needed |
| High | ray-traced soft shadows | probe GI | ray queries (entry RT) |
| Ultra | ray-traced (2 rays) | path tracing + NVIDIA NRD | discrete RT GPU, Vulkan |
On first run, before any settings are saved, the preset is detected: Ultra
on a discrete GPU with Vulkan ray queries, High on an integrated one with
them; without ray queries Medium on a discrete GPU, Low otherwise.
ROOD_LIGHTING_PRESET=low (any preset name, or auto) overrides it.
Choices a backend cannot run fall back to the next one (the editor shows
why). ROOD_GI=0 turns the dynamic lighting off entirely.
The editor (Escape or F1) is laid out like Unreal's: a toolbar,
an Outliner of the room's lights and glows, a Details panel (lighting,
atmosphere, post effects, graphics, diagnostics), Place Actors for light
prefabs, and Help > Keyboard shortcuts. Right-drag in the view flies a free
camera (WASD/QE); Play returns to the game camera. See
pc/README.md ("Renderer and developer overlay") for
everything it does.
Useful environment variables (more in pc/README.md): ROOD_WINDOW=WxH
(window size), ROOD_SCALE=1..8 (internal resolution, default 4),
ROOD_WIDESCREEN=1, ROOD_AUDIO=none, SDL_VIDEO_DRIVER=x11|wayland.
If something goes wrong, the terminal shows the log. A crash prints
[crash] and [stack] lines (pc/tools/where.sh resolve turns them into
function names); [UNIMPLEMENTED] name means the game reached code that is
not ported yet. Please include those lines, your GPU and driver, and what you
were doing when you report a problem.
The test runner starts the game headless (on the GPU through EGL, no X server, or on a private Xvfb display with software rendering) with scratch memory cards and settings, so your saves and settings are never touched:
cmake -S pc -B pc/build -G Ninja && cmake --build pc/build # CMake probes, once
python3 pc/tests/run.py --list # the suites
python3 pc/tests/run.py --arch 64 --renderer vulkan # everything, 64-bit Vulkan
python3 pc/tests/run.py --arch 64 --renderer vulkan rpc # suites matching "rpc"
python3 pc/tests/run.py # everything, 64-bit OpenGL
python3 pc/tests/run.py --arch 32 # the 32-bit build (no longer kept up)The runner prefers rendering on the GPU through EGL (python3 pc/tools/rood_rpc.py headless shows which mode and GPU it gets) and falls
back to Xvfb with software rendering, which is several times slower. It
prints one table with each suite's result and log
(pc/build/tests/<suite>/), and exits non-zero if any failed. It does not
build the game: build first. Some suites need a save on pc/save/card1.mcd
and are skipped without one; golden-frame references are generated locally
(pc/tests/golden_frames.py --update) and never committed. A quick boot
check without the runner:
pc/build/boot64/rood_battle_probe --skip-movies --title-checkpointexits with status 0 once the original title code reaches its input loop.
| Platform | Status |
|---|---|
| Linux x86-64 | Supported (Ubuntu 24.04 tested; X11, Wayland via XWayland or natively) |
| Windows 10/11 x64 | Native 64-bit build, cross-compiled from Linux or WSL with MinGW-w64 (Windows 11, NVIDIA RTX 4070 tested; Vulkan with ray queries and NRD) |
| macOS | Not supported, not tested |
| Linux on ARM | Not supported (the build and the guest memory layout assume x86) |
The 64-bit build runs natively on Windows as rood.exe (Vulkan or OpenGL,
ray-traced lighting and NRD, WASAPI audio, XInput/HID gamepads). It is
built on Linux, or in WSL2 on the Windows machine itself, since the
decompilation's make and the port's symbol analysis need Linux tools: the
build compiles every unit twice, for Linux (the analysis) and with MinGW-w64
(the executable). How it works and its limits are in
pc/docs/Platform_Support.md.
- In Linux or WSL2 (Ubuntu), follow Build steps 1-3 (in WSL, keep
the checkout in the Linux file system, e.g.
~/rood-boi, not under/mnt/c), and install MinGW-w64:sudo apt install mingw-w64. - Build:
python3 pc/tools/build_boot.py --target windows(it also builds the Linux 64-bit objects it analyses; NRD's Windows library is compiled from the Linux NRD build's sources and shaders). - Make a folder to play from (on WSL, a Windows drive):
python3 pc/tools/windows_dist.py /mnt/c/Games/rood-boi --disc. - On Windows, run
play.batin that folder. The log isrood.log; saves and settings stay in the folder'spc\saveandpc\useracross updates.
The developer RPC takes ROOD_RPC=tcp:PORT on Windows (a loopback TCP port:
Windows' Python has no Unix sockets); pc/tools/rood_rpc.py connects to it
from Windows or WSL. Every TCP connection must authenticate first, including
Lua eval/grant requests. Supply ROOD_RPC=tcp:PORT:TOKEN, or let the server
generate a secret in $ROOD_OUT/rpc.token (default pc/build/boot/rpc.token,
next to the default Unix socket). ROOD_RPC_TOKEN_FILE overrides this path;
rood_rpc.py reads it when the address has no token. The file is mode 0600
on Unix and owner-only on Windows; Windows refuses existing token files, so
remove the old file before restarting. Only ROOD_RPC_PRINT_TOKEN=1 prints
the generated secret to stdout. Generation/storage failure disables TCP RPC;
Unix socket behavior is unchanged. The Linux-only test harness (pc/tests,
Xvfb/EGL headless runs) does not run on Windows.
Not supported. Besides needing a Mach-O equivalent of the Windows work
(pc/docs/Platform_Support.md), macOS has no native Vulkan
(MoltenVK lacks the geometry shaders and ray queries the Vulkan renderer
uses) and caps OpenGL at 4.1 without compute shaders, and its ARM machines
would need the guest memory layout reworked.
The project's own code (the decompilation inherited from rood-reverse and the
port under pc/) is dedicated to the public domain under CC0 1.0 (see
LICENSE). Vendored third-party code under pc/third_party/
(SDL 3, Dear ImGui, ImGuizmo, glslang, PsyCross) keeps its own licence, and
NVIDIA NRD and its dependencies are downloaded at build time under their own
terms and never committed; see THIRD_PARTY.md.
rood-boi exists because of the rood-reverse decompilation.
- ser-pounce started rood-reverse and has done the overwhelming majority of the work on it. Turning Vagrant Story back into readable C that rebuilds the original game byte for byte is what made a native port like this possible at all. None of this would exist without it.
- Lil' Sassy is one of the decompilation's most prolific contributors; their work is part of the game code this port compiles and runs.
- eremtsov made the
Vagrant Story QoL mod (CC0); its
optional weapon slots quick swap (L2 + R2) is ported from it
(
pc/README.md). - Kenney made the
Input Prompts icons (CC0) that the
button prompts draw for keyboards and PlayStation, Xbox and Nintendo
controllers (
pc/README.md). - Andrew Kuhar designed the
Vagrant Story UI Remaster
(Figma prototype),
the inspiration for the optional modern menus and HUD
(
pc/docs/Modern_Menus.md). Our layouts are our own implementation; no assets from the prototype are used. - Thanks also to every other rood-reverse contributor, and to the projects and people credited in the upstream section below.
The rest of this README is the upstream project's, lightly adapted. rood-reverse is
a decompilation project for Vagrant Story for PlayStation 1, with a goal of
enabling interoperability with modern hardware and fixing bugs in the original
game. It does not contain any of the original files from the game disk; you
must own a copy of the game. The PS1 build in this repository still matches
the original binaries (make reports All files match).
Many thanks to the Chrono Cross Decompilation for much of the sound library code.
Heavily inspired by and indebted to the incredible work of the sotn-decomp team and the PS1/PS2 decompilation Discord server.
Grateful to the authors of Data Crystal’s Vagrant Story page for their excellent work and insights.
Thanks also to the following amazing projects (and their dependencies):
These badges track the upstream repository (ser-pounce/rood-reverse), not this fork's additions.
The entirety of the game's menu code and data is decompiled, including all files in MENU and SMALL, with the exceptions of MENU/MCDATA.BIN, MENU/OPMCIMG1.BIN and MENU/OPMCIMG2.BIN.
Much of the menu code has been refactored and is readable, and the menu executables are completely relocatable. It should be possible to rewrite the menu code arbitrarily, the method and data addresses in other modules will be relinked appropriately.
Due to the presence of a large number of empty sectors at the start of each directory on the disk, it should also be possible to rebuild the disk without affecting sector-based data loading in BATTLE.PRG, as long as the number of dummy sectors is adjusted accordingly.
For decompilation work, which is best contributed upstream to rood-reverse:
- n.b.: You may want to consider limiting the jobs spawned by make to something sensible like
-j8. - Fork the project
- Install system dependencies and copy disk image (see "Setup" below)
- Run
make -jto perform an initial split & build - Pick a function to decompile, use
make decompmeto create a scratch on decomp.me - Claim and decompile the scratch
- Copy the decompiled code where it belongs
- Optionally use
make permuteif needed - Run
make remake -j, and finallymake formatif the code compiles successfully - Open a PR
The project is mostly self-configuring but requires a minimal amount of setup.
- Make sure the following packages are installed, older versions may also work but this is not tested. This configuration works as-is on Ubuntu 26.04 on WSL; depending on your distro you may need additional packages.
| Package | Minimum Version |
|---|---|
| clang-format | 21.1.8 |
| g++ | 15.2.0 |
| binutils-mipsel-linux-gnu | 2.45.90 |
| make | 4.4. |
| python3 | 3.14.4 |
| python3-venv | 3.14.4 |
| unzip | 6.00 |
| wget | 1.25.0 |
Take a look at ./Dockerfile for a minimal setup on Ubuntu
- Dump your original disk to
disks/SLUS-01040.bin - Run
make -jto finish installation and perform an initial build
make -jshould be all that is needed most of the time. The first execution will configure the remaining dependencies in thetoolsdirectory and extract the files from the disk; from then on it will perform a minimal rebuild.make decompme TARGET=path/to/nonmatchings/source.suploads the target function to a new decomp.me scratch.make permute TARGET=path/to/nonmatchings/source.sinvokes the permuter for the target assembly file.make remake -jwill delete and re-split the targets; this can be necessary if the dependency management has failed to identify everything that needs rebuilding (in which case a bug report is appreciated!), or if the configuration has changed enough to be no longer valid (e.g. orphaned .d files). It's good practice to run this before submitting a pull request to make sure everything still works.make formatformats the source files and symbol addresses for consistency. Please run this before submitting a PR.make cleansimply deletes thebuildandnonmatchingsdirectoriesmake clean-allwill completely reset the project, including dropping any source changes and data files (but not the disk image). Use with caution.