pull/239/head
Peter Repukat 1 year ago
parent 738803fa2e
commit f7df3deb7d

File diff suppressed because it is too large Load Diff

@ -17,11 +17,12 @@ limitations under the License.
#include <spdlog/spdlog.h>
#include <nlohmann/json.hpp>
#include <utility>
#include "AppLauncher.h"
#include "..\common\Settings.h"
#include "../common/Settings.h"
HttpServer::HttpServer(AppLauncher& app_launcher, std::function<void()> close) : app_launcher_(app_launcher), close_(close)
HttpServer::HttpServer(AppLauncher& app_launcher, std::function<void()> close) : app_launcher_(app_launcher), close_(std::move(close))
{
}

@ -51,8 +51,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 0,1,2,0010004309958
PRODUCTVERSION 0,1,2,0010004309958
FILEVERSION 0,1,2,0011001030052
PRODUCTVERSION 0,1,2,0011001030052
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -69,12 +69,12 @@ BEGIN
BEGIN
VALUE "CompanyName", "Peter Repukat - FlatspotSoftware"
VALUE "FileDescription", "GlosSI - SteamTarget"
VALUE "FileVersion", "0.1.2.0-10-g43c9958"
VALUE "FileVersion", "0.1.2.0-11-g1f3fb52"
VALUE "InternalName", "GlosSITarget"
VALUE "LegalCopyright", "Copyright (C) 2021-2022 Peter Repukat - FlatspotSoftware"
VALUE "OriginalFilename", "GlosSITarget.exe"
VALUE "ProductName", "GlosSI"
VALUE "ProductVersion", "0.1.2.0-10-g43c9958"
VALUE "ProductVersion", "0.1.2.0-11-g1f3fb52"
END
END
BLOCK "VarFileInfo"
@ -107,256 +107,3 @@ IDI_ICON1 ICON "..\\GlosSI_Icon.ico"
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

@ -23,7 +23,6 @@ limitations under the License.
#include <numeric>
#include <regex>
#include <spdlog/spdlog.h>
#include <vdf_parser.hpp>
#ifdef _WIN32
#include "UWPOverlayEnabler.h"
@ -36,7 +35,7 @@ SteamTarget::SteamTarget()
: window_(
[this] { run_ = false; },
[this] { toggleGlossiOverlay(); },
getScreenshotHotkey(),
util::steam::getScreenshotHotkey(steam_path_, steam_user_id_),
[this]() {
target_window_handle_ = window_.getSystemHandle();
overlay_ = window_.getOverlay();
@ -65,17 +64,15 @@ int SteamTarget::run()
auto closeBPM = false;
auto closeBPMTimer = sf::Clock{};
if (!SteamOverlayDetector::IsSteamInjected()) {
return 1;
spdlog::warn("GlosSI not launched via Steam.\nEnabling EXPERIMENTAL global controller and overlay...");
if (Settings::common.standaloneModeGameId == L"") {
spdlog::error("No game id set for standalone mode. Controller will use desktop-config!");
}
SetEnvironmentVariable(L"SteamAppId", L"0");
SetEnvironmentVariable(L"SteamClientLaunch", L"0");
SetEnvironmentVariable(L"SteamEnv", L"1");
SetEnvironmentVariable(L"SteamPath", getSteamPath().wstring().c_str());
SetEnvironmentVariable(L"SteamPath", steam_path_.wstring().c_str());
SetEnvironmentVariable(L"SteamTenfoot", Settings::common.standaloneUseGamepadUI ? L"1" : L"0");
// SetEnvironmentVariable(L"SteamTenfootHybrid", L"1");
SetEnvironmentVariable(L"SteamGamepadUI", Settings::common.standaloneUseGamepadUI ? L"1" : L"0");
@ -94,7 +91,7 @@ int SteamTarget::run()
}
Sleep(6000); // DIRTY HACK to wait until BPM (GamepadUI) is initialized
// TODO: find way to force BPM even if BPM is not active
LoadLibrary((getSteamPath() / "GameOverlayRenderer64.dll").wstring().c_str());
LoadLibrary((steam_path_ / "GameOverlayRenderer64.dll").wstring().c_str());
// Overlay switches back to desktop one, once BPM is closed... Disable closing BPM for now.
// TODO: find way to force BPM even if BPM is not active
@ -102,14 +99,13 @@ int SteamTarget::run()
closeBPMTimer.restart();
}
else {
LoadLibrary( (getSteamPath() / "GameOverlayRenderer64.dll").wstring().c_str());
LoadLibrary((steam_path_ / "GameOverlayRenderer64.dll").wstring().c_str());
}
window_.setClickThrough(true);
if (!overlay_.expired())
overlay_.lock()->setEnabled(false);
steam_overlay_present_ = true;
}
else {
spdlog::info("Steam-overlay detected.");
@ -130,7 +126,7 @@ int SteamTarget::run()
}
#endif
}
getXBCRebindingEnabled();
util::steam::getXBCRebindingEnabled(steam_path_, steam_user_id_);
run_ = true;
@ -145,29 +141,7 @@ int SteamTarget::run()
keepControllerConfig(true);
#ifdef _WIN32
HICON icon = 0;
TCHAR path[MAX_PATH];
GetModuleFileName(nullptr, path, MAX_PATH);
icon = (HICON)LoadImage(
0,
path,
IMAGE_ICON,
GetSystemMetrics(SM_CXSMICON),
GetSystemMetrics(SM_CYSMICON),
LR_LOADFROMFILE | LR_LOADMAP3DCOLORS);
if (!icon) {
ExtractIconEx(path, 0, &icon, nullptr, 1);
}
Tray::Tray tray{"GlosSITarget", icon};
#else
Tray::Tray tray{"GlosSITarget", "ico.png"};
#endif
tray.addEntry(Tray::Button{
"Quit", [this, &tray]() {
run_ = false;
}});
const auto tray = createTrayMenu();
server_.run();
@ -191,7 +165,7 @@ int SteamTarget::run()
launcher_.update();
}
}
tray.exit();
tray->exit();
server_.stop();
#ifdef _WIN32
@ -290,154 +264,11 @@ void SteamTarget::focusWindow(WindowHandle hndl)
#endif
}
std::filesystem::path SteamTarget::getSteamPath() const
{
#ifdef _WIN32
try {
// TODO: check if keys/value exist
// steam should always be open and have written reg values...
winreg::RegKey key{HKEY_CURRENT_USER, L"SOFTWARE\\Valve\\Steam"};
const auto res = key.GetStringValue(L"SteamPath");
spdlog::info(L"Detected Steam Path: {}", res);
return res;
}
catch (const winreg::RegException& e) {
spdlog::error("Couldn't get Steam path from Registry; {}", e.what());
}
return Settings::common.steamPath;
#else
return L""; // TODO
#endif
}
std::wstring SteamTarget::getSteamUserId() const
{
#ifdef _WIN32
try {
// TODO: check if keys/value exist
// steam should always be open and have written reg values...
winreg::RegKey key{HKEY_CURRENT_USER, L"SOFTWARE\\Valve\\Steam\\ActiveProcess"};
const auto res = std::to_wstring(key.GetDwordValue(L"ActiveUser"));
spdlog::info(L"Detected Steam UserId: {}", res);
return res;
}
catch (const winreg::RegException& e) {
spdlog::error("Couldn't get Steam path from Registry; {}", e.what());
}
return Settings::common.steamUserId;
#else
return L""; // TODO
#endif
}
std::vector<std::string> SteamTarget::getOverlayHotkey()
{
const auto config_path = std::wstring(steam_path_) + std::wstring(user_data_path_) + steam_user_id_ + std::wstring(config_file_name_);
if (!std::filesystem::exists(config_path)) {
spdlog::warn(L"Couldn't read Steam config file: \"{}\"", config_path);
return {"Shift", "KEY_TAB"}; // default
}
std::ifstream config_file(config_path);
auto root = tyti::vdf::read(config_file);
std::shared_ptr<tyti::vdf::basic_object<char>> children = root.childs["system"];
if (!children || children->attribs.empty() || !children->attribs.contains("InGameOverlayShortcutKey")) {
spdlog::warn("Couldn't detect overlay hotkey, using default: Shift+Tab");
return {"Shift", "KEY_TAB"}; // default
}
auto hotkeys = children->attribs.at("InGameOverlayShortcutKey");
// has anyone more than 4 keys to open overlay?!
std::smatch m;
if (!std::regex_match(hotkeys, m, std::regex(R"((\w*)\s*(\w*)\s*(\w*)\s*(\w*))"))) {
spdlog::warn("Couldn't detect overlay hotkey, using default: Shift+Tab");
return {"Shift", "KEY_TAB"}; // default
}
std::vector<std::string> res;
for (auto i = 1; i < m.size(); i++) {
const auto s = std::string(m[i]);
if (!s.empty()) {
res.push_back(s);
}
}
if (res.empty()) {
spdlog::warn("Couldn't detect overlay hotkey, using default: Shift+Tab");
return {"Shift", "KEY_TAB"}; // default
}
spdlog::info("Detected Overlay hotkey(s): {}", std::accumulate(
res.begin() + 1, res.end(), res[0],
[](auto acc, const auto curr) { return acc += "+" + curr; }));
return res;
}
std::vector<std::string> SteamTarget::getScreenshotHotkey()
{
const auto config_path = std::wstring(steam_path_) + std::wstring(user_data_path_) + steam_user_id_ + std::wstring(config_file_name_);
if (!std::filesystem::exists(config_path)) {
spdlog::warn(L"Couldn't read Steam config file: \"{}\"", config_path);
return {"KEY_F12"}; // default
}
std::ifstream config_file(config_path);
auto root = tyti::vdf::read(config_file);
std::shared_ptr<tyti::vdf::basic_object<char>> children = root.childs["system"];
if (!children || children->attribs.empty() || !children->attribs.contains("InGameOverlayScreenshotHotKey")) {
spdlog::warn("Couldn't detect overlay hotkey, using default: F12");
return {"KEY_F12"}; // default
}
auto hotkeys = children->attribs.at("InGameOverlayScreenshotHotKey");
// has anyone more than 4 keys to screenshot?!
std::smatch m;
if (!std::regex_match(hotkeys, m, std::regex(R"((\w*)\s*(\w*)\s*(\w*)\s*(\w*))"))) {
spdlog::warn("Couldn't detect overlay hotkey, using default: F12");
return {"KEY_F12"}; // default
}
std::vector<std::string> res;
for (auto i = 1; i < m.size(); i++) {
const auto s = std::string(m[i]);
if (!s.empty()) {
res.push_back(s);
}
}
if (res.empty()) {
spdlog::warn("Couldn't detect overlay hotkey, using default: F12");
return {"KEY_F12"}; // default
}
spdlog::info("Detected screenshot hotkey(s): {}", std::accumulate(
res.begin() + 1, res.end(), res[0],
[](auto acc, const auto curr) { return acc += "+" + curr; }));
return res;
}
bool SteamTarget::getXBCRebindingEnabled()
{
const auto config_path = std::wstring(steam_path_) + std::wstring(user_data_path_) + steam_user_id_ + std::wstring(config_file_name_);
if (!std::filesystem::exists(config_path)) {
spdlog::warn(L"Couldn't read Steam config file: \"{}\"", config_path);
return false;
}
std::ifstream config_file(config_path);
auto root = tyti::vdf::read(config_file);
if (root.attribs.empty() || !root.attribs.contains("SteamController_XBoxSupport")) {
spdlog::warn("\"Xbox Configuration Support\" is disabled in Steam. This may cause doubled Inputs!");
return false;
}
auto xbsup = root.attribs.at("SteamController_XBoxSupport");
if (xbsup != "1") {
spdlog::warn("\"Xbox Configuration Support\" is disabled in Steam. This may cause doubled Inputs!");
}
return xbsup == "1";
}
/*
* The "magic" that keeps a controller-config forced (without hooking into Steam)
*
* Hook into own process and detour "GetForegroundWindow"
* Deatour function always returns HWND of own application window
* Detour function always returns HWND of own application window
* Steam now doesn't detect application changes and keeps the game-specific input config without reverting to desktop-conf
*/
void SteamTarget::keepControllerConfig(bool keep)
@ -488,6 +319,34 @@ HWND SteamTarget::keepFgWindowHookFn()
}
#endif
std::unique_ptr<Tray::Tray> SteamTarget::createTrayMenu()
{
#ifdef _WIN32
HICON icon = 0;
TCHAR path[MAX_PATH];
GetModuleFileName(nullptr, path, MAX_PATH);
icon = (HICON)LoadImage(
0,
path,
IMAGE_ICON,
GetSystemMetrics(SM_CXSMICON),
GetSystemMetrics(SM_CYSMICON),
LR_LOADFROMFILE | LR_LOADMAP3DCOLORS);
if (!icon) {
ExtractIconEx(path, 0, &icon, nullptr, 1);
}
auto tray = std::make_unique<Tray::Tray>("GlosSITarget", icon);
#else
auto tray = std::make_unique<Tray::Tray>("GlosSITarget", "ico.png");
#endif
tray->addEntry(Tray::Button{
"Quit", [this, &tray]() {
run_ = false;
}});
return tray;
}
void SteamTarget::overlayHotkeyWorkaround()
{
static bool pressed = false;

@ -26,13 +26,17 @@ limitations under the License.
#include <subhook.h>
#endif
#include <filesystem>
#include "AppLauncher.h"
#include "Overlay.h"
#include "HttpServer.h"
#include "../common/steam_util.h"
#include <filesystem>
namespace Tray {
class Tray;
}
class SteamTarget {
public:
explicit SteamTarget();
@ -42,15 +46,9 @@ class SteamTarget {
void onOverlayChanged(bool overlay_open);
void toggleGlossiOverlay();
void focusWindow(WindowHandle hndl);
std::filesystem::path getSteamPath() const;
std::wstring getSteamUserId() const;
std::filesystem::path steam_path_ = getSteamPath();
std::wstring steam_user_id_ = getSteamUserId();
std::vector<std::string> getOverlayHotkey();
std::vector<std::string> getScreenshotHotkey();
bool getXBCRebindingEnabled();
std::filesystem::path steam_path_ = util::steam::getSteamPath();
std::wstring steam_user_id_ = util::steam::getSteamUserId();
bool steam_overlay_present_ = false;
@ -65,6 +63,8 @@ class SteamTarget {
static inline HWND last_real_hwnd_ = nullptr;
#endif
std::unique_ptr<Tray::Tray> createTrayMenu();
/*
* Run once per frame
* detects steam configured overlay hotkey, and simulates key presses to window
@ -74,7 +74,7 @@ class SteamTarget {
void overlayHotkeyWorkaround();
bool run_ = false;
std::vector<std::string> overlay_hotkey_ = getOverlayHotkey();
std::vector<std::string> overlay_hotkey_ = util::steam::getOverlayHotkey(steam_path_, steam_user_id_);
#ifdef _WIN32
HidHide hidhide_;
@ -94,9 +94,4 @@ class SteamTarget {
bool delayed_shutdown_ = false;
sf::Clock delay_shutdown_clock_;
static constexpr std::wstring_view user_data_path_ = L"/userdata/";
static constexpr std::wstring_view config_file_name_ = L"/config/localconfig.vdf";
static constexpr std::string_view overlay_hotkey_name_ = "InGameOverlayShortcutKey ";
static constexpr std::string_view screenshot_hotkey_name_ = "InGameOverlayScreenshotHotKey ";
};

@ -3,7 +3,7 @@
!define APP_NAME "GlosSI"
!define COMP_NAME "Peter Repukat - Flatspotsoftware"
!define WEB_SITE "https://glossi.flatspot.pictures/"
!define VERSION "0.1.2.0-10-g43c9958"
!define VERSION "0.1.2.0-11-g1f3fb52"
!define COPYRIGHT "Peter Repukat - FlatspotSoftware © 2017-2022"
!define DESCRIPTION "SteamInput compatibility tool"
!define INSTALLER_NAME "GlosSI-Installer.exe"
@ -191,44 +191,3 @@ DeleteRegKey ${REG_ROOT} "${REG_APP_PATH}"
DeleteRegKey ${REG_ROOT} "${UNINSTALL_PATH}"
SectionEnd

@ -15,11 +15,13 @@ limitations under the License.
*/
#pragma once
#define SPDLOG_WCHAR_TO_UTF8_SUPPORT
#define SPDLOG_WCHAR_FILENAMES
#include <spdlog/spdlog.h>
#include <fstream>
#include <regex>
#include <string>
#include <nlohmann/json.hpp>
#include <spdlog/spdlog.h>
#ifdef WIN32
#define NOMINMAX
@ -75,8 +77,19 @@ namespace Settings {
std::wstring steamUserId;
std::wstring standaloneModeGameId; /* = L"12605636929694728192"; */
bool standaloneUseGamepadUI = false;
bool allowStandAlone = true;
} common;
inline const std::map<std::wstring, std::function<void()>> cmd_args = {
{L"-disableuwpoverlay", [&]() { common.no_uwp_overlay = true; }},
{L"-disablewatchdog", [&]() { common.disable_watchdog = true; }},
{L"-ignorelauncher", [&]() { launch.ignoreLauncher = true; }},
{L"-window", [&]() { window.windowMode = true; }},
{L"-extendedLogging", [&]() { common.extendedLogging = true; }},
{L"-standaloneUseGamepadUI", [&]() { common.standaloneUseGamepadUI = true; }},
{L"-disallowStandAlone", [&]() { common.allowStandAlone = false; }},
};
inline std::filesystem::path settings_path_ = "";
inline bool checkIsUwp(const std::wstring& launch_path)
@ -123,10 +136,18 @@ namespace Settings {
}
}
catch (const nlohmann::json::exception& e) {
if constexpr (std::is_same_v<T, std::wstring>) {
e.id == 403
? spdlog::trace("Err parsing \"{}\"; {}; Using default: {}", key, e.what(), util::string::to_string(value))
: spdlog::warn("Err parsing \"{}\"; {}", key, e.what());
}
else
{
e.id == 403
? spdlog::trace("Err parsing \"{}\"; {}", key, e.what())
? spdlog::trace("Err parsing \"{}\"; {}; Using default: {}", key, e.what(), value)
: spdlog::warn("Err parsing \"{}\"; {}", key, e.what());
}
}
catch (const std::exception& e) {
spdlog::warn("Err parsing \"{}\"; {}", key, e.what());
}
@ -140,7 +161,7 @@ namespace Settings {
// TODO: make this as much generic as fits in about the same amount of code if one would parse every value separately.
try {
if (auto launchconf = json["launch"]; !launchconf.is_null() && !launchconf.empty() && launchconf.is_object()) {
if (const auto launchconf = json["launch"]; !launchconf.is_null() && !launchconf.empty() && launchconf.is_object()) {
safeParseValue(launchconf, "launch", launch.launch);
safeParseValue(launchconf, "launchPath", launch.launchPath);
safeParseValue(launchconf, "launchAppArgs", launch.launchAppArgs);
@ -149,7 +170,7 @@ namespace Settings {
safeParseValue(launchconf, "killLauncher", launch.killLauncher);
safeParseValue(launchconf, "ignoreLauncher", launch.ignoreLauncher);
if (auto launcherProcs = launchconf["launcherProcesses"];
if (const auto launcherProcs = launchconf["launcherProcesses"];
!launcherProcs.is_null() && !launcherProcs.empty() && launcherProcs.is_array()) {
launch.launcherProcesses.clear();
launch.launcherProcesses.reserve(launcherProcs.size());
@ -159,12 +180,12 @@ namespace Settings {
}
}
if (auto devconf = json["devices"]; !devconf.is_null() && !devconf.empty() && devconf.is_object()) {
if (const auto devconf = json["devices"]; !devconf.is_null() && !devconf.empty() && devconf.is_object()) {
safeParseValue(devconf, "hideDevices", devices.hideDevices);
safeParseValue(devconf, "realDeviceIds", devices.realDeviceIds);
}
if (auto winconf = json["window"]; !winconf.is_null() && !winconf.empty() && winconf.is_object()) {
if (const auto winconf = json["window"]; !winconf.is_null() && !winconf.empty() && winconf.is_object()) {
safeParseValue(winconf, "windowMode", window.windowMode);
safeParseValue(winconf, "maxFps", window.maxFps);
safeParseValue(winconf, "scale", window.scale);
@ -173,7 +194,7 @@ namespace Settings {
safeParseValue(winconf, "disableGlosSIOverlay", window.disableGlosSIOverlay);
}
if (auto controllerConf = json["controller"]; !controllerConf.is_null() && !controllerConf.empty() && controllerConf.is_object()) {
if (const auto controllerConf = json["controller"]; !controllerConf.is_null() && !controllerConf.empty() && controllerConf.is_object()) {
safeParseValue(controllerConf, "maxControllers", controller.maxControllers);
safeParseValue(controllerConf, "allowDesktopConfig", controller.allowDesktopConfig);
safeParseValue(controllerConf, "emulateDS4", controller.emulateDS4);
@ -207,17 +228,9 @@ namespace Settings {
if (arg.empty()) {
continue;
}
if (arg == L"-disableuwpoverlay") {
common.no_uwp_overlay = true;
}
else if (arg == L"-disablewatchdog") {
common.disable_watchdog = true;
}
else if (arg == L"-ignorelauncher") {
launch.ignoreLauncher = true;
}
else if (arg == L"-window") {
window.windowMode = true;
if (cmd_args.contains(arg))
{
cmd_args.at(arg)();
}
else {
configName += L" " + std::wstring(arg.begin(), arg.end());

@ -18,6 +18,8 @@ limitations under the License.
#include "util.h"
#ifndef CONFIGAPP
#define SPDLOG_WCHAR_TO_UTF8_SUPPORT
#define SPDLOG_WCHAR_FILENAMES
#include <spdlog/spdlog.h>
#include "Settings.h"

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\packages\Microsoft.Windows.CppWinRT.2.0.220531.1\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('..\packages\Microsoft.Windows.CppWinRT.2.0.220531.1\build\native\Microsoft.Windows.CppWinRT.props')" />
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
@ -71,10 +72,10 @@
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<IncludePath>..\deps\json\include;..\deps\spdlog\include;..\deps\SFML\include;..\deps\imgui;$(IncludePath)</IncludePath>
<IncludePath>..\deps\json\include;..\deps\spdlog\include;..\deps\SFML\include;..\deps\imgui;..\deps\WinReg;..\deps\ValveFileVDF;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<IncludePath>..\deps\json\include;..\deps\spdlog\include;..\deps\SFML\include;..\deps\imgui;$(IncludePath)</IncludePath>
<IncludePath>..\deps\json\include;..\deps\spdlog\include;..\deps\SFML\include;..\deps\imgui;..\deps\WinReg;..\deps\ValveFileVDF;$(IncludePath)</IncludePath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
@ -138,6 +139,7 @@
<ClInclude Include="HidHide.h" />
<ClInclude Include="nlohmann_json_wstring.h" />
<ClInclude Include="Settings.h" />
<ClInclude Include="steam_util.h" />
<ClInclude Include="UnhookUtil.h" />
<ClInclude Include="util.h" />
</ItemGroup>
@ -147,5 +149,13 @@
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
<Import Project="..\packages\Microsoft.Windows.CppWinRT.2.0.220531.1\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\packages\Microsoft.Windows.CppWinRT.2.0.220531.1\build\native\Microsoft.Windows.CppWinRT.targets')" />
</ImportGroup>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\Microsoft.Windows.CppWinRT.2.0.220531.1\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Windows.CppWinRT.2.0.220531.1\build\native\Microsoft.Windows.CppWinRT.props'))" />
<Error Condition="!Exists('..\packages\Microsoft.Windows.CppWinRT.2.0.220531.1\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Windows.CppWinRT.2.0.220531.1\build\native\Microsoft.Windows.CppWinRT.targets'))" />
</Target>
</Project>

@ -30,6 +30,9 @@
<ClInclude Include="HidHide.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="steam_util.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="UnhookUtil.cpp">

@ -0,0 +1,181 @@
/*
Copyright 2021-2023 Peter Repukat - FlatspotSoftware
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#pragma once
#define SPDLOG_WCHAR_TO_UTF8_SUPPORT
#define SPDLOG_WCHAR_FILENAMES
#include <spdlog/spdlog.h>
#include <WinReg/WinReg.hpp>
#include <vdf_parser.hpp>
#include "util.h"
#include "Settings.h"
namespace util
{
namespace steam
{
static constexpr std::wstring_view user_data_path = L"/userdata/";
static constexpr std::wstring_view config_file_name = L"/config/localconfig.vdf";
static constexpr std::string_view overlay_hotkey_name = "InGameOverlayShortcutKey ";
static constexpr std::string_view screenshot_hotkey_name = "InGameOverlayScreenshotHotKey ";
inline std::filesystem::path getSteamPath()
{
#ifdef _WIN32
try {
// TODO: check if keys/value exist
// steam should always be open and have written reg values...
winreg::RegKey key{ HKEY_CURRENT_USER, L"SOFTWARE\\Valve\\Steam" };
const auto res = key.GetStringValue(L"SteamPath");
spdlog::info(L"Detected Steam Path: {}", res);
return res;
}
catch (const winreg::RegException& e) {
spdlog::error("Couldn't get Steam path from Registry; {}", e.what());
}
return Settings::common.steamPath;
#else
return L""; // TODO
#endif
}
inline std::wstring getSteamUserId()
{
#ifdef _WIN32
try {
// TODO: check if keys/value exist
// steam should always be open and have written reg values...
winreg::RegKey key{ HKEY_CURRENT_USER, L"SOFTWARE\\Valve\\Steam\\ActiveProcess" };
const auto res = std::to_wstring(key.GetDwordValue(L"ActiveUser"));
spdlog::info(L"Detected Steam UserId: {}", res);
return res;
}
catch (const winreg::RegException& e) {
spdlog::error("Couldn't get Steam path from Registry; {}", e.what());
}
return Settings::common.steamUserId;
#else
return L""; // TODO
#endif
}
inline std::vector<std::string> getOverlayHotkey(const std::wstring& steam_path = getSteamPath(), const std::wstring& steam_user_id = getSteamPath())
{
const auto config_path = std::wstring(steam_path) + std::wstring(user_data_path) + steam_user_id + std::wstring(config_file_name);
if (!std::filesystem::exists(config_path)) {
spdlog::warn(L"Couldn't read Steam config file: \"{}\"", config_path);
return { "Shift", "KEY_TAB" }; // default
}
std::ifstream config_file(config_path);
auto root = tyti::vdf::read(config_file);
std::shared_ptr<tyti::vdf::basic_object<char>> children = root.childs["system"];
if (!children || children->attribs.empty() || !children->attribs.contains("InGameOverlayShortcutKey")) {
spdlog::warn("Couldn't detect overlay hotkey, using default: Shift+Tab");
return { "Shift", "KEY_TAB" }; // default
}
auto hotkeys = children->attribs.at("InGameOverlayShortcutKey");
// has anyone more than 4 keys to open overlay?!
std::smatch m;
if (!std::regex_match(hotkeys, m, std::regex(R"((\w*)\s*(\w*)\s*(\w*)\s*(\w*))"))) {
spdlog::warn("Couldn't detect overlay hotkey, using default: Shift+Tab");
return { "Shift", "KEY_TAB" }; // default
}
std::vector<std::string> res;
for (auto i = 1; i < m.size(); i++) {
const auto s = std::string(m[i]);
if (!s.empty()) {
res.push_back(s);
}
}
if (res.empty()) {
spdlog::warn("Couldn't detect overlay hotkey, using default: Shift+Tab");
return { "Shift", "KEY_TAB" }; // default
}
spdlog::info("Detected Overlay hotkey(s): {}", std::accumulate(
res.begin() + 1, res.end(), res[0],
[](auto acc, const auto curr) { return acc += "+" + curr; }));
return res;
}
inline std::vector<std::string> getScreenshotHotkey(const std::wstring& steam_path = getSteamPath(), const std::wstring& steam_user_id = getSteamPath())
{
const auto config_path = std::wstring(steam_path) + std::wstring(user_data_path) + steam_user_id + std::wstring(config_file_name);
if (!std::filesystem::exists(config_path)) {
spdlog::warn(L"Couldn't read Steam config file: \"{}\"", config_path);
return { "KEY_F12" }; // default
}
std::ifstream config_file(config_path);
auto root = tyti::vdf::read(config_file);
std::shared_ptr<tyti::vdf::basic_object<char>> children = root.childs["system"];
if (!children || children->attribs.empty() || !children->attribs.contains("InGameOverlayScreenshotHotKey")) {
spdlog::warn("Couldn't detect overlay hotkey, using default: F12");
return { "KEY_F12" }; // default
}
auto hotkeys = children->attribs.at("InGameOverlayScreenshotHotKey");
// has anyone more than 4 keys to screenshot?!
std::smatch m;
if (!std::regex_match(hotkeys, m, std::regex(R"((\w*)\s*(\w*)\s*(\w*)\s*(\w*))"))) {
spdlog::warn("Couldn't detect overlay hotkey, using default: F12");
return { "KEY_F12" }; // default
}
std::vector<std::string> res;
for (auto i = 1; i < m.size(); i++) {
const auto s = std::string(m[i]);
if (!s.empty()) {
res.push_back(s);
}
}
if (res.empty()) {
spdlog::warn("Couldn't detect overlay hotkey, using default: F12");
return { "KEY_F12" }; // default
}
spdlog::info("Detected screenshot hotkey(s): {}", std::accumulate(
res.begin() + 1, res.end(), res[0],
[](auto acc, const auto curr) { return acc += "+" + curr; }));
return res;
}
inline bool getXBCRebindingEnabled(const std::wstring& steam_path = getSteamPath(), const std::wstring& steam_user_id = getSteamPath())
{
const auto config_path = std::wstring(steam_path) + std::wstring(user_data_path) + steam_user_id + std::wstring(config_file_name);
if (!std::filesystem::exists(config_path)) {
spdlog::warn(L"Couldn't read Steam config file: \"{}\"", config_path);
return false;
}
std::ifstream config_file(config_path);
auto root = tyti::vdf::read(config_file);
if (root.attribs.empty() || !root.attribs.contains("SteamController_XBoxSupport")) {
spdlog::warn("\"Xbox Configuration Support\" is disabled in Steam. This may cause doubled Inputs!");
return false;
}
auto xbsup = root.attribs.at("SteamController_XBoxSupport");
if (xbsup != "1") {
spdlog::warn("\"Xbox Configuration Support\" is disabled in Steam. This may cause doubled Inputs!");
}
return xbsup == "1";
}
}
}

@ -31,6 +31,8 @@ limitations under the License.
#include <filesystem>
#ifdef SPDLOG_H
#define SPDLOG_WCHAR_TO_UTF8_SUPPORT
#define SPDLOG_WCHAR_FILENAMES
#include <spdlog/spdlog.h>
#endif

Loading…
Cancel
Save