Initial commit
This commit is contained in:
39
docs/reverse-engineering/decoder.md
Normal file
39
docs/reverse-engineering/decoder.md
Normal 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`.
|
||||
Reference in New Issue
Block a user