diff --git a/README.md b/README.md index ae1c3da..4b632e6 100644 --- a/README.md +++ b/README.md @@ -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