Files
Hi3-Patcher/docs/ace.md
T
2026-10-31 23:35:41 +01:00

38 lines
1.8 KiB
Markdown

# ACE patch (Windows, clients ≤ 8.9)
Builds a patched `BH3.exe` from a capture of the clean client's
initialized state. Only `BH3.exe` is written, without a backup. 9.0+
clients use HoYoKProtect instead.
## Discovery (`ace/discovery.rs`)
Read-only; all checks must pass:
| File | Required layout |
| --- | --- |
| `BH3.exe` | 7 sections all named `.ace*`, 4 KiB section alignment, no TLS directory, entry calls the `BH3Base.dll` ordinal-1 import |
| `BH3_Data/sharedassets0.assets` | `ChannelConfig` resolves to a known region |
| `UnityPlayer.dll` | exports `UnityMain`; three writable decoder globals found via a `.text` code pattern |
| `BH3_Data/Native/UserAssembly.dll` | exports `il2cpp_get_api_table`; executable `.tvm0` section with a virtual tail larger than its raw size |
## Capture (`ace/capture.rs`, `ace/process.rs`)
After confirmation, launches the client (Windows directly; Linux via
`umu-run` + Proton) and reads its memory read-only — no injection or
protection tampering. Once the state is stable for 2 s (120 s timeout),
it captures the `.tvm0` section, the three decoder states and the
committed private executable allocations.
## Normalize and rebuild (`ace/runtime.rs`, `ace/generate.rs`)
`runtime.rs` checks the captured `.tvm0` against the original after PE
relocations, resolves `FF 25` jump slots against the captured
allocations, and emits a position-independent blob and two thunk tables.
`generate.rs` appends `.bh3code` (the `bootstrap.bin` stub, patched with
the discovered RVAs/sizes per `bootstrap.json`) and `.bh3imp` (imports,
decoder states and the runtime blob), then repoints the entry point.
A `HI3AUTO1` receipt with SHA-256 hashes of the patched image,
`UnityPlayer.dll` and `UserAssembly.dll` is appended; a repeat run that
validates it is a no-op. Written via `util::replace::verified`.