Skip to content

aowlspt_bridge.h

Source: abi/aowlspt_bridge.h — 544 lines, 18 file-scope functions.

What this header owns

Reproduced verbatim from the header's own banner comment — these notes are frequently the only written record of why the subsystem is shaped the way it is.

text
 aowlspt_bridge.h -- getting host-side work onto Unity's main thread.

## The problem this closes

`il2cpp_runtime_invoke` from the host's own injected thread crashes this
client. IL2CPP/Unity managed code -- the GC, the managed heap, every Unity
object -- is affine to the Unity **main thread** (the one that runs the
player loop). A managed call, a box, or a field read issued from a foreign
thread faults inside the runtime. The host boots on a thread of its own, so
everything it wants to do to a live game object is on the wrong thread.

The fix already lives in `host/Aowlspt.Host.Il2Cpp/aowlhost.nim`: detour a
method Unity calls once per frame on its main thread and drain the
`invoke_main` queue from inside the detour (`bindMainDrain` / `mainDrain`).
A closure pushed from any thread then runs, on the Unity thread, the next
frame. What was missing was a per-frame method the host could actually get a
usable code pointer for.

## Why the by-name path was not enough, and what this adds

`bindMainDrain`'s by-name path resolves a method through the runtime
(`il2cpp_class_from_name` -> `il2cpp_class_get_method_from_name` -> read
`MethodInfo.methodPointer`). On this build that returned nothing usable for
every candidate -- but NOT because the metadata is protected. Two real
reasons: one candidate, `EFT.MainApplication`, does not exist post-1.0 (the
root application MonoBehaviour is **`EFT.TarkovApplication`**); and, decisive,
`bindMainDrain` runs on the host's own boot thread, and reading IL2CPP
class/method metadata off the Unity main thread returns bogus pointers and
faults (see the repo memory `project_post1_menu_boot`). So `findClass` /
`findMethod` handed back garbage and `methodPointer` read garbage -> null.
That is a wrong-thread artifact, not proof of protected metadata.

The decrypted metadata's per-module `methodPointers` tables are in fact
INTACT and reliable on this build. Proof: this file's resolver reproduces all
five BE-bypass RVAs in `aowlspt_beclient.h` byte-for-byte (they live in the
`Assembly-CSharp-firstpass.dll` module, table base 0x186BF1380 -- an EARLIER
misread used `Assembly-CSharp.dll`'s table for every type and so missed them,
which is where the false "the table is null for BE" note used to be), and it
reproduces every VA in `docs/SETTINGS.md` (SettingsScreen.Show 0x171FA00,
OpenGroup 0x1720C80, ...). Two independent ground truths, exact.

So resolution is **static**, offline, the same mechanism as the BE patches:
type -> its image (from the metadata images table) -> that image's
`Il2CppCodeGenModule.methodPointers` -> `[token_rid - 1]` -> code RVA, then
byte-verify the prologue against `GameAssembly.dll` before use. No runtime
metadata read, no off-thread hazard.

## The target

  `EFT.TarkovApplication::Update`  @ RVA 0x977B10  (imagebase 0x180000000,
  build 1.1.0.1.46777, in the `il2cpp` PE section at VA 0x628000+).

It is the root application MonoBehaviour's per-frame `Update`. It is the best
of the candidates on all four counts a drain target needs:
  - once per frame,
  - on the Unity main thread only (a MonoBehaviour `Update` is a player-loop
    callback and runs nowhere else),
  - alive for the whole session, menu to desktop (the application root
    outlives every scene, unlike `GameWorld`, which exists only in a raid),
  - and its compiled prologue relocates cleanly -- `push rbx ; sub rsp,0x20 ;
    mov rbx,[rcx+0x110] ; test rbx,rbx`, sixteen bytes with no RIP-relative
    operand and no relative branch, which is exactly what the detour engine's
    length decoder in `aowlspt_detour.h` needs to steal a whole number of
    instructions for the trampoline.

How the RVA was found: the decrypted `global-metadata.dat` gives the method's
token RID within `Assembly-CSharp`, and the module's `Il2CppCodeGenModule.
methodPointers` table in `GameAssembly.dll`'s `.data` maps RID -> code RVA,
exactly as Il2CppDumper does. `EFT.TarkovApplication` is type index 7933; its
`Update` resolves to 0x977B10 and its `LateUpdate` to the adjacent 0x977C80,
the tight monotonic clustering a real compiler emits for one type's methods.

A secondary, raid-only target -- `EFT.GameWorldUnityTickListener::Update` @
RVA 0x251C6C0 -- is included as a fallback: it is present only inside a raid,
but a raid is where a mod most wants the main thread, and binding it late
beats not binding at all if the primary's prologue ever fails its guard.

## Safe by default

Every target checks the bytes it expects before it is handed out. On any
other build the prologue will not match, and this returns NULL -- the host
then falls through to its by-name candidates and, failing those, to the
existing host-thread behaviour, which is the documented fallback. A wrong
offset is a missed bind, never a corrupted game. Nothing here writes to the
game; it only *locates and verifies* a function pointer. The detour itself is
installed by the host through the same `aowl_hook_*` engine and slot table a
mod's patch uses, so it inherits that engine's thread-park write safety.

RVAs are for imagebase 0x180000000 and build 1.1.0.1.46777.

Constants

  • AOWLSPT_BRIDGE_H
  • AOWL_BRIDGE_RENDER_TARGET_COUNT
  • AOWL_BRIDGE_SETTINGSTAB_TARGET_COUNT
  • AOWL_BRIDGE_SETTINGSTICK_TARGET_COUNT
  • AOWL_BRIDGE_SETTINGS_TARGET_COUNT
  • AOWL_BRIDGE_TARGET_COUNT
  • AOWL_IL2CPP_SEC_RVA
  • AOWL_IL2CPP_SEC_SIZE

Types

  • struct AowlBridgeTarget

Functions

SignatureLine
void aowl_bridge_render_target_at(int32_t i)202
char aowl_bridge_render_target_name(int32_t i)229
int32_t aowl_bridge_render_target_count(void)234
void aowl_bridge_settings_target_at(int32_t i)261
char aowl_bridge_settings_target_name(int32_t i)282
int32_t aowl_bridge_settings_target_count(void)286
void aowl_bridge_settingstab_target_at(int32_t i)356
char aowl_bridge_settingstab_target_name(int32_t i)377
int32_t aowl_bridge_settingstab_target_count(void)381
void aowl_bridge_settingstick_target_at(int32_t i)429
char aowl_bridge_settingstick_target_name(int32_t i)450
int32_t aowl_bridge_settingstick_target_count(void)454
void aowl_bridge_target_at(int32_t i)465
int32_t aowl_bridge_target_perframe(int32_t i)498
char aowl_bridge_target_name(int32_t i)503
int32_t aowl_bridge_target_count(void)508
int32_t aowl_in_il2cpp_section(void* p)520
int64_t aowl_il2cpp_rva_of(void* p)536

aoughwl — self-hosted platform for things n stuff. Contact / Support on Discord for access to the private backends.