Cristian Gora 1ccaa8b398 Full correctness check against the docs: safer writes, reverts and texts
Safety
- Writes are serialized (Workspace.lock): two background jobs rebuilding one
  package (a sound and its subtitle applied side by side) lost an edit.
- A store copies a bank file or package as "original" only if it matches the
  shipped catalog (Workspace.unoriginal_files: in-memory sounds, bank copies of
  voice lines, subtitles); the editor refuses to switch stores while changes
  are applied. A second store could otherwise resurrect a reverted sound.
- Mod import in the editor asks before overwriting files changed outside the
  tool (it forced silently).
- Revert all in the editor reverts texts too; the uninstaller counts text
  edits before offering to delete the store.
- ackit restore-backup: the full-backup restore decisions.md described; it
  keeps the sounds of WADs without a full copy recorded.
- build_catalog also stops when a subtitle differs from the catalog.

Languages and texts
- Game.language() returns languages without voices (JPN, RUS, ...) and
  Game.voice_archive() their INT voices; ackit text --lang JPN works.
- Menu lookups parse one cached file (find & replace: minutes -> ms).
- Subtitles decode cp1252 as Windows does: the UTF-8-in-cp1252 line
  Speech_TAPE_J_Answer_1_00 (KOR/POL/POR/RUS) is written back byte-for-byte;
  SUB_KOR/SUB_RUS rebuilt from the original game (only those rows changed).
- Mods exported while another language is loaded keep name and line.

Other fixes
- Down-mix folds extra channels in at -3 dB (a 5.1 centre voice was dropped).
- e2e_editor no longer overwrites the user's settings.json; kill_game waits
  for the game to exit before reverts.
- Recorder handles Int32/UInt8 input and split frames; package block cache
  locked; conflict messages, CLI help examples, stale docstrings and doc
  references fixed; tests no longer read this PC's game language.

Docs (decisions, user guide, README, subtitles.md, banks.md, catalog README,
REPORT, NOTES, CLAUDE.md) updated; check_docs: 102 claims match. 148 tests;
e2e_features 9/9, e2e_editor and verify PASS; game original afterwards.
2026-10-13 21:34:13 +02:00
2026-10-09 02:57:04 +02:00
2026-10-09 02:57:04 +02:00

Arkham City Audio Toolkit

Replace any voice line, music track, ambience or sound effect in Batman: Arkham City (PC, Steam) with your own audio (by name, from a file or a recording) and edit subtitles and menu text, with one-click revert. No Wwise, no game patch, no external programs.

Unheard City, the editor
  • Unheard City (app/, user guide): the desktop editor for Windows and Linux. Browse and search all ~21,000 sounds of one language (its voice lines, music, ambience, and the effects stored inside soundbanks: footsteps, foley, combat, weapons, UI), filter by category and character, listen, replace or record, apply and revert. Edit subtitles (linked to their speech lines) and the menu text in their own sections. One Language setting (default: the game's) applies to sounds, subtitles and menu text.
  • ackit (ackit/): the Python library and command-line tool behind it.

How it works in one paragraph: the game's Wwise 2011.1 decoder only knows the standard Vorbis codebooks, so ackit encodes with libvorbis and rewrites the stream into exactly the layout the game expects (codebook IDs, packet format, seek table, header hash and memory size reversed from the game), then writes it in place into the .wad archives, the soundbanks and the game's compressed .upk packages (ackit reads and patches them itself), keeping the original files in a store for exact reverts. Subtitles live in the packages too, menu text in the localization files. Details in docs/.

Install

  • Editor (users), Windows: unzip UnheardCity-<version>-windows-amd64.zip and double-click Install.cmd. It installs for your user (no admin rights), adds a Start menu shortcut and an entry in Settings > Apps for uninstalling. Or skip installing and run UnheardCity.exe straight from the unzipped folder.
  • Editor (users), Linux: unpack the .tar.gz and run UnheardCity.
  • Nothing else is needed (no Python, no Wwise, no ffmpeg). To build it yourself: docs/building.md.
  • Toolkit (developers): Python 3.10+:
    python -m venv .venv && .venv/Scripts/activate         # Linux: source .venv/bin/activate
    pip install -e .[app,dev,verify]                       # app = editor, dev = tests/packaging, verify = in-game test
    python -m app.main                                     # run the editor from source
    

Quick start (command line)

ackit find joker tape                             # search by name, category or character
ackit extract Speech_TAPE_JOKER_1_04 orig.wav     # listen to the original (a line has one name in every language)
ackit replace Speech_TAPE_JOKER_1_04 my_line.wav --match-loudness
ackit revert Speech_TAPE_JOKER_1_04               # or: ackit revert --all (every sound and text)
ackit text find --lang INT protocol               # subtitles and menu texts (keys SUB:... / MENU:...; any of the
                                                  # 11 languages, e.g. --lang JPN)
ackit text set "MENU:INT:FRONTEND.int:Buttonpress:DoubleTap" "Tap twice"

More: ackit status, ackit list --character Joker, ackit export-mod my.acmod / ackit import-mod, ackit verify (offline self-check), ackit verify --catalog (catalog vs game files), ackit game (detected install, language, store), ackit restore-backup (last resort if the originals store is damaged). ackit -h lists all commands. The game folder is found through Steam (Windows, Linux, Flatpak, Proton); otherwise pass --game DIR.

Rules worth knowing: speech/effects replacements must fit in the original's size (the tool squeezes or refuses with the maximum length); music can be any length. Subtitles must fit the original text's length (menu text: any length). Close the game before writing.

Where things are

ackit/          library + CLI   (formats, encoder, injector, catalog, originals store, workspace)
ackit/verify/   offline self-check, in-game test harness (Windows, WinDbg)
app/            Unheard City (PySide6)
tests/          pytest suite (synthetic game data; real-game tests run when the game is installed)
data/catalog/   sound catalogs (CSV), character lists (source/), schema in data/catalog/README.md
docs/           formats, reverse engineering, decisions, categories, user guide, building
tools/          catalog builder, docs figure check, real-game e2e checks (e2e_editor.py, e2e_features.py), packaging
                (build_app.py, installer/), artwork, license and screenshot scripts
NOTES.md        project status and working notes; CLAUDE.md: guidance for AI sessions

Tests: pytest (the real-game tests are skipped when the game is not installed). Figures in the docs: python tools/check_docs.py [--scan] [--wems]. Real-game write round trips (no game launch): python tools/e2e_features.py [--lang all], python tools/e2e_editor.py. In-game tests (Windows, Steam running, WinDbg installed): ackit verify --ingame, --ingame --banks, --ingame --texts.

Description
Replace any voice line, music track, sound effect or subtitle in Batman: Arkham City
Readme GPL-3.0 20 MiB
Languages
Python 99%
PowerShell 1%