Phase 3: x86 (32-bit) game support via injector helper
Drive a nested Win32 sub-build (CMake ExternalProject, re-entrant via COOP_X86_HELPER_BUILD) from the normal x64 build to produce coop_hook_x86.dll and a 32-bit coop_inject_x86.exe, staged next to the x64 binaries. The host detects a WOW64 target with IsWow64Process2 and spawns the helper to load the x86 DLL, since a 64-bit process can't cleanly inject a 32-bit one. The shared-memory IPC is fixed-width / bitness-stable, so the x64 host and x86 hook interoperate. Validated end-to-end against Slaps and Beans (32-bit D3D11): all 15 hooks installed, heartbeat advancing, the Present hook engaged (shared a 1920x1080 backbuffer -- the real-game video-hook proof Phantom Brave's D3D9 couldn't give), and status/audio/video/log IPC all crossed the x64<->x86 boundary. coop_audio_probe now also delegates to the helper for WOW64 targets. All 5 tests pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
30
README.md
30
README.md
@@ -37,8 +37,12 @@ XInput game becomes Remote-Play-Together-able.
|
||||
co-op/local-multiplayer titles without active anti-cheat.
|
||||
- **XInput only:** the game must read controllers via XInput (the common case).
|
||||
DirectInput-only / RawInput-only games are not handled.
|
||||
- **x64 only:** the host and hook DLL must match the game's bitness, and only x64
|
||||
is built today. 32-bit games need the x86 hook + injector (see Roadmap).
|
||||
- **32-bit games supported via a helper:** the host is x64, but the build also
|
||||
produces an x86 hook DLL (`coop_hook_x86.dll`) and a 32-bit injector helper
|
||||
(`coop_inject_x86.exe`). When the target is a 32-bit (WOW64) process the host
|
||||
detects it (`IsWow64Process2`) and shells out to the helper to load the x86 DLL
|
||||
(a 64-bit process can't cleanly inject a 32-bit one). The shared-memory IPC is
|
||||
fixed-width / bitness-stable, so the x64 host and x86 hook interoperate.
|
||||
- **Local audio echo (fixed via the hook; falls back otherwise):** when the
|
||||
render-hook is active it silences the game's local playback while mirroring it,
|
||||
so there is no echo. If the hook can't attach or the game uses an
|
||||
@@ -143,14 +147,18 @@ Done:
|
||||
(drives a real D3D11 swapchain end-to-end and reads the pixels back through the
|
||||
shared texture).
|
||||
|
||||
- **x86 (32-bit) game support. ✅** A nested Win32 sub-build (CMake
|
||||
`ExternalProject`, driven from the normal x64 build) produces `coop_hook_x86.dll`
|
||||
and a 32-bit `coop_inject_x86.exe`, staged next to the x64 binaries. The host
|
||||
detects a WOW64 target with `IsWow64Process2` and spawns the helper to inject
|
||||
the x86 DLL. Validated end-to-end against Slaps and Beans (a 32-bit D3D11 game):
|
||||
all subsystems hooked, and the IPC channels (status, audio ring, video share,
|
||||
log) all flow across the x64↔x86 boundary.
|
||||
|
||||
Future work, roughly in priority order:
|
||||
|
||||
- **Steam Input:** consume guest input through the Steam Input API directly
|
||||
rather than XInput.
|
||||
- **x86 support:** add an x86 build of `coop_hook.dll` plus an x86 injector
|
||||
helper the x64 host spawns, so 32-bit games work (a 64-bit process can't
|
||||
cleanly inject a 32-bit one). Detect target bitness with `IsWow64Process2`.
|
||||
The shared-memory IPC layout is already fixed-width / bitness-stable.
|
||||
|
||||
## Building
|
||||
|
||||
@@ -166,6 +174,11 @@ cmake --build build --config Debug
|
||||
# output: bin/Debug/coop_host.exe (+ coop_hook.dll, test exes)
|
||||
```
|
||||
|
||||
The x64 build also drives a nested Win32 sub-build (CMake `ExternalProject`,
|
||||
configured into `build/x86/`) that produces `coop_hook_x86.dll` and
|
||||
`coop_inject_x86.exe` for 32-bit games, staged next to the x64 binaries. Disable
|
||||
it with `-DCOOP_BUILD_X86_HELPER=OFF` if you don't need 32-bit support.
|
||||
|
||||
Third-party dependencies (Dear ImGui, SafetyHook) are git submodules under
|
||||
`third_party/`; the Steamworks SDK is vendored manually there when wired. No
|
||||
vcpkg / package manager is used.
|
||||
@@ -259,8 +272,9 @@ Useful checks while developing without RPT: tick **Forward synthetic test input*
|
||||
in the Injection panel to make the game move on its own (proving forwarding is the
|
||||
source), and click away from the game to confirm focus spoofing keeps it running.
|
||||
|
||||
> Injection access error → run the host as administrator. "Target is 32-bit" →
|
||||
> that game needs the x86 hook (see Roadmap).
|
||||
> Injection access error → run the host as administrator. A 32-bit (WOW64) target
|
||||
> is injected automatically via `coop_inject_x86.exe` + `coop_hook_x86.dll`; if
|
||||
> those aren't next to the host, rebuild (the x86 sub-build stages them there).
|
||||
|
||||
## Lessons learned
|
||||
|
||||
|
||||
Reference in New Issue
Block a user