Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add xinput bindings to core:sys/windows #3208

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
210 changes: 210 additions & 0 deletions core/sys/windows/xinput.odin
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
// +build windows
package sys_windows

foreign import "system:xinput.lib"

// Device types available in XINPUT_CAPABILITIES
// Correspond to XINPUT_DEVTYPE_...
XINPUT_DEVTYPE :: enum BYTE {
GAMEPAD = 0x01,
}

// Device subtypes available in XINPUT_CAPABILITIES
// Correspond to XINPUT_DEVSUBTYPE_...
XINPUT_DEVSUBTYPE :: enum BYTE {
UNKNOWN = 0x00,
GAMEPAD = 0x01,
WHEEL = 0x02,
ARCADE_STICK = 0x03,
FLIGHT_STICK = 0x04,
DANCE_PAD = 0x05,
GUITAR = 0x06,
GUITAR_ALTERNATE = 0x07,
DRUM_KIT = 0x08,
GUITAR_BASS = 0x0B,
ARCADE_PAD = 0x13,
}

// Flags for XINPUT_CAPABILITIES
// Correspond to log2(XINPUT_CAPS_...)
XINPUT_CAP :: enum WORD {
FFB_SUPPORTED = 0,
WIRELESS = 1,
VOICE_SUPPORTED = 2,
PMD_SUPPORTED = 3,
NO_NAVIGATION = 4,
}
XINPUT_CAPS :: distinct bit_set[XINPUT_CAP;WORD]

// Constants for gamepad buttons
// Correspond to log2(XINPUT_GAMEPAD_...)
XINPUT_GAMEPAD_BUTTON_BIT :: enum WORD {
DPAD_UP = 0,
DPAD_DOWN = 1,
DPAD_LEFT = 2,
DPAD_RIGHT = 3,
START = 4,
BACK = 5,
LEFT_THUMB = 6,
RIGHT_THUMB = 7,
LEFT_SHOULDER = 8,
RIGHT_SHOULDER = 9,
A = 12,
B = 13,
X = 14,
Y = 15,
}
XINPUT_GAMEPAD_BUTTON :: distinct bit_set[XINPUT_GAMEPAD_BUTTON_BIT;WORD]

// Gamepad thresholds
XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE: SHORT : 7849
XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE: SHORT : 8689
XINPUT_GAMEPAD_TRIGGER_THRESHOLD: SHORT : 30

// Flags to pass to XInputGetCapabilities
// Corresponds to log2(XINPUT_FLAG_...)
XINPUT_FLAG_BIT :: enum WORD {
GAMEPAD = 0,
}
XINPUT_FLAG :: distinct bit_set[XINPUT_FLAG_BIT;DWORD]

// Devices that support batteries
// Corresponds to BATTERY_DEVTYPE_...
BATTERY_DEVTYPE :: enum BYTE {
GAMEPAD = 0x00,
HEADSET = 0x01,
}

// Flags for battery status level
// Correspond to BATTERY_TYPE_...
BATTERY_TYPE :: enum BYTE {
DISCONNECTED = 0x00, // This device is not connected
WIRED = 0x01, // Wired device, no battery
ALKALINE = 0x02, // Alkaline battery source
NIMH = 0x03, // Nickel Metal Hydride battery source
UNKNOWN = 0xFF, // Cannot determine the battery type
}

// These are only valid for wireless, connected devices, with known battery types
// The amount of use time remaining depends on the type of device.
// Correspond to BATTERY_LEVEL_...
BATTERY_LEVEL :: enum BYTE {
EMPTY = 0x00,
LOW = 0x01,
MEDIUM = 0x02,
FULL = 0x03,
}

// User index definitions

// Index of the gamer associated with the device
XUSER :: enum DWORD {
One = 0,
Two = 1,
Three = 2,
Four = 3,
Any = 0x000000FF, // Can be only used with XInputGetKeystroke
}

XUSER_MAX_COUNT :: 4

// Codes returned for the gamepad keystroke
// Corresponds to VK_PAD_...
VK_PAD :: enum WORD {
A = 0x5800,
B = 0x5801,
X = 0x5802,
Y = 0x5803,
RSHOULDER = 0x5804,
LSHOULDER = 0x5805,
LTRIGGER = 0x5806,
RTRIGGER = 0x5807,
DPAD_UP = 0x5810,
DPAD_DOWN = 0x5811,
DPAD_LEFT = 0x5812,
DPAD_RIGHT = 0x5813,
START = 0x5814,
BACK = 0x5815,
LTHUMB_PRESS = 0x5816,
RTHUMB_PRESS = 0x5817,
LTHUMB_UP = 0x5820,
LTHUMB_DOWN = 0x5821,
LTHUMB_RIGHT = 0x5822,
LTHUMB_LEFT = 0x5823,
LTHUMB_UPLEFT = 0x5824,
LTHUMB_UPRIGHT = 0x5825,
LTHUMB_DOWNRIGHT = 0x5826,
LTHUMB_DOWNLEFT = 0x5827,
RTHUMB_UP = 0x5830,
RTHUMB_DOWN = 0x5831,
RTHUMB_RIGHT = 0x5832,
RTHUMB_LEFT = 0x5833,
RTHUMB_UPLEFT = 0x5834,
RTHUMB_UPRIGHT = 0x5835,
RTHUMB_DOWNRIGHT = 0x5836,
RTHUMB_DOWNLEFT = 0x5837,
}

// Flags used in XINPUT_KEYSTROKE
// Correspond to log2(XINPUT_KEYSTROKE_...)
XINPUT_KEYSTROKE_BIT :: enum WORD {
KEYDOWN = 0,
KEYUP = 1,
REPEAT = 2,
}
XINPUT_KEYSTROKES :: distinct bit_set[XINPUT_KEYSTROKE_BIT;WORD]

// Structures used by XInput APIs
XINPUT_GAMEPAD :: struct {
wButtons: XINPUT_GAMEPAD_BUTTON,
bLeftTrigger: BYTE,
bRightTrigger: BYTE,
sThumbLX: SHORT,
sThumbLY: SHORT,
sThumbRX: SHORT,
sThumbRY: SHORT,
}

XINPUT_STATE :: struct {
dwPacketNumber: DWORD,
Gamepad: XINPUT_GAMEPAD,
}

XINPUT_VIBRATION :: struct {
wLeftMotorSpeed: WORD,
wRightMotorSpeed: WORD,
}

XINPUT_CAPABILITIES :: struct {
Type: XINPUT_DEVTYPE,
SubType: XINPUT_DEVSUBTYPE,
Flags: XINPUT_CAPS,
Gamepad: XINPUT_GAMEPAD,
Vibration: XINPUT_VIBRATION,
}

XINPUT_BATTERY_INFORMATION :: struct {
BatteryType: BATTERY_TYPE,
BatteryLevel: BATTERY_LEVEL,
}

XINPUT_KEYSTROKE :: struct {
VirtualKey: VK_PAD,
Unicode: WCHAR,
Flags: XINPUT_KEYSTROKES,
UserIndex: XUSER,
HidCode: BYTE,
}

// XInput APIs
@(default_calling_convention = "system")
foreign xinput {
XInputGetState :: proc(user: XUSER, pState: ^XINPUT_STATE) -> System_Error ---
XInputSetState :: proc(user: XUSER, pVibration: ^XINPUT_VIBRATION) -> System_Error ---
XInputGetCapabilities :: proc(user: XUSER, dwFlags: XINPUT_FLAG, pCapabilities: ^XINPUT_CAPABILITIES) -> System_Error ---
XInputEnable :: proc(enable: BOOL) ---
XInputGetAudioDeviceIds :: proc(user: XUSER, pRenderDeviceId: LPWSTR, pRenderCount: ^UINT, pCaptureDeviceId: LPWSTR, pCaptureCount: ^UINT) -> System_Error ---
XInputGetBatteryInformation :: proc(user: XUSER, devType: BATTERY_DEVTYPE, pBatteryInformation: ^XINPUT_BATTERY_INFORMATION) -> System_Error ---
XInputGetKeystroke :: proc(user: XUSER, dwReserved: DWORD, pKeystroke: ^XINPUT_KEYSTROKE) -> System_Error ---
XInputGetDSoundAudioDeviceGuids :: proc(user: XUSER, pDSoundRenderGuid: ^GUID, pDSoundCaptureGuid: ^GUID) -> System_Error ---
}