Initial commit

This commit is contained in:
2026-10-09 02:48:24 +02:00
commit e05d973a8d
133 changed files with 101507 additions and 0 deletions

View File

@@ -0,0 +1,39 @@
# BatmanAC.exe — Wwise Vorbis decoder notes (runtime addresses)
Image base 0x400000 (no ASLR). The on-disk exe is SteamStub-packed; `.text` is decrypted at runtime
(within ~0.15 s of process start). Static analysis uses the user's memory dump
`ArkhamCityModding\Audio\RE\BatmanAC_dump.bin` (a *mapped* image: file offset == RVA).
The Ghidra project `BAC` loaded it with raw-file section mapping, so **Ghidra address = runtime + 0xC00
in `.text`** (+0x1E00 in `.data`). All addresses below are runtime.
| runtime | Ghidra | what |
|---------|--------|------|
| 0x010B2340 | 0x010B2F40 | stream codec state machine (reads setup across stream buffers, creates setup) |
| 0x010B2C30 | 0x010B3830 | in-memory (bank) codec init |
| 0x010B3400 | 0x010B4000 | `GetOrCreateCodecSetup(cache, AkSrcInfo*, ...)`: cache bucket `hash % 31`, key = full hash |
| 0x010B347B | 0x010B407B | `mov ebx,[ebp+0x94]` = decode alloc size (user's crash patch site; decryption probe) |
| 0x010B351A | 0x010B411A | return from setup parse (`eax`=0 OK) — harness breakpoint |
| 0x010B3160 | 0x010B3D60 | per-packet synthesis (mode read as **1 bit**) |
| 0x010B3600 | 0x010B4200 | decode loop |
| 0x010B48F0 | 0x010B54F0 | mapping inverse |
| 0x010B4D10 | 0x010B5910 | `ParseSetupHeader(info, channels, reader, pool)` |
| 0x010B5140 | 0x010B5D40 | floor1 unpack |
| 0x010B5A60 | 0x010B6660 | residue unpack |
| 0x010B46D0 | 0x010B52D0 | mapping unpack |
| 0x010B5C00 | 0x010B6800 | residue inverse |
| 0x010B6340 | 0x010B6F40 | `_make_decode_table` (user called it WwiseDecodeVorbisToPCM) |
| 0x010B66F0 | 0x010B72F0 | codebook unpack (Tremor-lowmem `vorbis_book_unpack`, compact Wwise form) |
| 0x0158E748 | (.data) | codebook pointer table, 599 ptrs (598 books + end) |
`AkSrcInfo` (arg 2 of GetOrCreate): +0x6C channel mask, +0x78.. AkVorbisInfo copy (+0x94 decode alloc,
+0x98 x64 alloc, +0x9C hash, +0xA0/+0xA1 blocksizes, +0xA4 rate). total_frames reads 0 there.
Pool: one bump allocator per codec setup, capacity = dwDecodeAllocSize; first 0x30 bytes = setup info;
allocation failures return NULL and are not checked -> the old crash (`mov [ebx+eax*2],cx`, ebx=0).
The user's patch (double capacity) masked a too-small value produced by Wwise 2011.2.2.
## Harness hooks (ackit/verify/debugger.py, used by `ackit verify --ingame`)
- bp 0x010B3400: log hash/alloc of every stream/media setup (`ACKIT_SETUP`).
- bp 0x010B351A: log parse result (`ACKIT_PARSE ret=`).
- `sxd -c2` on AV: second-chance crash -> `ACKIT_CRASH` + registers + stack.
- WinDbg Store path changes on auto-update: cdb is located via `Get-AppxPackage Microsoft.WinDbg`.