Builds — retail vs GoG#
This page summarizes the two Lords of the Realm 2 executables tracked in this repository: what they share, what differs, and how evidence and spec work should treat each build.
Binary fingerprints: METADATA.md.
Builds in scope#
| Build | Filename | Ghidra export | Typical source |
|---|---|---|---|
| Retail | LORDS2.EXE |
src/LORDS2.EXE.c |
Original CD / retail install |
| GoG | Lords2-gog.exe |
src/Lords2-gog.exe.c |
GOG.com release |
Both are 32-bit Windows PE images from the same game era. They implement the same campaign core but diverge in multiplayer stack, some embedded data tables, and GoG-only skirmish mode.
Canonical policy#
flowchart LR
retail["LORDS2.EXE retail"]
gog["Lords2-gog.exe GoG"]
names["lotr2_* names retail canonical"]
map["Behavioral symbol map"]
spec["docs/spec normative rules"]
retail --> names
names --> map --> gog
retail --> spec
gog --> spec
- Retail
LORDS2.EXEis the canonical source forlotr2_*symbol names, struct VA validation, and DirectPlay networking evidence. - GoG
Lords2-gog.exeis a behavioral mirror: the same logical names are applied via fingerprint and call-graph mapping, not by matching retail virtual addresses. - Normative spec (
docs/spec/) describes game behavior. Where builds differ, spec pages must call out build-specific rules (see auto-calculation).
Symbol sync workflow: architecture/RENAME_WORKFLOW.md
(retail track + GoG parallel track).
Binary fingerprints#
| Field | Retail | GoG |
|---|---|---|
| SHA-256 | ff33c884…b034b (full hash in METADATA) |
TBD |
| File size | 1,152,000 bytes | TBD |
| Export layout | LORDS2.EXE.c, LORDS2.EXE.h |
Lords2-gog.exe.c only |
| Ghidra export date | TBD | TBD |
See METADATA.md for the authoritative fingerprint table and
re-export notes.
Feature matrix#
| Area | Retail | GoG | Notes |
|---|---|---|---|
| Campaign (map, diplomacy, siege) | yes | yes | Shared core; evidence mostly from retail |
| Tactical battles (campaign) | yes | yes | Same combat tick / pathfind / projectile logic |
| Skirmish mode | no | yes | GoG-only; see skirmish/ |
| Multiplayer stack | DirectPlay 3 (DPLAYX.DLL) |
ASIGS session strings | No DirectPlay strings in GoG export |
| Auto-calc casualty tables | retail VA / values | GoG VA / values | Different thresholds — see below |
| DirectDraw / DirectSound / WinMM | yes | yes | Same API imports per decompilation |
String data (L2.ENG) |
shared | shared | Edition-agnostic hash in METADATA |
| Symbol rename coverage | complete (FUN_* → lotr2_*) |
in progress (~3.8k FUN_* remain) |
gog-sync-progress.md |
| Networking spec | spec/networking/, protocols/dplay.md |
evidence only (skirmish MP) | ASIGS protocol not yet documented |
Shared behavior#
These areas are treated as the same game logic on both builds unless a spec page or struct note proves otherwise.
Campaign and combat core#
- Turn flow, province map, army movement, diplomacy, and siege resolution share the same subsystem structure once GoG symbols are mapped.
- Real-time tactical combat (figures, projectiles, battle AI) uses the same
code paths; skirmish adds session gates on GoG globals such as
lotr2_skirmish_active— seeskirmish/state-and-globals.md.
Multimedia stack#
Both builds import and use:
| API | Usage |
|---|---|
| DirectDraw | DirectDrawCreate |
| DirectSound | DirectSoundCreate |
| WinMM | mmioOpenA / mmioRead, timeSetEvent / timeKillEvent |
Confirmed for retail in METADATA.md; GoG export shows the same
import pattern.
Shared data files#
L2.ENG— English UI strings (SHA-256 in METADATA).- Campaign assets (
.PL8,.ENG, Smacker, etc.) are not duplicated per build in this repo; both clients read the same on-disk formats.
Symbol namespace#
Once mapped, GoG uses the same lotr2_* names as retail. Retail renames in
architecture/symbol-map.md are the name source;
GoG mapping reports live under
architecture/gog-symbol-map.md.
Known differences#
Networking#
| Build | Stack | Evidence |
|---|---|---|
| Retail | DirectPlay 3, DPLAYX.DLL, IDirectPlay3 |
architecture/net/MODULE.md, protocols/dplay.md |
| GoG | No DirectPlay / DPLAYX strings; ASIGS session configuration | skirmish/multiplayer-pvp.md |
Retail lotr2_net_* symbols are intentionally excluded from GoG symbol sync
until ASIGS equivalents are identified
(architecture/gog-symbol-map.md).
The normative networking spec under spec/networking/ covers
retail DirectPlay only today.
Skirmish mode (GoG only)#
Skirmish is a single tactical battle with no campaign map — SP vs AI or MP PvP.
The retail export has no Skirmish strings, no gateway wizard steps 0xb
/ 0xc, and post-battle flow always returns to campaign siege resolve. A
reimplementation targeting GoG skirmish parity should not expect retail to
implement this mode.
Full evidence tree: skirmish/README.md.
Auto-calculation casualty tables#
Auto-battle resolution uses static threshold tables embedded in each executable. Retail and GoG use different breakpoint values and survivor percentages.
| Build | Table VA | Spec |
|---|---|---|
| Retail | 0x004f9f10 |
spec/combat/auto-calculation.md |
| GoG | 0x004de710 |
same page (GoG section) |
Regenerate with:
python3 tools/ghidra/dump_combat_tables.py --all
Interop rule: a compatible client must use the tables from the same build as the session binary — mixing retail tables with a GoG session (or vice versa) will produce wrong casualties.
Addresses and code layout#
All code and data virtual addresses differ between builds. Never assume retail VA equality on GoG.
Examples of structural divergence:
| Pattern | Retail | GoG |
|---|---|---|
| Window procedure | lotr2_ui_wndproc + separate lotr2_ui_wndproc_impl |
merged into lotr2_ui_wndproc |
| Map AI | standard ordering | two symbols deferred due to AI step reorder |
| Combat MP stubs | — | a few unmatched symbols tied to GoG MP stubs |
See dual-address columns in module docs (e.g.
architecture/ui/MODULE.md) and per-subsystem
GoG maps (architecture/gog-symbol-map-*.md).
Symbol sync status#
GoG rename progress (approximate):
| Metric | GoG | Retail |
|---|---|---|
lotr2_* refs |
~17,380 | ~30,177 |
FUN_* refs remaining |
~3,796 | 0 |
Phases completed for ui, startup, game, gfx, map, combat; net deferred.
Live queue: architecture/gog-sync-progress.md.
Evidence workflow#
Retail rename track#
- Identify behavior in
src/LORDS2.EXE.c. - Rename to
lotr2_<area>_<purpose>perarchitecture/RENAME_WORKFLOW.md. - Record in
architecture/symbol-map.md.
GoG parallel track#
- Map behaviorally from retail names:
python3 tools/ghidra/map_gog_symbols.py --subsystem <ui|startup|game|gfx|map|combat>
- Apply renames to GoG export:
python3 tools/ghidra/apply_gog_renames.py --subsystem <name>
Do not rename lotr2_net_* on GoG until ASIGS mapping exists.
Build-specific table dumpers#
| Tool | Builds | Purpose |
|---|---|---|
dump_combat_tables.py --all |
retail + GoG | Auto-calc multiplier and casualty tables |
dump_skirmish_tables.py |
GoG only | Skirmish preset army / scenario tables |
These dump PE sections from on-disk binaries (bin/LORDS2.EXE, gog/Lords2.exe
when present); they are not general binary diff tools.
Interop notes for reimplementers#
- Pick a target build (retail, GoG, or both) before implementing build-specific tables, MP stack, or skirmish.
- Campaign + tactical combat — high behavioral parity expected between builds once the same formulas and tables are keyed to the correct binary.
- Multiplayer — retail DirectPlay and GoG ASIGS are not wire-compatible; separate protocol implementations are required.
- Skirmish — GoG-only; retail clients cannot join skirmish sessions.
- Saves and assets — treat as shared until proven otherwise; flag any format divergence in spec interop notes when found.
Related documentation#
| Topic | Path |
|---|---|
| Binary hashes and exports | METADATA.md |
| Retail symbol map | architecture/symbol-map.md |
| GoG symbol map index | architecture/gog-symbol-map.md |
| GoG sync progress | architecture/gog-sync-progress.md |
| Skirmish (GoG) | skirmish/README.md |
| Auto-calc spec (both builds) | spec/combat/auto-calculation.md |
| Retail DirectPlay protocols | protocols/dplay.md |
| Architecture modules | architecture/README.md |
Open gaps#
- GoG SHA-256, file size, and Ghidra export metadata — TBD in METADATA
(PE not in repo; only Ghidra
.cexport). - ASIGS protocol — no
docs/protocols/asigs.mdyet; skirmish MP evidence inskirmish/multiplayer-pvp.md. - Incomplete GoG symbol coverage — ~3,796
FUN_*remain; net subsystem entirely deferred. - Struct validation — many layouts validated at retail VAs; GoG re-validation
noted only where touched (e.g.
structs/lotr2_player_record.md). - Normative skirmish spec — evidence under
docs/skirmish/; not yet underdocs/spec/.