Files
AC6_recomp/docs/ac6_asset_extraction_walkthrough.txt
T
salh c2e2fbfbbc Add 60fps cutscene clamp for in-engine cinematics
Suspend the FPS unlock while a demo-manager Exec (DD sub_82184460 / EM sub_821856F8) ticks, so the frame-locked IngameCinematics Sequencer plays at native ~30fps instead of double speed. Adds ac6_cutscene_clamp CVar (default on).
2026-06-15 16:03:43 +03:00

236 lines
10 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 PAC archives can be decoded fully offline. The extractor reads DATA.TBL,
pulls each DATA00/01.PAC entry, applies the AC6 mode-1 descramble + raw DEFLATE
path, and then turns the decoded buffers into typed FHM children, NTXR textures,
audio banks, SWG metadata, etc. Runtime dumps are still useful for assets the
game synthesizes or touches only through live workflows, but they are no longer
required for normal PAC extraction.
--------------------------------------------------------------------------------
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. Optional: 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.
This is optional. 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. Optional: verify runtime 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:
python tools\run_ac6_asset_pipeline.py
The driver runs four stages in order:
1. extract_ac6_pac.py --decompress
Pulls all entries directly out of DATA00/01.PAC offline and decodes
mode-1 compressed entries. Outputs to out/ac6_pac_extracted_raw/.
2. extract_ac6_runtime_fhm.py
Walks every decoded PAC blob in out/ac6_pac_extracted_raw/files/ and
descends into FHM containers, writing typed children to
out/ac6_runtime_fhm_typed/.
3. extract_ac6_mdlp_parts.py
Splits embedded MDLP NDXR mesh chunks into named part folders and writes
manifests with face counts, bounds, UV/color/normal counts, material
texture hashes, primitive format histograms, primary-assembly grouping,
and LOD duplicate classification.
4. parse_ac6_swg.py
Parses the UI sprite/widget metadata (.swg children) into
out/ac6_runtime_swg_parsed/.
5. 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, --mdlp-out, --swg-out,
--ntxr-out. Add --skip-pac-extract if you only want to re-process existing
decoded PAC files. Add --include-runtime-dumps if you also want to merge entry_*
dumps from a live capture session.
--------------------------------------------------------------------------------
6. Where the output lives
--------------------------------------------------------------------------------
out/ac6_pac_runtime_dump/ Optional runtime decoded buffers.
out/ac6_pac_extracted_raw/ Offline raw/decompressed PAC entries.
out/ac6_runtime_fhm_typed/ FHM children classified by magic
(NTXR textures, BFX/BSN audio banks,
MDLP/NSXR models, SWG UI, etc.).
out/ac6_mdlp_parts/ MDLP packages copied with unique names,
split NDXR mesh parts, and mesh manifests.
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"
Runtime dumps are optional for the offline pipeline. This only matters if
you explicitly ran with --include-runtime-dumps or are debugging live
streamer behavior.
- 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"
- Confirm extract_ac6_pac.py was run with --decompress and produced
out/ac6_pac_extracted_raw/files/DATA0x/compressed/*.decompressed.bin.
- If you are using --include-runtime-dumps, the dump dir may be empty or
still contain .compressed.bin files. 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 Optional. Enables the runtime 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.