Files
UnheardCity/NOTES.md

89 lines
7.8 KiB
Markdown

# NOTES — Arkham City audio toolkit & editor
## Current status / Next steps (rewrite as you go)
- Mission 1 (2026-10-07): DONE. Format reversed, encoder + injector, verified in-game (no exe patch).
- Mission 2 Part 1 (2026-10-08): repository cleanup DONE — tag `pre-cleanup` holds the old state.
New layout (README "Where things are"); `ackit` refactored: portable encoder (libsndfile, no ffmpeg/vgmstream),
`Game` (Steam/Linux/Proton discovery), catalog from `data/catalog/*.csv` (user's character lists + rules),
originals store + `Workspace` (apply/revert/conflicts), mod packages, CLI. 63 tests pass; `ackit verify` PASS;
`ackit verify --ingame` PASS (E14: ncc 1.0, revert byte-identical).
- Part 2 (2026-10-08): Unheard City DONE (app/, PySide6): browser (search + group/category/character/
archive/tag/modified/favorites filters, sortable, multi-select, notes/tags/favorites), editor (original/installed/
replacement waveforms, A/B, loop, volume, file or recording, trim/gain/normalize/match loudness, apply/revert,
conflict + changed-underneath handling), mod export/import, settings. 72 tests incl. offscreen GUI tests.
Packaging: `python tools/build_app.py` -> dist/UnheardCity (self-contained, licenses); packaged exe passes
`--smoke-test` with PATH = C:\Windows only. Real e2e through the editor code path (tools/e2e_editor.py): PASS
(music heard in game ncc 1.0, reverts byte-identical, speech line apply/revert byte-identical).
- NEXT: editing of the ~15,800 in-memory sounds in soundbanks (loose `SFX\*.bnk` footsteps first, then banks
embedded in `.upk` packages); not listed or editable yet, survey in `docs/formats/banks.md`.
- NEXT (optional): verify >2-channel channel order in game; speech heard in-game (needs gameplay).
- OPEN: channel order for >2 channels unverified.
## Environment facts
- Game: Steam AppID 200260 "Batman: Arkham City GOTY", `C:\Program Files (x86)\Steam\steamapps\common\Batman Arkham
City GOTY`, exe `Binaries\Win32\BatmanAC.exe` (32-bit, SteamStub). buildid 3718300. Game language: Italian
(`Documents\WB Games\...\UserEngine.ini` is UTF-16, `Language=Ita`).
- Steam must be running and logged in for the in-game test (`steam.exe -silent`, wait for
HKCU\Software\Valve\Steam\ActiveProcess ActiveUser != 0). appmanifest AutoUpdateBehavior=0 (no updates expected).
- History: the ITA WAD in the game folder was once the user's modded copy; the clean original came from
`%USERPROFILE%\Desktop\ArkhamCityModding\Audio\49D84887_LOC_ITA\WAD\` (sha1 1238172C...). The game is clean now
(fingerprints match the old `_backup/`, deleted on 2026-10-08).
- Dev tools: `.venv` (Python 3.14.6, PySide6 6.10.3, soundfile 0.14.0 / libsndfile 1.2.2, soxr 1.1.0, numpy,
pytest, PyInstaller 6.22.3, soundcard 0.4.6). git at `C:\Program Files\Git\cmd`. WinDbg Store (path changes on
update; `ackit/verify/debugger.py: find_cdb`). No WSL distro, no Docker.
- User data (this PC): `%APPDATA%\UnheardCity\` (settings.json, stores\<id>\), cache `%LOCALAPPDATA%\UnheardCity\cache`.
- The user's own material: `%USERPROFILE%\Desktop\ArkhamCityModding` (old mod work, Ghidra project, dump);
their third-party downloads were moved from `tools/`, `repositories/` to `external/` (git-ignored).
- Ghidra project BAC: `.text` Ghidra address = runtime + 0xC00 (docs use runtime addresses).
## Where to look
- Findings, failed hypotheses, in-game experiment log E0-E14: `docs/reverse-engineering/findings.md`.
- Formats: `docs/formats/`. Decoder addresses: `docs/reverse-engineering/decoder.md`.
- Decisions (stack, deps, licenses, originals store, size rule): `docs/decisions.md`.
## Session log
- 2026-10-08: user added `my_catalog_for_ita/` (per-character lists, wemscan names) -> moved to
`data/catalog/source/ita/`; 3364 names labelled (2 wemscan name collisions label both candidates; one line had a
`.wem.wav` typo). Built catalogs for ITA/INT/FRA/DEU/ESN/SFX (identical names and counts across languages).
Assumption: speakers are the same in every language, so ITA labels apply to all.
- 2026-10-08: libsndfile's Vorbis writer crashed (C stack overflow) on a 30 s x 6 ch single write -> block writes.
- 2026-10-08: wad_fingerprint made structural (IDs + non-pack sizes) so music edits don't invalidate the catalog;
scan mode never borrows checksums from the shipped CSV (other builds / synthetic tests).
- 2026-10-08: editor async loading looked stuck: Job objects were garbage-collected before their queued result
signal arrived -> Runner keeps references until done. Qt 6.10 deprecates invalidateFilter/invalidateRowsFilter ->
SoundFilter.refilter uses begin/endFilterChange when available.
- 2026-10-08: search haystack must not contain the variation index (":2" matched "2"); IDs are matched separately
(words of >= 6 chars against the target id).
- Verification commands: `pytest -q`; `ackit verify`; `ackit verify --ingame`; `python tools/e2e_editor.py`
(needs Steam logged in); packaged: `dist/UnheardCity/UnheardCity.exe --smoke-test --report f.txt`.
- 2026-10-08: UI restyle on request: vector icon set (app/icons.py, no emoji), "Arkham" theme (app/theme.py: QSS +
palette, translucent panels over a wallpaper backdrop).
- 2026-10-08: user rejected the procedural icon/backdrop and supplied images (~/Downloads/Arkham City:
bac_logo_full.png, wallpaper.jpg). tools/make_assets.py builds git-ignored app/assets/ (icon = logo bat over a
red waveform; wallpaper copied); app/art.py, make_icon.py and the old icon files removed. Settings ->
Background toggle (background_enabled). Character filter is now a plain combobox like the others.
- 2026-10-08: theme selector and custom background image removed (one look); the wallpaper is painted only in the
filter panel (theme.Sidebar: scaled to panel height, left part shown).
- 2026-10-08: build simplified to one offline command: build_app.py runs make_assets when app/assets is missing
(--art FOLDER), and license texts live in tools/licenses/ (www.gnu.org was down; no more downloads).
- 2026-10-08: neutral dark theme (no blue), editor header icon removed, new icon: flat BAC bat with echolocation
arcs. build_app.py also regenerates app/assets when tools/make_assets.py is newer than the icon.
- 2026-10-08: background strength default 10 %; obsolete settings keys (theme, background_image) dropped on load.
Spinners (app/spinner.py): waveform overlay while loading, editor action row, status bar for global jobs.
Replacement files now decode in a background job.
- 2026-10-08: accent is now dark red (#b0242c; icons.ACCENT / theme.ACCENT, was AMBER). Icon: white rounded tile,
red waveform bars, black logo bat on top. Filter panel opens at its maximum width (320 px, can only shrink).
Sidebar veil alpha follows the background strength (at 10 % the wallpaper stays visible).
- 2026-10-09: editor renamed "Unheard City" (exe/zip UnheardCity, launcher unheard-city, user data %APPDATA%\UnheardCity).
Icon: 9 wider/taller bars (5 at <=24 px), bat 78% of the tile. Panel background #0c0c0c.
- 2026-10-09: editor panel opens fitted to its contents (MainWindow.fit_editor; refits on layout changes until
the divider is dragged). Windows installer: tools/installer (Install.cmd -> install.ps1/uninstall.ps1, per-user,
HKCU uninstall entry), copied into the build by build_app.py; install/upgrade/uninstall cycle verified.
User chose no new software (no Inno Setup).
- 2026-10-09: app/assets is committed (user: public artwork and generated content, not Warner Bros. pictures).
build_app.py regenerates it only when missing or with --art; after changing make_assets.py run it by hand.
- 2026-10-09: SFX coverage check (read-only): the catalog covers every WAD sound, but ~15,800 in-memory WEMs in
soundbanks are missing (docs/formats/banks.md). Packages were unpacked with Gildor's decompress.exe from
`%USERPROFILE%\Desktop\ArkhamCityModding\Audio\decompress\` (outside the repo). User: document now, implement
editing later.