Richard Burns Rally is from 2004. It is still alive because community plugins reach into one old executable at fixed addresses. This page describes a proposal: replace that executable one block at a time, with the game still playable after every step, with NGP, RSF and the stages people already have. At the end no original code would be left, and the plugins and the 500+ community stages would come along.
The proposal in pacenote form: rebuild, keep every byte → swap the blocks no plugin touches → swap the rest together with the plugin authors → no old code left.
Why
A living game on a frozen file
Twenty years on, Richard Burns Rally is still the reference for rally driving. That is the community's work: NGP physics, the RSF platform, hundreds of stages, plugins for HUD, controls, pacenotes and VR. All of it rests on one closed 32-bit executable from 2004 whose source was never published. Every plugin reaches into that file at fixed addresses, beside the official plugin SDK.
This makes the game frozen. The executable cannot be recompiled. So it cannot go 64-bit and cannot change inside: every improvement is a patch on top of patches, with the addresses as the contract. Graphics can be wrapped from outside, as the d3d9 proxies do, but the game underneath stays the 2004 code.
The rally-ng project rebuilds the executable as C++ source, function by function. Today 6,691 of 16,492 functions compile back to the original bytes; the rest stays original bytes at its place, so the whole file still relinks byte for byte. That would turn the frozen file into parts that can be changed safely: rebuild a block, prove it against the original, and only then replace it. The proofs on this page: the whole executable relinks byte for byte, a recorded run re-simulates bit-exact on the rebuilt executable's own physics, and the project's own renderer draws the live game, yes, with 3D trees. The trees are a nod to the community's running gag, not the point. The point is room for stage authors: today a stage can only hold what the 2004 renderer, collision and physics understand. A sidecar would let an author go beyond that, with real 3D models, weather zones, surface and collision data, authored in the same Blender workflow, while the stage still loads in the old game. The demo uses an existing stage only as a test bed.
PlayersWould keep the game as it is today, with NGP, RSF and their stages, and get better graphics, weather and a modern engine step by step. Old stages would keep loading; the RSF stage library comes along with RSF.
NGPDocumented interfaces instead of patches into a 2004 binary. The physics could follow the game to modern compilers, 64 bit and new platforms.
Stage authorsStages that could carry more. Shown today with the obligatory 3D trees; weather and a better collision model are proposed. Old stages would keep loading unchanged.
RSFThe platform and its stage library can carry over into the new game instead of ending with the old executable.
The rest of the page lays out the proposal: what the executable is made of, where each plugin plugs in, the phases to RBR Next Generation, and the phase at which each plugin needs its source.
The plan
Five proposed phases, block by block, the game playable after each
Every block below is a part of RichardBurnsRally_SSE.exe. Step through the phases to see each block change from original code to rebuilt code to a new implementation. Which plugins reach into which block follows in the explorer below.
The small letters after a fact say how it is known: O observed in bytes, files or runs; I inferred from observations; D documentation or community claim, not checked here; H hypothesis. Hover a letter for the same text.
RichardBurnsRally_SSE.exe
SHA-256 cd20966e…
original coderebuilt from source, same bytes and addressesnew implementation
Block phases are the plan, not measured per block.
How it fits together
One executable, its DLLs, and the plugins
The executable loads the graphics engine as a separate DLL, takes the system DLLs from Windows and carries original Microsoft libraries linked in. Plugins come in through the official SDK door, and through needles. A needle is a call, jump, patch or write from a plugin into a fixed address of the executable. It keeps working only while the code at that address stays where it is.
Black arrows are official interfaces: the plugin SDK, DLL loading, imports. The amber arrow stands for the plugins' needles into the game code. Green is rally-ng: the mirror plugin only reads each frame and hands it to the rally-ng renderer. The bar in each block is the share of its functions rebuilt from source. Who loads LocoMotion.dll and eax.dll is inferred, not traced.
Plugins
Where each plugin reaches in
Pick a plugin. The card says what it does, where its source stands and from which phase it would need it. The bars count its needles per block of the executable.
Loading explorer.json …
“Not tied to a block yet” is not a part of the executable. It holds the needles the scan cannot yet tie to a block, because their target has no name or class yet (an unnamed function, a plain global, or a number that only looks like an address). Each name recovered in the rebuild moves needles out of it. Third-party libraries in the install (OpenSSL, FMOD, OpenXR) are left out: they cannot reference the executable, so their hits are number coincidences.
Rebuilt source
C++ that compiles back to the original bytes
Each function below was written as C++ and compiled with the original compiler, Microsoft cl.exe 13.10 from Visual Studio .NET 2003. The output is byte-identical to the 2004 executable, verified by relinking the whole image. Names are the project's reconstruction, except where the published plugin SDK gives them.
Each example is a function NGP patches today. Above the source sits what a plugin author works from now: a few instructions around the patch site, under the disassembler's name for the function. The highlighted lines are the same place in both.
Loading examples.json …
One patch, three times
The ground query NGP redirects
The best way to see what the rebuild changes for a plugin author is one concrete patch. CGround::QuerySegment is how the 2004 physics asks the world: “a line from here to there, where does it hit the ground, with which normal and which material?” NGP wants that question answered by its own collision system.
Today
Six bytes in a 2004 binary
Inside the compiled function sits MOV ECX,[0x007c755c] at 0x0051bcb0: load the collision system before asking it. NGP rewrites the address in that one instruction, and does the same in the two sibling queries. The game now asks NGP without knowing it.
Works only while those bytes sit at exactly that address. Any other build of the executable, and the patch lands in the wrong place.
Now, rebuilt
The same bytes, readable
The function is C++ again and compiles to the identical bytes, so NGP's patch still lands. For the first time the patch can be read: the highlighted line in the example “A ground query NGP redirects” above is the one NGP rewrites (g_pCollisionSystem, the pointer to the collision system), and everything around it shows what the game expects back (hit point, normal, material, two ids).
Nothing changes for players. What changes is that the patch is now documented by source instead of by an address.
Phase 3, with the author
A door instead of a patch
When collision gets its new implementation, the three operand rewrites would become one registration call that NGP makes once at start. The game would ask whatever collision system is registered. NGP would keep its physics and lose its dependency on one exact build.
// sketch, to be designed with the NGP author
void RBR_RegisterCollisionSystem(ICollisionSystem *system);
Multiply this by NGP's 40 patch sites and 50 virtual-table slots, and the gain is clear. Every patch NGP maintains today can become a documented call, designed from what NGP already uses. With that, NGP could follow the game to newer compilers, 64 bit and new platforms.
The redirect reading of the patch is inferred from the patch map: the patch site and the instruction are observed in the bytes, the effect is not traced at run time. The registration call is a sketch, no code exists.
For plugin authors
Where each plugin needs its source
Under this proposal, every plugin runs unchanged through phase 1, because every address it touches stays put. From the phase on its card, a block the plugin reaches into would get a new implementation. From then on the plugin could only move forward with its source. What it would get in return: a documented interface instead of patched addresses in a 2004 binary, an interface that does not break when the executable changes, and a place in the new game.
NGP: the physics
NGP is the reason RBR is still the reference. It is also the plugin most deeply tied to the old executable: 40 patch sites in physics and collision, 50 virtual-table slots it calls, and 1,247 fixed reads of game state. Same-or-better physics in RBR Next Generation means NGP physics, which means its author would be part of phase 3. The physics interface would be designed from what NGP already uses, so NGP would shed those patches instead of chasing them.
RSF: the platform and the stages
Rallysimfans.hu.dll carries the RSF platform: online events over TLS, its Lua scripts and the stage delivery. It reaches into the executable at about 300 places (direct needles: calls, jumps, memory access, patches). The RSF stages of 2025 ship encrypted; where they are decrypted is not settled and not pursued. Backward compatibility with every stage would therefore run through RSF. The project does not decrypt and does not extract keys.
For stage authors
Old stages keep loading, new stages can do more
The proposal grows the stage format by sidecars: extra files next to the unchanged .lbs. A game without the sidecar sees the old stage. A game with it sees more. The first sidecar replaces the flat tree cards of a stage with real 3D trees in glTF, written either from a shipped stage or from Blender through an extension of the RBR track exporter. Yes, 3D trees, the running gag of rally game announcements. They are here for a different reason: this is more than another shader, it replaces a part of the stage itself. The aim is not to rework other people's stages. It is to free stage authors from the limits of the 2004 engine: whatever the old renderer, collision or physics cannot express, an author could put into a sidecar and decide how the stage looks and drives in the new game.
Shown
Own renderer, drawing the live game frame by frame from a scene stream, in its own window and process.
Tree sidecar: 3D trees in glTF next to the unchanged stage, from a shipped stage or from Blender.
A plain community stage (Mitterbach) runs through the same pipeline with no code change.
Planned
Dynamic weather and time of day per stage.
A better collision model that stage authors can describe.
Modern materials. The format would be built with the exporter authors, not around them.
Same free camera beside the road on Chirdonhead. Left: the stage's own tree, two crossed flat cards, thin from this angle. Right: the same tree replaced by a 3D tree from the sidecar. Both drawn by rally-ng.One frame of a recorded run, drawn three times by the rally-ng renderer: close to the original look, cel, and paper. The renderer is rally-ng's own code, not a filter on the old one.
Current state
Numbers, each with its source
Loading stats.json …
Labels: O observed in bytes, files or runs; I inferred from observations; D documentation or community claim, not checked here; H hypothesis. The live frame rate is the game's own pace, which the rally-ng renderer keeps up with. The throughput card is a separate off-screen measurement of the renderer alone. An unnamed read is not an unused read: a run-time trace covers only part of them.
Ground rules
What this project does not do
No game filesNo executables, stages, cars or sounds are shared. Everything runs from your own RBR install. No old code does not mean no old assets: the original assets stay in your copy.
No crackingNo decryption of RSF stages, no extracted keys, no bypassed protection.
Open sourceThe project's own code is open from the first public word. Code adapted from the GPL-3 track exporter stays GPL-3.
Nothing for saleNo company, no hiring, no money. Offline only, no online play with modified builds.