The Esoteric Path — 1.13c grimoire

A reverse-engineering canon for Diablo II: Lord of Destruction 1.13c (32-bit). 1,134 records covering functions, globals, structs, hooks and findings — every one carrying an explicit trust level, because most of them are not independently verified.

Read this before using any address.

Files

FileSizeUse it for
symbols.jsonl1.6 MB Start here if you are a program or a model. Line-delimited JSON — one record per line, parse with a loop. The canonical form; everything else is derived from it.
GRIMOIRE.md1.3 MB The same corpus as prose Markdown, grouped and cross-referenced. Better for reading and reasoning end-to-end; worse for lookup.
search.html3.0 MB Human browsing — self-contained page with client-side search over every record. Not useful to a crawler: the search needs JavaScript, so fetch the two files above instead.

Working notes

Eight documents the records cite directly, published so those citations resolve. They are lab notes, not essays — written to survive a hostile fact-check rather than to be read for pleasure, and internal in register. Absolute paths like C:\Diablo II\BH 1.5s2-1.13c\BH.dll appear throughout on purpose: they record which binary was measured, which is the difference between a measurement and a claim.

DocumentSizeWhat it is
research/BH-CONFIG-HOTSWAP.md13 KB Swapping a loot filter's config at runtime, including the version that logged success and changed nothing, and the fault guard the optimiser silently deleted.
research/LIFEBAR-COORDINATE-ORIGIN.md54 KB Deriving a unit's screen position from its cached iso coordinates, with both camera corrections. The longest of these and the most worked-through.
research/WHIST-113c-COMPILATION-INDEX.md44 KB An index over a community address compilation. See the note below.
kb/reference/d2-re-reference-1.13c.md26 KB General 1.13c reverse-engineering reference.
research/HARDCODED-MONSTER-INDICES.md13 KB Monster indices the engine hardcodes rather than reading from a table.
research/SOUND-VOLUME-EDITS.md7 KB Every changed row of the sound-volume pass, with before and after values.
research/MODULE-BASE-MAP.md3 KB Module load addresses, and which of them relocate.
tools/dc6/count_arrow_removals.py5 KB Counts edited regions between two DC6 sprite sheets. Histogram-matches luminance first, because a global tone shift otherwise reports thousands of false differences.
On the compilation index.

WHIST-113c-COMPILATION-INDEX.md is an index over an address compilation assembled by whist. The compilation is whist's work, not Doug's. What is his in that document is the verification pass — checking those addresses against live binaries and recording which held. Nothing in it claims the underlying compilation, and it should not be read as doing so.

Record schema

Two shapes coexist. The older, dominant shape is keyed on desc; 419 newer records use title/body. Handle both.

{
  "id":      "D2Client.DrawGame",      // unique key, referenced by refs[]
  "kind":    "function",               // see distribution below
  "module":  "D2Client",               // owning module (89% of records)
  "rva":     "0x44230",                // offset from module base (17% of records)
  "status":  "verified",               // sourced | verified | confirmed | open | testing | closed | noted
  "trust":   "verified",               // verified | trusted | sourced   <-- READ THIS FIELD
  "desc":    "main world render entry…",
  "source":  "['re:esoteric']",        // provenance; 'discord:…' = community corpus
  "note":    "corpus-sourced; may be 1.10f-era — rebase + verify",
  "locator": "…", "value": "…", "refs": ["other.record.id"], "fields": […]
}

Kinds (1,134 total)

function 296finding 286global 160note 151struct 131reference 75solution 16openquestion 11hook 4other 4

Trust

verified 262trusted 396 sourced 384untagged 90plausible 2

Module bases (1.13c)

VA = module_base + rva. Bases are the stock load addresses; ASLR is not in play for these DLLs on a normal install, but confirm against your own process before trusting a computed VA.

ModuleBaseModuleBase
D2Client.dll0x6FAB0000D2Common.dll0x6FD50000
D2Game.dll0x6FC20000D2Win.dll0x6F8E0000
D2Gfx.dll0x6FA80000D2Glide.dll0x6F850000
Fog.dll0x6FF50000

Note: D2Win's 1.10f base is 0x6F8A0000 and its 1.13c base is 0x6F8E0000 — a frequent source of bogus cross-version conclusions.

If you are a model, start here

  1. Fetch symbols.jsonl and parse line-by-line.
  2. Filter on BOTH fields: trust == "verified" and status not in ("superseded","failed","decoy"). They are orthogonal and you need both — trust records how well-sourced a claim was, status records whether it survived. A rigorously-derived claim later falsified keeps trust: verified and gets status: superseded, with its desc opening in a bracketed [SUPERSEDED <date>: <why>] block naming what fell and what still stands. Filtering on trust alone will hand you disproven theories.
  3. Follow refs[] to assemble context; kind:"finding" and kind:"note" records carry the reasoning, not just the addresses.
  4. Check kind:"openquestion" (11 records) — those are the known-unknowns, and the most useful place to contribute.
  5. Treat anything sourced as a hypothesis to test against the binary.
  6. Superseded records are kept deliberately, not deleted — the chain of what was tried and why it fell is often more useful than the answer. Read the [SUPERSEDED …] prefix before reusing any address from one.