Phase 1a: per-slot poll viz + input-path diagnostics
Surfaced by a game (Life is Strange: Before the Storm) that ignores controller input when it lacks true OS focus even though it still polls XInput. To find the focus-gated detection path, instrument the hook. Protocol v3 status back-channel now reports: - per-slot XInputGetState and XInputGetCapabilities counters (replacing the single aggregate), so the overlay shows exactly which slots the game polls and how fast; - focus-API call counts (GetForegroundWindow/GetActiveWindow/GetFocus) to see whether the game consults the APIs we spoof; - input-path diagnostics: whether the process registered Raw Input for a gamepad usage and whether it set RIDEV_INPUTSINK (background delivery), and whether a DirectInput dll is loaded. Host overlay gains a per-slot poll table and an "Input path" section. The DLL refreshes input diagnostics each worker tick via GetRegisteredRawInputDevices. hook_selftest updated for per-slot counters; passes. This is diagnostic-only: once a real run shows which path LiS uses, the targeted focus fix (e.g. forcing RIDEV_INPUTSINK or DI background coop) follows. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -57,14 +57,28 @@ public:
|
||||
|
||||
// --- Status back-channel (hook -> host diagnostics) --------------------
|
||||
|
||||
// Record that the game queried a controller slot; the host turns the
|
||||
// cumulative count into a poll rate to prove the hook is live.
|
||||
void note_query(std::uint32_t user_index)
|
||||
// Record that the game queried a controller slot via XInputGetState/Ex.
|
||||
void note_state_query(std::uint32_t user_index)
|
||||
{
|
||||
if (block_ != nullptr)
|
||||
if (block_ != nullptr && user_index < kMaxPads)
|
||||
{
|
||||
block_->status.xinput_queries.fetch_add(1, std::memory_order_relaxed);
|
||||
block_->status.last_user_index = user_index;
|
||||
block_->status.get_state_calls[user_index].fetch_add(1, std::memory_order_relaxed);
|
||||
}
|
||||
}
|
||||
|
||||
void note_caps_query(std::uint32_t user_index)
|
||||
{
|
||||
if (block_ != nullptr && user_index < kMaxPads)
|
||||
{
|
||||
block_->status.get_caps_calls[user_index].fetch_add(1, std::memory_order_relaxed);
|
||||
}
|
||||
}
|
||||
|
||||
void note_focus_query(FocusApi which)
|
||||
{
|
||||
if (block_ != nullptr && which < FocusApi_Count)
|
||||
{
|
||||
block_->status.focus_query_calls[which].fetch_add(1, std::memory_order_relaxed);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,6 +100,17 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void set_input_diagnostics(bool raw_registered, bool raw_gamepad, bool raw_gamepad_sink, bool dinput)
|
||||
{
|
||||
if (block_ != nullptr)
|
||||
{
|
||||
block_->status.raw_input_registered = raw_registered ? 1u : 0u;
|
||||
block_->status.raw_input_gamepad = raw_gamepad ? 1u : 0u;
|
||||
block_->status.raw_input_gamepad_sink = raw_gamepad_sink ? 1u : 0u;
|
||||
block_->status.dinput_loaded = dinput ? 1u : 0u;
|
||||
}
|
||||
}
|
||||
|
||||
void heartbeat()
|
||||
{
|
||||
if (block_ != nullptr)
|
||||
|
||||
Reference in New Issue
Block a user