MSVC 7.1 (cl 13.10.3077) under Wine, PE/COFF matcher with relocation verification, side-by-side diff, progress, Ghidra-seeded symbol map (15,323 functions), and the first three matched functions (/O1). Co-Authored-By: Claude Opus 5.5 <[email protected]>
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 game code or data. 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 /Gy (size-optimised; 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.
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
- Pick a function:
python3 tools/eq.py todolists unmatched game functions, smallest first. Look at it withpython3 tools/eq.py diff 0x00401050. - Write C++ for it under
src/and mark it with// FUNCTION: EQGAME 0xADDR. python3 tools/eq.py build, then map the compiled (mangled) name to the address:python3 tools/eq.py map 0x00401050 '?Append@CList@@QAEXPAUCListNode@@@Z'.checklists compiled functions that aren't mapped yet, with their mangled names.- Iterate with
diffuntilchecksaysMATCH. python3 tools/eq.py check --learnadds the globals and callees that a matching function proves (e.g.operator newat0x0060d071) to the map.
Check statuses
| Status | Meaning |
|---|---|
MATCH |
every byte equal, every relocation points at the right symbol |
MATCH? |
bytes equal, but some referenced symbols aren't in the map yet (--learn fills them) |
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
/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
liband excluded from progress. - Names are placeholders until identified. The EQEmu project and MacroQuest's Titanium-era offsets are good references for structures and function names.