Skip to content

Commit

Permalink
Fixed internal deadzone on PlayStation controller input used to deter…
Browse files Browse the repository at this point in the history
…mine which gamepad has the most recent input (i.e. if the same controller is attached to USB and Bluetooth simultaneously), being applied to the readings sent to games
  • Loading branch information
Kaldaien committed Dec 2, 2024
1 parent 563de03 commit 07b6037
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 8 deletions.
11 changes: 10 additions & 1 deletion CHANGELOG.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
24.12.2
24.12.2.1
=========
+ Fixed internal deadzone on PlayStation controller input used to determine
which gamepad has the most recent input (i.e. if the same controller is
attached to USB and Bluetooth simultaneously), being applied to the
readings sent to games.

* This was causing stick drift.

24.12.2
=======
+ Added a trigger deadzone applied during trigger force feedback to keep
games from registering the small force feedback movement as actual user
Expand Down
4 changes: 2 additions & 2 deletions include/SpecialK/DLL_VERSION.H
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
#define SK_YEAR 24
#define SK_MONTH 12
#define SK_DATE 2
#define SK_REV_N 0
#define SK_REV 0
#define SK_REV_N 1
#define SK_REV 1

#ifndef _A2
#define _A2(a) #a
Expand Down
60 changes: 59 additions & 1 deletion src/diagnostics/debug_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1628,6 +1628,16 @@ using SetThreadContext_pfn = BOOL (WINAPI *)(HANDLE,const CONTEXT *);
GetThreadContext_pfn GetThreadContext_Original = nullptr;
SetThreadContext_pfn SetThreadContext_Original = nullptr;

enum IO_PRIORITY_HINT : int
{
IoPriorityVeryLow = 0, // Defragging, content indexing and other background I/Os.
IoPriorityLow, // Prefetching for applications.
IoPriorityNormal, // Normal I/Os.
IoPriorityHigh, // Used by filesystems for checkpoint I/O.
IoPriorityCritical, // Used by memory manager. Not available for applications.
MaxIoPriorityTypes
};

typedef enum _SK_THREAD_INFORMATION_CLASS {
ThreadBasicInformation,
ThreadTimes,
Expand All @@ -1646,10 +1656,46 @@ typedef enum _SK_THREAD_INFORMATION_CLASS {
ThreadPriorityBoost,
ThreadSetTlsArrayAddress,
ThreadIsIoPending_,
ThreadHideFromDebugger
ThreadHideFromDebugger,
ThreadBreakOnTermination,
ThreadSwitchLegacyState,
ThreadIsTerminated,
ThreadLastSystemCall,
ThreadIoPriority,
ThreadCycleTime,
ThreadPagePriority,
ThreadActualBasePriority,
ThreadTebInformation,
ThreadCSwitchMon,
ThreadCSwitchPmu,
ThreadWow64Context,
ThreadGroupInformation,
ThreadUmsInformation,
ThreadCounterProfiling,
ThreadIdealProcessorEx,
ThreadCpuAccountingInformation,
ThreadSuspendCount,
ThreadHeterogeneousCpuPolicy,
ThreadContainerId,
_ThreadNameInformation,
ThreadSelectedCpuSets,
ThreadSystemThreadInformation,
ThreadActualGroupAffinity,
ThreadDynamicCodePolicyInfo,
ThreadExplicitCaseSensitivity,
ThreadWorkOnBehalfTicket,
ThreadSubsystemInformation,
ThreadDbgkWerReportActive,
ThreadAttachContainer,
ThreadManageWritesToExecutableMemory,
ThreadPowerThrottlingState,
} SK_THREAD_INFORMATION_CLASS,
*PSK_THREAD_INFORMATION_CLASS;

#ifndef NT_SUCCESS
# define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
#endif

#define THREAD_CREATE_FLAGS_CREATE_SUSPENDED 0x00000001
#define THREAD_CREATE_FLAGS_SKIP_THREAD_ATTACH 0x00000002
#define THREAD_CREATE_FLAGS_HIDE_FROM_DEBUGGER 0x00000004
Expand Down Expand Up @@ -1701,6 +1747,18 @@ typedef void (NTAPI* RtlReleasePebLock_pfn)(void);
static RtlAcquirePebLock_pfn RtlAcquirePebLock_Original = nullptr;
static RtlReleasePebLock_pfn RtlReleasePebLock_Original = nullptr;

bool
SK_SetThreadIOPriority (HANDLE hThread, int priority)
{
IO_PRIORITY_HINT io_priority =
(IO_PRIORITY_HINT)priority;
static NtSetInformationThread_pfn
NtSetInformationThread =
(NtSetInformationThread_pfn)SK_GetProcAddress (L"NtDll", "NtSetInformationThread");
return
(NT_SUCCESS (NtSetInformationThread(hThread, ThreadIoPriority, &io_priority, sizeof(IO_PRIORITY_HINT))));
}

#define SK_ANTIDEBUG_PARANOIA_STAGE2
#define SK_ANTIDEBUG_PARANOIA_STAGE3

Expand Down
20 changes: 16 additions & 4 deletions src/input/hid_reports/playstation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ SK_HID_PlayStationDevice::~SK_HID_PlayStationDevice (void)
}
}

extern bool SK_SetThreadIOPriority (HANDLE hThread, int priority);

void SK_HID_SetupPlayStationControllers (void)
{
// Only do this once, and make all other threads trying to do it wait
Expand Down Expand Up @@ -1105,7 +1107,8 @@ SK_HID_PlayStationDevice::request_input_report (void)

SK_Thread_CreateEx ([](LPVOID pUser)->DWORD
{
SK_Thread_SetCurrentPriority (THREAD_PRIORITY_TIME_CRITICAL);
SK_Thread_SetCurrentPriority (THREAD_PRIORITY_HIGHEST);
SK_SetThreadIOPriority (SK_GetCurrentThread(),3);

SK_HID_PlayStationDevice* pDevice =
(SK_HID_PlayStationDevice *)pUser;
Expand Down Expand Up @@ -2262,7 +2265,7 @@ SK_HID_PlayStationDevice::request_input_report (void)

//
// God-awful hacks for games with impulse triggers that might register
// the changing analog position caused by force feedback as actual input.
// the changing analog input caused by force feedback as actual input.
//
if (pDevice->_vibration.trigger.last_left == 0 && pDevice->_vibration.trigger.left != 0)
pDevice->_vibration.trigger.start_left = pDevice->xinput.report.Gamepad.bLeftTrigger;
Expand Down Expand Up @@ -2414,7 +2417,7 @@ SK_HID_PlayStationDevice::request_input_report (void)
}
}

if (bIsInputActive)
if (bIsInputActive) // This indicates that the controller is active -after- deadzone checks
{
// Give most recently active device a +75 ms advantage,
// we may have the same device connected over two
Expand All @@ -2428,6 +2431,13 @@ SK_HID_PlayStationDevice::request_input_report (void)
}
}

// Deadzone checks make it inconclusive if this is the most recently used
// controller, but it does have new input and the game should see it...
else if (bIsInputNew)
{
WriteULong64Release (&pDevice->xinput.last_active, SK_QueryPerf ().QuadPart);
}

const bool bAllowSpecialButtons =
( config.input.gamepad.disabled_to_game == 0 ||
SK_IsGameWindowActive () ) &&
Expand Down Expand Up @@ -2537,6 +2547,7 @@ SK_HID_PlayStationDevice::write_output_report (bool force)
SK_Thread_CreateEx ([](LPVOID pData)->DWORD
{
SK_Thread_SetCurrentPriority (THREAD_PRIORITY_TIME_CRITICAL);
SK_SetThreadIOPriority (SK_GetCurrentThread (), 3);

SK_HID_PlayStationDevice* pDevice =
(SK_HID_PlayStationDevice *)pData;
Expand Down Expand Up @@ -3231,6 +3242,7 @@ SK_HID_PlayStationDevice::write_output_report (bool force)
SK_Thread_CreateEx ([](LPVOID pData)->DWORD
{
SK_Thread_SetCurrentPriority (THREAD_PRIORITY_TIME_CRITICAL);
SK_SetThreadIOPriority (SK_GetCurrentThread (), 3);

SK_HID_PlayStationDevice* pDevice =
(SK_HID_PlayStationDevice *)pData;
Expand Down Expand Up @@ -3458,7 +3470,7 @@ SK_HID_PlayStationDevice::write_output_report (bool force)
// :
//static_cast <uint8_t> ((100.0f - config.input.gamepad.scepad.rumble_power_level) / 12.5f);

if (config.input.gamepad.scepad.led_color_r >= 0 ||
if (config.input.gamepad.scepad.led_color_r >= 0 ||
config.input.gamepad.scepad.led_color_g >= 0 ||
config.input.gamepad.scepad.led_color_b >= 0)
{
Expand Down

0 comments on commit 07b6037

Please sign in to comment.