Version 3.2.0: fast lists with loading spinners, names from the game files, INT docs and screenshots, cleanup
This commit is contained in:
@@ -62,10 +62,10 @@ Two separate fields, because Wwise names describe a *scene*, not the speaker of
|
||||
alternates speakers between `NAME_1`, `NAME_2`, ...):
|
||||
|
||||
- **character** - the verified speaker, only from the curated lists in `data/catalog/source/<lang>/*.txt`
|
||||
(one file per character, listening-based). The lists name ITA sounds by their position in the ITA WAD
|
||||
(wemscan names); positions differ between languages, so each listed recording is found at its ITA position
|
||||
and the label goes to its line (`characters.csv`, keyed by the line's name), i.e. to the same recording in
|
||||
every language. A label applies to exactly the listed recordings (not to other versions of the same event).
|
||||
(one file per character, listening-based; the lists so far were made on the Italian voices, `source/ita/`).
|
||||
A list names sounds by their position in its language's WAD (wemscan names); positions differ between
|
||||
languages, so each listed recording is found at its position in that language and the label goes to its line
|
||||
(`characters.csv`, keyed by the line's name), i.e. to the same recording in every language. A label applies to exactly the listed recordings (not to other versions of the same event).
|
||||
Checked by `ackit verify --catalog` against the speaker field of the game's dialogue objects: 2,766 labelled
|
||||
lines agree (spelling aside: Mister Freeze, Bruce Wayne, TwoFace, Mysterious_stranger = Azrael), 25 listed
|
||||
as Unknown are named there, 19 differ (to listen to: `Batman_sword_raised_01-04` game: Ra's al Ghul,
|
||||
|
||||
@@ -77,7 +77,7 @@ tables): high risk for little gain, not done.
|
||||
ackit wrote.
|
||||
- **Prefetch heads:** 396 speech lines (about 79 per language) have their first bytes copied into banks; a
|
||||
replacement of such a line rewrites those heads too, otherwise the start would play the old line.
|
||||
- **Names:** the hash list names none of these media. Names come from Wwise events whose names are in the
|
||||
- **Names:** no list names these media. Names come from Wwise events whose names are in the
|
||||
packages' name and export tables (FNV-1 of the name = event ID), following event -> action -> containers ->
|
||||
sounds (6,456 sounds); the rest are numbered per bank. Categories use the bank name. A localized speech line
|
||||
has the same name in every language (its line, section 5).
|
||||
@@ -111,6 +111,9 @@ copy per voice language) is filtered the same way, so the sound list never mixes
|
||||
## 5. Catalog
|
||||
- Shipped CSVs per archive (names, categories, characters, original size + checksum) make loading instant and
|
||||
enable change detection; any other build is scanned at runtime (header reads only, cached).
|
||||
- Names come from the game files only: a WAD entry or stream pack is named after its soundbank in the game's
|
||||
`CookedBanks.txt` (entry ID = FNV-1 of the bank name; this gives exactly the names of the community hash list
|
||||
the toolkit used to ship, which was removed), speech lines after their events (below).
|
||||
- Verified speakers come only from the user's lists; name-based character inference is kept in a separate field.
|
||||
- Voice lines are identified by the game's own data, not by names or positions (`docs/formats/banks.md`,
|
||||
*Lines*): the recordings that are sources of the same Wwise Sound objects are one line, with exactly one
|
||||
@@ -159,8 +162,13 @@ copy per voice language) is filtered the same way, so the sound list never mixes
|
||||
- Background: the wallpaper sits only behind the filter panel, scaled to the panel height so its left part fills
|
||||
the panel, under a light veil. Settings -> Background toggles it and sets its strength (default 10 %).
|
||||
- Loading feedback stays where the work is, never modal: a spinner inside the waveform being loaded (sound or
|
||||
replacement file, decoded off the GUI thread), next to the Apply/Revert buttons while encoding/writing, and in
|
||||
the status bar for game loading and bulk changes.
|
||||
replacement file, decoded off the GUI thread), next to the Apply/Revert buttons while encoding/writing, over
|
||||
a list while it loads (the sound list at start and on a language change, the subtitles / menu text of a
|
||||
language, read off the GUI thread), and in the status bar for game loading and bulk changes.
|
||||
- Lists filter and sort in Python, not with Qt's QSortFilterProxyModel (`app/models.py: RowView`): the view
|
||||
computes the visible rows in one pass and one sort over cached keys (~10-20 ms for 21,000 sounds; the Qt
|
||||
proxy called back into Python for every comparison: up to 1.5 s per sort or widened filter). Rows a filter
|
||||
shows again keep their sorted place; selection and the current row survive every change.
|
||||
All filter selectors (including Character) are plain, non-editable drop-downs so they look and behave alike.
|
||||
|
||||
## 8. Verification
|
||||
|
||||
@@ -28,7 +28,7 @@ All WEMs seen are Vorbis (format tag 0xFFFF), the same codec as the WADs: the fo
|
||||
the embedded ones mono or stereo (~22 % stereo in a 2,533-WEM sample).
|
||||
|
||||
## Names
|
||||
- The community hash list names none of these media IDs; only the bank names are known.
|
||||
- No list names these media IDs (the community hash list names only WAD entries and banks).
|
||||
- `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`,
|
||||
|
||||
@@ -9,7 +9,7 @@ per language (INT, ITA, FRA, DEU, ESN, ESM, POL, POR, RUS, JPN, KOR), ~37 files
|
||||
- UTF-16LE with a BOM (`FF FE`), CRLF line ends; the first line is empty. (`INT\Version.int` and
|
||||
`VersionData.int` are plain ASCII build IDs, not UI text: ackit ignores them.)
|
||||
- `[Section]` lines, `Key=Value` lines, `;` comments. A few values are in double quotes (`Quit="Quit game"`).
|
||||
- File extension = language code (`FRONTEND.int`, `FRONTEND.ITA`); case varies, lookups are case-insensitive.
|
||||
- File extension = language code (`FRONTEND.int`, `FRONTEND.FRA`); case varies, lookups are case-insensitive.
|
||||
- Markers inside values (e.g. `\n`, button tags) are the game's own; ackit keeps them as plain text.
|
||||
|
||||
## Keys and writing
|
||||
|
||||
@@ -21,11 +21,13 @@ Rules:
|
||||
- Each payload starts at the next **0x1000-aligned** offset after the previous one.
|
||||
- `size` = payload length rounded up to **0x800**; padding is zero.
|
||||
- File ends 0x1000-aligned; header area after the table is zero.
|
||||
- `hash` = Wwise media/file ID (names: `hashlist.txt`, e.g. `CHR_RadioScanner`, `AMB_Steel_B3`, `Music`).
|
||||
- `hash` = Wwise ID of the soundbank whose streamed media the entry holds: FNV-1 of a bank name listed in
|
||||
`CookedPCConsole\CookedBanks.txt` (e.g. `CHR_RadioScanner`, `AMB_Steel_B3`, `Music`); this names every
|
||||
entry the game uses (2,544 of 2,547; ackit takes the names from there).
|
||||
|
||||
Payload kinds:
|
||||
- **LOC WADs**: each entry is a group of WEMs, the variations of one line (ITA: 10816 WEMs in
|
||||
2464 entries; e.g. `CHR_RadioScanner` holds 91). Each WEM starts at the next 0x800 boundary after
|
||||
- **LOC WADs**: each entry is a group of WEMs, the variations of one line (every language: 10,816 WEMs in
|
||||
2,464 entries; e.g. `CHR_RadioScanner` holds 91). Each WEM starts at the next 0x800 boundary after
|
||||
the previous one (zero padding); 3 entries pack two WEMs back to back. Addressed `HASH:i`. The WEMs of an
|
||||
entry are stored in media-ID order and the languages have different media IDs, so variation `i` is a
|
||||
different line in each language (75 % of the lines). Which recording is which line comes from the banks
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
# WEM format accepted by Arkham City (Wwise 2011.1, Vorbis)
|
||||
|
||||
Derived from the game's WEMs; `ackit verify` / `tests/test_realgame.py` rebuild them byte-for-byte from these rules
|
||||
alone (all 10816 ITA WEMs; in SFX only the 4 looping music tracks with loop points differ).
|
||||
alone. Checked on every WEM of the 5 speech WADs: 54,079 of 54,080 are identical; the exception (INT
|
||||
`FE9963E8:74`) differs only in the informational avg-bytes/s field (one lower than the formula below). In SFX
|
||||
only the 4 looping music tracks with loop points differ.
|
||||
|
||||
## RIFF layout
|
||||
`RIFF` size `WAVE`, then `fmt ` (0x42 bytes), optional `cue `/`LIST` (37 files), `data`.
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 204 KiB After Width: | Height: | Size: 219 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 48 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 192 KiB After Width: | Height: | Size: 191 KiB |
@@ -80,7 +80,7 @@ Conclusion: approach A works end-to-end in-game. Use >= 30 s probes for the intr
|
||||
starts and runs, all 68 probe byte patterns are found in its memory (it loaded the patched packages), revert
|
||||
byte-identical: PASS. Not shown: a probe being *heard*. Only 7 Vorbis streams start on the title screen
|
||||
(setups 4f708975, 6ded1c65, 92f94a3f, d93b5944, d4b2e824: shared by hundreds of sounds, music included) and
|
||||
none is a probe. Tried: Enter/arrow keys posted to the game window (`debugger.post_key`, WM_KEYDOWN) to reach
|
||||
none is a probe. Tried: Enter/arrow keys posted to the game window (WM_KEYDOWN/WM_KEYUP; that helper was removed later) to reach
|
||||
the main menu: no UI sound followed (the game probably reads input another way; global SendInput is not
|
||||
used on purpose); a breakpoint on the setup parser entry: no extra events. Hypotheses: no in-memory sound
|
||||
plays without input; the decode path is the same as for WAD sounds (same WEM rules, 300/300 in-memory WEMs
|
||||
|
||||
@@ -28,7 +28,7 @@ Changing it reloads the lists; the next start is again in the game's language.
|
||||
|
||||
## Names
|
||||
Every voice line has one name in every language, taken from the game itself (e.g. `Speech_TAPE_JOKER_1_04`, the
|
||||
same as in the Subtitles tab): the line `Speech_X` in Italian is the same line `Speech_X` in English, French,
|
||||
same as in the Subtitles tab): the line `Speech_X` in English is the same line `Speech_X` in French, Italian,
|
||||
German and Spanish. Inside a WAD entry the game stores the variations of a line in a different order in each
|
||||
language, so the position-based name is kept only as a second name (`Speech_TAPE_JOKER_1#4` = the 4th WEM of
|
||||
that entry in this language; search finds both). When the game plays one of two versions of a line, the
|
||||
@@ -118,7 +118,7 @@ Click the **★** column to mark favorites. These are stored in your user data f
|
||||
data plus the audio, so it also works for another language whose original has a different size).
|
||||
- **Import mod…**: shows which sounds match this game, then installs them. You can revert them like any change.
|
||||
- Changed subtitles and menu texts are exported and imported with the sounds (listed as *Text*); a text stays
|
||||
in its language (an Italian subtitle edit changes the Italian subtitle).
|
||||
in its language (a French subtitle edit changes the French subtitle).
|
||||
- In another language, voice lines are matched by the game's own identity of the line, so the same line is
|
||||
replaced even where its position differs. Voice lines from packages made with versions before 3.1 carry no
|
||||
such identity: the import lists them instead of guessing (export the mod again with this version).
|
||||
|
||||
Reference in New Issue
Block a user