mirror of
https://github.com/ddeverill/SteamlessController.git
synced 2026-10-18 20:59:45 -05:00
A hand-off stick does not read exactly zero, and the virtual pad passed whatever it read straight through. XInput games mostly hide that behind a deadzone of their own; an emulator waiting for "press the input to bind", or a gamepad tester, takes the pad's word for it and sees the sticks moving all the time, so a bind prompt latches onto them before a button can be pressed. StickRestProbe measured what a deadzone has to clear, hands off, on two units. The reading is a steady offset from zero rather than noise: jitter about the mean is under 0.5%, while the offset reaches 5.9% of the range on one stick and wanders by over a point from one settle to the next. So the deadzone is 8%, about 1.4 times the worst resting reading, rather than a number that clears the measurement by a hair. Radial rather than per-axis, so a direction is left alone, and rescaled so the output does not jump the moment the stick leaves the deadzone. The scale is applied per axis and each axis clamped on its own, so a diagonal pushed into a stick's corner still reaches full on both axes as it did before. Applied in one place, ReadStick, which both the Xbox and DualShock 4 reports read their sticks through, so the two cannot disagree about what rest is. Fixed rather than a setting: a stick does not need tuning per game the way a trigger threshold does. Also invert the DualShock 4 Y axis before quantising it rather than after. 255 - u8 turned a centred 128 into 127, so a stick at rest sat one step off on Y and nowhere near it on X, which a gamepad tester showed as a constant nonzero value. StickDeadzoneProbe checks the maths without a controller, including that the worst measured resting position reads as nothing. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
276 lines
9.7 KiB
CMake
276 lines
9.7 KiB
CMake
cmake_minimum_required(VERSION 3.20)
|
|
project(SteamlessController CXX)
|
|
|
|
include(FetchContent)
|
|
|
|
set(CMAKE_CXX_STANDARD 20)
|
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
|
|
# Shared HID + Steam Controller library code
|
|
add_library(SteamController STATIC
|
|
src/hid/HidDevice.cpp
|
|
src/steam/SteamController.cpp
|
|
)
|
|
target_include_directories(SteamController PUBLIC src)
|
|
target_link_libraries(SteamController PUBLIC hid setupapi)
|
|
if (MSVC)
|
|
target_compile_options(SteamController PRIVATE /W4 /WX /utf-8)
|
|
endif()
|
|
|
|
# Diagnostic probe tool (console)
|
|
add_executable(SteamProbe
|
|
src/main.cpp
|
|
)
|
|
target_link_libraries(SteamProbe PRIVATE SteamController)
|
|
if (MSVC)
|
|
target_compile_options(SteamProbe PRIVATE /W4 /WX /utf-8)
|
|
set_target_properties(SteamProbe PROPERTIES LINK_FLAGS_DEBUG "/SUBSYSTEM:CONSOLE")
|
|
endif()
|
|
|
|
# ViGEmClient (built from source, static)
|
|
add_library(ViGEmClient STATIC
|
|
third_party/ViGEmClient-b66d02d/src/ViGEmClient.cpp
|
|
)
|
|
target_include_directories(ViGEmClient PUBLIC
|
|
third_party/ViGEmClient-b66d02d/include
|
|
)
|
|
target_link_libraries(ViGEmClient PUBLIC setupapi)
|
|
if (MSVC)
|
|
target_compile_options(ViGEmClient PRIVATE /W0 /utf-8 /wd4828)
|
|
endif()
|
|
|
|
# RawGameController diagnostic probe (WinRT)
|
|
add_executable(RawControllerProbe
|
|
src/probe/RawControllerProbe.cpp
|
|
)
|
|
target_link_libraries(RawControllerProbe PRIVATE windowsapp)
|
|
if (MSVC)
|
|
target_compile_options(RawControllerProbe PRIVATE /W4 /utf-8)
|
|
endif()
|
|
|
|
# Game-library diagnostic probe — dumps every source the picker draws on
|
|
add_executable(GameLibraryProbe
|
|
src/probe/GameLibraryProbe.cpp
|
|
src/app/GameLibrary.cpp
|
|
src/app/LauncherGames.cpp
|
|
src/app/ProcessIdentity.cpp
|
|
)
|
|
target_include_directories(GameLibraryProbe PRIVATE src)
|
|
target_link_libraries(GameLibraryProbe PRIVATE ole32 shell32 shlwapi version windowsapp)
|
|
if (MSVC)
|
|
target_compile_options(GameLibraryProbe PRIVATE /W4 /WX /utf-8)
|
|
set_target_properties(GameLibraryProbe PROPERTIES LINK_FLAGS_DEBUG "/SUBSYSTEM:CONSOLE")
|
|
endif()
|
|
|
|
# Foreground-watcher diagnostic probe — prints what the per-game profile
|
|
# matcher would see as the user switches applications
|
|
add_executable(ForegroundProbe
|
|
src/probe/ForegroundProbe.cpp
|
|
src/app/ForegroundWatcher.cpp
|
|
src/app/ProcessIdentity.cpp
|
|
)
|
|
target_include_directories(ForegroundProbe PRIVATE src)
|
|
if (MSVC)
|
|
target_compile_options(ForegroundProbe PRIVATE /W4 /WX /utf-8)
|
|
set_target_properties(ForegroundProbe PROPERTIES LINK_FLAGS_DEBUG "/SUBSYSTEM:CONSOLE")
|
|
endif()
|
|
|
|
# Steam manifest diagnostic probe — dumps the app id to install directory map
|
|
# that per-game profiles for Steam games are matched through
|
|
add_executable(SteamAppProbe
|
|
src/probe/SteamAppProbe.cpp
|
|
src/app/SteamAppLocator.cpp
|
|
)
|
|
target_include_directories(SteamAppProbe PRIVATE src)
|
|
if (MSVC)
|
|
target_compile_options(SteamAppProbe PRIVATE /W4 /WX /utf-8)
|
|
set_target_properties(SteamAppProbe PROPERTIES LINK_FLAGS_DEBUG "/SUBSYSTEM:CONSOLE")
|
|
endif()
|
|
|
|
# Binding encoding checks — the packed and wire forms both have to keep
|
|
# decoding values written by earlier builds
|
|
add_executable(BindingCodecProbe
|
|
src/probe/BindingCodecProbe.cpp
|
|
)
|
|
target_include_directories(BindingCodecProbe PRIVATE src)
|
|
if (MSVC)
|
|
target_compile_options(BindingCodecProbe PRIVATE /W4 /WX /utf-8)
|
|
set_target_properties(BindingCodecProbe PROPERTIES LINK_FLAGS_DEBUG "/SUBSYSTEM:CONSOLE")
|
|
endif()
|
|
|
|
# Dual-stage trigger checks — the detector's hysteresis and mode changes, the
|
|
# clamps on persisted thresholds, and that profiles written before the feature
|
|
# read back as a plain analog trigger. No controller needed.
|
|
add_executable(TriggerDetectorProbe
|
|
src/probe/TriggerDetectorProbe.cpp
|
|
)
|
|
target_include_directories(TriggerDetectorProbe PRIVATE src)
|
|
if (MSVC)
|
|
target_compile_options(TriggerDetectorProbe PRIVATE /W4 /WX /utf-8)
|
|
set_target_properties(TriggerDetectorProbe PROPERTIES LINK_FLAGS_DEBUG "/SUBSYSTEM:CONSOLE")
|
|
endif()
|
|
|
|
# Virtual gamepad bus probe — dumps every bus the ViGEm client can see, which
|
|
# is the one question a "vigem_connect failed" report cannot answer on its own
|
|
add_executable(ViGEmBusProbe
|
|
src/probe/ViGEmBusProbe.cpp
|
|
src/app/ViGEmBusInfo.cpp
|
|
)
|
|
target_include_directories(ViGEmBusProbe PRIVATE src)
|
|
target_link_libraries(ViGEmBusProbe PRIVATE ViGEmClient)
|
|
if (MSVC)
|
|
target_compile_options(ViGEmBusProbe PRIVATE /W4 /WX /utf-8 /wd4828)
|
|
set_target_properties(ViGEmBusProbe PROPERTIES LINK_FLAGS_DEBUG "/SUBSYSTEM:CONSOLE")
|
|
endif()
|
|
|
|
# Elevated on-demand helper — restarts the controller device node so the tray
|
|
# app (which never runs elevated) can take the device from a running Steam.
|
|
add_executable(SteamlessDeviceCycle WIN32
|
|
src/helper/DeviceCycleHelper.cpp
|
|
src/app/DeviceRestart.cpp
|
|
src/app/HandleFinder.cpp
|
|
)
|
|
target_link_libraries(SteamlessDeviceCycle PRIVATE SteamController cfgmgr32)
|
|
if (MSVC)
|
|
target_compile_options(SteamlessDeviceCycle PRIVATE /W4 /WX /utf-8)
|
|
endif()
|
|
|
|
# Directional pad checks — the sector maths wraps at 0/360, holds a sector
|
|
# against hysteresis, and latches a press's zone, none of which fail loudly
|
|
add_executable(TrackpadDirectionProbe
|
|
src/probe/TrackpadDirectionProbe.cpp
|
|
src/app/TrackpadInput.cpp
|
|
src/app/InputInjection.cpp
|
|
src/app/EventLog.cpp
|
|
)
|
|
target_include_directories(TrackpadDirectionProbe PRIVATE src)
|
|
target_link_libraries(TrackpadDirectionProbe PRIVATE SteamController)
|
|
if (MSVC)
|
|
target_compile_options(TrackpadDirectionProbe PRIVATE /W4 /WX /utf-8)
|
|
set_target_properties(TrackpadDirectionProbe PROPERTIES LINK_FLAGS_DEBUG "/SUBSYSTEM:CONSOLE")
|
|
endif()
|
|
|
|
# TrackpadZoneProbe — measures where a thumb lands when it clicks a pad, so the
|
|
# Directional Pad ring boundary is calibrated rather than guessed.
|
|
add_executable(TrackpadZoneProbe
|
|
src/probe/TrackpadZoneProbe.cpp
|
|
)
|
|
target_link_libraries(TrackpadZoneProbe PRIVATE SteamController)
|
|
if (MSVC)
|
|
target_compile_options(TrackpadZoneProbe PRIVATE /W4 /WX /utf-8)
|
|
set_target_properties(TrackpadZoneProbe PROPERTIES LINK_FLAGS_DEBUG "/SUBSYSTEM:CONSOLE")
|
|
endif()
|
|
|
|
# TriggerProbe — measures trigger rest/travel/speed/jitter and benches haptic
|
|
# click candidates, so a simulated dual-stage trigger (issue #75) has real
|
|
# numbers behind its threshold and its feedback.
|
|
add_executable(TriggerProbe
|
|
src/probe/TriggerProbe.cpp
|
|
)
|
|
target_link_libraries(TriggerProbe PRIVATE SteamController)
|
|
if (MSVC)
|
|
target_compile_options(TriggerProbe PRIVATE /W4 /WX /utf-8)
|
|
set_target_properties(TriggerProbe PROPERTIES LINK_FLAGS_DEBUG "/SUBSYSTEM:CONSOLE")
|
|
endif()
|
|
|
|
# Stick deadzone checks — rest reads as nothing, the edge has no step, and full
|
|
# deflection still reaches full. No controller needed.
|
|
add_executable(StickDeadzoneProbe
|
|
src/probe/StickDeadzoneProbe.cpp
|
|
)
|
|
target_include_directories(StickDeadzoneProbe PRIVATE src)
|
|
if (MSVC)
|
|
target_compile_options(StickDeadzoneProbe PRIVATE /W4 /WX /utf-8)
|
|
set_target_properties(StickDeadzoneProbe PROPERTIES LINK_FLAGS_DEBUG "/SUBSYSTEM:CONSOLE")
|
|
endif()
|
|
|
|
# StickRestProbe — measures what the sticks report at rest, so the stick
|
|
# deadzone (issue #117) is sized from numbers rather than a guess.
|
|
add_executable(StickRestProbe
|
|
src/probe/StickRestProbe.cpp
|
|
)
|
|
target_link_libraries(StickRestProbe PRIVATE SteamController)
|
|
if (MSVC)
|
|
target_compile_options(StickRestProbe PRIVATE /W4 /WX /utf-8)
|
|
set_target_properties(StickRestProbe PROPERTIES LINK_FLAGS_DEBUG "/SUBSYSTEM:CONSOLE")
|
|
endif()
|
|
|
|
# PowerOffProbe — tries the firmware "turn off controller" command candidates and
|
|
# watches whether the pad goes quiet, so Steam + Y can power it down (issue #106).
|
|
add_executable(PowerOffProbe
|
|
src/probe/PowerOffProbe.cpp
|
|
)
|
|
target_link_libraries(PowerOffProbe PRIVATE SteamController)
|
|
if (MSVC)
|
|
target_compile_options(PowerOffProbe PRIVATE /W4 /WX /utf-8)
|
|
set_target_properties(PowerOffProbe PROPERTIES LINK_FLAGS_DEBUG "/SUBSYSTEM:CONSOLE")
|
|
endif()
|
|
|
|
# HapticTester — local-only interactive haptic tuning tool (source is gitignored)
|
|
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/src/probe/HapticTester.cpp")
|
|
add_executable(HapticTester src/probe/HapticTester.cpp)
|
|
target_link_libraries(HapticTester PRIVATE SteamController)
|
|
if (MSVC)
|
|
target_compile_options(HapticTester PRIVATE /W4 /utf-8)
|
|
set_target_properties(HapticTester PROPERTIES LINK_FLAGS_DEBUG "/SUBSYSTEM:CONSOLE")
|
|
endif()
|
|
endif()
|
|
|
|
# WebView2 — downloaded from NuGet (.nupkg is a zip; FetchContent extracts it)
|
|
FetchContent_Declare(WebView2
|
|
URL https://www.nuget.org/api/v2/package/Microsoft.Web.WebView2/1.0.2849.39
|
|
DOWNLOAD_EXTRACT_TIMESTAMP ON
|
|
)
|
|
FetchContent_MakeAvailable(WebView2)
|
|
|
|
# Map CMake architecture to the NuGet lib subdirectory name
|
|
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
|
set(WV2_ARCH "x64")
|
|
else()
|
|
set(WV2_ARCH "x86")
|
|
endif()
|
|
|
|
# System tray app (no console window)
|
|
add_executable(SteamlessController WIN32
|
|
src/app/main.cpp
|
|
src/app/TrayApp.cpp
|
|
src/app/ControllerManager.cpp
|
|
src/app/VirtualController.cpp
|
|
src/app/TrackpadInput.cpp
|
|
src/app/KeyInput.cpp
|
|
src/app/TouchKeyboard.cpp
|
|
src/app/InputInjection.cpp
|
|
src/app/SteamWatcher.cpp
|
|
src/app/DeviceRestart.cpp
|
|
src/app/EventLog.cpp
|
|
src/app/ForegroundWatcher.cpp
|
|
src/app/GameLibrary.cpp
|
|
src/app/GameLiveness.cpp
|
|
src/app/GameProfiles.cpp
|
|
src/app/HandleFinder.cpp
|
|
src/app/LauncherGames.cpp
|
|
src/app/ProcessIdentity.cpp
|
|
src/app/RemapWindow.cpp
|
|
src/app/SteamAppLocator.cpp
|
|
src/app/ViGEmBusInfo.cpp
|
|
resources/app.rc
|
|
)
|
|
target_include_directories(SteamlessController PRIVATE
|
|
resources
|
|
${webview2_SOURCE_DIR}/build/native/include
|
|
)
|
|
target_link_libraries(SteamlessController PRIVATE
|
|
SteamController
|
|
ViGEmClient
|
|
${webview2_SOURCE_DIR}/build/native/${WV2_ARCH}/WebView2LoaderStatic.lib
|
|
version
|
|
ole32
|
|
shell32
|
|
shlwapi
|
|
cfgmgr32
|
|
windowsapp
|
|
)
|
|
if (MSVC)
|
|
target_compile_options(SteamlessController PRIVATE /W4 /WX /utf-8 /wd4828)
|
|
endif()
|