# Star Wars Episode 1 Racer Decompilation Project The goal of this repository is to document and re-implement some functions of the original game to enable the modding community. It is NOT to do matching compilation, or decompile the game entirely. The current source of truth is `data_symbols.syms` for global variables and `src/generated/hook_generated.c` for functions (Generated by `scripts/GenerateHooks.py` on `hook_generated_c.j2`) The project is heavily influenced by the [OpenJKDF2](https://github.com/shinyquagsire23/OpenJKDF2) project. # HD replacement Mod Project For the time being, the HD replacement mod is another separate project located in the `dinput_hook/` directory [here](https://github.com/tim-tim707/SW_RACER_RE/tree/master/dinput_hook). It uses knowledge such as function location and global variable locations from the decompilation project in order to replace the rendering functions. You can find releases of this mod [here](https://github.com/tim-tim707/SW_RACER_RE/releases) # Community All this work, discussion and collaboration is done in the official [Discord server](https://discord.com/servers/star-wars-episode-i-racer-441839750555369474) # Development ## Progress The progress here lists the functions which have been analysed (not necessarily re-implemented) - 25 October 2023, 30.54% (656 / 2148). - 30 March 2024, 51.3% (1106 / 2156) - 5 February 2025: Initial release of the 3D model HD replacement pack - 12 June 2026: 71.2% (1518 / 2132) ## Programs used - git - Ghidra 10.2.2 for decompilation - x32dbg as an assembly level debugger ## File formats Original file format decompilation is done in [this repository](https://github.com/louriccia/blender-swe1r). The project is a Blender addon to decompress and recompress the original game files ## Contributing This repository still lacks a lot of functions, symbols and global variables. If you want to contribute, you'll need python, a windows C compiler and Ghidra. ### Ghidra Setup Symbols can be imported using scripts in the `scripts/Ghidra` directory. You should "Parse C source" on the `src/types.h` file before using the scripts to import functions prototypes via headers. One can import the `master_header.h` generated by `GenerateMasterHeader.py` into Ghidra by running `ImportHeaderInfos.py` inside Ghidra. Global variables can be imported from the `data_symbols.syms` file using `scripts/Ghidra/importDataSymbols.py` and running it inside Ghidra. ## Building The `dinput.dll` hook is built with clang targeting 32-bit MinGW. CI uses [llvm-mingw 20260922](https://github.com/mstorsjo/llvm-mingw/releases/tag/20260922) (`llvm-mingw-20260922-ucrt-x86_64.zip`); the clang bundled with [WinLibs](https://winlibs.com/) (the "+ LLVM/Clang" i686 packages) works too. Point `LLVM_MINGW_ROOT` at the toolchain (or put its `bin` on `PATH`) and use a preset: ``` cmake --preset clang-release -DGAME_DIR="" cmake --build --preset clang-release ``` If `GAME_DIR` is set, the compiled `dinput.dll` is placed into the game directory. Presets need Ninja; without it, pass `-G "MinGW Makefiles" --toolchain cmake/toolchains/clang-mingw-i686.cmake` to a plain `cmake -S . -B build` (llvm-mingw ships `mingw32-make`). ### Memory safety | Preset / option | What it does | | --- | --- | | `ENABLE_HARDENING` (on by default) | stdlib bounds assertions (`_LIBCPP_HARDENING_MODE` / `_GLIBCXX_ASSERTIONS`), `-fstack-protector-strong`, zero-initialized locals (pattern-initialized in Debug) | | `clang-asan` (`ENABLE_ASAN`) | AddressSanitizer. The game's own allocators are poisoned too (`dinput_hook/memsafety.cpp`): freed `daAlloc` blocks sit in a quarantine and the asset buffer is poisoned above its top after each rewind, so a stale pointer into game memory reports `use-after-poison` at the read. The ASan runtime (`libclang_rt.asan_dynamic-i386.dll`, `libc++.dll`, `libunwind.dll`) is copied into `GAME_DIR`. | | `clang-ubsan` (`ENABLE_UBSAN`) | UndefinedBehaviorSanitizer (minus signed overflow and alignment, which faithful reimpls reproduce on purpose) | ASan reports are written to `/crashes/asan.`. The runtime starts before `dinput.dll` can configure it, so symbolize the report afterwards: ``` python scripts/asan_symbolize.py "/crashes/asan." ``` (`llvm-symbolizer` from the toolchain must be on `PATH`, or pass `--symbolizer`.) Only code compiled into `dinput.dll` is checked; the original game code is not instrumented. CI runs the clang static analyzer (scan-build's `analyze-build`) with extra memory-safety checkers. It fails on findings that are not in `scripts/static_analysis_baseline.json`; the HTML report is attached to the run. To reproduce locally or accept findings: ``` python scripts/static_analysis.py --cdb build/clang-release/compile_commands.json [--update-baseline] ``` ### dinput.dll configuration - USE_RELEASE_HOOK - GAME_DIR="pathToGame" (Move the compiled `dinput.dll` directly into the game directory) - PYTHON_EXECUTABLE="pathToPython" (Cmake Specific) The hook writes debug information into `hook.log` while running and makes all original game functions callable, as long as they have a valid address and function prototype in `./src`. To test the decompilation of single functions they can be marked with a `// 0xADDRESS HOOK` comment to replace the original function in the game: ```cpp // 0x004238d0 HOOK int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR pCmdLine, int nCmdShow) { ... this function will be called instead of the original WinMain function. } ``` Remove the word `HOOK` if you don't want to replace the original function: ``` // 0x004238d0 int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR pCmdLine, int nCmdShow) { ... this function will NOT be called. } ``` ## Miscellaneous The freshly installed GOG version of the game (`SWEP1RCR.EXE`) has the following md5: e1fcf50c8de2dbef70e6ad8e09371322 Other versions are not yet tested Download the vcpp5 iso for original compiler configuration here: https://winworldpc.com/product/visual-c/5x See NOTES.md for more infos ## Special Thanks Special thanks goes to - George Lucas - the LucasArt team that made all these years of fun possible, - JayFoxRox for the original work on the decompilation back in 2018, - LightningPirate and Galeforce from the SWEP1RCR discord community for their work on asset packing and decomp, - Aphex from the SWEP1RCR discord for his work on asset export to modern file formats and decompilation symbols. - Urgon from the Indiana Jones and the Infernal Machine decomp project, for his bindiff with swe1r - Ben1138 for the custom Tracks decomp, code and hooks - Angello from the SWEP1RCR discord for decompilation - tly000 for his great help on the replacement renderer and scenegraph part of this game ## Copyright Disclaimer The original game (Star Wars Episode 1 Racer) is a property of the LucasArts Entertainment Company LLC. ## Fair Use Disclaimer The content provided on this repository is for informational and educational purposes only. It is not intended to infringe upon any copyrighted material. If you believe that any content on this repository violates your copyright or intellectual property rights, please contact us immediately to seek resolution. I am not liable for any loss or damage, including but not limited to indirect or consequential loss or damage, arising from the use of or reliance on any content found on this repository.