Index: src/OFGameController.h ================================================================== --- src/OFGameController.h +++ src/OFGameController.h @@ -242,10 +242,11 @@ #elif defined(OF_NINTENDO_3DS) OFMutableSet *_pressedButtons; OFPoint _leftAnalogStickPosition; #elif defined(OF_WINDOWS) DWORD _index; + OFNumber *_Nullable _vendorID, *_Nullable productID; OFMutableSet *_pressedButtons; OFPoint _leftAnalogStickPosition, _rightAnalogStickPosition; float _ZLPressure, _ZRPressure; #endif } Index: src/platform/Windows/OFGameController.m ================================================================== --- src/platform/Windows/OFGameController.m +++ src/platform/Windows/OFGameController.m @@ -19,10 +19,11 @@ #include "config.h" #import "OFGameController.h" #import "OFArray.h" +#import "OFNumber.h" #import "OFSet.h" #import "OFInitializationFailedException.h" #import "OFReadFailedException.h" @@ -29,14 +30,26 @@ #include @interface OFGameController () - (instancetype)of_initWithIndex: (DWORD)index OF_METHOD_FAMILY(init); @end + +struct XInputCapabilitiesEx { + XINPUT_CAPABILITIES capabilities; + WORD vendorID; + WORD productID; + WORD versionNumber; + WORD unknown1; + DWORD unknown2; +}; static WINAPI DWORD (*XInputGetStateFuncPtr)(DWORD, XINPUT_STATE *); +static WINAPI DWORD (*XInputGetCapabilitiesExFuncPtr)(DWORD, DWORD, DWORD, + struct XInputCapabilitiesEx *); @implementation OFGameController +@synthesize vendorID = _vendorID, productID = _productID; @synthesize leftAnalogStickPosition = _leftAnalogStickPosition; @synthesize rightAnalogStickPosition = _rightAnalogStickPosition; + (void)initialize { @@ -43,14 +56,18 @@ HMODULE module; if (self != [OFGameController class]) return; - if ((module = LoadLibraryA("xinput1_3.dll")) != NULL) + if ((module = LoadLibraryA("xinput1_4.dll")) != NULL) { XInputGetStateFuncPtr = (WINAPI DWORD (*)(DWORD, XINPUT_STATE *)) GetProcAddress(module, "XInputGetState"); + XInputGetCapabilitiesExFuncPtr = (WINAPI DWORD (*)(DWORD, DWORD, + DWORD, struct XInputCapabilitiesEx *)) + GetProcAddress(module, "XInputGetCapabilitiesEx"); + } } + (OFArray OF_GENERIC(OFGameController *) *)controllers { OFMutableArray *controllers = [OFMutableArray array]; @@ -95,10 +112,26 @@ if (XInputGetStateFuncPtr(index, &state) == ERROR_DEVICE_NOT_CONNECTED) @throw [OFInitializationFailedException exception]; _index = index; + + if (XInputGetCapabilitiesExFuncPtr != NULL) { + struct XInputCapabilitiesEx capabilities; + + if (XInputGetCapabilitiesExFuncPtr(1, _index, + XINPUT_FLAG_GAMEPAD, &capabilities) == + ERROR_SUCCESS) { + _vendorID = [[OFNumber alloc] + initWithUnsignedShort: + capabilities.vendorID]; + _productID = [[OFNumber alloc] + initWithUnsignedShort: + capabilities.productID]; + } + } + _pressedButtons = [[OFMutableSet alloc] initWithCapacity: 16]; [self retrieveState]; } @catch (id e) { [self release]; @@ -108,10 +141,12 @@ return self; } - (void)dealloc { + [_vendorID release]; + [_productID release]; [_pressedButtons release]; [super dealloc]; } @@ -178,20 +213,10 @@ - (OFString *)name { return @"XInput 1.3"; } -- (OFNumber *)vendorID -{ - return nil; -} - -- (OFNumber *)productID -{ - return nil; -} - - (OFSet OF_GENERIC(OFGameControllerButton) *)buttons { return [OFSet setWithObjects: OFGameControllerButtonA, OFGameControllerButtonB, OFGameControllerButtonX, OFGameControllerButtonY,