Files
UnheardCity/data/catalog/README.md

5.1 KiB

Sound catalog

file content
<ARCHIVE>.csv every sound of one audio archive: ITA, INT, FRA, DEU, ESN (speech WADs, one per language), SFX (music, ambience and effects streamed from the SFX WAD) and BANK (in-memory sounds stored inside soundbanks: footsteps, foley, combat, weapons, UI, efforts; docs/formats/banks.md)
BANK_locations.csv.gz every stored copy of the BANK sounds, and the prefetch heads of speech lines (below)
SUB_<LANG>.csv subtitles of the speech lines, one file per language (11 languages; docs/formats/subtitles.md)
SUB_locations.csv.gz every stored copy of each subtitle string (dialogue objects in the packages)
characters.csv name,character: verified speaker per sound name (language independent)
index.json per archive: fingerprint of the game files the CSV was built from (ackit/game.py: wad_fingerprint, ackit/banks.py: game_fingerprint) and counts
source/<lang>/*.txt the curated original lists (one file per character, one wemscan-style file name per line, e.g. Speech_TAPE_JOKER_1_4.wem). Files.txt = all files, Stats.txt = counts, Checkpoint.txt = progress marker. Never edited by tools.

All CSVs are UTF-8 with a header row. They contain only names and metadata (no game audio).

<ARCHIVE>.csv columns

column meaning
archive ITA, INT, ..., SFX or BANK
target location: HASH (WAD entry with one WEM), HASH:i (i-th variation, 0-based), PACK/MEDIA (music stream pack), MEDIA (BANK: Wwise media ID)
name display name: NAME, NAME_1..n for variations (NAME#i when NAME_i is already another entry's own name); BANK: the Wwise event that plays it (Play_..._i) or <Bank>_<n>
aliases other accepted names, |-separated (NAME_1 for single entries, NAME#i for variations, <Bank>/<MEDIA> for BANK)
group Speech, Music, Ambience, SFX, Unknown (docs/categories.md)
category finer category (docs/categories.md)
bank BANK: the soundbank holding the sound (first by name if several do); empty for WAD sounds
character verified speaker(s) from characters.csv, ; -separated, empty if unknown
characters_inferred characters/roles mentioned by the name (and bank) (hint only)
seconds, rate, channels of the original sound
size size of the original WEM in bytes = maximum size of a replacement (except music packs: any size)
sha1 first 16 hex digits of the original WEM's SHA-1 (detects files changed outside the tool; empty when the copies of a BANK sound differ)
notes free text (empty; for future curation, e.g. transcripts)

BANK_locations.csv.gz columns (gzip-compressed CSV)

column meaning
media Wwise media ID (hex)
file file under BmGame/CookedPCConsole, /-separated (SFX/xxxxxxxx.bnk or Name.upk)
offset position of the WEM in the uncompressed file (hex; docs/formats/upk.md)
size bytes reserved for it there
kind m = copy of a BANK sound, p = prefetch head of a speech line
sound p rows: key of that speech line (e.g. ITA:2B14E472:3); each language has its own lines and heads

A replacement is written into every m copy of a BANK sound; replacing a speech line also rewrites its p heads (docs/formats/banks.md).

SUB_<LANG>.csv columns

column meaning
speech the speech event of the line (e.g. Speech_CHURCH_B1_Ch2_POST_Explosion_BM_Cash_04)
line 0-based line of a multi-line subtitle
text original subtitle text
room maximum length of a replacement in characters (it is written in place)
enc a = cp1252 string, w = UTF-16 string
sound key of the linked speech sound (this language's WAD, or INT: for languages without speech WADs); empty when no event reaches a sound

SUB_locations.csv.gz: lang, speech, line, file, pos (hex, uncompressed offset of the FString), size, enc. Menu text has no catalog: the localization files are read directly (docs/formats/text.md).

The editor uses these files directly when the installed game matches index.json; for another game build it scans the game itself and applies the same rules (no checksums then; the bank scan takes a few minutes). ackit verify --catalog cross-checks the catalog in use against the game files (--quick samples packages).

Rebuilding / adding a language

  1. Make sure the game files are original (ackit status; ackit revert --all).
  2. Optional: add listening-based lists for another language in source/<lang>/<Character>.txt (same format; names are the same in every language, so the Italian lists already label all languages).
  3. Run python tools/build_catalog.py - it scans every archive and all soundbanks of the installed game (all languages present; ~5 minutes) and rewrites the CSVs, the location index, characters.csv and index.json.
  4. Run ackit verify --catalog (no issues expected). New character labels need a display name in ackit/classify.py: USER_LABELS (otherwise the file name is used).