Skip to content

Commit

Permalink
Update native XInput timestamps correctly when calling SK_XInput_Poll…
Browse files Browse the repository at this point in the history
…Controller (...)
  • Loading branch information
Kaldaien committed Dec 19, 2024
1 parent 4063bd0 commit d1da871
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 54 deletions.
4 changes: 2 additions & 2 deletions include/SpecialK/input/input.h
Original file line number Diff line number Diff line change
Expand Up @@ -1146,7 +1146,7 @@ struct SK_HID_PlayStationDevice
bool setPollingFrequency (DWORD dwFreq);
bool setBufferCount (DWORD dwBuffers);

void reset_force_feedback (void);
void reset_force_feedback (void) noexcept;

bool initialize_serial (void);
void reset_device (void);
Expand Down Expand Up @@ -1382,7 +1382,7 @@ void SK_ScePad_PaceMaker (void);

void SK_HID_ProcessGamepadButtonBindings (void);

std::wstring* SK_HID_GetGamepadButtonBinding (UINT idx);
std::wstring* SK_HID_GetGamepadButtonBinding (UINT idx) noexcept;
void SK_HID_AssignGamepadButtonBinding (UINT idx, const wchar_t* wszKeyName, UINT vKey);

extern HidD_GetAttributes_pfn SK_HidD_GetAttributes;
Expand Down
119 changes: 70 additions & 49 deletions src/input/game_input.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,9 @@ SK_IWrapGameInput::GetCurrentReading (_In_ GameInputKind inputKind

bool capture_input = false;

// Always poll XInput 0 so we can detect native Xbox activity
SK_XInput_PollController (0);

if (device == s_virtual_gameinput_device)
{
static SK_IPlayStationGameInputReading virtual_current_reading (0);
Expand Down Expand Up @@ -324,6 +327,12 @@ IGameInputDevice_SetRumbleState_Override (IGameInputDevice *This, GameInputRumbl
params_.leftTrigger = params_.rightTrigger = 0.0f;
}

// Do not rumble on Xbox controllers while a virtual controller is substituting
if (config.input.gamepad.xinput.emulate && SK_HID_GetActivePlayStationDevice (true))
{
return;
}

return
IGameInputDevice_SetRumbleState_Original (This, &params_);
}
Expand Down Expand Up @@ -900,26 +909,55 @@ SK_IGameInputDevice::GetDeviceInfo (void) noexcept

dev_info.infoSize = sizeof (GameInputDeviceInfo);

// Traditional Xbox 360 Controller
#if 0
dev_info.controllerAxisCount = 6;
dev_info.controllerButtonCount = 13;

dev_info.deviceId = {1};
dev_info.deviceRootId = {1};
dev_info.deviceId = {1};
dev_info.deviceRootId = {1};

dev_info.capabilities = GameInputDeviceCapabilityPowerOff | GameInputDeviceCapabilityWireless;
dev_info.capabilities = GameInputDeviceCapabilityPowerOff | GameInputDeviceCapabilityWireless;

dev_info.vendorId = 0x45e;
dev_info.productId = 0x28e;
dev_info.vendorId = 0x45e;
dev_info.productId = 0x28e;

dev_info.deviceFamily = GameInputFamilyXbox360;
dev_info.usage.id = 5;
dev_info.usage.page = 1;

dev_info.interfaceNumber = 0;

dev_info.supportedInput = GameInputKindControllerAxis | GameInputKindControllerButton | GameInputKindGamepad | GameInputKindUiNavigation;
dev_info.supportedInput = GameInputKindControllerAxis | GameInputKindControllerButton |
GameInputKindGamepad | GameInputKindUiNavigation;
dev_info.supportedRumbleMotors = GameInputRumbleLowFrequency | GameInputRumbleHighFrequency;
dev_info.supportedSystemButtons = GameInputSystemButtonGuide;
#else
// Xbox One
dev_info.controllerAxisCount = 6;
dev_info.controllerButtonCount = 13;

dev_info.deviceId = {1};
dev_info.deviceRootId = {1};

dev_info.capabilities = GameInputDeviceCapabilitySynchronization | GameInputDeviceCapabilityPowerOff |
GameInputDeviceCapabilityWireless;

dev_info.vendorId = 0x45e;
dev_info.productId = 0xb12;

dev_info.deviceFamily = GameInputFamilyXboxOne;
dev_info.usage.id = 5;
dev_info.usage.page = 1;

dev_info.interfaceNumber = 0;

dev_info.supportedInput = GameInputKindRawDeviceReport | GameInputKindControllerAxis |
GameInputKindControllerButton | GameInputKindGamepad | GameInputKindUiNavigation;
dev_info.supportedRumbleMotors = GameInputRumbleLowFrequency | GameInputRumbleHighFrequency|
GameInputRumbleLeftTrigger | GameInputRumbleRightTrigger;
dev_info.supportedSystemButtons = GameInputSystemButtonGuide | GameInputSystemButtonShare;
#endif

return &dev_info;
}
Expand Down Expand Up @@ -1015,33 +1053,25 @@ SK_IGameInputDevice::SetRumbleState (GameInputRumbleParams const *params) noexce

if (config.input.gamepad.xinput.emulate && (! config.input.gamepad.xinput.blackout_api) && (! SK_ImGui_WantGamepadCapture ()))
{
if (params_.leftTrigger == 0 && params_.rightTrigger == 0)
{
const float left = params_.lowFrequency;
const float right = params_.highFrequency;

SK_XInput_PulseController ( 0, std::clamp (left, 0.0f, 1.0f),
std::clamp (right, 0.0f, 1.0f) );
}

else
if (SK_HID_PlayStationDevice *pNewestInputDevice = nullptr; (pNewestInputDevice = SK_HID_GetActivePlayStationDevice (true)) != nullptr)
{
if (SK_HID_PlayStationDevice *pNewestInputDevice = nullptr; config.input.gamepad.xinput.emulate && (! config.input.gamepad.xinput.blackout_api) && (pNewestInputDevice = SK_HID_GetActivePlayStationDevice ()) != nullptr)
{
SK_GameInput_EmulatedPlayStation = true;
SK_GameInput_EmulatedPlayStation = true;

pNewestInputDevice->setVibration (
static_cast <USHORT> (std::min (65535UL, static_cast <ULONG> (std::clamp (params_.lowFrequency, 0.0f, 1.0f) * 65536.0f))),
static_cast <USHORT> (std::min (65535UL, static_cast <ULONG> (std::clamp (params_.highFrequency, 0.0f, 1.0f) * 65536.0f))),
static_cast <USHORT> (std::min (65535UL, static_cast <ULONG> (std::clamp (params_.leftTrigger, 0.0f, 1.0f) * 65536.0f))),
static_cast <USHORT> (std::min (65535UL, static_cast <ULONG> (std::clamp (params_.rightTrigger, 0.0f, 1.0f) * 65536.0f))),
65535ui16
);

pNewestInputDevice->setVibration (
static_cast <USHORT> (std::min (65535UL, static_cast <ULONG> (std::clamp (params_.lowFrequency, 0.0f, 1.0f) * 65536.0f))),
static_cast <USHORT> (std::min (65535UL, static_cast <ULONG> (std::clamp (params_.highFrequency, 0.0f, 1.0f) * 65536.0f))),
static_cast <USHORT> (std::min (65535UL, static_cast <ULONG> (std::clamp (params_.leftTrigger, 0.0f, 1.0f) * 65536.0f))),
static_cast <USHORT> (std::min (65535UL, static_cast <ULONG> (std::clamp (params_.rightTrigger, 0.0f, 1.0f) * 65536.0f))),
65535ui16
);
pNewestInputDevice->write_output_report ();

pNewestInputDevice->write_output_report ();
}
return;
}
}

SK_GameInput_EmulatedPlayStation = false;
}

void
Expand Down Expand Up @@ -1457,7 +1487,6 @@ SK_IWrapGameInputReading::GetGamepadState (GameInputGamepadState *state) noexcep
{
SK_LOG_FIRST_CALL


if (pReal->GetGamepadState (state))
{
if (SK_ImGui_WantGamepadCapture ())
Expand Down Expand Up @@ -1843,47 +1872,37 @@ SK_IPlayStationGameInputReading::GetGamepadState (GameInputGamepadState *state)

ZeroMemory (state, sizeof (GameInputGamepadState));

SK_GameInput_EmulatedPlayStation = false;

if (! SK_HID_PlayStationControllers.empty ())
{
XINPUT_STATE _state = {};
SK_ImGui_PollGamepad_EndFrame (&_state);

if (config.input.gamepad.xinput.emulate && (! config.input.gamepad.xinput.blackout_api))
{
SK_HID_PlayStationDevice *pNewestInputDevice = nullptr;

for ( auto& controller : SK_HID_PlayStationControllers )
{
if (controller.bConnected)
{
if (pNewestInputDevice == nullptr || controller.xinput.isNewer (pNewestInputDevice->xinput))
{
pNewestInputDevice = &controller;
}
}
}

if (pNewestInputDevice != nullptr)
auto pNewestInputDevice = SK_HID_GetActivePlayStationDevice (true);
if ( pNewestInputDevice != nullptr )
{
if (! SK_ImGui_WantGamepadCapture ())
{
const auto latest_state =
pNewestInputDevice->xinput.getLatestState ();

state->leftThumbstickX =
static_cast <float> (static_cast <double> (latest_state.Gamepad.sThumbLX) / 32767.0);
static_cast <float> (static_cast <double> (latest_state.Gamepad.sThumbLX) / 32767);
state->leftThumbstickY =
static_cast <float> (static_cast <double> (latest_state.Gamepad.sThumbLY) / 32767.0);
static_cast <float> (static_cast <double> (latest_state.Gamepad.sThumbLY) / 32767);

state->rightThumbstickX =
static_cast <float> (static_cast <double> (latest_state.Gamepad.sThumbRX) / 32767.0);
static_cast <float> (static_cast <double> (latest_state.Gamepad.sThumbRX) / 32767);
state->rightThumbstickY =
static_cast <float> (static_cast <double> (latest_state.Gamepad.sThumbRY) / 32767.0);
static_cast <float> (static_cast <double> (latest_state.Gamepad.sThumbRY) / 32767);

state->leftTrigger =
static_cast <float> (static_cast <double> (latest_state.Gamepad.bLeftTrigger) / 255.0);
static_cast <float> (static_cast <double> (latest_state.Gamepad.bLeftTrigger) / 255);
state->rightTrigger =
static_cast <float> (static_cast <double> (latest_state.Gamepad.bRightTrigger) / 255.0);
static_cast <float> (static_cast <double> (latest_state.Gamepad.bRightTrigger) / 255);

state->buttons |= (latest_state.Gamepad.wButtons & XINPUT_GAMEPAD_A) != 0 ? GameInputGamepadA : GameInputGamepadNone;
state->buttons |= (latest_state.Gamepad.wButtons & XINPUT_GAMEPAD_B) != 0 ? GameInputGamepadB : GameInputGamepadNone;
Expand All @@ -1903,6 +1922,8 @@ SK_IPlayStationGameInputReading::GetGamepadState (GameInputGamepadState *state)

state->buttons |= (latest_state.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_THUMB) != 0 ? GameInputGamepadLeftThumbstick : GameInputGamepadNone;
state->buttons |= (latest_state.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_THUMB) != 0 ? GameInputGamepadRightThumbstick : GameInputGamepadNone;

SK_GameInput_EmulatedPlayStation = true;
}
}
}
Expand Down
6 changes: 3 additions & 3 deletions src/input/xinput_core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3435,10 +3435,10 @@ SK_XInput_PollController ( INT iJoyID,
{
SK_XInput_UpdateSlotForUI (TRUE, iJoyID, xstate.dwPacketNumber);

if (xstate.dwPacketNumber > ReadULongAcquire (&last_packet [iJoyID]))
if (xstate.dwPacketNumber > ReadULongAcquire (&last_native_packet [iJoyID]))
{
InterlockedExchange (&last_packet [iJoyID], xstate.dwPacketNumber);
InterlockedExchange (&last_time [iJoyID], SK_QueryPerf ().QuadPart);
InterlockedExchange (&last_native_packet [iJoyID], xstate.dwPacketNumber);
InterlockedExchange (&last_native_time [iJoyID], SK_QueryPerf ().QuadPart);
}
}

Expand Down

0 comments on commit d1da871

Please sign in to comment.