Drop the names taken from an external offset header (functions and globals), keeping only names the binary itself proves: _WinMain@16 from the CRT entry call, and Class::Method names from the client's own log strings. The six functions Ghidra missed stay in the map under neutral FUN_ names, justified by vtable/pointer references. NAMES.md, README and ROADMAP no longer point at third-party offset lists. Co-Authored-By: Claude Opus 5.5 <[email protected]>
2.7 KiB
Roadmap: from scaffold to an identical eqgame.exe
End state: python3 tools/eq.py link produces an eqgame.exe with SHA1
e8fdc68b46df69dde0094d57fd7ba2cb33aef1c5, where every byte of game code and
game data comes from the C++ in this repository.
What can never live in this repo
These are copyrighted by Microsoft, Daybreak or RAD/Miles. The build takes them
from the contributor's own orig/eqgame.exe at build time, never from git:
| Part | Size | Plan |
|---|---|---|
MSVC 7.1 static CRT + Dinkumware STL non-inline code (LIBCMT, LIBCPMT) |
~6.9k small functions | carved from the original (kind lib), or linked from a contributor's own VS.NET 2003 Lib/ |
| VC6-built third-party libs found in the Rich header | tbd | identify, then carve or build from source if it's open (zlib 1.1.2 is) |
.rsrc (icons, dialogs, version info) |
190 KB | carved; optionally an .rc script later |
| PE headers / Rich header | 4 KB | generated from config once the link is done with link.exe |
Phases
- Function matching. Done for 3 functions. ~8.4k game functions (1.94 MB) remain.
Each needs C++ that compiles byte-identically (
eq.py check=MATCH). Ghidra pseudo-C for every function lands inbuild/decomp/<addr>.c. - Types and names. Recover classes, vtables and struct layouts into
include/. EQEmu's Titanium packet structs help here. - Translation units. Group functions into the original
.cppfiles. Function order in.textfollows link order, so consecutive address ranges are files. String literal and.dataorder inside each range confirm the boundaries. - Data. Move
.rdataand.data(strings, vtables, tables, float constants) into source via// GLOBAL:definitions.eq.py linkalready places annotated initialised globals. - Real link. Replace the placing linker in
eq.py linkwith MSVC 7.1link.exe, using the recovered object order, carved library objects and generated import libs. Then rebuild the headers and verify the hash.
How link works today
It starts from the original image and overwrites every matched function and every annotated initialised global with the compiled bytes. Relocations are resolved from the symbol map, not copied. The hash must stay equal to the original's, so any wrong relocation or misplaced object fails the build. The coverage line it prints is the real progress number for the "same hash from source" goal.
Parallel work
Contributors (or agent sessions) take disjoint address ranges and put their code in
src/eqgame/ files named for that range or the recovered class. Names and globals
come from // FUNCTION: / // GLOBAL: annotations in the source, so nobody needs
to edit config/eqgame/symbols.txt while decompiling.