diff --git a/CHANGELOG.txt b/CHANGELOG.txt index d61107d97..500e5e6cb 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,4 +1,9 @@ -24.12.1.1 +24.12.1.3 +========= + + XInput emulation now bypasses GameInput.dll for systems that do not have + this DLL. + +24.12.1.1 ========= + Allow Starfield to read Windows.Gaming.Input and write XInput diff --git a/SpecialK.def b/SpecialK.def index 0f3c0e9f6..2bd7031aa 100644 --- a/SpecialK.def +++ b/SpecialK.def @@ -526,6 +526,8 @@ RegisterRawInputDevices_Override = RegisterRawInputDevices_Detour PRI GetRawInputData_Override = GetRawInputData_Detour PRIVATE HidP_GetData_Override = HidP_GetData_Detour PRIVATE +GameInputCreate = GameInputCreate_BypassSystemDLL + SK_Input_GetDI8Keyboard = SK_Input_GetDI8Keyboard SK_Input_GetDI8Mouse = SK_Input_GetDI8Mouse SK_XInput_PollController = SK_XInput_PollController diff --git a/include/SpecialK/DLL_VERSION.H b/include/SpecialK/DLL_VERSION.H index 55ed2c4e3..ba928fd00 100644 --- a/include/SpecialK/DLL_VERSION.H +++ b/include/SpecialK/DLL_VERSION.H @@ -3,8 +3,8 @@ #define SK_YEAR 24 #define SK_MONTH 12 #define SK_DATE 1 -#define SK_REV_N 1 -#define SK_REV 1 +#define SK_REV_N 3 +#define SK_REV 3 #ifndef _A2 #define _A2(a) #a diff --git a/include/SpecialK/input/game_input.h b/include/SpecialK/input/game_input.h index fd8b4d5f4..5b018d0cf 100644 --- a/include/SpecialK/input/game_input.h +++ b/include/SpecialK/input/game_input.h @@ -116,7 +116,7 @@ class SK_IGameInputDevice : IGameInputDevice { public: SK_IGameInputDevice (IGameInputDevice *pGameInputDevice) : pReal (pGameInputDevice), - ver_ (0) + ver_ (0) { if (pGameInputDevice == nullptr) return; diff --git a/include/SpecialK/input/input.h b/include/SpecialK/input/input.h index 9e8420b17..06f724e09 100644 --- a/include/SpecialK/input/input.h +++ b/include/SpecialK/input/input.h @@ -1046,6 +1046,7 @@ struct SK_HID_PlayStationDevice volatile ULONG right; ULONG last_left; ULONG last_right; + bool used; // Flagged the first time a game sets trigger vibration } trigger; volatile ULONG max_val = 0; diff --git a/src/control_panel/cfg_input.cpp b/src/control_panel/cfg_input.cpp index 8263df860..4afc5b3c6 100644 --- a/src/control_panel/cfg_input.cpp +++ b/src/control_panel/cfg_input.cpp @@ -1412,6 +1412,8 @@ SK::ControlPanel::Input::Draw (void) ImGui::Separator ( ); } + SK_HID_PlayStationDevice *pNewestInput = nullptr; + if (bHasPlayStation) { ImGui::PushStyleColor (ImGuiCol_Header, ImVec4 (0.90f, 0.40f, 0.40f, 0.45f)); @@ -1430,7 +1432,6 @@ SK::ControlPanel::Input::Draw (void) ImGui::TreePop (); - SK_HID_PlayStationDevice *pNewestInput = nullptr; UINT64 last_input = 0; for ( auto& ps_controller : SK_HID_PlayStationControllers ) @@ -2080,7 +2081,7 @@ SK::ControlPanel::Input::Draw (void) static bool has_gameinput = GetModuleHandleW (L"GameInput.dll") != nullptr; - if (has_gameinput && SK_GameInput_Backend->reads [2] > 0) + if ((has_gameinput && SK_GameInput_Backend->reads [2] > 0) || (pNewestInput != nullptr && pNewestInput->_vibration.trigger.used)) { ImGui::TreePush (""); bool changed = ImGui::SliderFloat ("Left Trigger", &config.input.gamepad.impulse_strength_l, 0.0f, 1.5f, "%3.1fx Impulse Strength"); diff --git a/src/diagnostics/load_library.cpp b/src/diagnostics/load_library.cpp index cd7474149..3e5637073 100644 --- a/src/diagnostics/load_library.cpp +++ b/src/diagnostics/load_library.cpp @@ -764,6 +764,11 @@ LoadLibrary_Marshal ( LPVOID lpRet, if (lpFileName == nullptr) return nullptr; + if (config.input.gamepad.xinput.emulate && StrStrIW (lpFileName, L"GameInput.dll")) + { + return SK_GetDLL (); + } + SK_LockDllLoader (); HMODULE hModEarly = nullptr; @@ -1167,6 +1172,11 @@ LoadLibraryEx_Marshal ( LPVOID lpRet, LPCWSTR lpFileName, if (lpFileName == nullptr) return nullptr; + if (config.input.gamepad.xinput.emulate && StrStrIW (lpFileName, L"GameInput.dll")) + { + return SK_GetDLL (); + } + wchar_t* compliant_path = const_cast (lpFileName); diff --git a/src/input/game_input.cpp b/src/input/game_input.cpp index cc3833d03..d67817de6 100644 --- a/src/input/game_input.cpp +++ b/src/input/game_input.cpp @@ -115,6 +115,9 @@ SK_IWrapGameInput::QueryInterface (REFIID riid, void **ppvObject) noexcept return S_OK; } + if (! pReal) + return E_NOTIMPL; + HRESULT hr = pReal->QueryInterface (riid, ppvObject); @@ -145,7 +148,7 @@ SK_IWrapGameInput::AddRef (void) noexcept InterlockedIncrement (&refs_); return - pReal->AddRef (); + pReal != nullptr ? pReal->AddRef () : 1; }; ULONG @@ -154,7 +157,7 @@ SK_IWrapGameInput::Release (void) noexcept { ULONG xrefs = InterlockedDecrement (&refs_), - refs = pReal->Release (); + refs = pReal != nullptr ? pReal->Release () : 1; if (xrefs == 0) { @@ -179,7 +182,8 @@ SK_IWrapGameInput::GetCurrentTimestamp (void) noexcept { SK_LOG_FIRST_CALL - return pReal->GetCurrentTimestamp (); + return + pReal != nullptr ? pReal->GetCurrentTimestamp () : SK_QueryPerf ().QuadPart; } static concurrency::concurrent_unordered_map >> _current_readings; @@ -256,7 +260,7 @@ SK_IWrapGameInput::GetCurrentReading (_In_ GameInputKind inputKind return S_OK; } - else if (reading != nullptr) + else if (reading != nullptr && pReal != nullptr) { HRESULT hr = pReal->GetCurrentReading (inputKind, device, reading); @@ -267,7 +271,7 @@ SK_IWrapGameInput::GetCurrentReading (_In_ GameInputKind inputKind } return - pReal->GetCurrentReading (inputKind, device, reading); + pReal != nullptr ? pReal->GetCurrentReading (inputKind, device, reading) : E_NOTIMPL; } using IGameInputDevice_SetHapticMotorState_pfn = HRESULT (STDMETHODCALLTYPE *)(IGameInputDevice*,uint32_t,GameInputHapticFeedbackParams const*) noexcept; @@ -622,7 +626,7 @@ SK_IWrapGameInput::RegisterDeviceCallback (_In_opt_ IGame SK_LOG_FIRST_CALL HRESULT hr = - pReal->RegisterDeviceCallback (device, inputKind, statusFilter, enumerationKind, context, callbackFunc, callbackToken); + pReal == nullptr ? S_OK : pReal->RegisterDeviceCallback (device, inputKind, statusFilter, enumerationKind, context, callbackFunc, callbackToken); if (SUCCEEDED (hr) && inputKind == GameInputKindGamepad && (statusFilter & GameInputDeviceConnected) != 0 && (config.input.gamepad.xinput.emulate || ! SK_XInput_PollController (0))) { @@ -647,6 +651,7 @@ SK_IWrapGameInput::RegisterSystemButtonCallback (_In_opt_ SK_LOG_FIRST_CALL return + pReal == nullptr ? S_OK : pReal->RegisterSystemButtonCallback (device, buttonFilter, context, callbackFunc, callbackToken); } @@ -660,6 +665,7 @@ SK_IWrapGameInput::RegisterKeyboardLayoutCallback (_In_opt_ SK_LOG_FIRST_CALL return + pReal == nullptr ? S_OK : pReal->RegisterKeyboardLayoutCallback (device, context, callbackFunc, callbackToken); } @@ -669,8 +675,8 @@ SK_IWrapGameInput::StopCallback (_In_ GameInputCallbackToken callbackToken) noex { SK_LOG_FIRST_CALL - return - pReal->StopCallback (callbackToken); + if (pReal != nullptr) + pReal->StopCallback (callbackToken); } bool @@ -681,6 +687,7 @@ SK_IWrapGameInput::UnregisterCallback (_In_ GameInputCallbackToken callbackToken SK_LOG_FIRST_CALL return + pReal == nullptr ? S_OK : pReal->UnregisterCallback (callbackToken, timeoutInMicroseconds); } @@ -691,6 +698,7 @@ SK_IWrapGameInput::CreateDispatcher (_COM_Outptr_ IGameInputDispatcher **dispatc SK_LOG_FIRST_CALL return + pReal == nullptr ? S_OK : pReal->CreateDispatcher (dispatcher); } @@ -702,6 +710,7 @@ SK_IWrapGameInput::CreateAggregateDevice (_In_ GameInputKind inputK SK_LOG_FIRST_CALL return + pReal == nullptr ? S_OK : pReal->CreateAggregateDevice (inputKind, device); } @@ -713,6 +722,7 @@ SK_IWrapGameInput::FindDeviceFromId (_In_ APP_LOCAL_DEVICE_ID const *va SK_LOG_FIRST_CALL return + pReal == nullptr ? S_OK : pReal->FindDeviceFromId (value, device); } @@ -724,6 +734,7 @@ SK_IWrapGameInput::FindDeviceFromObject (_In_ IUnknown *value, SK_LOG_FIRST_CALL return + pReal == nullptr ? S_OK : pReal->FindDeviceFromObject (value, device); } @@ -735,6 +746,7 @@ SK_IWrapGameInput::FindDeviceFromPlatformHandle (_In_ HANDLE SK_LOG_FIRST_CALL return + pReal == nullptr ? S_OK : pReal->FindDeviceFromPlatformHandle (value, device); } @@ -746,6 +758,7 @@ SK_IWrapGameInput::FindDeviceFromPlatformString (_In_ LPCWSTR SK_LOG_FIRST_CALL return + pReal == nullptr ? S_OK : pReal->FindDeviceFromPlatformString (value, device); } @@ -759,6 +772,7 @@ SK_IWrapGameInput::EnableOemDeviceSupport (_In_ uint16_t vendorId, SK_LOG_FIRST_CALL return + pReal == nullptr ? S_OK : pReal->EnableOemDeviceSupport (vendorId, productId, interfaceNumber, collectionNumber); } @@ -768,8 +782,8 @@ SK_IWrapGameInput::SetFocusPolicy (_In_ GameInputFocusPolicy policy) noexcept { SK_LOG_FIRST_CALL - return - pReal->SetFocusPolicy (policy); + if (pReal != nullptr) + pReal->SetFocusPolicy (policy); } @@ -784,9 +798,9 @@ GameInputCreate_Detour (IGameInput** gameInput) HRESULT hr = GameInputCreate_Original (&pReal); - if (SUCCEEDED (hr)) + if (SUCCEEDED (hr) || config.input.gamepad.xinput.emulate) { - if (gameInput != nullptr) + //if (gameInput != nullptr) { // Turn on XInput emulation by default on first-run for Unreal Engine. // @@ -805,13 +819,17 @@ GameInputCreate_Detour (IGameInput** gameInput) } } - *gameInput = (IGameInput *)new SK_IWrapGameInput (pReal); + if (config.input.gamepad.xinput.emulate) + { + *gameInput = (IGameInput *)new SK_IWrapGameInput (pReal); + return S_OK; + } } - else - { - pReal->Release (); - } + //else + //{ + // pReal->Release (); + //} } return hr; @@ -1490,11 +1508,13 @@ SK_Input_HookGameInput (void) if (! config.input.gamepad.hook_game_input) return; - if (GetModuleHandleW (L"GameInput.dll") != nullptr) + if (GetModuleHandleW (L"GameInput.dll") != nullptr || config.input.gamepad.xinput.emulate) { static volatile LONG hooked = FALSE; if (! InterlockedCompareExchange (&hooked, TRUE, FALSE)) { + if (config.input.gamepad.xinput.emulate) + SK_LoadLibraryW ( L"GameInput.dll"); SK_CreateDLLHook2 ( L"GameInput.dll", "GameInputCreate", GameInputCreate_Detour, @@ -1915,4 +1935,15 @@ SK_IPlayStationGameInputReading::GetUiNavigationState (GameInputUiNavigationStat SK_RunOnce (SK_LOGi0 (L"Stub")); return false; +} + + +HRESULT +WINAPI +GameInputCreate_BypassSystemDLL (IGameInput** gameInput) +{ + SK_LOG_FIRST_CALL + + return + GameInputCreate_Detour (gameInput); } \ No newline at end of file diff --git a/src/input/hid_reports/playstation.cpp b/src/input/hid_reports/playstation.cpp index ff83871b6..003b79705 100644 --- a/src/input/hid_reports/playstation.cpp +++ b/src/input/hid_reports/playstation.cpp @@ -828,6 +828,11 @@ SK_HID_PlayStationDevice::setVibration ( USHORT right_trigger, USHORT max_val ) { + if (left_trigger + right_trigger != 0) + { + _vibration.trigger.used = true; + } + if (max_val == 0) { const auto last_max = ReadULongAcquire (&_vibration.max_val);