Version 3.2.1: whole bank copies of voice lines, unique names, docs figures checked by tools/check_docs.py

This commit is contained in:
2026-10-10 19:30:06 +02:00
parent 1586abb8e9
commit cac52e7597
29 changed files with 919 additions and 188 deletions

View File

@@ -5,17 +5,19 @@ editor Unheard City (mission 2).
## What works (verified)
- **Every sound of the game is cataloged and editable**: the speech WADs (5 languages x 10,816), the SFX WAD (651)
and, new, the **15,404 in-memory sounds** stored inside soundbanks (archive `BANK`: footsteps, foley, combat,
weapons, UI, efforts; 8,098 shared by all languages + ~1,460 localized speech lines per voice language) in 65
loose `.bnk` files and 975 `.upk` packages. ackit reads and patches the
and, new, the **15,355 in-memory sounds** stored inside soundbanks (archive `BANK`: footsteps, foley, combat,
weapons, UI, efforts; 8,092 shared by all languages, ~1,450 localized speech lines per voice language, 6
shared by several) in 65 loose `.bnk` files and 975 `.upk` packages. ackit reads and patches the
LZO-compressed UE3 packages itself (`ackit/upk.py`, `lzo.py`; no external tools). A replacement goes into every
copy (93,910 copies); 396 speech lines with prefetch heads in banks get their heads rewritten too.
Names: 6,456 BANK sounds are named after their Wwise event (`Play_...`), the rest after their bank.
copy (93,826 copies). 445 WAD voice recordings (89 lines) also have bank copies (396 prefetch heads, 49
whole copies; 2,185 copies), which are rewritten with them.
Names: 13,501 BANK sounds are named after the Wwise event that plays them (`Play_...`, `Speech_...`), the
other 1,854 after their bank.
- **Catalog check**: `ackit verify --catalog` compares the catalog with a fresh scan of the game (missing, extra,
duplicate, size/checksum, category, character, language, bank copies, subtitle copies/texts) and re-derives
every relation from the game files (lines, names, subtitle links, prefetch heads, copies): **catalog OK** on
the full game.
- **Subtitles**: found in `RDialogueEvent` objects inside the packages (9,016 speech lines x 11 languages) and
- **Subtitles**: found in `RDialogueEvent` objects inside the packages (9,032 speech lines x 11 languages) and
in 41 scripted `RSubtitle` objects (radio, encryption cards, Riddler; linked through `RSubtitleLookup`),
parsed, cataloged (`SUB_<LANG>.csv`) and linked to their voice recordings through the soundbanks: 103,304 of
103,658 strings in 11 languages (INT 9,373 of 9,404), each on the same line in every language; an event that
@@ -25,8 +27,8 @@ editor Unheard City (mission 2).
WAD recording to its media by its own language's BKPK table (10,816 / 10,816 in each language). Result:
12,434 lines (WAD + in-memory) with exactly one recording in each of the 5 voice languages, no gap and no
conflict; recordings stored twice (5 per language) are written together. Independent checks: every WAD
recording is a source in a bank of its own language (54,055 / 54,055), every prefetch head is the start of
its recording (2,101 / 2,101). Each line has one name in every language and carries its identity (`line`):
recording is a source in a bank of its own language (54,055 / 54,055), every prefetch head or whole bank copy
is the start of its recording (2,185 / 2,185). Each line has one name in every language and carries its identity (`line`):
speaker labels (3,366 in every language), subtitles and mod packages (another language: the same line)
follow it. Speaker labels vs the game's dialogue speaker field: 2,766 agree, 19 differ (categories.md).
- **Menu text**: the localization files (`BmGame\Localization\<LANG>\*.int`, ~7,000 strings per language),
@@ -40,13 +42,14 @@ editor Unheard City (mission 2).
- **Safety**: every changed file (WAD, bank, package, localization file) is rebuilt from a verified original copy
in the store + the edits applied now; reverting the last edit restores it byte-for-byte; files changed by
another tool or Steam are detected (whole-file SHA-1) and not overwritten without confirmation.
- **Tests**: 130 automated tests (unit, synthetic game with packages/banks/dialogues/localization, a
two-language game for the lines, real-game read-only, offscreen GUI incl. list order, selection and loading
overlays) pass. `ackit verify` PASS (incl.
- **Tests**: 133 automated tests (unit, synthetic game with packages/banks/dialogues/localization, a
two-language game for the lines (incl. a recording also stored whole in a bank), the shipped catalog's cross-references, real-game read-only (every
name of every language's catalog resolves to its own sound), offscreen GUI incl. list order, selection and
loading overlays) pass. `ackit verify` PASS (incl.
300/300 in-memory WEMs rebuilt byte-identically).
- **Real game** (2026-10-10), all reverting and checking byte-identity themselves:
`tools/e2e_features.py --lang all` 78/78 PASS in all 11 languages (every copy of an in-memory sound, each
language's localized line, prefetch heads, a multi-copy subtitle, a scripted subtitle, a menu text, sound +
`tools/e2e_features.py --lang all` 89/89 PASS in all 11 languages (every copy of an in-memory sound, each
language's localized line, prefetch heads, a line also stored whole in banks, a multi-copy subtitle, a scripted subtitle, a menu text, sound +
subtitle in one package, a mod moved to another voice language and matched to the same line at another
position); `ackit verify --ingame` PASS (music heard, ncc 1.0);
`--banks` PASS (77 in-memory sounds of the front-end packages replaced in 54 files: the game loads them, 68
@@ -54,9 +57,9 @@ editor Unheard City (mission 2).
found in the game's memory, no crash); `tools/e2e_editor.py` PASS. Game files original at the end
(`ackit status`). The catalog builder refuses to run on a modified game, so the catalog always describes the
original files.
- **Package**: `dist/UnheardCity-3.2.0-windows-amd64.zip` (86 MB, catalogs included). With `PATH` reduced to
- **Package**: `dist/UnheardCity-3.2.1-windows-amd64.zip` (86 MB, catalogs included). With `PATH` reduced to
the Windows folders the packaged exe passes its smoke test (in the game's language - Italian on the test PC:
21,025 sounds loaded, encode + inject, 9,377 subtitles and 7,020 menu texts loaded, an in-memory sound decoded from a package) and the GUI starts and
21,015 sounds loaded, encode + inject, 9,377 subtitles and 7,020 menu texts loaded, an in-memory sound decoded from a package) and the GUI starts and
quits cleanly. The installer is unchanged since mission 2 (install/upgrade/uninstall verified then).
## Unresolved / limitations
@@ -68,17 +71,21 @@ editor Unheard City (mission 2).
text's length ("room"); cp1252 subtitles accept cp1252 characters only. Lifting these limits means moving
objects inside the packages (new export offsets/sizes, added chunks): designed but not done, because it could
not be verified automatically in the game (decisions 4c).
- **Unlinked subtitles**: 29 speech names (~32 strings per language: Riddler trophy texts, Arkham City Stories,
radio reports and tapes) have no event in any bank; they are listed and editable but not linked.
- **Subtitle coverage is uneven in the game itself**: no subtitles exist for efforts/grunts, few for combat barks
(11 %) and cutscene lines (10 %; most cutscene lines are not played through speech events and have no dialogue
object). No other subtitle storage was found in the packages (all classes with subtitle data checked).
- 659 voice lines are played by no event whose name the game stores; they are named after their English
- **Unlinked subtitles**: 24 speech names (24-36 strings per language, INT 31: Riddler trophy texts, Arkham City
Stories, radio reports and tapes) have no event in any bank; they are listed and editable but not linked.
- **Subtitle coverage is uneven in the game itself** (INT voice lines with a subtitle): none for efforts/grunts,
few for combat barks (9 %), cinematics and boss fights (23 %; most cutscene lines are not played through speech
events and have no dialogue object), 89-97 % for story, predator, character and open-world lines. No other
subtitle storage was found in the packages (all classes with subtitle data checked).
- 637 voice lines are played by no event whose name the game stores; they are named after their English
recording's position (the same name in every language). Mod packages from versions before 3.1 carry no line
identity: their voice lines are not moved to another language (listed instead of guessed).
- Speaker labels: 2 names of the curated lists match two recordings each (wemscan name collision), both are
labelled; 19 labels differ from the game's dialogue speaker field (to be checked by listening).
- **Unnamed sounds**: ~9,000 BANK sounds have no event name and are named `<Bank>_<n>`.
- **Unnamed sounds**: 1,854 BANK sounds are reached by no event whose name the game stores and are named
`<Bank>_<n>`.
- 25 SFX originals (music seek tables and sample counts, looping ambience) are not reproduced byte-for-byte by
the WEM rules (`docs/formats/wem.md`); writing is not affected (replaced music plays in game).
- Two copies of media `1C898731` differ; its checksum is left empty. Channel order for 4-6 channel sounds is
unverified. M4A/AAC/WMA input needs an ffmpeg on the system.
- Another game build is scanned at first start (WADs: seconds; banks, lines and subtitles: a few minutes,