|
|
|
|
@@ -10,29 +10,31 @@ Survey of the installed game (buildid 3718300), 2026-10-09.
|
|
|
|
|
| where | banks | unique in-memory WEMs |
|
|
|
|
|
|-------|-------|-----------------------|
|
|
|
|
|
| loose `SFX\*.bnk` (Batman/Catwoman footsteps, 32 surfaces each, + `TST_Prep_Media`) | 65 | 1,117 |
|
|
|
|
|
| banks embedded in `.upk` packages (in 1,432 of the 2,650 packages) | 3,340 | 15,641 (~276 MB) |
|
|
|
|
|
| banks embedded in `.upk` packages (in 1,432 of the 2,650 packages) | 3,340 | 14,802 |
|
|
|
|
|
|
|
|
|
|
All of them are in the catalog (archive `BANK`).
|
|
|
|
|
|
|
|
|
|
The two sets share 119 media IDs: 15,800 unique media IDs in 96,011 places (bank copies). 396 of them are
|
|
|
|
|
**prefetch heads** of streamed WAD sounds (below), so there are **15,404 in-memory sounds**. All copies of a
|
|
|
|
|
**prefetch heads** of streamed WAD sounds and 49 are **whole copies** of WAD recordings (below), so there are
|
|
|
|
|
**15,355 in-memory sounds**. All copies of a
|
|
|
|
|
media ID are byte-identical except `1C898731` (two variants). The WADs, by comparison, are fully covered: the
|
|
|
|
|
BKPK tables in the packages reference 2,543 WAD entries, all of them in the catalog.
|
|
|
|
|
|
|
|
|
|
Embedded WEMs by bank name prefix: `Speech` 7,872, `CHR` (character foley, combat, bosses) 3,896, `PSO` 781,
|
|
|
|
|
`WPN` 664, `NPC` 475, `OBJ` 439, `SEQ` 265, `GUI` 208, `PSA` 203, `MTN` 196, `PX` 195, `DVC` 100, `GEN` 80,
|
|
|
|
|
`PHY` 73, `AMB` 65, `SBJ` 50, others < 30. The `Speech_` banks (e.g. `Speech_EMOTE_Batman`, `..._GRUNT`) hold
|
|
|
|
|
speech: grunts and efforts (language-neutral, 165) and **localized lines** (about 1,460 per language, see
|
|
|
|
|
*Localized banks*).
|
|
|
|
|
All WEMs seen are Vorbis (format tag 0xFFFF), the same codec as the WADs: the footsteps are mono (4 stereo),
|
|
|
|
|
the embedded ones mono or stereo (~22 % stereo in a 2,533-WEM sample).
|
|
|
|
|
Embedded WEMs by bank name prefix (a media held by banks of two prefixes counts for both): `Speech` 7,827, `CHR`
|
|
|
|
|
(character foley, combat, bosses) 3,624, `PSO` 737, `WPN` 577, `NPC` 471, `OBJ` 411, `SEQ` 253, `PSA` 203,
|
|
|
|
|
`PX` 195, `MTN` 191, `GUI` 155, `DVC` 100, `GEN` 80, `PHY` 73, `AMB` 61, `SBJ` 50, others < 30. The `Speech_` banks (e.g. `Speech_EMOTE_Batman`, `..._GRUNT`) hold
|
|
|
|
|
speech: efforts, grunts and a few other lines stored once for every language (119 sounds) and **localized
|
|
|
|
|
lines** (about 1,450 per language, see *Localized banks*).
|
|
|
|
|
All WEMs seen are Vorbis (format tag 0xFFFF), the same codec as the WADs: the loose footsteps are mono (4
|
|
|
|
|
stereo); of all 15,355 in-memory sounds 13,982 are mono, 1,196 stereo, 177 have 3-6 channels.
|
|
|
|
|
|
|
|
|
|
## Names
|
|
|
|
|
- No list names these media IDs (the community hash list names only WAD entries and banks).
|
|
|
|
|
- Media IDs have no names of their own: a sound is named after the Wwise event that plays it (event names
|
|
|
|
|
are in the packages' name and export tables, event ID = FNV-1 of the name), else after its bank.
|
|
|
|
|
- `CookedPCConsole\CookedBanks.txt` lists all 3,345 cooked bank names. Bank ID = FNV-1 32 of the lowercased
|
|
|
|
|
name (the same hash Wwise uses for every name). 3,338 of them are embedded in packages, 4 are loose `.bnk`
|
|
|
|
|
files (`Init`, `Global`, `Music`, `Music_PDLC`); `AMB_OW_A6`, `AMB_OW_C1`, `AMB_OW_E1`,
|
|
|
|
|
`Speech_EMOTE_Thug_Muffled_Stop` and `Speech_GFxUI_ArkhamCityStories` were found nowhere.
|
|
|
|
|
name (the same hash Wwise uses for every name). 3,338 of them are embedded in packages (`Music`, `Music_PDLC`
|
|
|
|
|
also as loose `.bnk` files), 2 are only loose `.bnk` files (`Global`, `Init`); `AMB_OW_A6`, `AMB_OW_C1`,
|
|
|
|
|
`AMB_OW_E1`, `Speech_EMOTE_Thug_Muffled_Stop` and `Speech_GFxUI_ArkhamCityStories` were found nowhere.
|
|
|
|
|
- Loose footstep banks are named in their STID chunk (`CHR_BatmanFootsteps_Concrete_Media`, ...).
|
|
|
|
|
|
|
|
|
|
## Bank layout (version 56, Wwise 2011.1)
|
|
|
|
|
@@ -51,6 +53,12 @@ with bank id 0 whose media is not in the same bank (loaded by another bank); 133
|
|
|
|
|
(`wad.md`). A prefetch source's media is also in the bank's DIDX: that in-memory copy is the **head** of the
|
|
|
|
|
streamed WEM (its size = the source's size), which the game plays while the rest is read from the WAD. 396
|
|
|
|
|
WAD sounds have such heads (2,101 copies); replacing one of them must rewrite the heads too.
|
|
|
|
|
49 more WAD recordings (9-11 per language: game-over taunts, an encryption-card line, a cutscene line, scripted
|
|
|
|
|
story lines) are
|
|
|
|
|
also stored **whole** in banks: an in-memory source with the WAD recording's own media ID, byte-identical to
|
|
|
|
|
the WAD WEM (84 copies). They are handled like heads: part of the WAD line, written and reverted with it, not
|
|
|
|
|
sounds of their own (`catalog._whole_recordings`). Heads and whole copies together: 445 recordings, 2,185
|
|
|
|
|
copies (`BANK_locations.csv.gz` kind `p`).
|
|
|
|
|
|
|
|
|
|
## Localized banks
|
|
|
|
|
Speech banks are localized inside the (language-neutral) packages: one `AkBank` export starts with a language
|
|
|
|
|
@@ -58,9 +66,10 @@ list (FStrings `INT FRA ITA DEU ESN`) and then holds one block per language, in
|
|
|
|
|
of the speech WAD entry for that language (`wad.md`) and a complete bank, with the same bank ID in every
|
|
|
|
|
language. ackit gives each bank and each BKPK table the language of its position in that list (an export
|
|
|
|
|
whose block count differs from its language count would be reported; none does). Each in-memory media gets
|
|
|
|
|
the languages of the banks that hold it (`BANK.csv` column `language`): 8,098 sounds are language-neutral,
|
|
|
|
|
~1,460 belong to one voice language, 6 to several (a DLC intro line shared by INT/FRA/ITA/ESN while DEU has
|
|
|
|
|
its own); a media stored in the banks of every language is listed as `''` (the same recording everywhere).
|
|
|
|
|
the languages of the banks that hold it (`BANK.csv` column `language`): 8,092 sounds are language-neutral,
|
|
|
|
|
1,450-1,456 belong to one voice language, 6 to several (5 shared by INT/FRA/ITA/ESN while DEU has its own, 1
|
|
|
|
|
by INT/FRA/ITA); a media stored in the banks of every language is listed as `''` (the same recording
|
|
|
|
|
everywhere; 167 of these are voice lines, e.g. efforts and radio chatter).
|
|
|
|
|
A catalog shows the neutral sounds plus the loaded language's lines; names are unique per language.
|
|
|
|
|
|
|
|
|
|
## Lines: one recording per language
|
|
|
|
|
@@ -73,17 +82,18 @@ and the game ties the recordings together itself:
|
|
|
|
|
- Every recording, streamed, prefetched or in memory, is the source of a Wwise Sound object; Sound objects,
|
|
|
|
|
events, actions and containers have the same IDs in every language, only the media differ. A *line* = the
|
|
|
|
|
recordings that are sources of the same Sound objects: 12,434 lines (WAD and in-memory), each with exactly
|
|
|
|
|
one recording in each of the 5 voice languages (61,510 recordings), no Sound object with two recordings in
|
|
|
|
|
one recording in each of the 5 voice languages (61,485 recordings), no Sound object with two recordings in
|
|
|
|
|
one language. Line identity (`line` column) = the smallest Sound object ID.
|
|
|
|
|
- Prefetched sources count too: the 396 lines with a prefetch head (mostly the game-over taunts) are linked
|
|
|
|
|
only through them.
|
|
|
|
|
- Prefetched sources count too: the 81 lines with a prefetch head (396 recordings over the 5 languages; mostly
|
|
|
|
|
the game-over taunts) are linked only through them. A WAD recording that a bank also stores whole (49) is
|
|
|
|
|
the same recording (same media ID), so its line is unchanged and the bank copies are written with it.
|
|
|
|
|
- 5 recordings per language are stored twice in that language's WAD (same media ID in two entries, byte-
|
|
|
|
|
identical, e.g. `Speech_STEEL_A1_CH2_Thug_behinddoormuffled` and `DIA_SteelA1Muffled`): the second place
|
|
|
|
|
is a copy of the line (same `line`, keeps its position name) and is written and reverted with it, because
|
|
|
|
|
the game plays whichever place the loaded package's table names.
|
|
|
|
|
- Independent checks (no BKPK involved): every WAD recording is named as a source by a Sound object of a bank
|
|
|
|
|
of its own language (54,055 of 54,055); every stored prefetch head equals the start of the recording its
|
|
|
|
|
line gives it (2,101 of 2,101); a line's recordings have similar lengths across languages (11,761 of 12,434
|
|
|
|
|
of its own language (54,055 of 54,055); every stored head or whole copy equals the start of the recording
|
|
|
|
|
its line gives it (2,185 of 2,185); a line's recordings have similar lengths across languages (11,761 of 12,434
|
|
|
|
|
within a factor 1.5; the others are different edits, e.g. a 0.55 s ESN line vs 5.46 s elsewhere).
|
|
|
|
|
|
|
|
|
|
## Banks inside packages
|
|
|
|
|
@@ -99,10 +109,12 @@ and the game ties the recordings together itself:
|
|
|
|
|
|
|
|
|
|
## How ackit edits them
|
|
|
|
|
- Catalog archive `BANK` (one row per media ID) + `data/catalog/BANK_locations.csv.gz` (every copy, and the
|
|
|
|
|
prefetch heads of speech lines); built by `tools/build_catalog.py`, checked by `ackit verify --catalog`.
|
|
|
|
|
heads and whole copies of WAD speech recordings); built by `tools/build_catalog.py`, checked by `ackit verify
|
|
|
|
|
--catalog`.
|
|
|
|
|
- A replacement is written **in place into every copy** (no larger than the smallest copy, zero-padded), so
|
|
|
|
|
DIDX/HIRC offsets and sizes and the package layout never change. Loose banks are patched directly; in
|
|
|
|
|
packages only the touched blocks are re-encoded (`upk.md`). A sound left in one package only would let the
|
|
|
|
|
game load the original from another one.
|
|
|
|
|
- Replacing a speech line that has prefetch heads rewrites the heads (first bytes of the new, zero-padded line).
|
|
|
|
|
- Replacing a speech line that has prefetch heads or whole copies rewrites them (the first bytes of the new,
|
|
|
|
|
zero-padded line; for a whole copy, all of it).
|
|
|
|
|
- Design and revert rules: `docs/decisions.md` (4b). The same WEM rules apply (`wem.md`).
|
|
|
|
|
|