Created
February 22, 2023 23:10
-
-
Save skeeto/bbfaaba4fe525e0015233b5f5114e028 to your computer and use it in GitHub Desktop.
Infinite gamepad rumble on Windows
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// $ cc -nostartfiles example.c | |
// $ cl example.c /link /subsystem:console kernel32.lib | |
#define WIN32_LEAN_AND_MEAN | |
#include <windows.h> | |
#include <xinput.h> | |
struct gamepad { | |
void (*XInputEnable)(BOOL); | |
DWORD (*XInputSetState)(DWORD, XINPUT_VIBRATION *); | |
DWORD (*XInputGetState)(DWORD, XINPUT_STATE *); | |
DWORD (*XInputGetKeystroke)(DWORD, DWORD, PXINPUT_KEYSTROKE); | |
int enabled; // per-controller bit flags | |
}; | |
static struct gamepad loadgamepad(void) | |
{ | |
struct gamepad g = {0}; | |
HINSTANCE h = 0; | |
h = h ? h : LoadLibraryA("xinput1_4.dll"); | |
h = h ? h : LoadLibraryA("xinput1_3.dll"); | |
h = h ? h : LoadLibraryA("xinput9_1_0.dll"); | |
if (h) { | |
g.XInputEnable = (void *)GetProcAddress(h, "XInputEnable"); | |
g.XInputSetState = (void *)GetProcAddress(h, "XInputSetState"); | |
g.XInputGetState = (void *)GetProcAddress(h, "XInputGetState"); | |
g.XInputGetKeystroke = (void *)GetProcAddress(h, "XInputGetKeystroke"); | |
if (g.XInputEnable) { | |
g.XInputEnable(TRUE); | |
for (int i = 0; i < 4; i++) { | |
XINPUT_STATE state; | |
if (!g.XInputGetState(i, &state)) { | |
g.enabled |= 1 << i; | |
} | |
} | |
} | |
} | |
return g; | |
} | |
int mainCRTStartup(void) | |
{ | |
struct gamepad gp = loadgamepad(); | |
XINPUT_VIBRATION vibration; | |
vibration.wLeftMotorSpeed = -1; | |
vibration.wRightMotorSpeed = -1; | |
for (int i = 0; i < 4; i++) { | |
if (gp.enabled & (1<<i)) { | |
gp.XInputSetState(i, &vibration); | |
} | |
} | |
Sleep(INFINITE); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment