diff --git a/README.md b/README.md index 8708557..61a5dfc 100644 --- a/README.md +++ b/README.md @@ -108,7 +108,79 @@ default** and covers anything the hooked path doesn't. ## Roadmap -Completed work lives in **Lessons learned** + the test suite, not here. +### Current work + +From an in-depth review pass. Each item is fixed test-first (a failing test, then the fix) and lands +as its own commit; "verify" items are confirmed real before any change, and dropped if not. + +Confirmed bugs: +- **Shutdown use-after-free of `ui`** — the ImGui settings handler holds `&ui`, but `~ImGuiLayer`'s + `DestroyContext` saves settings *after* `ui` (declared later in `run()`) is destroyed. Reorder / + remove the handler before teardown. +- **Host device loss unhandled** — `Present`/`ResizeBuffers`/`CreateRenderTargetView` HRESULTs are + ignored and a removed/reset device spins silently. Detect `DEVICE_REMOVED/RESET`, log + `GetDeviceRemovedReason`, surface it, and halt the render loop cleanly. +- **Keyed-mutex `WAIT_ABANDONED` not handled** — `shared_texture` treats it as "skip", so a mirror + never recovers after a host crash + reconnect. Treat it as acquired (copy + release). + +Correctness (verify, then fix if real): +- **`vk_hook` / `vk_layer` `g_swaps`** — no synchronization on push/iterate and never pruned on + swapchain destroy (unbounded growth + stale-handle match). Add a guard + a `vkDestroySwapchainKHR` + prune. +- **`mkb_hook` raw-input slot reuse** — a 64-slot ring can overwrite an event before the game reads + the `WM_INPUT`. Verify; fix if real. +- **Non-atomic cross-process diagnostic counters** — `present_calls`, `frames_dropped`, + `frames_rendered` are plain `+=`/stores read by the host. Make them atomic. +- **`publish()` synthetic-input timing** — confirm it doesn't read ImGui/UI state from the input + thread; fix if so. + +Performance (failing perf-regression test first): +- **D3D9 capture readback off the present thread** — move the swizzle/flip to an off-thread reaper + (the inline-readback pattern that caused the Vulkan 144→3 FPS stall), add a present-thread overhead + guard + dedicated test. +- **OpenGL capture readback off the present thread** — async PBO readback + off-thread swizzle/flip, + with an overhead guard. + +Robustness (verify, then fix if real): +- **`mkb_forward` sticky mouse-up** — a held button isn't released when mirroring toggles off / ImGui + grabs the mouse. Release held buttons. +- **Swallowed audio loopback `start()` failures** — surface a process-loopback activation failure + distinctly from "no correlation" in the verifier + loopback. +- **Permissive injector bitness gate** — `IsWow64Process2` failure is treated as 64-bit; fall back to + `IsWow64Process` instead of mis-injecting. +- **Ignored HRESULT/BOOL returns** — `CreateShaderResourceView`, `GetClientRect`/`ClientToScreen`, + `XInputSetState`, `GetExitCodeProcess`: check and surface/handle. + +Cross-process / ABI: +- **Tie `kProtocolVersion` to the layout** — `static_assert` `sizeof(SharedBlock)` + the full offset + set, and make `hook_selftest`'s `dump_layout` assert instead of only printing. +- **`log_ring` torn-text window** — verify the MPSC overwrite race; fix or bound it. +- **`narrow`/`widen` not inverse** — make the audio-override name round-trip lossless (or document). + +Test coverage: +- **`log_ring`** — threaded push/drain + wrap-skip generation test (currently zero coverage). +- **Seqlock reader paths** — torn-read retry, odd-sequence skip, attempt-exhaustion → false. +- **Version/magic mismatch rejection** — negative test that the hook refuses a bad version. +- **Dedicated hook tests** — `focus_spoof`, `vk_hook` (present), `d3d9_hook`. +- **Misc units** — `SharedMemory` RAII/move, `wav` malformed input, `tool_paths` resolution, injector + bitness check; strengthen the `audio_ring` overrun-at-seam case. + +Features: +- **Static CRT (`/MT`) for `coop_hook.dll`** (x64 + x86) so it loads in games without the VC++ redist. +- **Stale Vulkan-layer registration cleanup** — remove a leftover `HKCU` implicit-layer entry from a + crashed prior run on host startup. + +UX: +- **Auto re-attach control** — keep it visible/controllable when not connected (today it can be + enabled-but-invisible). +- **Tooltips on disabled controls** — explain *why* Inject/subsystem controls are disabled. +- **Case-insensitive log filter.** + +Code quality: +- **Stale comments** — `hook_guard.hpp` top block (still the old destroy-on-remove model), + `input_source.hpp` ("future" Steam source), `audio_ring.hpp` (v1/reserved), `shared_memory.hpp` / + `audio_ring.hpp` ("20-byte pads"). +- **Consolidate `VtableHook`** — remove the duplicate copy in `audio_hook.cpp`. ### Future work