# EverQuest Decomp/Recomp A byte-for-byte matching decompilation of the EverQuest **Titanium** client (`eqgame.exe`, linked 2005-10-31 18:36:26 UTC). The goal is C++ source that recompiles with the original toolchain to the exact same machine code, which can then be ported, fixed and recompiled freely. This repository contains **no original binaries or game assets**, only decompiled source and tools. You need your own copy of the client; the tools check it against the expected hash. | | | |---|---| | Target | `eqgame.exe`, SHA1 `e8fdc68b46df69dde0094d57fd7ba2cb33aef1c5` | | Compiler | MSVC 7.1 (Visual Studio .NET 2003), `cl` 13.10.3077, run under Wine | | Flags so far | `/O1 /GX /GS` (size-optimised, EH, stack cookies; confirmed by matching code) | | Functions | ~15.3k found by Ghidra: ~8.4k game code, ~6.9k CRT/STL/library | ## Setup Requirements: Linux (or WSL/macOS) with `wine`, `python3` + PyYAML, `ninja`, `i686-w64-mingw32-objdump` (binutils for mingw), and optionally Ghidra. ```sh tools/setup.sh /path/to/EverQuest/eqgame.exe # links orig/, fetches MSVC 7.1, verifies both python3 tools/eq.py build # compile src/ -> build/obj/ python3 tools/eq.py check # compare against the original python3 tools/eq.py progress ``` ## Workflow 1. Pick a function: `python3 tools/eq.py todo` lists unmatched game functions, smallest first. `build/decomp/.c` has Ghidra's pseudo-C for it (`tools/ghidra/ExportDecomp.java`), and `python3 tools/eq.py diff 0x00401050` shows the disassembly. 2. Write C++ under `src/`, with an annotation directly above each definition: ```cpp // FUNCTION: EQGAME 0x00401050 void CList::Append(CListNode* node) { ... } // GLOBAL: EQGAME 0x0079c100 CSpellPointManager* g_pSpellPointManager; ``` Annotations on declarations (`extern` globals, called functions) tell the checker where referenced symbols live. `// LIBRARY: EQGAME 0xADDR mangled` names CRT helpers (see `include/crt_symbols.h`). Add `NONMATCHING` after the address for code that is functionally right but not yet byte-exact. 3. `python3 tools/eq.py build && python3 tools/eq.py check`. The tools pair each annotation with the compiled (mangled) symbol, so there's no need to edit `symbols.txt` by hand. 4. Iterate with `diff` until `check` says `MATCH`. 5. `python3 tools/eq.py link` rebuilds `build/eqgame.exe` from the compiled objects and checks its SHA1 against the original. It also prints how much of the binary now comes from source. See [docs/ROADMAP.md](docs/ROADMAP.md). ### Check statuses | Status | Meaning | |---|---| | `MATCH` | every byte equal, every relocation points at the right symbol | | `MATCH?` | bytes equal, but some referenced symbols have no address yet (annotate them, or `check --learn`) | | `NONMAT` | marked `NONMATCHING`, still differs | | `BADREF` | bytes equal, but a call/global resolves to a different address than the map says | | `DIFF` | code differs | Relocated fields (calls, globals, string literals) are masked when comparing bytes and then verified separately: against the symbol map for named symbols, and by content for string literals and float constants. ## Layout ``` config/eqgame/config.yaml target hash, compiler flags config/eqgame/symbols.txt ADDR SIZE KIND NAME for every known function/global src/ decompiled source (one .cpp per original translation unit, eventually) include/ shared headers tools/eq.py build / check / diff / progress / map tools/binfmt.py PE + COFF readers tools/cl.sh MSVC 7.1 under Wine tools/ghidra/ headless export used to seed symbols.txt orig/ your eqgame.exe (git-ignored) ``` Per-file compiler flags: put `// CFLAGS: /O2` (etc.) near the top of a source file. ### Re-seeding the symbol map from Ghidra ```sh /opt/ghidra/support/analyzeHeadless build/ghidra eqgame -import orig/eqgame.exe \ -scriptPath tools/ghidra -postScript ExportFunctions.java "$PWD/build/ghidra_functions.txt" python3 tools/eq.py import-ghidra build/ghidra_functions.txt # keeps existing names ``` ## Notes - The Rich header shows ~640 C++ objects from cl 13.10.3077, plus libraries built with VC6 (build 8447/9178), likely Miles Sound System, DirectX helpers, etc. Those are classified as `lib` and excluded from progress. - Names are placeholders until identified from the binary itself (its own log strings and code structure); see `config/eqgame/NAMES.md`.