Commit Graph
2 Commits
Author SHA1 Message Date
gromandClaude Opus 5 e61976bc0e formats: the world-map goldens, and a nondeterministic continent lookup
The four map tables against the realm's own files. One real bug, and three
findings that are the realm's data rather than ours.

**`WorldMapArea::continent` was a coin flip.** It `find`s the `area_id == 0`
row for a map id, and 5875 had exactly one per map so order never mattered. The
realm ships two for map 0 — 14 "Azeroth" and its own 694 "World" — and the
lookup iterated the `by_id` `HashMap`, whose order is seeded per process. So
`continent(0)` answered Azeroth or World depending on the run. Now it walks
file order, which is the reference's own walk and picks 1.12's row; the test
asserts 14 and passes eight runs in a row where it used to flip.

- **WorldMapArea** 51 -> 132 rows loaded, of 175 in the file. The 43 dropped are
  dropped on purpose: `AreaName` empty, `AreaID` 0, the whole rect zero, one per
  instance map (33 Shadowfang through 533 Naxxramas, then the realm's 800s). An
  instance has no continent art — but `AreaID == 0` is exactly what
  `ui_world_map.rs:146` reads as "this row is a continent", so keeping them
  would put 43 unnamed continents in `GetMapContinents()`. `str_at` folds an
  empty string to `None` and the row falls out; the test now pins that as
  deliberate. The realm's third *named* continent is 694 "World", a second sheet
  over map 0 whose art ships (patch-M) but whose four rect columns are all zero
  — the only named row like that. `map_proj::zone_uv` already refuses a zero
  span and answers 0.0 instead of dividing, so that sheet puts a blip in the
  corner rather than NaN.

- **WorldMapContinent** 2 -> 3 rows. The new row's `MapID` is 42, which the same
  patch *deleted* from `Map.dbc` along with the rest of 1.12's dev test maps
  (13 "Testing", 25 "Scott Test", 29 "CashTest", 37 "Azshara Crater", 42
  "Collin's Test", 44 "<unused> Monastery"). It is inert rather than broken: the
  continent list comes from `WorldMapArea`, and this table is only ever reached
  by `wmc.get(map_id)` for maps 0 and 1, so nothing asks for continent 42.

- **The zone bitmaps are repainted.** `Azeroth.zmp` and `Kalimdor.zmp` have the
  realm's own copies in patch-3 and patch-4, and every id they write is a
  **zone** where 1.12 wrote sub-areas and left the client to roll them up.
  Azeroth: 1874 labelled cells over 34 distinct ids, all zone-level, against
  2630 over 334 of which 310 were sub-areas (Northshire Valley, Crystal Lake,
  Fargodeep Mine). After the one-hop rollup `ui_world_map.rs:193` applies, 1280
  cells agree, 534 name a *different* zone, 816 lost a zone and 60 gained one —
  a redrawn map, not a mechanical flattening. Nothing of ours needed changing:
  the rollup is a no-op on an already-flat grid. The test asserts the structural
  claim behind the number (every labelled cell is a top-level zone), which 1.12's
  own file would fail, so a decode slip cannot hide inside a re-recorded count.

- **WorldMapOverlay** 526 -> 707, and not an extension: 360 ids added, 179
  removed, 347 survivors given a different texture and rect. None of this
  table's numbering is 1.12's, so only the joins are worth asserting.

`dbc_diff` gained `--row=N`, which dumps a row from the winning copy *and* the
baseline — the only way to read a row the realm deleted, which is how the six
test maps above got their names.

benilla-formats: 25 -> 21 failures, no regressions.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SgstFWtn1RxEJ5kVrpgYwn
2026-10-31 19:20:54 -06:00
gromandClaude Opus 5 e58ddc10ab formats: re-record the sound and visual goldens, and a tool to say what moved
Six modules' data goldens against the realm's own files, plus the thing that
made the last three honest rather than guessed: `examples/dbc_diff.rs`.

The tool reads the copy of a DBC the chain *wins* and the copy it shadows and
diffs them row by row. `Chain::copies` is ascending priority and several
`patch-*` archives are mounted, so 1.12's own file is usually still underneath
the realm's; the baseline is the highest copy in a stock archive (`dbc.MPQ`,
`patch.MPQ`, `patch-2`) so the diff reads "what OctoWoW changed about 1.12".
Schema-free — field 0 is the id, a row is its raw 4-byte slots — so an
undecoded column still shows up as "id N differs at slot K". `--row=N` dumps a
row with its text slots as text, which is how three ids below got names.

Two findings, both the shape of a reference into a table that has no such row:

- **The glow band.** The realm rewrote `ItemDisplayInfo.dbc` (patch-5) and left
  `ItemVisuals.dbc` as 1.12's out of base `patch.MPQ` — 34 rows, ids `1..=134`.
  22 ids its new displays name run past that end, where a later expansion's
  table continues, so 61 items wear no glow. The reference drops them exactly
  as we do (`0x479700` skips a visual id past the max id), so this is the
  realm's data, not our decode. Pinned by id with the displays behind each.

- **The silent kits.** `SoundEntries.dbc` grew 4623 -> 8805 rows and 4764 of
  its 16537 variation cells name a file the chain has not got: 236 directories
  hold no file at all (LesserManaFiend, ChineseDragon, ZoneMusic\BloodElf), and
  the ones that exist miss the TBC boss voices — Illidan, Akama, Lady Vashj,
  Kael'thas — plus 552 of `Sound\Doodad`. What makes that an observation about
  the data and not about our path join is *where* the misses fall: of the 2834
  kits with a dead variation, 2832 have an id past 4623, the last row 5875
  shipped. A faulty separator would miss evenly across old rows and new. Only
  395 OgreFidget and 3792 WaterFallLarge predate the realm, and only 3792 is
  wholly silent, so nothing that used to make a sound has gone quiet.

The rest are censuses re-recorded with their 5875 figures beside them. Every
one is safe to re-record for a mechanical reason: `benilla-dbc` fails the load
outright when a schema's expanded field count differs from the header's
(`lib.rs:215`), so a test that *reaches* a count assertion has already proved
its layout unchanged.

- SoundEntries 4623 -> 8805 rows, EAXDef census (2072,2,2549) -> (6241,4,2560),
  type-17 NPC voices 275 -> 529 (still every one authored dry), variation cells
  8961 -> 16537. Kit 8940's ten ASH_SPEAK misses stay, and now assert *why*:
  the asset ships and it is the authored leading `\` that cannot reach it.
- VocalUISounds 533 -> 688 rows, live normal kits 785 -> 1085.
- ItemSounds nonzero field-11 20513 -> 32728.
- CreatureSoundData 406 -> 525 rows. A fifth row carries pet barks, and
  `dbc_diff` settles what it is: row 348 is 1.12's own and columns 27-29 are
  the only thing patch-4 changed about it, filled with the Imp's own kits — so
  an imp barks whichever of its three models is in play, `Creature\Imp\Imp.mdx`
  and TBC's `Impoutland` and `Moargminion`. Row 348 says nothing else at all.
- SpellVisual 2165 -> 2313, SpellVisualKit 1772 -> 1969, SpellChainEffects
  18 -> 21, chain CharProc census (68,48,20) -> (110,51,59). The three new
  beams are HarvestBeam, SpiritLinkBeam and Beam_ChainIron_NoAlpha, and unlike
  the sound rows the art ships with them; 23 zeroes every parameter the others
  animate. All three keep 1.12's segment length.
- ItemVisuals: enchants carrying a glow 102 -> 109, and 108 of 109 resolve —
  still exactly the one -1, so every new glowing enchant names a row that
  exists. Only the display side dangles.

benilla-formats: 38 -> 25 failures, no regressions.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SgstFWtn1RxEJ5kVrpgYwn
2026-10-31 19:10:27 -06:00