# rr-decomp Matching decompilation of **Ridge Racer** (PlayStation 1, Namco, 1994 — Japan release, `RIDGERACER` volume, SLPS-00001), and a static recompilation that runs it natively. > **No game is distributed here, and none can be.** There is no download that plays > Ridge Racer: everything is built from `PSX.EXE` and the game reads its data from the disc. > You need **your own legally-owned copy** (SLPS-00001), dumped from your own disc, > to build or verify anything. Without it, what is offered is the code and the notes. No copyrighted game data is committed here — no disc image, no executable, no textures, no audio, and no disassembly. `asm/`, `assets/` and `build/m0/asm/` are regenerated on your machine from your own copy by `python3 tools/setup.py` — the same practice as every project on [decomp.dev](https://decomp.dev). ## Status ``` $ python3 tools/progress.py game code: 408/408 functions in C, 186536/186536 bytes (100.00 %) $ python3 build.py build/PSX.EXE 31ec5d3616a0fdb456da27a984fc5b92259ff1f6 OK - matches the original ``` What that figure covers, exactly: - **All 408 game functions** (`0x800121F4`–`0x8003FA9C`, the code Namco wrote) are plain C in `src/fn/`, one file per function. There is no `INCLUDE_ASM`, no `__asm__` and no inline MIPS anywhere in `src/`. Each file is compiled by **GCC 2.5.7** (`-O2 -G0 -mips1 -msoft-float`) through maspsx (ASPSX 2.21 mode). The result is linked, and the whole executable is compared with the original: byte-identical. - **The PsyQ libraries** (Sony's runtime, from `0x8003FA9C`) stay assembly (`asm/psyq.s`, regenerated locally). They are not part of the game. - **Data and rodata** stay splat output (`asm/data/`, regenerated locally). `tools/progress.py` counts a function as done only if it has a C file in `src/fn/`. The size column comes from the original's function table, not from the build. > **History note.** Until August 2026 this repo reported "949/949 byte-matching". That count > came from transcribing the original MIPS into `__asm__` blocks, so it matched by > construction and proved nothing. It was replaced by the standard splat layout and an > honest count: 23 % of functions and 5.6 % of instructions in real C. The figure above is > that same honest count, now complete — every game function is real, compiled C. ## Building the matching decomp ```sh sh tools/toolchain.sh # once: GCC 2.5.7 PSX, binutils-mips, m2c (Linux/WSL) cp /path/to/PSX.EXE . # SLPS-00001, sha1 31ec5d36... python3 tools/setup.py # splat: asm/ (libs + data), assets/, build/m0/asm/ python3 build.py # compiles src/fn/*.c, links, checks the sha1 ``` `build.py` reads `RR_GCC` (the compiler directory, `/opt/decomp/gcc/2.5.7` by default). maspsx is vendored in `tools/maspsx` (MIT). splat is pinned to 0.50.0 / spimdisasm 1.42.4 by `tools/setup.py`. | path | what | |---|---| | `rr.yaml`, `symbol_addrs.txt`, `undefined_syms.txt` | splat config of the matching build | | `src/fn/*.c` | the game, one file per function. `func_80034050.c` also holds `func_8003446C`: the two only match when compiled together (`/* covers: */` marker) | | `include/` | `common.h`, `game.h`, assembler macros | | `tools/segments.py` | regenerates the `src/fn` subsegments of `rr.yaml` | | `tools/try.py` | compiles one C file and diffs it against the original function | | `tools/jtbl.py`, `tools/fixjtbl.py` | jump tables (`/* jtbl: … */` markers in the C files) | | `tools/autodec.py`, `tools/perm_*` | m2c drafts and decomp-permuter batches used while matching | | `m0.yaml`, `m0_symbol_addrs.txt`, `m0_reloc_addrs.txt` | listing for the native runtime (below). `m0_symbol_addrs.txt` also holds the descriptive names found so far (`st_race_main`, `car_simulate`, …) | ## Notes from the matching - The rodata boundary fix (`0x29E8 → 0x29F4`) and the game/PsyQ seam at `0x8003FA94`, both found by the earlier pipeline, held. - The earlier belief that the game was built with four flag sets (`-O1` and `-O2`, GCC 2.5.7 and 2.7.2) did not hold: **every game function matches GCC 2.5.7 `-O2`**. The apparent `-O1` units were `-O2` register-allocation and scheduling effects that the C had not yet reproduced. - What it took for the last hundred functions, for anyone matching GCC 2.5.7: nested assignments to fix operand order (`m = i + (m = m + 1)`), `do { } while (0)` to raise a pseudo's allocation priority, dead stores to break CSE, statements repeated in each branch to reproduce cross-jumping, globals accessed as struct fields to pin the scheduler, implicit-`int` callees for the delay-slot `nop` before a `jal`, and `cc1 -dlg` dumps to read the allocation order. ## The native runtime A second track runs alongside the decompilation: a **static recompilation**. `tools/recomp.py` translates every MIPS instruction of `PSX.EXE` into C mechanically, and `tools/m0/` supplies a model of the hardware. The point is not emulation — it is to have a native milestone that boots today, so that each byte-matched function can replace its translated twin one at a time without ever breaking the whole. **It is playable today — `v0.1.0`.** It boots from your own disc image to the loading screen, the title, the menu and a race; it draws, it plays the disc's twelve Red Book audio tracks and synthesises the SPU's twenty-four voices, and it takes a keyboard or a gamepad. Analogue steering and pedals go through the neGcon protocol the 1994 game already speaks. It builds natively on Linux and, with `--windows`, on Windows. [`CHANGELOG.md`](CHANGELOG.md) says what that covers, what it does not, and which defects had to be found on the way. See [`tools/m0/README.md`](tools/m0/README.md) to build and run it, and [`RECOMP_NOTES.md`](RECOMP_NOTES.md) for the defects found along the way — the translator's own bugs were found by differential testing against qemu-mipsel (114/116 functions bit-identical over 1856 cases), and the GTE's against an independent second implementation (11 600 comparisons, 29 encodings). Its listing comes from `m0.yaml`, written to `build/m0/asm/` by `tools/setup.py`. Nothing generated by this track is committed: `game.c` is the game's own code in another notation, exactly as `asm/` is. ## Asset formats - [`MAP_RRM_FORMAT.md`](MAP_RRM_FORMAT.md) — track geometry file. - [`TRACK_SPINE_FORMAT.md`](TRACK_SPINE_FORMAT.md) — **the track centreline node tables in `PSX.EXE`**. This closes the "Not found" item in the MAP.RRM writeup: there is no per-section transform because there is nothing to place. The track is a 20-byte-per-node polyline (`D_8005A44C` / `D_8005B84C` / `D_8005CC4C`) and MAP.RRM's quads are skinned along it. All three tables decode to closed loops. - [`DISC_NOTES.md`](DISC_NOTES.md) — disc layout. ## Next steps 1. Names: carry the descriptive names in `m0_symbol_addrs.txt` (345 functions) into `src/fn` and `symbol_addrs.txt`, and type the globals. 2. Group `src/fn` back into the original translation units. 3. In the native runtime, replace the recompiled functions with the matched C, one at a time. ## Transparency Heavily AI-assisted: tooling, splitting and C conversions are driven by Anthropic's Claude under human direction and review. Nothing here requires trust — with your own copy of the game, `python3 tools/setup.py && python3 build.py` reproduces the result locally.