s-b-repo/nfsmw-2005-re

GitHub: s-b-repo/nfsmw-2005-re

Stars: 4 | Forks: 0

# NFSMW Reverse-Engineering Project ## What this repo contains . ├── README.md ← you are here ├── LICENSE ← BSD-3 ├── docs/ ← Documentation, schemas, indices (the core deliverable) │ ├── ARCHITECTURE.md ← 817-line canonical reference │ ├── ANTI_RE_AND_PATTERNS.md ← 18 anti-RE techniques + how we beat each │ ├── PROGRESS.md ← Wave-by-wave session log │ ├── attribute_hashes.md ← attributes.bin schema + per-type crack tables │ ├── attribute_cracks_verified.json ← 294 hash→name pairs (re-hash verified) │ ├── sdk_addrs.json ← 181 hardcoded addresses from NFSPluginSDK │ ├── sdk_enums.json ← 65 enum definitions │ ├── sdk_structs.json ← 245 struct definitions (1,712 fields) │ ├── renames.csv ← 6,513 Ghidra-named functions │ ├── nfsplugin_sdk_mw05/ ← Mirrored BSD-3 SDK headers (berkayylmao) │ ├── GHIDRA_MCP_ENDPOINTS.md ← Tooling reference (Ghidra HTTP plugin) │ ├── DEBUGGER_PLAN.md ← Wine + gdbserver attach walkthrough │ └── plan.txt ← Project plan / status board ├── tools/ ← Linux-native CLI + scripts │ └── nfsmw-tool/ ← Pure-Python multi-command CLI │ ├── nfsmw_tool.py ← Hash, JDLZ decompress, save verify, SDK lookup, etc. │ ├── Makefile │ └── README.md └── mods/ ← Proof-of-concept mods └── infinite_trainer/ ← Working .asi (Tweak_InfiniteNOS + Tweak_InfiniteRaceBreaker) ├── nfsmw_trainer.c ├── Makefile ← Cross-compiles via i686-w64-mingw32-gcc └── README.md ## Headline findings | Finding | Reference | |---|---| | **bChunk hash = Bob Jenkins mix3 (1996), seed `0xABCDEF00`** — not DJB2/FNV | [`docs/ANTI_RE_AND_PATTERNS.md`](docs/ANTI_RE_AND_PATTERNS.md) §1 | | **Script VM is vanilla Lua 5.0.2** — confirmed by error-string match | [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md) wave-5 section | | **JDLZ v0x02** algorithm fully RE'd from `speed.exe @ 0x64db40` | [`tools/nfsmw-tool/nfsmw_tool.py`](tools/nfsmw-tool/nfsmw_tool.py) `jdlz_decompress()` | | **Save files use MD5 trailer** (not CRC) — IV constants verified | [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md) §wave-5 save/load | | **Cutscenes use On2 VP6 + MAD audio**, not Bink | [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md) §wave-5 cutscenes | | **AI doesn't draft and doesn't use nitrous** — "slipstream" is just rubber-banding | [`docs/ANTI_RE_AND_PATTERNS.md`](docs/ANTI_RE_AND_PATTERNS.md) §14 | | **Drift mode is NOT in MW** — leftover Underground-era string | [`docs/ANTI_RE_AND_PATTERNS.md`](docs/ANTI_RE_AND_PATTERNS.md) §14 | | **NO physics worker thread** — integrator runs inline on main thread | [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md) wave-9 correction | | All 5 original mystery hashes cracked: AUTO_SIMPLIFY, BEHAVIORS, SimplePhysics, ExplosionEffect, DROPOUT | [`docs/attribute_cracks_verified.json`](docs/attribute_cracks_verified.json) | | **HUD per-frame walker** = `CHudWidgetArray_Tick @ 0x58ca30` (vt[1] of vtable @ 0x8a2538); inline iteration of 11 fixed slots; mode-filter via widget[6..9] masks | [`docs/wave13_hud_walker.md`](docs/wave13_hud_walker.md) | | **24 HUD widgets** mapped to exact CHudWidgetArray storage offsets (+0x2c0..+0x32c). Only 10 walker-ticked; 14 are FNG-bus / passive | [`docs/wave14_hud_slot_map.md`](docs/wave14_hud_slot_map.md) | | **BustedMeter is a passive widget** — Update is no-op; external writer pokes the data into the FNG | [`docs/hud_widget_decomps/BustedMeter_Update.txt`](docs/hud_widget_decomps/BustedMeter_Update.txt) | ## Quick start ### Install the CLI cd tools/nfsmw-tool make install # symlinks ~/.local/bin/nfsmw-tool nfsmw-tool stats # show project coverage ### Compute / look up a bChunk hash $ nfsmw-tool hash MASS bChunk("MASS") = 0x4A56503D $ nfsmw-tool lookup 0xC2094707 0xC2094707 = YAW_SPEED (Float-typed attribute) ### Decompress a JDLZ bundle $ nfsmw-tool jdlz /path/to/GLOBAL/GLOBALB.LZC Decompressed 2803648 bytes → /path/to/GLOBAL/GLOBALB.LZC.bin ### Build the infinite-NOS trainer sudo pacman -S mingw-w64-gcc # or apt install gcc-mingw-w64-i686 cd mods/infinite_trainer make # produces nfsmw_trainer.asi cp nfsmw_trainer.asi /path/to/NFSMW/scripts/ Run NFSMW, race, use NOS — never depletes. Validates the entire docs-to-runtime chain. ## Companion: the mod SDK A header-only, cross-platform mod SDK built on top of this RE database lives in its own repo: **[s-b-repo/nfsmw-2005-sdk](https://github.com/s-b-repo/nfsmw-2005-sdk)**. Build mods from Linux/Windows/macOS (MinGW-w64 i686); the output DLL loads under **both** Ultimate-ASI-Loader and **BepInEx 6** from a single file. Its address tables are generated from this repo's `docs/sdk_addrs.json`, `docs/attribute_cracks_verified.json`, and `docs/sdk_enums.json`. ## How to use this repo for your own modding 1. **Find what you want to change.** Use [`docs/attribute_hashes.md`](docs/attribute_hashes.md) to find an attribute name (e.g. `MASS`, `TopSpeed`, `RubberBandGain`), or [`docs/sdk_addrs.json`](docs/sdk_addrs.json) to find a global (e.g. `Tweak_InfiniteNOS`, `DrawCars`). 2. **Compute the hash if needed.** `nfsmw-tool hash ` gives you the 32-bit key. 3. **Find the read/write site in Ghidra.** Open `speed.exe`, search for the constant. With our 460 disassembly annotations applied, the hashes are pre-labeled with their cracked names. 4. **Write a mod.** Easiest path: use the [nfsmw-2005-sdk](https://github.com/s-b-repo/nfsmw-2005-sdk) (`NFSMW_PLUGIN_MAIN`, typed globals, hook helpers). Or copy `mods/infinite_trainer/` as a bare `.asi` template and replace the address constants. ## How this work was done Eight reverse-engineering "waves" (parallel agent + direct work) over ~6 days: | Wave | Date | Achievement | |---|---|---| | Baseline | pre-2026-05-09 | ~6,338 fns named, JDLZ algorithm, attributes.bin schema | | Wave-1 | 2026-05-09 | 10 subsystems mapped (allocator, world streamer, particles, audio, customization, FNG, network, damage, input, replay) | | Wave-2/3/4 | mid-May | EAGL physics anchor, Cop AI, Render passes, Animation, Career, Script VM | | Wave-5 | 2026-05-14 | NFSPluginSDK integration (178 headers), Lua 5.0 confirmed, 8 more subsystems mapped | | Wave-6 | 2026-05-14 | +50 attribute cracks (manual + compound wordlists) → 121 / 345 (35 %) | | Wave-7 | 2026-05-14 | Community NFS hash DB integration (Attribulator + OpenNFSTools + nfsu2-re) → 294 / 345 (85.2 %); all 5 mystery hashes cracked | | Wave-8 | 2026-05-14 | Input-binding system fully mapped, 13 HUD widgets mapped, prior misreadings corrected | | Wave-9 | 2026-05-14 | Infinite-NOS trainer built + validated, EAGL physics correction (no worker thread), event-bus API mapped, semantic roles for 15 hashes | See [`docs/PROGRESS.md`](docs/PROGRESS.md) for the full log. ## What this repo does NOT contain - **No copyrighted game assets.** No `speed.exe`, no bundles, no music, no models. You need a legally-acquired copy of the game to use these tools. - **No game installer.** Bring your own copy. - **No PDB / source leak.** Everything here is community-derived from a clean-room reverse-engineering effort. ## Acknowledgments - **berkayylmao** for the [NFSPluginSDK](https://github.com/berkayylmao/NFSPluginSDK) — BSD-3 plugin SDK with 178 type headers. Saved months of work. - **NFSTools/Attribulator** for [the community attribute hash database](https://github.com/NFSTools/Attribulator) (43,102 names) — single-pass match took attribute crack rate from 35 % to 85 %. - **MWisBest/OpenNFSTools** for [`res/hashes.txt`](https://github.com/MWisBest/OpenNFSTools) — curated MW-specific names. - **yugecin/nfsu2-re** for the [runtime-trace hash dumps](https://github.com/yugecin/nfsu2-re). - The broader NFS modding community for a decade of accumulated knowledge. ## License BSD-3-Clause. See [`LICENSE`](LICENSE).