The host can now inject coop_hook.dll into a running game and forward
controller state to it over shared memory, so the game reads the host's
(eventually the guest's) input and nothing else.
- hook/: coop_hook.dll. DllMain spawns a worker that opens the shared-memory
channel (named by the game's pid) and installs SafetyHook inline hooks on
XInputGetState/GetStateEx/GetCapabilities/SetState. Detours synthesize state
from shared memory; unmanaged slots report disconnected, hiding physical pads.
- host/: process picker (Toolhelp32), CreateRemoteThread(LoadLibraryW) injector
with an IsWow64Process2 bitness guard, IPC server publishing pads each frame,
and an ImGui Injection panel wiring it together.
- tests/: hook_selftest exercises the IPC seqlock + hook detours in-process
(no game/controller needed); passes.
Build: SafetyHook wired in (COOP_BUILD_HOOK=ON), Zydis via FetchContent.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Scaffold CoopAllTheThings: Remote Play Together for any XInput game via a
mirror app under a donor appid (real game keeps its own appid, so DRM,
achievements, and playtime stay intact).
- Build: CMake skeleton, ImGui + SafetyHook submodules (no vcpkg)
- common/: host<->hook IPC contract (seqlock pad state, shared-memory RAII)
- host/: borderless D3D11 window + ImGui overlay listing visible XInput pads,
behind an InputSource interface (Steam Input slots in later)
- README documents the Phase 0 donor-launch validation procedure, anti-cheat
limitation, and XInput/bitness constraints
Phase 0 validates the riskiest assumption (Steam RPT streams an arbitrary
window under a donor appid and routes guest input to it) before capture and
injection are built.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>