Add Current Tasks roadmap: injection hardening + audio-format correlation

Replace the Future-work section with a single "Current Tasks" list:
- Injection hardening: toggling "Mirror video" has crashed a real game
  (Brotato) via a hook install/remove race. Test-first task -- make
  mock_game_test's hook/unhook stress aggressive enough to reproduce the
  crash (tight video-subsystem toggles from a separate thread while the game
  presents, across all backends), then apply the audio hooks' safe-unhook
  guard (epoch bump + restore-then-drain in-flight detours) to the Present /
  D3D9 / D3D10 / OpenGL / Vulkan hooks.
- Audio format by correlating the loopback (known device format) and
  render-hook (unknown format) captures instead of guessing: (a) rate
  verification/correction, (b) channel + bit-depth recovery.
- Mouse + keyboard forwarding (Raw Input / DirectInput) folded in.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-23 00:55:23 +02:00
parent 62c65c7438
commit 7d29abf60e

View File

@@ -107,7 +107,41 @@ default** and covers anything the hooked path doesn't.
## Roadmap
### Future work
### Current Tasks
- **Injection hardening — provoke, then fix, the hook install/remove races.** Rapidly
toggling the **"Mirror video"** button has crashed a real game (Brotato): flipping the
Present-hook video subsystem on/off in quick succession races hook install/remove against
the game's Present thread and the host's capture path. Per the test-first rule, *first make
the crash reproducible in a test* — make `mock_game_test`'s hook/unhook stress against
`coop_mock_game` far more aggressive: tight, repeated subsystem toggles (especially video)
while the game is actively presenting, driven from a separate thread so the toggles interleave
with the Present detour, sustained long enough that an unguarded race is near-certain to
fault, and across all backends (DX11/12/9/10/GL/Vulkan). Then fix what it surfaces — the
install/remove path is the same safe-unhook problem the **audio** hooks already solved (bump
an epoch on each toggle, restore the vtable/inline first so no new detour starts, then drain
in-flight detours before tearing down shared state); apply the equivalent guard to the
Present / D3D9 / D3D10 / OpenGL / Vulkan hooks.
- **Determine a pre-existing stream's audio format by *correlating* the two capture
paths, instead of guessing.** When we attach to an already-running game we never saw its
`IAudioClient::Initialize`, so the render-hook assumes the device mix format and measures
only the sample rate from the render cadence — which can be wrong on a jittery game
(intermittent pitch shift) and can't recover channels/bit-depth at all. But during the
measurement window the game is still audible, so we already have *both* signals of the
same audio: the **process-loopback** capture (post-mix, at the **known** device format)
and the **render-hook** capture (pre-mix, at the unknown format). Cross-correlating them
pins the real format from ground truth rather than a guess. Two tasks:
- **(a) Rate verification/correction.** Resample the hook stream by each candidate standard
rate and cross-correlate against the loopback; the rate that holds alignment with no drift
over the window is the truth. Robust where cadence measurement is noisy — directly hardens
the intermittent pitch-shift symptom. Lands as a verify-and-correct step feeding the
existing rate path (the operator override stays as the manual escape hatch).
- **(b) Channels + bit-depth recovery.** Extend the correlation to the layout the cadence
method *can't* recover: interpret the hook bytes under candidate layouts (float32 vs
int16; mono/stereo/…) and keep whichever de-interleaving correlates with the loopback (a
wrong interpretation is noise and won't). Removes the "channels/bit-depth assumed = device"
limitation, so the garbled-layout case stops being undetectable.
- **Mouse + keyboard forwarding for Raw Input / DirectInput games.** The MKB
subsystem forwards via window messages (`PostMessage`) plus synthesized