Files
AC6_recomp/docs/ac6_asset_extraction_walkthrough.txt
salh 64f8efbb2b Restore AC6 mode-1 decoder dump hook via midasm at 0x821CCC5C
Recovers the Apr 23 hand-edit (lost in subsequent refactors) and re-wires
it as a TOML midasm hook so codegen regeneration can no longer drop it.
Hook fires immediately after the guest decompressor (bl 0x822CF510)
returns, reads the entry record via r11 (codec at +1, csize at +8,
usize at +12), source offset from *(r31+22888), entry tag from r10, and
calls Ac6DumpPacDecodedEntry with the decoded buffer at r4. With
AC6_DUMP_PAC_DECODED=1, all 800 compressed entries now drop as
FHM-magic'd entry_*_mode1_*.bin in out/ac6_pac_runtime_dump/.

Also adds streamer-worker dispatch probes (AC6_TRACE_PAC_WORK_ITEMS),
PPC stack walking on PAC reads (AC6_TRACE_PAC_STACKS), the AC6 PAC
index parser, the chunk-coalescing dump fallback, and a user-facing
walkthrough at docs/ac6_asset_extraction_walkthrough.txt.
2026-05-01 21:22:14 +03:00

220 lines
9.2 KiB
Plaintext

================================================================================
AC6 Asset Extraction Walkthrough
================================================================================
Goal: go from a fresh clone of this repository to decoded AC6 asset files
(textures, FHM containers, SWG metadata) on disk.
The recompiled binary patches the guest decompressor at runtime via a midasm
hook (see docs/ac6_extraction_roadmap.md). When the env var
AC6_DUMP_PAC_DECODED=1 is set, every PAC entry the game touches is written
to disk in already-decoded form. The asset pipeline then turns those raw
buffers into typed FHM children, NTXR textures, etc.
--------------------------------------------------------------------------------
0. Prerequisites
--------------------------------------------------------------------------------
- Windows 10/11 x64. (Linux clang-20 also works; commands below assume Windows.)
- Visual Studio 2022 with the "Desktop development with C++" workload installed,
OR a standalone clang-cl/MSVC toolchain.
- LLVM/Clang 20+ on PATH (the project pins clang for codegen).
- CMake 3.25 or newer, Ninja, and Python 3.11+ (for the asset pipeline tools).
- Your own legally obtained copy of Ace Combat 6: Fires of Liberation. The
repository ships no game data.
--------------------------------------------------------------------------------
1. First-time build
--------------------------------------------------------------------------------
Open a 64-bit shell (x64 Native Tools Command Prompt for VS 2022, or any shell
with the right toolchain on PATH). From the repo root, run:
cmake --preset win-amd64-relwithdebinfo
cmake --build --preset win-amd64-relwithdebinfo --target ac6recomp_codegen
cmake --preset win-amd64-relwithdebinfo
cmake --build --preset win-amd64-relwithdebinfo
The two-phase configure is required because the codegen target produces
sources that the second configure has to pick up. Output exe lands at:
out/build/win-amd64-relwithdebinfo/ac6recomp.exe
setup_and_build.bat wraps the same sequence if you would rather run it once.
--------------------------------------------------------------------------------
2. Place the game assets
--------------------------------------------------------------------------------
The game expects DATA.TBL, DATA00.PAC, and DATA01.PAC alongside the exe in an
"assets" subfolder:
out/build/win-amd64-relwithdebinfo/assets/DATA.TBL
out/build/win-amd64-relwithdebinfo/assets/DATA00.PAC
out/build/win-amd64-relwithdebinfo/assets/DATA01.PAC
You will also need a default.xex and any other files the game requires; consult
the project README for the full layout. Without the PAC archives the dumper
has nothing to capture.
--------------------------------------------------------------------------------
3. Run the game with PAC dumping enabled
--------------------------------------------------------------------------------
Use the helper launcher from PowerShell at the repo root:
.\tools\launch_ac6_with_pac_dump.ps1
That sets AC6_DUMP_PAC_DECODED=1 and starts ac6recomp.exe with the working
directory pointing at the build output.
Optional switches (only set these when you need them):
.\tools\launch_ac6_with_pac_dump.ps1 -TraceWorkItems
Lifts the [fs] log category to info so the dumper's
"[AC6 PAC] dumped decoded entry ..." lines appear in ac6recomp.log,
and enables the PAC stream-worker dispatch probes.
.\tools\launch_ac6_with_pac_dump.ps1 -TraceStacks
Adds PPC back-chain stack=[...] traces on each PAC NtReadFile call.
Useful for debugging the stream worker; not needed for routine runs.
Play long enough for the streamer to load the assets you care about. As a
rough guide:
- Title screen + intro: enough for the boot/menu PACs.
- One mission start: enough for that mission's PAC entries.
- Anything new the game streams in adds new dumps; replays do not duplicate
entries that have already been written.
When you are done, close the game window normally.
--------------------------------------------------------------------------------
4. Verify the decoded dumps
--------------------------------------------------------------------------------
The dumper writes to (relative to the repo root):
out/ac6_pac_runtime_dump/
A successful run looks like:
entry_<tag>_mode0_c<csize>_u<usize>_off<hex>.bin <- raw entries
entry_<tag>_mode1_c<csize>_u<usize>_off<hex>.bin <- decoded entries
You should NOT see any .compressed.bin files. If you do, the midasm hook at
0x821CCC5C did not fire for those entries (see Troubleshooting below).
Quick sanity check on a decoded blob:
powershell -Command "(Get-Content out\ac6_pac_runtime_dump\<file>.bin -Encoding Byte -TotalCount 4) -join ','"
The first 4 bytes of any mode-1 dump should be 70,72,77,32 (ASCII "FHM ").
--------------------------------------------------------------------------------
5. Run the asset extraction pipeline
--------------------------------------------------------------------------------
From the repo root, with the dumps in place:
python tools\run_ac6_asset_pipeline.py
The driver runs four stages in order:
1. extract_ac6_pac.py
Pulls the raw 126 entries directly out of DATA00/01.PAC offline.
Outputs to out/ac6_pac_extracted_raw/.
2. extract_ac6_runtime_fhm.py
Walks every entry_*_mode*.bin in out/ac6_pac_runtime_dump/ and
descends into FHM containers, writing typed children to
out/ac6_runtime_fhm_typed/.
3. parse_ac6_swg.py
Parses the UI sprite/widget metadata (.swg children) into
out/ac6_runtime_swg_parsed/.
4. export_ac6_ntxr.py
Converts NTXR texture entries into DDS/TGA in
out/ac6_runtime_ntxr_exported/.
Override any output path with --raw-out, --typed-out, --swg-out, --ntxr-out.
Add --skip-pac-extract if you only want to re-process the runtime dumps.
--------------------------------------------------------------------------------
6. Where the output lives
--------------------------------------------------------------------------------
out/ac6_pac_runtime_dump/ Raw decoded buffers, one file per entry.
out/ac6_pac_extracted_raw/ 126 raw (mode-0) entries pulled offline.
out/ac6_runtime_fhm_typed/ FHM children classified by magic
(NTXR textures, BFX/BSN audio banks,
MDLP/NSXR models, SWG UI, etc.).
out/ac6_runtime_swg_parsed/ JSON metadata for UI sprites.
out/ac6_runtime_ntxr_exported/ DDS/TGA files (one per texture entry).
--------------------------------------------------------------------------------
7. Troubleshooting
--------------------------------------------------------------------------------
* "no entry_*_mode1_*.bin files appeared"
- The game did not stream any compressed entries during the session.
Boot further or load a mission and try again.
- AC6_DUMP_PAC_DECODED was not set. Always launch via the helper script,
or set the env var manually before starting the exe.
* ".compressed.bin files appeared"
- The midasm hook at 0x821CCC5C did not fire. Codegen may have shifted
the underlying instruction sequence. Verify the anchor instruction in
generated/ac6recomp_recomp.10.cpp:
// lwz r11,-18100(r26)
// add r11,r9,r11
// addi r3,r10,8 <- PC of this instruction is the hook address
If the surrounding ops differ, re-anchor by finding the unique
"lwz r11,-18100(r26)" sequence and updating the address in
ac6recomp_config.toml under [[midasm_hook]] name = "ac6PacDecoderDumpHook".
* "logs do not show any [AC6 PAC] lines"
- ac6_performance_mode is on by default and forces log_level=error,
which silences the [fs] category. Run with -TraceWorkItems to lift
[fs] to info. Note: dumps still land in out/ac6_pac_runtime_dump/
regardless of log level.
* "extract_ac6_runtime_fhm.py reports 0 containers"
- The dump dir is empty or the files are still .compressed.bin.
Re-run with the hook fix above.
* "log files rotate and the early dumper lines are gone"
- At trace-level logging the rotating buffer fills in seconds. Do not
raise log_level globally; the per-category lift in -TraceWorkItems
keeps volume manageable.
* "I changed ac6recomp_config.toml and the new hook does nothing"
- You skipped the codegen pass. TOML changes only take effect after:
cmake --build --preset win-amd64-relwithdebinfo --target ac6recomp_codegen
cmake --build --preset win-amd64-relwithdebinfo
--------------------------------------------------------------------------------
8. Quick reference: env vars
--------------------------------------------------------------------------------
AC6_DUMP_PAC_DECODED=1 Required. Enables the dumper sink.
AC6_TRACE_PAC_WORK_ITEMS=1 Optional. Lifts [fs] log category to info,
enables L1/L2 streamer-worker probes.
AC6_TRACE_PAC_STACKS=1 Optional. PPC back-chain on PAC NtReadFile.
The launcher script (.\tools\launch_ac6_with_pac_dump.ps1) sets the first
unconditionally and the others only when -TraceWorkItems / -TraceStacks
are passed.