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

50 lines
2.7 KiB
Markdown

# 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.
## 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.