Files
SalastilandClaude Opus 5.5 b1cc8a1b0d Keep only symbol names proven from the shipped binary
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]>
2026-10-19 23:01:25 -04:00

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

  1. 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 in build/decomp/<addr>.c.
  2. Types and names. Recover classes, vtables and struct layouts into include/. EQEmu's Titanium packet structs help here.
  3. Translation units. Group functions into the original .cpp files. Function order in .text follows link order, so consecutive address ranges are files. String literal and .data order inside each range confirm the boundaries.
  4. Data. Move .rdata and .data (strings, vtables, tables, float constants) into source via // GLOBAL: definitions. eq.py link already places annotated initialised globals.
  5. Real link. Replace the placing linker in eq.py link with MSVC 7.1 link.exe, using the recovered object order, carved library objects and generated import libs. Then rebuild the headers and verify the hash.

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.