Skip to content

Repository files navigation

Need for Speed: Most Wanted Decompilation Build Status Code Progress Data Progress Discord Badge

A work-in-progress decompilation of the GameCube, Xbox 360 and PS2 versions of Need for Speed: Most Wanted. The focus is currently on the GameCube version.

This repository does not contain any game assets or assembly whatsoever. An existing copy of the game is required.

Supported versions:

  • GOWE69: Rev 0 (GC USA)
  • EUROPEGERMILESTONE: Oct 21, 2005 prototype (Xbox 360 PAL)
  • SLES-53558-A124: Sep 20, 2005 prototype (Alpha 124) (PS2 PAL)
  • SLUS-21351: Black Edition (PS2 USA)
  • SPEED_EXE_1_3: PC version 1.3

SAY NO TO SLOP

We expect that as we progress on this decompilation, vibecoders will attempt to take what we have and slop out a broken port before us. Please do not give sloppers attention. Any releases and ports will be available here when they are ready.

LLMs have been used on this project. Here's why, dispite this, our project isn't slop.

  • LLMs are ONLY used as a rough pass to get code somewhere in the ballpark that we can then reference or to create tooling. All LLM code must go through extensive manual review to clean it up to the point of being usable. No slop is allowed to be merged into main. If we accepted slop we could have been "done" months ago. Raw LLM output is unacceptable due to the mistakes it makes, such as:

    • Manually assigning registers to variables to force a fake match
    • Accessing struct members by pointer offsets
    • Replacing every string and float value with something completely random
    • Renaming parameters and variables randomly
    • Reimplementing the same code multiple times and using include guards to fix the compile errors
    • Redeclaring every referenced function at the top of each file, often incorrectly
    • Casting variables to the type they already are
  • We are matching compiled machine code and debug symbols against multiple versions of the game accross multiple platforms, as well as other games in the series with shared code. To match all at once the code must be accurate to the original. This project has a large focus on accuracy to what the original code might have been. This includes matching macros, inlines, and static constants stripped from usage sites.

  • No feature or porting work is to be done until we have a near-perfect matching base to work against, and no AI will be used for this work.

As long as this canary remains here, NO AI has been used for any feature or porting work.

Dependencies

Windows

On Windows, it's highly recommended to use native tooling. WSL or msys2 are not required.
When running under WSL, objdiff is unable to get filesystem notifications for automatic rebuilds.

  • Install Python and add it to %PATH%.
  • Download ninja and add it to %PATH%.
    • Quick install via pip: pip install ninja

macOS

  • Install ninja:

    brew install ninja

wibo, a minimal 32-bit Windows binary wrapper, will be automatically downloaded and used.

Linux

wibo, a minimal 32-bit Windows binary wrapper, will be automatically downloaded and used.

Dev Container

  • Install docker

  • VSCode

    • Ensure the VSCode extension Dev Containers is installed
    • When prompted to "Reopen folder to develop in a container" select "Reopen in Contianer" or run Dev Containers: Reopen in Container
  • Zed

    • When asked "Would you like to re-open it in a container?" select "Yes, Open in Container" or run projects: open dev container

Dependencies and extensions will be included automatically
Run objdiff by running objdiff -p . in the editor's terminal

Building

  • Clone the repository:

    git clone https://github.com/dbalatoni13/nfsmw.git
  • Install dependencies (PS2 only)

    python -m pip install -r requirements.txt
  • Configure:

    python configure.py

    To use a version other than GOWE69 (USA), specify it with --version, for example --version EUROPEGERMILESTONE.

  • Build:

    ninja
  • Extracting the binaries

    • GC: Extract NFSMWRELEASE.ELF, copy it into orig/GOWE69, and convert it into a DOL using the following command:

      ./build/tools/dtk elf2dol ./orig/GOWE69/NFSMWRELEASE.ELF ./orig/GOWE69/sys/main.dol
    • Xbox 360: simply rename NfsMWEuropeGerMilestone.exe to NfsMWEuropeGerMilestone.xex and copy it to ./orig/EUROPEGERMILESTONE/

    • PS2: Copy NFS.ELF to ./orig/SLES-53558-A124/

Diffing

Once the initial build succeeds, an objdiff.json should exist in the project root.

Download the latest release from encounter/objdiff. Under project settings, set Project directory. The configuration should be loaded automatically.

Select an object from the left sidebar to begin diffing. Changes to the project will rebuild automatically: changes to source files, headers, configure.py, splits.txt or symbols.txt.

Contribution

Ghidra

To get a proper Ghidra output, you should either install the necessary extensions or ask me for access to the shared Ghidra project on decomp.dev.

Ghidra server

Recommended Ghidra build

Manual setup

Dwarf1 extension to properly load the GC debug info into Ghidra

PS2 Ghidra extension

Unfortunately the vtables can't (currently?) be loaded from the GC ELF into Ghidra, so you'll have to copy them over from the PS2 ELF and adjust the corresponding classes. Nested classes have the same problem and solution.

Use Deprecated Demangler

For Gamecube binaries the standard demangler doesn't work and you have to use the deprecated version. For PS2 binaries the deprecated version gives nicer results.

  1. From the Ghidra project window, double-click the program file to open it in the CodeBrowser.
  2. In the CodeBrowser, navigate to Analysis > Auto Analyze... (or press Shift + F12).
  3. In the Auto Analysis options window, find the "Demangler GNU" analyzer in the list and select it.
  4. In the options area (usually on the right side of the window), locate the option named "Use Deprecated Demangler".

symbols/mw_dwarfdump.nothpp

./build/tools/dtk dwarf dump ./orig/GOWE69/NFSMWRELEASE.ELF -o ./symbols/mw_dwarfdump.nothpp

This is the dwarf dump of the whole GC version of the game. The .nothpp extension is to make sure that the IDE doesn't parse it on weak laptops. This should be your main source of information. It even shows which inlines a function calls. Namespaces only show up in generics. For regular functions and variables you can search symbols.txt for the right name.

symbols/PS2

This folder contains the debug info dump of PS2 build alpha 124. It is useful for figuring out member visibility and the declaration order of virtual functions.

symbols/debug_lines.txt

GameCube Address -> line mapping

symbols/file_names.txt

GameCube file list. Headers that don't contain any inlines are not listed.

ProStreet's PDBs

Another great source where you can see visibility and namespaces is the PDBs of the Xbox 360 builds of ProStreet. You can use resym to open them up in the browser.

symbols/vlt.txt

This file contains the hashes used in AttribSys.

symbols/hashes.txt

This file contains hashes used in different parts of the game. We are currently using a template solution to calculate the hash at compile time. But as you can see in the file, this is quite verbose, we'll want to find a better solution.

symbols/bchunks.txt

This file contains bChunk chunk IDs.

Ghidra CLI setup

  • Run

    ./build/tools/dtk dwarf dump ./orig/GOWE69/NFSMWRELEASE.ELF -o ./symbols/mw_dwarfdump.nothpp
    python ./tools/split_dwarf_info.py ./symbols/mw_dwarfdump.nothpp ./symbols/Dwarf
    
  • Set up the project and Ghidra as described above (take the Ghidra repo from the decomp.dev server, you'll have to request access).

  • Import the ELF files from orig/ into the Ghidra project so the program names stay NFSMWRELEASE.ELF and NFS.ELF:

    ghidra import ./orig/GOWE69/NFSMWRELEASE.ELF
    ghidra import ./orig/SLES-53558-A124/NFS.ELF
  • Download ghidra-cli and put it into your path.

  • Tell ghidra-cli your Ghidra installation's path

    ghidra config set ghidra_install_dir <YOUR_PATH>/ghidra_11.4_DEV_20250425/ghidra_11.4_DEV
    
  • Tell ghidra-cli the path to the Ghidra project

    ghidra config set ghidra_project_dir <PATH>
    
  • Set NeedForSpeed as the default project

    ghidra config set default_project NeedForSpeed
    
  • Set the GC version as the default program

    ghidra config set default_program NFSMWRELEASE.ELF
    

Contributors

Special thanks to Brawltendo for helping with tooling and letting me use his partial decomp.

Special thanks to r033 and Toru the Red Fox for sharing their knowledge with us.

Special thanks to all the people who help us with decomp.me scratches, especially Roeming, chippy and Hummer12007.

About

WIP 1:1 Decompilation of multiple versions of NFS:MW

Topics

Resources

Stars

181 stars

Watchers

16 watching

Forks

Releases

Packages

Contributors

Languages

Generated from encounter/dtk-template