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>
90 lines
3.6 KiB
CMake
90 lines
3.6 KiB
CMake
cmake_minimum_required(VERSION 3.21)
|
|
|
|
project(CoopAllTheThings
|
|
VERSION 0.0.1
|
|
DESCRIPTION "Steam Remote Play Together for any XInput game"
|
|
LANGUAGES CXX)
|
|
|
|
if(NOT WIN32)
|
|
message(FATAL_ERROR "CoopAllTheThings targets Windows only.")
|
|
endif()
|
|
|
|
set(CMAKE_CXX_STANDARD 20)
|
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
set(CMAKE_CXX_EXTENSIONS OFF)
|
|
|
|
# Emit compile_commands.json so clangd resolves includes/flags. Ignored by the
|
|
# Visual Studio generator, so configure the Ninja build (build-clangd/) for this;
|
|
# .clangd points clangd at that compilation database.
|
|
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
|
|
|
# Single output dir keeps the donor-launch / inject workflow simple: host exe and
|
|
# hook dll land next to each other under /bin (already in .gitignore).
|
|
set(COOP_OUTPUT_DIR "${CMAKE_SOURCE_DIR}/bin/$<CONFIG>")
|
|
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${COOP_OUTPUT_DIR}")
|
|
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${COOP_OUTPUT_DIR}")
|
|
|
|
if(MSVC)
|
|
add_compile_options(/W4 /permissive- /Zc:__cplusplus /utf-8 /MP)
|
|
add_compile_definitions(UNICODE _UNICODE WIN32_LEAN_AND_MEAN NOMINMAX)
|
|
endif()
|
|
|
|
# --- x86 sub-build (internal, re-entrant) ----------------------------------
|
|
# When the ExternalProject below reconfigures this same tree with -A Win32 and
|
|
# -DCOOP_X86_HELPER_BUILD=ON, build ONLY the 32-bit hook DLL + injector helper
|
|
# (staged alongside the x64 binaries) and stop -- no host, tests, or imgui, and
|
|
# crucially no recursive ExternalProject.
|
|
option(COOP_X86_HELPER_BUILD "Internal: x86 sub-build (hook DLL + injector helper only)" OFF)
|
|
if(COOP_X86_HELPER_BUILD)
|
|
add_subdirectory(common)
|
|
set(SAFETYHOOK_BUILD_TEST OFF CACHE BOOL "" FORCE)
|
|
set(SAFETYHOOK_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
|
|
set(SAFETYHOOK_BUILD_DOCS OFF CACHE BOOL "" FORCE)
|
|
add_subdirectory(third_party/safetyhook)
|
|
add_subdirectory(hook)
|
|
add_subdirectory(tools/inject_helper)
|
|
return()
|
|
endif()
|
|
|
|
add_subdirectory(third_party)
|
|
add_subdirectory(common)
|
|
add_subdirectory(host)
|
|
|
|
# The injected hook DLL pulls in SafetyHook, which fetches Zydis via FetchContent
|
|
# at configure time (allowed for transitive deps).
|
|
option(COOP_BUILD_HOOK "Build the injected game-side hook DLL" ON)
|
|
if(COOP_BUILD_HOOK)
|
|
# SafetyHook's own tests/examples/docs are noise for us.
|
|
set(SAFETYHOOK_BUILD_TEST OFF CACHE BOOL "" FORCE)
|
|
set(SAFETYHOOK_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
|
|
set(SAFETYHOOK_BUILD_DOCS OFF CACHE BOOL "" FORCE)
|
|
add_subdirectory(third_party/safetyhook)
|
|
add_subdirectory(hook)
|
|
enable_testing()
|
|
add_subdirectory(tools/audio_tone) # coop_tone: audio source for the loopback test
|
|
add_subdirectory(tools/audio_probe) # coop_audio_probe: inject + diagnose the render-hook
|
|
add_subdirectory(tests)
|
|
endif()
|
|
|
|
# --- x86 helper artifacts for 32-bit (WOW64) games -------------------------
|
|
# A 64-bit process can't cleanly inject a 32-bit one, so build the x86 hook DLL
|
|
# (coop_hook_x86.dll) + a 32-bit injector helper (coop_inject_x86.exe) via a
|
|
# nested Win32 configure of this same tree, staged next to the x64 binaries. Only
|
|
# the multi-config Visual Studio generator is supported here (the Ninja
|
|
# build-clangd/ tree is just for compile_commands and skips this).
|
|
option(COOP_BUILD_X86_HELPER "Build the x86 hook DLL + injector helper for 32-bit games" ON)
|
|
if(COOP_BUILD_HOOK AND COOP_BUILD_X86_HELPER AND CMAKE_GENERATOR MATCHES "Visual Studio")
|
|
include(ExternalProject)
|
|
ExternalProject_Add(coop_x86
|
|
SOURCE_DIR "${CMAKE_SOURCE_DIR}"
|
|
BINARY_DIR "${CMAKE_BINARY_DIR}/x86"
|
|
CMAKE_GENERATOR "${CMAKE_GENERATOR}"
|
|
CMAKE_GENERATOR_PLATFORM "Win32"
|
|
CMAKE_ARGS "-DCOOP_X86_HELPER_BUILD=ON"
|
|
BUILD_COMMAND "${CMAKE_COMMAND}" --build <BINARY_DIR> --config $<CONFIG>
|
|
INSTALL_COMMAND ""
|
|
BUILD_ALWAYS ON
|
|
USES_TERMINAL_CONFIGURE ON
|
|
USES_TERMINAL_BUILD ON)
|
|
endif()
|