Architecture¶
The oracle idea¶
The target binaries were compiled with Microsoft Visual C++ 6.0. To reproduce
them byte-for-byte, each function is transcribed from its original machine code
into a __declspec(naked) MSVC6 inline-assembly function. The compiler emits
the transcribed instructions directly; no C++ code generation is involved.
Every func_<VA>.c source is therefore both:
- a readable, annotated record of the function's instructions and behavior, and
- an input to a build that must reproduce the reference bytes exactly.
The result is an oracle: a source tree that compiles to the canonical binary. It is not an attempt to recover the original C++ source.
Source layout¶
Sources are organized by binary target and PE section, not by subsystem:
src/
mw4mercs/
text/ func_<VA>.c + in-.text data_<VA>.c
rdata/ data_0x*.c section runs
data/ data_0x*.c section runs
rsrc/ data_0x*.c section runs
txt2/ SafeDisc .txt2 leftover
artifacts/ committed PE build artifacts + CSV metadata
blade/ text/ rdata/ data/ artifacts/
gundll/ text/ rdata/ data/ artifacts/
language/ text/ rdata/ data/ artifacts/
missionlang_mercs/ text/ rdata/ data/ artifacts/
mw4stats/ text/ rdata/ data/ artifacts/
zloglib/ text/ rdata/ data/ artifacts/
Filenames are canonical: func_<8-hex-va>.c and data_<8-hex-va>.c. Semantics
live in the file header and inline comments, never in the filename. The
per-binary subsystem indexes under docs/va_index/ provide the semantic
map.
Non-.text sections (.rdata, .data, .rsrc, .txt2) are byte-exact data
runs. The generated data_0x*.c sources are committed, so the default build
does not need the reference. nmake data remains the optional regeneration
path; see BUILD.md.
Building an image¶
The default EXE build has three stages:
- Compile
.textsources — allsrc/mw4mercs/text/*.care compiled with the pinned MSVC6 flags intobuild/obj/. - Compile data sources — the committed
src/mw4mercs/{rdata,data,rsrc,txt2}/data_0x*.cruns are compiled intobuild/obj/data/. - Assemble —
exe_image_assemble.pyplaces every object at its reference RVA, resolves relocation sites, fills pads from the committed artifact, composes the sections, and writesbuild/MW4Mercs.exe.--diffcompares the result to the reference when it is present.
The PE header, inter-function pad bytes, and residual extern table are
committed artifacts. exe_image_assemble.py --init is the optional
regeneration path that rebuilds them from a reference EXE.
Module DLLs use the same model with data_assemble.py and
image_assemble.py; their data sources and .bin artifacts are committed.
gundll's in-scope VA list is provided at reference/in_scope/gundll.txt for
its coverage report.
Relocation resolution¶
An unlinked object's relocation slots contain placeholder values. The assembler resolves each slot from the symbol name:
- Address-embedded names (
FUN_00401000,g_0076B000, ...). - The committed
src/<target>/artifacts/extern_addrs.csvtable for residual symbols whose names carry no address. - The import map parsed from the assembled
.rdatafor imported functions.
The committed extern table is authoritative. The source-comment fallback is legacy and must never drive the build; the assembler hard-errors if a symbol would resolve that way.
Verification model¶
There are four levels of checking:
- Hash gate — compares the built image to the canonical SHA-256; this is the reference-free acceptance check.
- Full-image byte diff — composes the complete binary and compares it to a reference binary when one is present. It catches ordering, padding, alignment, relocation, and section-composition errors.
- Masked per-function diff — compares one compiled object against the reference function, masking 4-byte relocation sites.
- No-mask per-function check — places the object at its VA, resolves every relocation, and compares every byte.
The hash gate is the default gate. The byte-level checks are optional diagnostics that require the reference binaries.
What is intentionally out of scope¶
- The
.txt2SafeDisc leftover (preserved only as committed bytes for layout). - External DRM/SafeDisc components and the bundled DRM DLLs; the in-image wrapper is part of the platform surface.
- External CRT and middleware code; CRT ranges inside a target module are part of that module's surface.
- The four editor/config tools shipped with the game (documented under
docs/editor_tools/, not oracle targets). ScriptStrings_MERCS.dll(resource-only, no code).