Phase 0: donor-launch spike foundation

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>
This commit is contained in:
2026-06-18 22:48:31 +02:00
commit cf058aecfa
23 changed files with 1129 additions and 0 deletions

54
host/src/imgui_layer.cpp Normal file
View File

@@ -0,0 +1,54 @@
#include "imgui_layer.hpp"
#include <imgui.h>
#include <imgui_impl_dx11.h>
#include <imgui_impl_win32.h>
namespace coop
{
ImGuiLayer::~ImGuiLayer()
{
if (initialized_)
{
ImGui_ImplDX11_Shutdown();
ImGui_ImplWin32_Shutdown();
ImGui::DestroyContext();
initialized_ = false;
}
}
bool ImGuiLayer::init(HWND hwnd, ID3D11Device* device, ID3D11DeviceContext* context)
{
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO();
io.IniFilename = nullptr; // don't litter the cwd with imgui.ini during the spike
ImGui::StyleColorsDark();
if (!ImGui_ImplWin32_Init(hwnd))
{
return false;
}
if (!ImGui_ImplDX11_Init(device, context))
{
return false;
}
initialized_ = true;
return true;
}
void ImGuiLayer::begin_frame()
{
ImGui_ImplDX11_NewFrame();
ImGui_ImplWin32_NewFrame();
ImGui::NewFrame();
}
void ImGuiLayer::end_frame()
{
ImGui::Render();
ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());
}
} // namespace coop