2
0
mirror of https://github.com/Thracky/GlosSI.git synced 2024-11-03 09:40:18 +00:00

begin rewrite

This commit is contained in:
Peter Repukat 2018-03-10 23:02:39 +01:00
parent e2fc546d69
commit 9f61d9fb3f
20 changed files with 436 additions and 76 deletions

View File

@ -71,7 +71,7 @@
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(SolutionDir)\build\Win32Only\$(Configuration)</OutDir>
<OutDir>$(SolutionDir)\build\$(Platform)\$(Configuration)\</OutDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>

View File

@ -1,5 +1,5 @@
/*
Copyright 2016 Peter Repukat - FlatspotSoftware
Copyright 2018 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.

View File

@ -1,5 +1,5 @@
/*
Copyright 2016 Peter Repukat - FlatspotSoftware
Copyright 2018 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.

View File

@ -1,5 +1,5 @@
/*
Copyright 2016 Peter Repukat - FlatspotSoftware
Copyright 2018 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.

View File

@ -1,5 +1,5 @@
/*
Copyright 2016 Peter Repukat - FlatspotSoftware
Copyright 2018 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.

View File

@ -1,5 +1,5 @@
/*
Copyright 2016 Peter Repukat - FlatspotSoftware
Copyright 2018 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.

View File

@ -1,5 +1,5 @@
/*
Copyright 2016 Peter Repukat - FlatspotSoftware
Copyright 2018 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.

View File

@ -1,5 +1,5 @@
/*
Copyright 2016 Peter Repukat - FlatspotSoftware
Copyright 2018 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.

View File

@ -1,5 +1,5 @@
/*
Copyright 2016 Peter Repukat - FlatspotSoftware
Copyright 2018 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.

View File

@ -0,0 +1,86 @@
#include "SteamTarget.h"
#include <Windows.h>
#include <QTimer>
#include <QSettings>
#include <qmessagebox.h>
#include <iostream>
SteamTarget::SteamTarget(int& argc, char** argv) : QApplication(argc, argv)
{
}
void SteamTarget::init()
{
connect(this, SIGNAL(aboutToQuit()), this, SLOT(onAboutToQuit()));
SetConsoleCtrlHandler(reinterpret_cast<PHANDLER_ROUTINE>(ConsoleCtrlCallback), true);
read_ini();
SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);
target_overlay_.init(!enable_overlay_);
if (enable_controllers_)
controller_thread_.run();
}
BOOL SteamTarget::ConsoleCtrlCallback(DWORD dwCtrlType)
{
if (dwCtrlType == CTRL_CLOSE_EVENT || dwCtrlType == CTRL_BREAK_EVENT || dwCtrlType == CTRL_C_EVENT)
{
quit();
return true;
}
return false;
}
void SteamTarget::onAboutToQuit()
{
controller_thread_.stop();
target_overlay_.stop();
}
void SteamTarget::read_ini()
{
if (arguments().size() == 1)
{
QMessageBox::warning(nullptr, "Error", "Target configuration file must be specified! Using default Values!");
}
else {
QSettings settings(arguments().at(1), QSettings::IniFormat);
settings.beginGroup("BaseConf");
QStringList childKeys = settings.childKeys();
for (auto &childkey : childKeys)
{
if (childkey == "bEnableOverlay") {
enable_overlay_ = settings.value(childkey).toBool();
}
else if (childkey == "bEnableControllers") {
enable_controllers_ = settings.value(childkey).toBool();
}
else if (childkey == "bHookSteam") {
hook_steam_ = settings.value(childkey).toBool();
}
else if (childkey == "bUseDesktopConfig") {
use_desktop_conf_ = settings.value(childkey).toBool();
}
}
settings.endGroup();
settings.beginGroup("LaunchGame");
childKeys = settings.childKeys();
for (auto &childkey : childKeys)
{
if (childkey == "bLaunchGame") {
launch_game_ = settings.value(childkey).toBool();
}
else if (childkey == "Path") {
launch_app_path_ = settings.value(childkey).toString().toStdString();
}
else if (childkey == "Type") {
launch_uwp_ = settings.value(childkey).toString() == QString("UWP");
}
else if (childkey == "bCloseWhenDone") {
close_launched_done_ = settings.value(childkey).toBool();
}
}
settings.endGroup();
}
}

58
SteamTarget/SteamTarget.h Normal file
View File

@ -0,0 +1,58 @@
/*
Copyright 2018 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
#include <QApplication>
#include <thread>
#include <Windows.h>
#include <dwmapi.h>
#include "TargetOverlay.h"
#include "VirtualControllerThread.h"
class SteamTarget : public QApplication
{
Q_OBJECT
public:
SteamTarget(int& argc, char** argv);
~SteamTarget() = default;
void init();
static BOOL WINAPI ConsoleCtrlCallback(DWORD dwCtrlType);
public slots:
void onAboutToQuit();
private:
void read_ini();
TargetOverlay target_overlay_;
VirtualControllerThread controller_thread_;
//Settings from .ini file
bool hook_steam_ = true;
bool enable_overlay_ = true;
bool enable_controllers_ = true;
bool use_desktop_conf_ = false;
bool launch_game_ = false;
bool close_launched_done_ = false;
bool launch_uwp_ = false;
std::string launch_app_path_ = "";
std::string launch_app_args_ = "";
};

View File

@ -131,6 +131,10 @@
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="GeneratedFiles\Debug\moc_SteamTarget.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="GeneratedFiles\Debug\moc_SteamTargetRenderer.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
@ -145,12 +149,18 @@
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
</PrecompiledHeader>
</ClCompile>
<ClCompile Include="GeneratedFiles\Release\moc_SteamTarget.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="GeneratedFiles\Release\moc_SteamTargetRenderer.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="main.cpp" />
<ClCompile Include="SteamTarget.cpp" />
<ClCompile Include="SteamTargetRenderer.cpp" />
<ClCompile Include="TargetOverlay.cpp" />
<ClCompile Include="VirtualControllerThread.cpp" />
</ItemGroup>
<ItemGroup>
@ -195,6 +205,25 @@
</ItemGroup>
<ItemGroup>
<ClInclude Include="resource.h" />
<CustomBuild Include="SteamTarget.h">
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Moc%27ing %(Identity)...</Message>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -D_CONSOLE -D_X86_ -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\..\dependencies\ViGEmClient" "-I.\..\dependencies\SFML-2.4.2-x86\include" "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets"</Command>
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Moc%27ing %(Identity)...</Message>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -D_CONSOLE -D_AMD64_ -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\..\dependencies\ViGEmClient" "-I.\..\dependencies\SFML-2.4.2-x64\include" "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets"</Command>
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
<Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Moc%27ing %(Identity)...</Message>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -D_CONSOLE -D_X86_ -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\..\dependencies\ViGEmClient" "-I.\..\dependencies\SFML-2.4.2-x86\include" "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets"</Command>
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
<Message Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Moc%27ing %(Identity)...</Message>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -D_CONSOLE -D_AMD64_ -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\..\dependencies\ViGEmClient" "-I.\..\dependencies\SFML-2.4.2-x64\include" "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets"</Command>
</CustomBuild>
<ClInclude Include="TargetOverlay.h" />
<ClInclude Include="VirtualControllerThread.h" />
</ItemGroup>
<ItemGroup>

View File

@ -58,6 +58,18 @@
<ClCompile Include="VirtualControllerThread.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="SteamTarget.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="GeneratedFiles\Debug\moc_SteamTarget.cpp">
<Filter>Generated Files\Debug</Filter>
</ClCompile>
<ClCompile Include="GeneratedFiles\Release\moc_SteamTarget.cpp">
<Filter>Generated Files\Release</Filter>
</ClCompile>
<ClCompile Include="TargetOverlay.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<CustomBuild Include="SteamTarget.qrc">
@ -66,6 +78,9 @@
<CustomBuild Include="SteamTargetRenderer.h">
<Filter>Header Files</Filter>
</CustomBuild>
<CustomBuild Include="SteamTarget.h">
<Filter>Header Files</Filter>
</CustomBuild>
</ItemGroup>
<ItemGroup>
<ClInclude Include="resource.h">
@ -74,6 +89,9 @@
<ClInclude Include="VirtualControllerThread.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="TargetOverlay.h">
<Filter>Source Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="SteamTarget.rc" />

View File

@ -1,5 +1,5 @@
/*
Copyright 2016 Peter Repukat - FlatspotSoftware
Copyright 2018 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.

View File

@ -1,5 +1,5 @@
/*
Copyright 2016 Peter Repukat - FlatspotSoftware
Copyright 2018 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.

View File

@ -0,0 +1,122 @@
/*
Copyright 2018 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.
*/
#include "TargetOverlay.h"
#include <Windows.h>
#include <dwmapi.h>
#include <SFML/Window/Event.hpp>
bool TargetOverlay::init(bool hidden)
{
window_.create(sf::VideoMode::getDesktopMode(), "GloSC-SteamTarget");
window_.setFramerateLimit(30);
window_.setPosition({ 0, 0 });
makeSfWindowTransparent();
hidden_ = hidden;
if (window_.setActive(false))
{
overlay_thread_ = std::thread(&TargetOverlay::overlayLoop, this);
return true;
}
return false;
}
void TargetOverlay::stop()
{
run_ = false;
overlay_thread_.join();
}
void TargetOverlay::overlayLoop()
{
if (window_.setActive(true))
{
if (hidden_)
{
ShowWindow(window_.getSystemHandle(), SW_HIDE);
window_.setFramerateLimit(1); //Window is not shown anyway,
}
else
{
SetWindowPos(window_.getSystemHandle(), HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_ASYNCWINDOWPOS);
}
while (window_.isOpen() && run_)
{
mtx_.lock();
sf::Event event{};
while (window_.pollEvent(event))
{
if (event.type == sf::Event::Closed)
window_.close();
}
window_.clear(sf::Color::Transparent);
window_.display();
mtx_.unlock();
}
}
}
void TargetOverlay::onOverlayOpened()
{
mtx_.lock();
//TODO: impl
mtx_.unlock();
}
void TargetOverlay::onOverlayClosed()
{
mtx_.lock();
//TODO: impl
mtx_.unlock();
}
void TargetOverlay::makeSfWindowTransparent()
{
HWND hwnd = window_.getSystemHandle();
SetWindowLong(hwnd, GWL_STYLE, WS_VISIBLE | WS_POPUP &~ WS_CAPTION);
SetWindowLong(hwnd, GWL_EXSTYLE, WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_TOPMOST);
MARGINS margins;
margins.cxLeftWidth = -1;
DwmExtendFrameIntoClientArea(hwnd, &margins);
SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE);
window_.clear(sf::Color::Transparent);
window_.display();
}
void TargetOverlay::moveMouseIntoOverlay() const
{
RECT rect = { 0,0,0,0 };
if (GetWindowRect(window_.getSystemHandle(), &rect))
{
POINT cursor_pos = { 0,0 };
GetCursorPos(&cursor_pos);
if (PtInRect(&rect, cursor_pos))
{
SetCursorPos(cursor_pos.x + 1, cursor_pos.y);
}
else
{
SetCursorPos(rect.left + 16, rect.top + 16);
}
}
}

View File

@ -0,0 +1,46 @@
/*
Copyright 2018 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
#include <SFML/Graphics/RenderWindow.hpp>
#include <thread>
#include <mutex>
class TargetOverlay
{
public:
TargetOverlay() = default;
bool init(bool hidden = false);
void stop();
void overlayLoop();
void onOverlayOpened();
void onOverlayClosed();
private:
void makeSfWindowTransparent();
void moveMouseIntoOverlay() const;
std::thread overlay_thread_;
sf::RenderWindow window_;
std::mutex mtx_;
bool run_ = true;
bool hidden_ = false;
};

View File

@ -1,5 +1,5 @@
/*
Copyright 2016 Peter Repukat - FlatspotSoftware
Copyright 2018 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.
@ -18,9 +18,9 @@ limitations under the License.
VirtualControllerThread::VirtualControllerThread()
{
driver = vigem_alloc();
driver_ = vigem_alloc();
if (!VIGEM_SUCCESS(vigem_connect(driver)))
if (!VIGEM_SUCCESS(vigem_connect(driver_)))
{
std::cout << "Error initializing ViGem!" << std::endl;
MessageBoxW(NULL, L"Error initializing ViGem!", L"GloSC-SteamTarget", MB_OK);
@ -29,24 +29,24 @@ VirtualControllerThread::VirtualControllerThread()
for (int i = 0; i < XUSER_MAX_COUNT; i++)
{
vtX360[i] = vigem_target_x360_alloc();
vt_x360_[i] = vigem_target_x360_alloc();
}
seven = IsWindows7OrGreater() != IsWindows8OrGreater();
seven_ = IsWindows7OrGreater() != IsWindows8OrGreater();
}
VirtualControllerThread::~VirtualControllerThread()
{
if (controllerThread.joinable())
controllerThread.join();
vigem_disconnect(driver);
if (controller_thread_.joinable())
controller_thread_.join();
vigem_disconnect(driver_);
}
void VirtualControllerThread::run()
{
bShouldRun = true;
controllerThread = std::thread(&VirtualControllerThread::controllerLoop, this);
controller_thread_ = std::thread(&VirtualControllerThread::controllerLoop, this);
}
void VirtualControllerThread::stop()
@ -54,34 +54,32 @@ void VirtualControllerThread::stop()
bShouldRun = false;
for (int i = 0; i < XUSER_MAX_COUNT; i++)
{
vigem_target_remove(driver, vtX360[i]);
vigem_target_remove(driver_, vt_x360_[i]);
}
}
bool VirtualControllerThread::isRunning()
bool VirtualControllerThread::isRunning() const
{
return bShouldRun;
}
void VirtualControllerThread::controllerLoop()
{
DWORD result;
DWORD result2;
sf::Clock waitForHookTimer;
while (bShouldRun)
{
sfClock.restart();
sf_clock_.restart();
// We have to retrieve the XInputGetState function by loading it via GetProcAdress
// otherwise the M$ compiler calls to a jumptable, jumping to the real function
// otherwise we get calls to a jumptable, jumping to the real function
// We can't have this if we wan't to dynamically unpatch and repatch Valve's XInput hook
// Also wait a second, jut to be sure Steam has done it's hooking thing...
if (XGetState == nullptr && waitForHookTimer.getElapsedTime().asSeconds() > 1)
if (x_get_state_ == nullptr && waitForHookTimer.getElapsedTime().asSeconds() > 1)
{
HMODULE xinputmod = nullptr;
HANDLE hProcess = GetCurrentProcess();
const HANDLE hProcess = GetCurrentProcess();
HMODULE hMods[1024];
DWORD cbNeeded;
EnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded);
@ -103,31 +101,31 @@ void VirtualControllerThread::controllerLoop()
}
}
XInputGetState_t realXgstate = reinterpret_cast<XInputGetState_t>(GetProcAddress(xinputmod, "XInputGetState"));
const XInputGetState_t realXgstate = reinterpret_cast<XInputGetState_t>(GetProcAddress(xinputmod, "XInputGetState"));
std::cout << "realXgstate: " << std::hex << realXgstate << "\n";
for (int i = 0; i < 5; i++)
{
valveHookBytes[i] = *reinterpret_cast<uint8_t*>(reinterpret_cast<uint64_t>(*realXgstate) + i);
valve_hook_bytes_[i] = *reinterpret_cast<uint8_t*>(reinterpret_cast<uint64_t>(*realXgstate) + i);
}
XGetState = realXgstate;
controllerCount = 1;
x_get_state_ = realXgstate;
controller_count_ = 1;
}
if (XGetState != nullptr)
if (x_get_state_ != nullptr)
{
for (int i = 0; i < XUSER_MAX_COUNT; i++)
{
////////
XINPUT_STATE state = { 0 };
result = XInputGetStateWrapper(i, &state);
const DWORD result = XInputGetStateWrapper(i, &state);
XINPUT_STATE state2 = { 0 };
result2 = callRealXinputGetState(i, &state2);
const DWORD result2 = callRealXinputGetState(i, &state2);
if (result == ERROR_SUCCESS)
{
if ( (result2 != ERROR_SUCCESS) == seven )
if ( (result2 != ERROR_SUCCESS) == seven_ )
{
// By using VID and PID of Valve's SteamController, Steam doesn't give us ANOTHER "fake" XInput device
// Leading to endless pain and suffering.
@ -135,38 +133,40 @@ void VirtualControllerThread::controllerLoop()
// Also annoying the shit out of the user when they open the overlay as steam prompts to setup new XInput devices
// Also avoiding any fake inputs from Valve's default controllerprofile
// -> Leading to endless pain and suffering
vigem_target_set_vid(vtX360[i], 0x28de); //Valve SteamController VID
vigem_target_set_pid(vtX360[i], 0x1102); //Valve SteamController PID
vigem_target_set_vid(vt_x360_[i], 0x28de); //Valve SteamController VID
vigem_target_set_pid(vt_x360_[i], 0x1102); //Valve SteamController PID
int vigem_res = vigem_target_add(driver, vtX360[i]);
const int vigem_res = vigem_target_add(driver_, vt_x360_[i]);
if (vigem_res == VIGEM_ERROR_TARGET_UNINITIALIZED)
{
vtX360[i] = vigem_target_x360_alloc();
vt_x360_[i] = vigem_target_x360_alloc();
}
if (vigem_res == VIGEM_ERROR_NONE)
{
std::cout << "Plugged in controller " << vigem_target_get_index(vtX360[i]) << std::endl;
vigem_target_x360_register_notification(driver, vtX360[i], reinterpret_cast<PVIGEM_X360_NOTIFICATION>(&VirtualControllerThread::controllerCallback));
std::cout << "Plugged in controller " << vigem_target_get_index(vt_x360_[i]) << std::endl;
vigem_target_x360_register_notification(driver_, vt_x360_[i],
reinterpret_cast<PVIGEM_X360_NOTIFICATION>(&VirtualControllerThread::
controllerCallback));
}
}
if (vtX360[i] != nullptr)
vigem_target_x360_update(driver, vtX360[i], *reinterpret_cast<XUSB_REPORT*>(&state.Gamepad));
if (vt_x360_[i] != nullptr)
vigem_target_x360_update(driver_, vt_x360_[i], *reinterpret_cast<XUSB_REPORT*>(&state.Gamepad));
}
else
{
if (VIGEM_SUCCESS(vigem_target_remove(driver, vtX360[i])))
if (VIGEM_SUCCESS(vigem_target_remove(driver_, vt_x360_[i])))
{
std::cout << "Unplugged controller " << vigem_target_get_index(vtX360[i]) << std::endl;
std::cout << "Unplugged controller " << vigem_target_get_index(vt_x360_[i]) << std::endl;
}
}
}
}
tickTime = sfClock.getElapsedTime().asMicroseconds();
if (tickTime < delay)
tick_time_ = sf_clock_.getElapsedTime().asMicroseconds();
if (tick_time_ < delay_)
{
std::this_thread::sleep_for(std::chrono::microseconds(delay - tickTime));
std::this_thread::sleep_for(std::chrono::microseconds(delay_ - tick_time_));
}
}
@ -192,20 +192,20 @@ DWORD VirtualControllerThread::callRealXinputGetState(DWORD dwUserIndex, XINPUT_
DWORD ret;
DWORD dwOldProtect, dwBkup;
BYTE* Address = reinterpret_cast<BYTE*>(XGetState);
VirtualProtect(Address, opPatchLenght, PAGE_EXECUTE_READWRITE, &dwOldProtect); //Change permissions of memory..
for (DWORD i = 0; i < opPatchLenght; i++) //unpatch Valve's hook
BYTE* Address = reinterpret_cast<BYTE*>(x_get_state_);
VirtualProtect(Address, op_patch_lenght, PAGE_EXECUTE_READWRITE, &dwOldProtect); //Change permissions of memory..
for (DWORD i = 0; i < op_patch_lenght; i++) //unpatch Valve's hook
{
*(Address + i) = realBytes[i];
*(Address + i) = real_bytes_[i];
}
ret = XGetState(dwUserIndex, pState); //Cal REAL XInputGetState...
ret = x_get_state_(dwUserIndex, pState); //Cal REAL XInputGetState...
for (int i = 0; i < opPatchLenght; i++) //repatch Valve's hook
for (int i = 0; i < op_patch_lenght; i++) //repatch Valve's hook
{
*(Address + i) = valveHookBytes[i];
*(Address + i) = valve_hook_bytes_[i];
}
VirtualProtect(Address, opPatchLenght, dwOldProtect, &dwBkup); //Revert permission change...
VirtualProtect(Address, op_patch_lenght, dwOldProtect, &dwBkup); //Revert permission change...
return ret;
}

View File

@ -1,5 +1,5 @@
/*
Copyright 2016 Peter Repukat - FlatspotSoftware
Copyright 2018 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.
@ -39,7 +39,7 @@ public:
void run();
void stop();
bool isRunning();
bool isRunning() const;
private:
@ -48,33 +48,33 @@ private:
typedef DWORD(WINAPI* XInputGetState_t)(DWORD dwUserIndex, XINPUT_STATE* pState);
static const uint8_t opPatchLenght = 5;
uint8_t valveHookBytes[5];
static const uint8_t op_patch_lenght = 5;
uint8_t valve_hook_bytes_[5];
bool seven = false;
bool seven_ = false;
#ifdef _AMD64_
const uint8_t realBytes[5] = {0x48, 0x89, 0x5C, 0x24, 0x08};
#else
const uint8_t realBytes[5] = { 0x8B, 0xFF, 0x55, 0x8B, 0xEC };
const uint8_t real_bytes_[5] = { 0x8B, 0xFF, 0x55, 0x8B, 0xEC };
#endif
//uint8_t realBytes[5] = { 0xDE, 0xAD, 0xBE, 0xEF, 0x90 };
int controllerCount = 0;
XInputGetState_t XGetState = nullptr;
int controller_count_ = 0;
XInputGetState_t x_get_state_ = nullptr;
PVIGEM_CLIENT driver;
PVIGEM_TARGET vtX360[XUSER_MAX_COUNT];
PVIGEM_CLIENT driver_;
PVIGEM_TARGET vt_x360_[XUSER_MAX_COUNT];
std::thread controllerThread;
std::thread controller_thread_;
sf::Clock sfClock;
int tickTime = 0;
int delay = 1000000 / 200;
sf::Clock sf_clock_;
int tick_time_ = 0;
int delay_ = 1000000 / 200;
void controllerLoop();
static void controllerCallback(PVIGEM_CLIENT client, PVIGEM_TARGET Target, UCHAR LargeMotor, UCHAR SmallMotor, UCHAR LedNumber);
static void __RPC_CALLEE controllerCallback(PVIGEM_CLIENT client, PVIGEM_TARGET Target, UCHAR LargeMotor, UCHAR SmallMotor, UCHAR LedNumber);
static DWORD XInputGetStateWrapper(DWORD dwUserIndex, XINPUT_STATE* pState); //Easier to find in x64dbg...

View File

@ -1,5 +1,5 @@
/*
Copyright 2016 Peter Repukat - FlatspotSoftware
Copyright 2018 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.
@ -15,11 +15,12 @@ limitations under the License.
*/
#include "SteamTargetRenderer.h"
#include <QtCore/QCoreApplication>
#include "SteamTarget.h"
int main(int argc, char *argv[])
{
SteamTargetRenderer renderer(argc, argv);
renderer.run();
return renderer.exec();
SteamTarget target(argc, argv);
target.init();
return target.exec();
}