mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-02-01 02:21:26 +02:00
Merge pull request #10565 from AdmiralCurtiss/wgi-win7
Core/WGInput: Dynamically load winrt function addresses.
This commit is contained in:
commit
0c7f9921bc
@ -12,11 +12,17 @@
|
|||||||
#include <windows.gaming.input.h>
|
#include <windows.gaming.input.h>
|
||||||
#include <wrl.h>
|
#include <wrl.h>
|
||||||
|
|
||||||
|
#include "Common/DynamicLibrary.h"
|
||||||
#include "Common/Logging/Log.h"
|
#include "Common/Logging/Log.h"
|
||||||
#include "Common/StringUtil.h"
|
#include "Common/StringUtil.h"
|
||||||
#include "InputCommon/ControllerInterface/ControllerInterface.h"
|
#include "InputCommon/ControllerInterface/ControllerInterface.h"
|
||||||
|
|
||||||
#pragma comment(lib, "runtimeobject.lib")
|
using PIsApiSetImplemented = BOOL(APIENTRY*)(PCSTR Contract);
|
||||||
|
using PRoInitialize = decltype(&RoInitialize);
|
||||||
|
using PRoUninitialize = decltype(&RoUninitialize);
|
||||||
|
using PRoGetActivationFactory = decltype(&RoGetActivationFactory);
|
||||||
|
using PWindowsCreateStringReference = decltype(&WindowsCreateStringReference);
|
||||||
|
using PWindowsGetStringRawBuffer = decltype(&WindowsGetStringRawBuffer);
|
||||||
|
|
||||||
namespace WGI = ABI::Windows::Gaming::Input;
|
namespace WGI = ABI::Windows::Gaming::Input;
|
||||||
using ABI::Windows::Foundation::Collections::IVectorView;
|
using ABI::Windows::Foundation::Collections::IVectorView;
|
||||||
@ -26,6 +32,11 @@ namespace
|
|||||||
{
|
{
|
||||||
bool g_runtime_initialized = false;
|
bool g_runtime_initialized = false;
|
||||||
bool g_runtime_needs_deinit = false;
|
bool g_runtime_needs_deinit = false;
|
||||||
|
PRoInitialize g_RoInitialize_address = nullptr;
|
||||||
|
PRoUninitialize g_RoUninitialize_address = nullptr;
|
||||||
|
PRoGetActivationFactory g_RoGetActivationFactory_address = nullptr;
|
||||||
|
PWindowsCreateStringReference g_WindowsCreateStringReference_address = nullptr;
|
||||||
|
PWindowsGetStringRawBuffer g_WindowsGetStringRawBuffer_address = nullptr;
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
namespace ciface::WGInput
|
namespace ciface::WGInput
|
||||||
@ -571,12 +582,77 @@ private:
|
|||||||
ControlState m_battery_level = 0;
|
ControlState m_battery_level = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static bool LoadFunctionPointers()
|
||||||
|
{
|
||||||
|
static Common::DynamicLibrary winrt_l1_1_0_handle;
|
||||||
|
static Common::DynamicLibrary winrt_string_l1_1_0_handle;
|
||||||
|
if (!winrt_l1_1_0_handle.IsOpen() && !winrt_string_l1_1_0_handle.IsOpen())
|
||||||
|
{
|
||||||
|
Common::DynamicLibrary kernelBase("KernelBase.dll");
|
||||||
|
if (!kernelBase.IsOpen())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
void* const IsApiSetImplemented_address = kernelBase.GetSymbolAddress("IsApiSetImplemented");
|
||||||
|
if (!IsApiSetImplemented_address)
|
||||||
|
return false;
|
||||||
|
if (!static_cast<PIsApiSetImplemented>(IsApiSetImplemented_address)(
|
||||||
|
"api-ms-win-core-winrt-l1-1-0"))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!static_cast<PIsApiSetImplemented>(IsApiSetImplemented_address)(
|
||||||
|
"api-ms-win-core-winrt-string-l1-1-0"))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
winrt_l1_1_0_handle.Open("api-ms-win-core-winrt-l1-1-0.dll");
|
||||||
|
winrt_string_l1_1_0_handle.Open("api-ms-win-core-winrt-string-l1-1-0.dll");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!winrt_l1_1_0_handle.IsOpen() || !winrt_string_l1_1_0_handle.IsOpen())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
g_RoInitialize_address =
|
||||||
|
static_cast<PRoInitialize>(winrt_l1_1_0_handle.GetSymbolAddress("RoInitialize"));
|
||||||
|
if (!g_RoInitialize_address)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
g_RoUninitialize_address =
|
||||||
|
static_cast<PRoUninitialize>(winrt_l1_1_0_handle.GetSymbolAddress("RoUninitialize"));
|
||||||
|
if (!g_RoUninitialize_address)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
g_RoGetActivationFactory_address = static_cast<PRoGetActivationFactory>(
|
||||||
|
winrt_l1_1_0_handle.GetSymbolAddress("RoGetActivationFactory"));
|
||||||
|
if (!g_RoGetActivationFactory_address)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
g_WindowsCreateStringReference_address = static_cast<PWindowsCreateStringReference>(
|
||||||
|
winrt_string_l1_1_0_handle.GetSymbolAddress("WindowsCreateStringReference"));
|
||||||
|
if (!g_WindowsCreateStringReference_address)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
g_WindowsGetStringRawBuffer_address = static_cast<PWindowsGetStringRawBuffer>(
|
||||||
|
winrt_string_l1_1_0_handle.GetSymbolAddress("WindowsGetStringRawBuffer"));
|
||||||
|
if (!g_WindowsGetStringRawBuffer_address)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void Init()
|
void Init()
|
||||||
{
|
{
|
||||||
if (g_runtime_initialized)
|
if (g_runtime_initialized)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const HRESULT hr = RoInitialize(RO_INIT_MULTITHREADED);
|
if (!LoadFunctionPointers())
|
||||||
|
{
|
||||||
|
ERROR_LOG(CONTROLLERINTERFACE, "WGInput: System lacks support, skipping init.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const HRESULT hr = g_RoInitialize_address(RO_INIT_MULTITHREADED);
|
||||||
switch (hr)
|
switch (hr)
|
||||||
{
|
{
|
||||||
case S_OK:
|
case S_OK:
|
||||||
@ -602,13 +678,21 @@ void DeInit()
|
|||||||
|
|
||||||
if (g_runtime_needs_deinit)
|
if (g_runtime_needs_deinit)
|
||||||
{
|
{
|
||||||
RoUninitialize();
|
g_RoUninitialize_address();
|
||||||
g_runtime_needs_deinit = false;
|
g_runtime_needs_deinit = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_runtime_initialized = false;
|
g_runtime_initialized = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <unsigned int size>
|
||||||
|
static HRESULT WindowsCreateStringReferenceAutoSizeWrapper(wchar_t const (&source_string)[size],
|
||||||
|
HSTRING_HEADER* hstring_header,
|
||||||
|
HSTRING* hstring)
|
||||||
|
{
|
||||||
|
return g_WindowsCreateStringReference_address(source_string, size - 1, hstring_header, hstring);
|
||||||
|
}
|
||||||
|
|
||||||
void PopulateDevices()
|
void PopulateDevices()
|
||||||
{
|
{
|
||||||
if (!g_runtime_initialized)
|
if (!g_runtime_initialized)
|
||||||
@ -617,8 +701,6 @@ void PopulateDevices()
|
|||||||
g_controller_interface.RemoveDevice(
|
g_controller_interface.RemoveDevice(
|
||||||
[](const auto* dev) { return dev->GetSource() == SOURCE_NAME; });
|
[](const auto* dev) { return dev->GetSource() == SOURCE_NAME; });
|
||||||
|
|
||||||
using Microsoft::WRL::Wrappers::HStringReference;
|
|
||||||
|
|
||||||
// WGI Interfaces to potentially use:
|
// WGI Interfaces to potentially use:
|
||||||
// Gamepad: Buttons, 2x Sticks and 2x Triggers, 4x Vibration Motors
|
// Gamepad: Buttons, 2x Sticks and 2x Triggers, 4x Vibration Motors
|
||||||
// RawGameController: Buttons, Switches (Hats), Axes, Haptics
|
// RawGameController: Buttons, Switches (Hats), Axes, Haptics
|
||||||
@ -628,18 +710,36 @@ void PopulateDevices()
|
|||||||
// RacingWheel: Buttons, Clutch, Handbrake, PatternShifterGear, Throttle, Wheel, WheelMotor
|
// RacingWheel: Buttons, Clutch, Handbrake, PatternShifterGear, Throttle, Wheel, WheelMotor
|
||||||
// UINavigationController: Directions, Scrolling, etc.
|
// UINavigationController: Directions, Scrolling, etc.
|
||||||
|
|
||||||
|
HSTRING_HEADER header_raw_game_controller;
|
||||||
|
HSTRING hstr_raw_game_controller;
|
||||||
|
if (FAILED(WindowsCreateStringReferenceAutoSizeWrapper(L"Windows.Gaming.Input.RawGameController",
|
||||||
|
&header_raw_game_controller,
|
||||||
|
&hstr_raw_game_controller)))
|
||||||
|
{
|
||||||
|
ERROR_LOG(CONTROLLERINTERFACE, "WGInput: Failed to create string reference.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
HSTRING_HEADER header_gamepad;
|
||||||
|
HSTRING hstr_gamepad;
|
||||||
|
if (FAILED(WindowsCreateStringReferenceAutoSizeWrapper(L"Windows.Gaming.Input.Gamepad",
|
||||||
|
&header_gamepad, &hstr_gamepad)))
|
||||||
|
{
|
||||||
|
ERROR_LOG(CONTROLLERINTERFACE, "WGInput: Failed to create string reference.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ComPtr<WGI::IRawGameControllerStatics> raw_stats;
|
ComPtr<WGI::IRawGameControllerStatics> raw_stats;
|
||||||
if (FAILED(
|
if (FAILED(g_RoGetActivationFactory_address(
|
||||||
RoGetActivationFactory(HStringReference(L"Windows.Gaming.Input.RawGameController").Get(),
|
hstr_raw_game_controller, __uuidof(WGI::IRawGameControllerStatics), &raw_stats)))
|
||||||
__uuidof(WGI::IRawGameControllerStatics), &raw_stats)))
|
|
||||||
{
|
{
|
||||||
ERROR_LOG(CONTROLLERINTERFACE, "WGInput: Failed to get IRawGameControllerStatics.");
|
ERROR_LOG(CONTROLLERINTERFACE, "WGInput: Failed to get IRawGameControllerStatics.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ComPtr<WGI::IGamepadStatics2> gamepad_stats;
|
ComPtr<WGI::IGamepadStatics2> gamepad_stats;
|
||||||
if (FAILED(RoGetActivationFactory(HStringReference(L"Windows.Gaming.Input.Gamepad").Get(),
|
if (FAILED(g_RoGetActivationFactory_address(hstr_gamepad, __uuidof(WGI::IGamepadStatics2),
|
||||||
__uuidof(WGI::IGamepadStatics2), &gamepad_stats)))
|
&gamepad_stats)))
|
||||||
{
|
{
|
||||||
ERROR_LOG(CONTROLLERINTERFACE, "WGInput: Failed to get IGamepadStatics2.");
|
ERROR_LOG(CONTROLLERINTERFACE, "WGInput: Failed to get IGamepadStatics2.");
|
||||||
return;
|
return;
|
||||||
@ -667,7 +767,10 @@ void PopulateDevices()
|
|||||||
{
|
{
|
||||||
HSTRING hstr = {};
|
HSTRING hstr = {};
|
||||||
if (SUCCEEDED(rgc2->get_DisplayName(&hstr)) && hstr)
|
if (SUCCEEDED(rgc2->get_DisplayName(&hstr)) && hstr)
|
||||||
device_name = StripSpaces(WStringToUTF8(WindowsGetStringRawBuffer(hstr, nullptr)));
|
{
|
||||||
|
device_name =
|
||||||
|
StripSpaces(WStringToUTF8(g_WindowsGetStringRawBuffer_address(hstr, nullptr)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (device_name.empty())
|
if (device_name.empty())
|
||||||
|
Loading…
Reference in New Issue
Block a user