Cocoa Port:

- Do a bunch of optimization and cleanup of the input handler.
- Add support for using analog inputs in their native format.
- The paddle controller now supports native analog control.
- NOTE: Due to the changes in the input handler, users will need to rebind any hatswitch inputs that were previously used. Only hatswitch inputs were affected by these changes.
This commit is contained in:
rogerman 2014-01-07 18:35:40 +00:00
parent ac146b26d2
commit 0ec2b21a20
17 changed files with 2072 additions and 831 deletions

View File

@ -129,4 +129,14 @@ public:
}
};
u16 Paddle_GetValue()
{
return nds.paddle;
}
void Paddle_SetValue(u16 theValue)
{
nds.paddle = theValue;
}
ISlot2Interface* construct_Slot2_Paddle() { return new Slot2_Paddle(); }

View File

@ -20,6 +20,7 @@
<string>Microphone</string>
<string>Lid</string>
<string>Debug</string>
<string>Paddle</string>
<string>Execute/Pause</string>
<string>Reset</string>
<string>Mute/Unmute</string>
@ -33,7 +34,6 @@
<string>Enable/Disable Auto Frame Skip</string>
<string>Enable/Disable Cheats</string>
<string>Enable/Disable GPU State</string>
<string>Paddle</string>
</array>
<key>DefaultInputProfiles</key>
<array>
@ -281,6 +281,45 @@
</array>
<key>Debug</key>
<array/>
<key>Paddle</key>
<array>
<dict>
<key>deviceInfoSummary</key>
<string>Keyboard: K</string>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>40</string>
<key>elementName</key>
<string>K</string>
<key>isInputAnalog</key>
<false/>
<key>inputSettingsSummary</key>
<string>Paddle Adjust: -5</string>
<key>intValue1</key>
<integer>-5</integer>
</dict>
<dict>
<key>deviceInfoSummary</key>
<string>Keyboard: L</string>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>37</string>
<key>elementName</key>
<string>L</string>
<key>isInputAnalog</key>
<false/>
<key>inputSettingsSummary</key>
<string>Paddle Adjust: +5</string>
<key>intValue1</key>
<integer>5</integer>
</dict>
</array>
<key>HUD</key>
<array>
<dict>
@ -411,8 +450,6 @@
<array/>
<key>Enable/Disable GPU State</key>
<array/>
<key>Paddle</key>
<array/>
</dict>
</dict>
</array>

View File

@ -69,12 +69,14 @@ enum
NSPoint touchLocation;
bool controllerState[DSControllerState_StatesCount];
AudioSampleBlockGenerator *selectedAudioFileGenerator;
NSInteger paddleAdjust;
OSSpinLock spinlockControllerState;
}
@property (assign) NSInteger micMode;
@property (assign) AudioSampleBlockGenerator *selectedAudioFileGenerator;
@property (assign) NSInteger paddleAdjust;
- (void) setControllerState:(BOOL)theState controlID:(const NSUInteger)controlID;
- (void) setTouchState:(BOOL)theState location:(const NSPoint)theLocation;

View File

@ -20,6 +20,7 @@
#import "cocoa_globals.h"
#include "../NDSSystem.h"
#include "../slot2.h"
#undef BOOL
@ -27,6 +28,7 @@
@synthesize micMode;
@synthesize selectedAudioFileGenerator;
@synthesize paddleAdjust;
- (id)init
{
@ -45,6 +47,7 @@
micMode = MICMODE_NONE;
selectedAudioFileGenerator = NULL;
touchLocation = NSMakePoint(0.0f, 0.0f);
paddleAdjust = 0;
return self;
}
@ -131,6 +134,13 @@
NDS_releaseTouch();
}
// Setup the paddle.
if (slot2_GetSelectedType() == NDS_SLOT2_PADDLE)
{
const u16 newPaddleValue = Paddle_GetValue() + (u16)[self paddleAdjust];
Paddle_SetValue(newPaddleValue);
}
// Setup the DS mic.
AudioGenerator *selectedGenerator = &nullSampleGenerator;
switch (theMicMode)

View File

@ -49,7 +49,6 @@
@property (copy) NSURL *gbaCartridgeURL;
@property (copy) NSURL *gbaSRamURL;
@property (readonly) BOOL doesGbaCartridgeSaveExist;
@property (assign) UInt16 paddleValue;
- (CocoaDSSlot2Device *) autoSelectedDevice;
- (NSString *) autoSelectedDeviceName;

View File

@ -47,8 +47,6 @@
- (void) dealloc
{
[self setEnabled:nil];
[super dealloc];
}
@ -91,7 +89,6 @@
@dynamic gbaCartridgeURL;
@dynamic gbaSRamURL;
@dynamic doesGbaCartridgeSaveExist;
@dynamic paddleValue;
- (id) init
{
@ -211,16 +208,6 @@
return NO;
}
- (void) setPaddleValue:(UInt16)value
{
nds.paddle = value;
}
- (UInt16) paddleValue
{
return nds.paddle;
}
- (CocoaDSSlot2Device *) autoSelectedDevice
{
return [self findDeviceByType:slot2_DetermineType()];

File diff suppressed because it is too large Load Diff

View File

@ -1792,14 +1792,13 @@ static std::tr1::unordered_map<NSScreen *, DisplayWindowController *> _screenMap
}
#pragma mark InputHIDManagerTarget Protocol
- (BOOL) handleHIDQueue:(IOHIDQueueRef)hidQueue
- (BOOL) handleHIDQueue:(IOHIDQueueRef)hidQueue hidManager:(InputHIDManager *)hidManager
{
BOOL isHandled = NO;
DisplayWindowController *windowController = (DisplayWindowController *)[[self window] delegate];
InputAttributesList inputList = InputManagerEncodeHIDQueue(hidQueue);
char inputStr[INPUT_HANDLER_STRING_LENGTH*2];
memset(inputStr, '\0', INPUT_HANDLER_STRING_LENGTH*2);
InputAttributesList inputList = InputManagerEncodeHIDQueue(hidQueue, [hidManager inputManager], false);
NSString *newStatusText = nil;
const size_t inputCount = inputList.size();
@ -1807,18 +1806,21 @@ static std::tr1::unordered_map<NSScreen *, DisplayWindowController *> _screenMap
{
const InputAttributes &inputAttr = inputList[i];
if (inputAttr.state == INPUT_ATTRIBUTE_STATE_ON)
if (inputAttr.isAnalog)
{
strlcpy(inputStr, inputAttr.deviceName, INPUT_HANDLER_STRING_LENGTH*2);
strlcat(inputStr, ":", INPUT_HANDLER_STRING_LENGTH*2);
strlcat(inputStr, inputAttr.elementName, INPUT_HANDLER_STRING_LENGTH*2);
newStatusText = [NSString stringWithFormat:@"%s:%s (%1.2f)", inputAttr.deviceName, inputAttr.elementName, inputAttr.scalar];
break;
}
else if (inputAttr.state == INPUT_ATTRIBUTE_STATE_ON)
{
newStatusText = [NSString stringWithFormat:@"%s:%s", inputAttr.deviceName, inputAttr.elementName];
break;
}
}
if (inputStr[0] != '\0' && inputStr[0] != ':')
if (newStatusText != nil)
{
[[windowController emuControl] setStatusText:[NSString stringWithCString:inputStr encoding:NSUTF8StringEncoding]];
[[windowController emuControl] setStatusText:newStatusText];
}
CommandAttributesList cmdList = [inputManager generateCommandListUsingInputList:&inputList];
@ -1842,12 +1844,8 @@ static std::tr1::unordered_map<NSScreen *, DisplayWindowController *> _screenMap
if (keyPressed && [theEvent window] != nil)
{
char inputStr[INPUT_HANDLER_STRING_LENGTH*2];
strlcpy(inputStr, inputAttr.deviceName, INPUT_HANDLER_STRING_LENGTH*2);
strlcat(inputStr, ":", INPUT_HANDLER_STRING_LENGTH*2);
strlcat(inputStr, inputAttr.elementName, INPUT_HANDLER_STRING_LENGTH*2);
[[windowController emuControl] setStatusText:[NSString stringWithCString:inputStr encoding:NSUTF8StringEncoding]];
NSString *newStatusText = [NSString stringWithFormat:@"%s:%s", inputAttr.deviceName, inputAttr.elementName];
[[windowController emuControl] setStatusText:newStatusText];
}
isHandled = [inputManager dispatchCommandUsingInputAttributes:&inputAttr];
@ -1862,30 +1860,13 @@ static std::tr1::unordered_map<NSScreen *, DisplayWindowController *> _screenMap
// Convert the clicked location from window coordinates, to view coordinates,
// and finally to DS touchscreen coordinates.
NSPoint touchLoc = NSMakePoint(-2.0, -2.0);
if (displayModeID == DS_DISPLAY_TYPE_TOUCH || displayModeID == DS_DISPLAY_TYPE_DUAL)
{
touchLoc = [self dsPointFromEvent:theEvent];
}
const NSPoint touchLoc = (displayModeID == DS_DISPLAY_TYPE_MAIN) ? NSMakePoint(0.0, 0.0) : [self dsPointFromEvent:theEvent];
const InputAttributes inputAttr = InputManagerEncodeMouseButtonInput([theEvent buttonNumber], touchLoc, buttonPressed);
if (buttonPressed && [theEvent window] != nil)
{
static char inputStr[INPUT_HANDLER_STRING_LENGTH*2] = {0};
strlcpy(inputStr, inputAttr.deviceName, INPUT_HANDLER_STRING_LENGTH*2);
strlcat(inputStr, ":", INPUT_HANDLER_STRING_LENGTH*2);
strlcat(inputStr, inputAttr.elementName, INPUT_HANDLER_STRING_LENGTH*2);
if (inputAttr.intCoordX >= 0)
{
static char inputCoordBuf[64] = {0};
snprintf(inputCoordBuf, 64, " X:%i Y:%i", (int)inputAttr.intCoordX, (int)inputAttr.intCoordY);
strlcat(inputStr, inputCoordBuf, INPUT_HANDLER_STRING_LENGTH*2);
}
[[windowController emuControl] setStatusText:[NSString stringWithCString:inputStr encoding:NSUTF8StringEncoding]];
NSString *newStatusText = (displayModeID == DS_DISPLAY_TYPE_MAIN) ? [NSString stringWithFormat:@"%s:%s", inputAttr.deviceName, inputAttr.elementName] : [NSString stringWithFormat:@"%s:%s X:%i Y:%i", inputAttr.deviceName, inputAttr.elementName, (int)inputAttr.intCoordX, (int)inputAttr.intCoordY];
[[windowController emuControl] setStatusText:newStatusText];
}
isHandled = [inputManager dispatchCommandUsingInputAttributes:&inputAttr];

View File

@ -987,15 +987,32 @@
}
else if (controlID == DSControllerState_Paddle)
{
if (cmdAttr.useInputForScalar)
if (cmdAttr.input.isAnalog)
{
const float paddleScalar = cmdAttr.floatValue[0];
[(Slot2WindowDelegate *)[slot2WindowController content] setPaddleDirectWithScalar:paddleScalar];
const NSInteger paddleSensitivity = cmdAttr.floatValue[0];
const float paddleScalar = cmdAttr.input.scalar;
float paddleAdjust = (paddleScalar * 2.0f) - 1.0f;
// Clamp the paddle value.
if (paddleAdjust < -1.0f)
{
paddleAdjust = -1.0f;
}
if (paddleAdjust > 1.0f)
{
paddleAdjust = 1.0f;
}
// Normalize the input value for the paddle.
paddleAdjust *= (float)paddleSensitivity;
[[cdsCore cdsController] setPaddleAdjust:paddleAdjust];
}
else
{
const NSInteger paddleRelativeAdjustment = cmdAttr.intValue[1];
[(Slot2WindowDelegate *)[slot2WindowController content] setPaddleRelativeWithInteger:paddleRelativeAdjustment];
const NSInteger paddleAdjust = (theState) ? cmdAttr.intValue[1] : 0;
[[cdsCore cdsController] setPaddleAdjust:paddleAdjust];
}
}
else

View File

@ -47,7 +47,7 @@ enum InputAttributeState
@protocol InputHIDManagerTarget <NSObject>
@required
- (BOOL) handleHIDQueue:(IOHIDQueueRef)hidQueue;
- (BOOL) handleHIDQueue:(IOHIDQueueRef)hidQueue hidManager:(InputHIDManager *)hidManager;
@end
@ -57,6 +57,7 @@ typedef struct
char deviceCode[INPUT_HANDLER_STRING_LENGTH];
char elementName[INPUT_HANDLER_STRING_LENGTH];
char elementCode[INPUT_HANDLER_STRING_LENGTH];
bool isAnalog; // This is an analog input, as opposed to being a digital input.
InputAttributeState state; // The input state that is sent on command dispatch
int32_t intCoordX; // The X-coordinate as an int for commands that require a location
@ -81,6 +82,7 @@ typedef struct
bool useInputForSender; // The command will prefer the input device's sender
InputAttributes input; // The input device's attributes
bool allowAnalogInput; // Flag for allowing a command to accept analog inputs
} CommandAttributes;
typedef std::vector<InputAttributes> InputAttributesList;
@ -141,12 +143,12 @@ typedef std::tr1::unordered_map<std::string, AudioSampleBlockGenerator> AudioFil
@end
bool GetOnStateFromHIDValueRef(IOHIDValueRef hidValueRef);
void InputDeviceCodeFromHIDDevice(const IOHIDDeviceRef hidDeviceRef, char *charBuffer);
void InputDeviceNameFromHIDDevice(const IOHIDDeviceRef hidDeviceRef, char *charBuffer, const char *altName);
InputAttributes InputAttributesOfHIDValue(IOHIDValueRef hidValueRef, const char *altElementCode, const char *altElementName, const bool *altOnState);
InputAttributesList InputListFromHIDValue(IOHIDValueRef hidValueRef);
InputAttributesList InputListFromHatSwitchValue(IOHIDValueRef hidValueRef, bool useEightDirection);
bool InputElementCodeFromHIDElement(const IOHIDElementRef hidElementRef, char *charBuffer);
bool InputElementNameFromHIDElement(const IOHIDElementRef hidElementRef, char *charBuffer);
bool InputDeviceCodeFromHIDDevice(const IOHIDDeviceRef hidDeviceRef, char *charBuffer);
bool InputDeviceNameFromHIDDevice(const IOHIDDeviceRef hidDeviceRef, char *charBuffer);
InputAttributes InputAttributesOfHIDValue(IOHIDValueRef hidValueRef);
InputAttributesList InputListFromHIDValue(IOHIDValueRef hidValueRef, InputManager *inputManager, bool forceDigitalInput);
size_t ClearHIDQueue(const IOHIDQueueRef hidQueue);
void HandleQueueValueAvailableCallback(void *inContext, IOReturn inResult, void *inSender);
@ -238,7 +240,7 @@ NSMutableDictionary* DeviceInfoDictionaryWithCommandAttributes(const CommandAttr
NSString *elementCode,
NSString *elementName);
InputAttributesList InputManagerEncodeHIDQueue(const IOHIDQueueRef hidQueue);
InputAttributesList InputManagerEncodeHIDQueue(const IOHIDQueueRef hidQueue, InputManager *inputManager, bool forceDigitalInput);
InputAttributes InputManagerEncodeKeyboardInput(const unsigned short keyCode, BOOL keyPressed);
InputAttributes InputManagerEncodeMouseButtonInput(const NSInteger buttonNumber, const NSPoint touchLoc, BOOL buttonPressed);
InputAttributes InputManagerEncodeIBAction(const SEL theSelector, id sender);

View File

@ -221,6 +221,7 @@ static NSDictionary *hidUsageTable = nil;
- (void)dealloc
{
[self stopForceFeedback];
[self stop];
[self setRunLoop:nil];
[self setHidManager:nil];
@ -233,8 +234,8 @@ static NSDictionary *hidUsageTable = nil;
if (ffDevice != NULL)
{
FFReleaseDevice(ffDevice);
FFEffectUnload(ffEffect);
FFReleaseDevice(ffDevice);
ffDevice = NULL;
}
@ -411,9 +412,6 @@ static NSDictionary *hidUsageTable = nil;
Takes:
hidValueRef - The IOHIDValueRef to parse.
altElementCode - A char buffer that overrides the default element code.
altElementName - A char buffer that overrides the default element name.
altOnState - A pointer to a bool value that overrides the default on state.
Returns:
An InputAttributes struct with the parsed input attributes.
@ -421,7 +419,7 @@ static NSDictionary *hidUsageTable = nil;
Details:
None.
********************************************************************************************/
InputAttributes InputAttributesOfHIDValue(IOHIDValueRef hidValueRef, const char *altElementCode, const char *altElementName, const bool *altOnState)
InputAttributes InputAttributesOfHIDValue(IOHIDValueRef hidValueRef)
{
InputAttributes inputAttr;
@ -430,63 +428,25 @@ InputAttributes InputAttributesOfHIDValue(IOHIDValueRef hidValueRef, const char
return inputAttr;
}
IOHIDElementRef hidElementRef = IOHIDValueGetElement(hidValueRef);
NSInteger elementUsagePage = IOHIDElementGetUsagePage(hidElementRef);
NSInteger elementUsage = IOHIDElementGetUsage(hidElementRef);
if (altElementCode == NULL)
{
snprintf(inputAttr.elementCode, INPUT_HANDLER_STRING_LENGTH, "0x%04lX/0x%04lX", (long)elementUsagePage, (long)elementUsage);
}
else
{
strncpy(inputAttr.elementCode, altElementCode, INPUT_HANDLER_STRING_LENGTH);
}
if (altElementName == NULL)
{
CFStringRef cfElementName = IOHIDElementGetName(hidElementRef);
if (cfElementName == nil)
{
if (elementUsagePage == kHIDPage_Button)
{
snprintf(inputAttr.elementName, INPUT_HANDLER_STRING_LENGTH, "Button %li", (long)elementUsage);
}
else if (elementUsagePage == kHIDPage_VendorDefinedStart)
{
snprintf(inputAttr.elementName, INPUT_HANDLER_STRING_LENGTH, "VendorDefined %li", (long)elementUsage);
}
else
{
NSDictionary *elementUsagePageDict = (NSDictionary *)[hidUsageTable valueForKey:[NSString stringWithFormat:@"0x%04lX", (long)elementUsagePage]];
NSString *elementNameLookup = (NSString *)[elementUsagePageDict valueForKey:[NSString stringWithFormat:@"0x%04lX", (long)elementUsage]];
if (elementNameLookup != nil)
{
strncpy(inputAttr.elementName, [elementNameLookup cStringUsingEncoding:NSUTF8StringEncoding], 256);
}
}
}
else
{
CFStringGetCString(cfElementName, inputAttr.elementName, INPUT_HANDLER_STRING_LENGTH, kCFStringEncodingUTF8);
}
}
else
{
strncpy(inputAttr.elementName, altElementName, INPUT_HANDLER_STRING_LENGTH);
}
const IOHIDElementRef hidElementRef = IOHIDValueGetElement(hidValueRef);
const IOHIDDeviceRef hidDeviceRef = IOHIDElementGetDevice(hidElementRef);
InputDeviceCodeFromHIDDevice(hidDeviceRef, inputAttr.deviceCode);
InputDeviceNameFromHIDDevice(hidDeviceRef, inputAttr.deviceName, inputAttr.deviceCode);
const bool onState = (altOnState == NULL) ? GetOnStateFromHIDValueRef(hidValueRef) : *altOnState;
InputElementCodeFromHIDElement(hidElementRef, inputAttr.elementCode);
InputDeviceCodeFromHIDDevice(hidDeviceRef, inputAttr.deviceCode);
strncpy(inputAttr.elementName, inputAttr.elementCode, INPUT_HANDLER_STRING_LENGTH);
InputElementNameFromHIDElement(hidElementRef, inputAttr.elementName);
strncpy(inputAttr.deviceName, inputAttr.deviceCode, INPUT_HANDLER_STRING_LENGTH);
InputDeviceNameFromHIDDevice(hidDeviceRef, inputAttr.deviceName);
const NSInteger logicalValue = IOHIDValueGetIntegerValue(hidValueRef);
const NSInteger logicalMin = IOHIDElementGetLogicalMin(hidElementRef);
const NSInteger logicalMax = IOHIDElementGetLogicalMax(hidElementRef);
const NSInteger elementType = IOHIDElementGetType(hidElementRef);
const NSInteger elementUsage = IOHIDElementGetUsage(hidElementRef);
inputAttr.state = (onState) ? INPUT_ATTRIBUTE_STATE_ON : INPUT_ATTRIBUTE_STATE_OFF;
inputAttr.isAnalog = (elementType != kIOHIDElementTypeInput_Button) && !(logicalMin == 0 && logicalMax == 1);
inputAttr.intCoordX = 0;
inputAttr.intCoordY = 0;
inputAttr.floatCoordX = 0.0f;
@ -494,10 +454,61 @@ InputAttributes InputAttributesOfHIDValue(IOHIDValueRef hidValueRef, const char
inputAttr.scalar = (float)(logicalValue - logicalMin) / (float)(logicalMax - logicalMin);
inputAttr.sender = nil;
if (!inputAttr.isAnalog)
{
inputAttr.state = (logicalValue == 1) ? INPUT_ATTRIBUTE_STATE_ON : INPUT_ATTRIBUTE_STATE_OFF;
}
else if (elementUsage == kHIDUsage_GD_Hatswitch)
{
// For hatswitch inputs, use the intCoord fields to store the axis information.
inputAttr.state = (logicalValue >= logicalMin && logicalValue <= logicalMax) ? INPUT_ATTRIBUTE_STATE_ON : INPUT_ATTRIBUTE_STATE_OFF;
if (inputAttr.state == INPUT_ATTRIBUTE_STATE_ON)
{
struct IntCoord
{
int x;
int y;
};
static const IntCoord coords4Way[4] = {
{0, -1}, // Up
{1, 0}, // Right
{0, 1}, // Down
{-1, 0} // Left
};
static const IntCoord coords8Way[8] = {
{0, -1}, // Up
{1, -1}, // Up/Right
{1, 0}, // Right
{1, 1}, // Down/Right
{0, 1}, // Down
{-1, 1}, // Down/Left
{-1, 0}, // Left
{-1, -1} // Up/Left
};
if (logicalMax == 3) // For a 4-way hatswitch
{
inputAttr.intCoordX = coords4Way[logicalValue].x;
inputAttr.intCoordY = coords4Way[logicalValue].y;
}
else if (logicalMax == 7) // For an 8-way hatswitch
{
inputAttr.intCoordX = coords8Way[logicalValue].x;
inputAttr.intCoordY = coords8Way[logicalValue].y;
}
}
}
else // Some generic analog input
{
inputAttr.state = (inputAttr.scalar <= 0.30f || inputAttr.scalar >= 0.7f) ? INPUT_ATTRIBUTE_STATE_ON : INPUT_ATTRIBUTE_STATE_OFF;
}
return inputAttr;
}
InputAttributesList InputListFromHIDValue(IOHIDValueRef hidValueRef)
InputAttributesList InputListFromHIDValue(IOHIDValueRef hidValueRef, InputManager *inputManager, bool forceDigitalInput)
{
InputAttributesList inputList;
@ -506,10 +517,6 @@ InputAttributesList InputListFromHIDValue(IOHIDValueRef hidValueRef)
return inputList;
}
IOHIDElementRef hidElementRef = IOHIDValueGetElement(hidValueRef);
NSInteger elementUsagePage = IOHIDElementGetUsagePage(hidElementRef);
NSInteger elementUsage = IOHIDElementGetUsage(hidElementRef);
// IOHIDValueGetIntegerValue() will crash if the value length is too large.
// Do a bounds check here to prevent crashing. This workaround makes the PS3
// controller usable, since it returns a length of 39 on some elements.
@ -518,245 +525,199 @@ InputAttributesList InputListFromHIDValue(IOHIDValueRef hidValueRef)
return inputList;
}
NSInteger logicalValue = IOHIDValueGetIntegerValue(hidValueRef);
NSInteger logicalMin = IOHIDElementGetLogicalMin(hidElementRef);
NSInteger logicalMax = IOHIDElementGetLogicalMax(hidElementRef);
inputList.resize(2);
if (logicalMin == 0 && logicalMax == 1)
InputAttributes inputAttr = InputAttributesOfHIDValue(hidValueRef);
if (inputAttr.deviceCode[0] == '\0' || inputAttr.elementCode[0] == '\0')
{
inputList.push_back(InputAttributesOfHIDValue(hidValueRef, NULL, NULL, NULL));
return inputList;
}
if (!inputAttr.isAnalog)
{
inputList.push_back(inputAttr);
}
else
{
const NSInteger lowerThreshold = ((logicalMax - logicalMin) / 4) + logicalMin;
const NSInteger upperThreshold = (((logicalMax - logicalMin) * 3) / 4) + logicalMin;
const bool onState = true;
const bool offState = false;
const IOHIDElementRef hidElementRef = IOHIDValueGetElement(hidValueRef);
const NSInteger elementUsage = IOHIDElementGetUsage(hidElementRef);
char elementCodeLowerThresholdBuf[256] = {0};
char elementCodeUpperThresholdBuf[256] = {0};
snprintf(elementCodeLowerThresholdBuf, 256, "0x%04lX/0x%04lX/LowerThreshold", (long)elementUsagePage, (long)elementUsage);
snprintf(elementCodeUpperThresholdBuf, 256, "0x%04lX/0x%04lX/UpperThreshold", (long)elementUsagePage, (long)elementUsage);
if (logicalValue <= lowerThreshold)
if (elementUsage == kHIDUsage_GD_Hatswitch)
{
inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeLowerThresholdBuf, NULL, &onState));
inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeUpperThresholdBuf, NULL, &offState));
}
else if (logicalValue >= upperThreshold)
{
inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeLowerThresholdBuf, NULL, &offState));
inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeUpperThresholdBuf, NULL, &onState));
InputAttributes hatUp = inputAttr;
hatUp.isAnalog = false;
strncat(hatUp.elementName, "/Up", INPUT_HANDLER_STRING_LENGTH);
strncat(hatUp.elementCode, "/Up", INPUT_HANDLER_STRING_LENGTH);
InputAttributes hatRight = inputAttr;
hatRight.isAnalog = false;
strncat(hatRight.elementName, "/Right", INPUT_HANDLER_STRING_LENGTH);
strncat(hatRight.elementCode, "/Right", INPUT_HANDLER_STRING_LENGTH);
InputAttributes hatDown = inputAttr;
hatDown.isAnalog = false;
strncat(hatDown.elementName, "/Down", INPUT_HANDLER_STRING_LENGTH);
strncat(hatDown.elementCode, "/Down", INPUT_HANDLER_STRING_LENGTH);
InputAttributes hatLeft = inputAttr;
hatLeft.isAnalog = false;
strncat(hatLeft.elementName, "/Left", INPUT_HANDLER_STRING_LENGTH);
strncat(hatLeft.elementCode, "/Left", INPUT_HANDLER_STRING_LENGTH);
if (inputAttr.intCoordX == -1)
{
hatRight.state = INPUT_ATTRIBUTE_STATE_OFF;
hatLeft.state = INPUT_ATTRIBUTE_STATE_ON;
}
else if (inputAttr.intCoordX == 1)
{
hatRight.state = INPUT_ATTRIBUTE_STATE_ON;
hatLeft.state = INPUT_ATTRIBUTE_STATE_OFF;
}
else
{
hatRight.state = INPUT_ATTRIBUTE_STATE_OFF;
hatLeft.state = INPUT_ATTRIBUTE_STATE_OFF;
}
if (inputAttr.intCoordY == -1)
{
hatDown.state = INPUT_ATTRIBUTE_STATE_OFF;
hatUp.state = INPUT_ATTRIBUTE_STATE_ON;
}
else if (inputAttr.intCoordY == 1)
{
hatDown.state = INPUT_ATTRIBUTE_STATE_ON;
hatUp.state = INPUT_ATTRIBUTE_STATE_OFF;
}
else
{
hatDown.state = INPUT_ATTRIBUTE_STATE_OFF;
hatUp.state = INPUT_ATTRIBUTE_STATE_OFF;
}
inputList.resize(4);
inputList.push_back(hatUp);
inputList.push_back(hatRight);
inputList.push_back(hatDown);
inputList.push_back(hatLeft);
}
else
{
inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeLowerThresholdBuf, NULL, &offState));
inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeUpperThresholdBuf, NULL, &offState));
CommandAttributes cmdAttr = [inputManager mappedCommandAttributesOfDeviceCode:inputAttr.deviceCode elementCode:inputAttr.elementCode];
if (cmdAttr.tag[0] == '\0' || cmdAttr.selector == nil)
{
std::string tempElementCode = std::string(inputAttr.elementCode) + "/LowerThreshold";
cmdAttr = [inputManager mappedCommandAttributesOfDeviceCode:inputAttr.deviceCode elementCode:tempElementCode.c_str()];
if (cmdAttr.tag[0] == '\0' || cmdAttr.selector == nil)
{
tempElementCode = std::string(inputAttr.elementCode) + "/UpperThreshold";
cmdAttr = [inputManager mappedCommandAttributesOfDeviceCode:inputAttr.deviceCode elementCode:tempElementCode.c_str()];
}
}
const bool useAnalog = (cmdAttr.tag[0] == '\0' || cmdAttr.selector == nil) ? !forceDigitalInput : (!forceDigitalInput && cmdAttr.allowAnalogInput);
if (useAnalog)
{
inputList.push_back(inputAttr);
}
else
{
InputAttributes loInputAttr = inputAttr;
loInputAttr.isAnalog = false;
strncat(loInputAttr.elementName, "-", INPUT_HANDLER_STRING_LENGTH);
strncat(loInputAttr.elementCode, "/LowerThreshold", INPUT_HANDLER_STRING_LENGTH);
InputAttributes hiInputAttr = inputAttr;
hiInputAttr.isAnalog = false;
strncat(hiInputAttr.elementName, "+", INPUT_HANDLER_STRING_LENGTH);
strncat(hiInputAttr.elementCode, "/UpperThreshold", INPUT_HANDLER_STRING_LENGTH);
if (loInputAttr.scalar <= 0.30f)
{
loInputAttr.state = INPUT_ATTRIBUTE_STATE_ON;
hiInputAttr.state = INPUT_ATTRIBUTE_STATE_OFF;
}
else if (loInputAttr.scalar >= 0.70f)
{
loInputAttr.state = INPUT_ATTRIBUTE_STATE_OFF;
hiInputAttr.state = INPUT_ATTRIBUTE_STATE_ON;
}
else
{
loInputAttr.state = INPUT_ATTRIBUTE_STATE_OFF;
hiInputAttr.state = INPUT_ATTRIBUTE_STATE_OFF;
}
inputList.resize(2);
inputList.push_back(loInputAttr);
inputList.push_back(hiInputAttr);
}
}
}
return inputList;
}
InputAttributesList InputListFromHatSwitchValue(IOHIDValueRef hidValueRef, bool useEightDirection)
bool InputElementCodeFromHIDElement(const IOHIDElementRef hidElementRef, char *charBuffer)
{
InputAttributesList inputList;
NSInteger elementUsagePage = IOHIDElementGetUsagePage(hidElementRef);
NSInteger elementUsage = IOHIDElementGetUsage(hidElementRef);
snprintf(charBuffer, INPUT_HANDLER_STRING_LENGTH, "0x%04lX/0x%04lX", (long)elementUsagePage, (long)elementUsage);
if (hidValueRef == NULL)
return true;
}
bool InputElementNameFromHIDElement(const IOHIDElementRef hidElementRef, char *charBuffer)
{
CFStringRef cfElementName = IOHIDElementGetName(hidElementRef);
bool propertyExists = (cfElementName != nil);
if (propertyExists)
{
return inputList;
CFStringGetCString(cfElementName, charBuffer, INPUT_HANDLER_STRING_LENGTH, kCFStringEncodingUTF8);
return propertyExists;
}
IOHIDElementRef hidElementRef = IOHIDValueGetElement(hidValueRef);
// If the name property is not present, then generate a name ourselves.
NSInteger elementUsagePage = IOHIDElementGetUsagePage(hidElementRef);
NSInteger elementUsage = IOHIDElementGetUsage(hidElementRef);
if (elementUsage != kHIDUsage_GD_Hatswitch)
if (elementUsage == kHIDUsage_GD_Hatswitch)
{
return inputList;
strncpy(charBuffer, "Hatswitch", INPUT_HANDLER_STRING_LENGTH);
propertyExists = true;
return propertyExists;
}
inputList.resize(8);
NSInteger logicalMax = IOHIDElementGetLogicalMax(hidElementRef);
NSInteger logicalValue = IOHIDValueGetIntegerValue(hidValueRef);
bool onState = true;
bool offState = false;
char elementCodeFourWay[4][256];
for (size_t i = 0; i < 4; i++)
else if (elementUsagePage == kHIDPage_Button)
{
snprintf(elementCodeFourWay[i], 256, "0x%04lX/0x%04lX/%d-FourDirection", (long)elementUsagePage, (long)elementUsage, (unsigned int)i);
snprintf(charBuffer, INPUT_HANDLER_STRING_LENGTH, "Button %li", (long)elementUsage);
propertyExists = true;
return propertyExists;
}
const char *elementNameFourWay[4] = {
"Hatswitch - Up",
"Hatswitch - Right",
"Hatswitch - Down",
"Hatswitch - Left" };
char elementCodeEightWay[8][256];
for (size_t i = 0; i < 8; i++)
else if (elementUsagePage == kHIDPage_VendorDefinedStart)
{
snprintf(elementCodeEightWay[i], 256, "0x%04lX/0x%04lX/%d-EightDirection", (long)elementUsagePage, (long)elementUsage, (unsigned int)i);
snprintf(charBuffer, INPUT_HANDLER_STRING_LENGTH, "VendorDefined %li", (long)elementUsage);
propertyExists = true;
return propertyExists;
}
const char *elementNameEightWay[8] = {
"Hatswitch - Up",
"Hatswitch - Up/Right",
"Hatswitch - Right",
"Hatswitch - Down/Right",
"Hatswitch - Down",
"Hatswitch - Down/Left",
"Hatswitch - Left",
"Hatswitch - Up/Left" };
if (logicalMax == 3)
else
{
for (size_t i = 0; i <= (size_t)logicalMax; i++)
// Only look up the HID Usage Table as a last resort, since this can be relatively slow.
NSDictionary *elementUsagePageDict = (NSDictionary *)[hidUsageTable valueForKey:[NSString stringWithFormat:@"0x%04lX", (long)elementUsagePage]];
NSString *elementNameLookup = (NSString *)[elementUsagePageDict valueForKey:[NSString stringWithFormat:@"0x%04lX", (long)elementUsage]];
propertyExists = (elementNameLookup != nil);
if (propertyExists)
{
inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeFourWay[i], elementNameFourWay[i], (i == (size_t)logicalValue) ? &onState : &offState));
}
}
else if (logicalMax == 7)
{
if (useEightDirection)
{
for (size_t i = 0; i <= (size_t)logicalMax; i++)
{
inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[i], elementNameEightWay[i], (i == (size_t)logicalValue) ? &onState : &offState));
}
}
else
{
switch (logicalValue)
{
case 0:
inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[0], elementNameEightWay[0], &onState));
inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[2], elementNameEightWay[2], &offState));
inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[4], elementNameEightWay[4], &offState));
inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[6], elementNameEightWay[6], &offState));
break;
case 1:
inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[0], elementNameEightWay[0], &onState));
inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[2], elementNameEightWay[2], &onState));
inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[4], elementNameEightWay[4], &offState));
inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[6], elementNameEightWay[6], &offState));
break;
case 2:
inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[0], elementNameEightWay[0], &offState));
inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[2], elementNameEightWay[2], &onState));
inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[4], elementNameEightWay[4], &offState));
inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[6], elementNameEightWay[6], &offState));
break;
case 3:
inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[0], elementNameEightWay[0], &offState));
inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[2], elementNameEightWay[2], &onState));
inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[4], elementNameEightWay[4], &onState));
inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[6], elementNameEightWay[6], &offState));
break;
case 4:
inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[0], elementNameEightWay[0], &offState));
inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[2], elementNameEightWay[2], &offState));
inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[4], elementNameEightWay[4], &onState));
inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[6], elementNameEightWay[6], &offState));
break;
case 5:
inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[0], elementNameEightWay[0], &offState));
inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[2], elementNameEightWay[2], &offState));
inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[4], elementNameEightWay[4], &onState));
inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[6], elementNameEightWay[6], &onState));
break;
case 6:
inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[0], elementNameEightWay[0], &offState));
inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[2], elementNameEightWay[2], &offState));
inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[4], elementNameEightWay[4], &offState));
inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[6], elementNameEightWay[6], &onState));
break;
case 7:
inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[0], elementNameEightWay[0], &onState));
inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[2], elementNameEightWay[2], &offState));
inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[4], elementNameEightWay[4], &offState));
inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[6], elementNameEightWay[6], &onState));
break;
default:
inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[0], elementNameEightWay[0], &offState));
inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[2], elementNameEightWay[2], &offState));
inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[4], elementNameEightWay[4], &offState));
inputList.push_back(InputAttributesOfHIDValue(hidValueRef, elementCodeEightWay[6], elementNameEightWay[6], &offState));
break;
}
strncpy(charBuffer, [elementNameLookup cStringUsingEncoding:NSUTF8StringEncoding], INPUT_HANDLER_STRING_LENGTH);
return propertyExists;
}
}
return inputList;
return propertyExists;
}
bool GetOnStateFromHIDValueRef(IOHIDValueRef hidValueRef)
{
bool onState = false;
if (hidValueRef == nil)
{
return onState;
}
const IOHIDElementRef hidElementRef = IOHIDValueGetElement(hidValueRef);
const NSInteger logicalValue = IOHIDValueGetIntegerValue(hidValueRef);
const NSInteger logicalMin = IOHIDElementGetLogicalMin(hidElementRef);
const NSInteger logicalMax = IOHIDElementGetLogicalMax(hidElementRef);
const NSInteger lowerThreshold = ((logicalMax - logicalMin) / 4) + logicalMin;
const NSInteger upperThreshold = (((logicalMax - logicalMin) * 3) / 4) + logicalMin;
const NSInteger elementType = IOHIDElementGetType(hidElementRef);
switch (elementType)
{
case kIOHIDElementTypeInput_Misc:
{
if ( (logicalMin == 0 && logicalMax == 1 && logicalValue == 1) ||
(logicalValue <= lowerThreshold || logicalValue >= upperThreshold) )
{
onState = true;
}
break;
}
case kIOHIDElementTypeInput_Button:
{
if (logicalValue == 1)
{
onState = true;
}
break;
}
case kIOHIDElementTypeInput_Axis:
{
if ( (logicalMin == 0 && logicalMax == 1 && logicalValue == 1) ||
(logicalValue <= lowerThreshold || logicalValue >= upperThreshold) )
{
onState = true;
}
break;
}
default:
break;
}
return onState;
}
void InputDeviceCodeFromHIDDevice(const IOHIDDeviceRef hidDeviceRef, char *charBuffer)
bool InputDeviceCodeFromHIDDevice(const IOHIDDeviceRef hidDeviceRef, char *charBuffer)
{
CFNumberRef cfVendorIDNumber = (CFNumberRef)IOHIDDeviceGetProperty(hidDeviceRef, CFSTR(kIOHIDVendorIDKey));
SInt32 vendorID = 0;
@ -781,19 +742,25 @@ void InputDeviceCodeFromHIDDevice(const IOHIDDeviceRef hidDeviceRef, char *charB
CFStringGetCString(cfDeviceCode, cfDeviceCodeBuf, 256, kCFStringEncodingUTF8);
snprintf(charBuffer, INPUT_HANDLER_STRING_LENGTH, "%d/%d/%s", (int)vendorID, (int)productID, cfDeviceCodeBuf);
}
return true;
}
void InputDeviceNameFromHIDDevice(const IOHIDDeviceRef hidDeviceRef, char *charBuffer, const char *altName)
bool InputDeviceNameFromHIDDevice(const IOHIDDeviceRef hidDeviceRef, char *charBuffer)
{
CFStringRef cfDeviceName = (CFStringRef)IOHIDDeviceGetProperty(hidDeviceRef, CFSTR(kIOHIDProductKey));
if (cfDeviceName == nil)
{
strncpy(charBuffer, (altName != NULL) ? altName : "Unknown Device", INPUT_HANDLER_STRING_LENGTH);
}
else
bool propertyExists = (cfDeviceName != nil);
if (propertyExists)
{
CFStringGetCString(cfDeviceName, charBuffer, INPUT_HANDLER_STRING_LENGTH, kCFStringEncodingUTF8);
}
else
{
strncpy(charBuffer, "Unknown Device", INPUT_HANDLER_STRING_LENGTH);
}
return propertyExists;
}
size_t ClearHIDQueue(const IOHIDQueueRef hidQueue)
@ -837,7 +804,7 @@ void HandleQueueValueAvailableCallback(void *inContext, IOReturn inResult, void
if (target != nil)
{
NSAutoreleasePool *tempPool = [[NSAutoreleasePool alloc] init];
[[hidManager target] handleHIDQueue:hidQueue];
[[hidManager target] handleHIDQueue:hidQueue hidManager:hidManager];
[tempPool release];
}
else
@ -1162,9 +1129,9 @@ static std::tr1::unordered_map<unsigned short, std::string> keyboardNameTable; /
CommandAttributes cmdPianoHighC = NewCommandAttributesForDSControl("Piano: High C", DSControllerState_Piano_HighC);
CommandAttributes cmdPaddle = NewCommandAttributesForDSControl("Paddle", DSControllerState_Paddle);
cmdPaddle.useInputForScalar = false;
cmdPaddle.allowAnalogInput = true;
cmdPaddle.intValue[1] = 0;
cmdPaddle.floatValue[0] = 0.0f;
cmdPaddle.floatValue[0] = 10.0f;
CommandAttributes cmdLoadEmuSaveStateSlot = NewCommandAttributesForSelector("Load State Slot", commandSelector["Load State Slot"]);
CommandAttributes cmdSaveEmuSaveStateSlot = NewCommandAttributesForSelector("Save State Slot", commandSelector["Save State Slot"]);
@ -1373,6 +1340,7 @@ static std::tr1::unordered_map<unsigned short, std::string> keyboardNameTable; /
[NSString stringWithCString:inputAttr->elementCode encoding:NSUTF8StringEncoding],
[NSString stringWithCString:inputAttr->elementName encoding:NSUTF8StringEncoding]);
[deviceInfo setValue:[NSNumber numberWithBool:(cmdAttr->allowAnalogInput) ? inputAttr->isAnalog : NO] forKey:@"isInputAnalog"];
[self addMappingUsingDeviceInfoDictionary:deviceInfo commandAttributes:cmdAttr];
}
@ -1740,22 +1708,23 @@ static std::tr1::unordered_map<unsigned short, std::string> keyboardNameTable; /
}
else if (strncmp(commandTag, "Paddle", INPUT_HANDLER_STRING_LENGTH) == 0)
{
const BOOL useInputForScalar = [(NSNumber *)[deviceInfo valueForKey:@"useInputForScalar"] boolValue];
const BOOL isInputAnalog = [(NSNumber *)[deviceInfo valueForKey:@"isInputAnalog"] boolValue];
if (useInputForScalar)
if (isInputAnalog)
{
inputSummary = @"Direct Control";
const float paddleSensitivity = [(NSNumber *)[deviceInfo valueForKey:@"floatValue0"] floatValue];
inputSummary = [NSString stringWithFormat:@"Paddle Sensitivity: %1.1f", paddleSensitivity];
}
else
{
const NSInteger paddleRelativeAdjustment = [(NSNumber *)[deviceInfo valueForKey:@"intValue1"] integerValue];
if (paddleRelativeAdjustment > 0)
const NSInteger paddleAdjust = [(NSNumber *)[deviceInfo valueForKey:@"intValue1"] integerValue];
if (paddleAdjust > 0)
{
inputSummary = [NSString stringWithFormat:@"Paddle Adjust: +%ld", (long)paddleRelativeAdjustment];
inputSummary = [NSString stringWithFormat:@"Paddle Adjust: +%ld", (long)paddleAdjust];
}
else
{
inputSummary = [NSString stringWithFormat:@"Paddle Adjust: %ld", (long)paddleRelativeAdjustment];
inputSummary = [NSString stringWithFormat:@"Paddle Adjust: %ld", (long)paddleAdjust];
}
}
}
@ -1958,6 +1927,7 @@ CommandAttributes NewDefaultCommandAttributes(const char *commandTag)
cmdAttr.useInputForFloatCoord = false;
cmdAttr.useInputForScalar = false;
cmdAttr.useInputForSender = false;
cmdAttr.allowAnalogInput = false;
return cmdAttr;
}
@ -2001,6 +1971,7 @@ void UpdateCommandAttributesWithDeviceInfoDictionary(CommandAttributes *cmdAttr,
NSNumber *useInputForFloatCoord = (NSNumber *)[deviceInfo valueForKey:@"useInputForFloatCoord"];
NSNumber *useInputForScalar = (NSNumber *)[deviceInfo valueForKey:@"useInputForScalar"];
NSNumber *useInputForSender = (NSNumber *)[deviceInfo valueForKey:@"useInputForSender"];
NSNumber *isInputAnalog = (NSNumber *)[deviceInfo valueForKey:@"isInputAnalog"];
if (intValue0 != nil) cmdAttr->intValue[0] = [intValue0 intValue];
if (intValue1 != nil) cmdAttr->intValue[1] = [intValue1 intValue];
@ -2014,6 +1985,7 @@ void UpdateCommandAttributesWithDeviceInfoDictionary(CommandAttributes *cmdAttr,
if (useInputForFloatCoord != nil) cmdAttr->useInputForFloatCoord = [useInputForFloatCoord boolValue];
if (useInputForScalar != nil) cmdAttr->useInputForScalar = [useInputForScalar boolValue];
if (useInputForSender != nil) cmdAttr->useInputForSender = [useInputForSender boolValue];
if (isInputAnalog != nil) cmdAttr->allowAnalogInput = [isInputAnalog boolValue];
cmdAttr->object[0] = object0;
cmdAttr->object[1] = object1;
@ -2043,7 +2015,7 @@ NSMutableDictionary* DeviceInfoDictionaryWithCommandAttributes(const CommandAttr
deviceName, @"deviceName",
elementCode, @"elementCode",
elementName, @"elementName",
[NSNumber numberWithBool:NO], @"isElementAnalog",
[NSNumber numberWithBool:cmdAttr->allowAnalogInput], @"isInputAnalog",
deviceInfoSummary, @"deviceInfoSummary",
@"", @"inputSettingsSummary",
[NSNumber numberWithInt:cmdAttr->intValue[0]], @"intValue0",
@ -2069,7 +2041,7 @@ NSMutableDictionary* DeviceInfoDictionaryWithCommandAttributes(const CommandAttr
return newDeviceInfo;
}
InputAttributesList InputManagerEncodeHIDQueue(const IOHIDQueueRef hidQueue)
InputAttributesList InputManagerEncodeHIDQueue(const IOHIDQueueRef hidQueue, InputManager *inputManager, bool forceDigitalInput)
{
InputAttributesList inputList;
if (hidQueue == nil)
@ -2084,21 +2056,11 @@ InputAttributesList InputManagerEncodeHIDQueue(const IOHIDQueueRef hidQueue)
{
break;
}
InputAttributesList hidInputList = InputListFromHatSwitchValue(hidValueRef, false);
if (hidInputList.empty())
{
hidInputList = InputListFromHIDValue(hidValueRef);
}
InputAttributesList hidInputList = InputListFromHIDValue(hidValueRef, inputManager, forceDigitalInput);
const size_t hidInputCount = hidInputList.size();
for (size_t i = 0; i < hidInputCount; i++)
{
if (hidInputList[i].deviceCode[0] == '\0' || hidInputList[i].elementCode[0] == '\0')
{
continue;
}
inputList.push_back(hidInputList[i]);
}
@ -2125,6 +2087,7 @@ InputAttributes InputManagerEncodeKeyboardInput(const unsigned short keyCode, BO
snprintf(inputAttr.elementCode, INPUT_HANDLER_STRING_LENGTH, "%d", keyCode);
strncpy(inputAttr.elementName, (elementName.empty()) ? inputAttr.elementCode : elementName.c_str(), INPUT_HANDLER_STRING_LENGTH);
inputAttr.isAnalog = false;
inputAttr.state = (keyPressed) ? INPUT_ATTRIBUTE_STATE_ON : INPUT_ATTRIBUTE_STATE_OFF;
inputAttr.intCoordX = 0;
inputAttr.intCoordY = 0;
@ -2162,6 +2125,7 @@ InputAttributes InputManagerEncodeMouseButtonInput(const NSInteger buttonNumber,
break;
}
inputAttr.isAnalog = false;
inputAttr.state = (buttonPressed) ? INPUT_ATTRIBUTE_STATE_ON : INPUT_ATTRIBUTE_STATE_OFF;
inputAttr.intCoordX = (int32_t)touchLoc.x;
inputAttr.intCoordY = (int32_t)touchLoc.y;
@ -2181,6 +2145,7 @@ InputAttributes InputManagerEncodeIBAction(const SEL theSelector, id sender)
strncpy(inputAttr.elementCode, sel_getName(theSelector), INPUT_HANDLER_STRING_LENGTH);
strncpy(inputAttr.elementName, inputAttr.elementCode, INPUT_HANDLER_STRING_LENGTH);
inputAttr.isAnalog = false;
inputAttr.state = INPUT_ATTRIBUTE_STATE_ON;
inputAttr.intCoordX = 0;
inputAttr.intCoordY = 0;

View File

@ -130,7 +130,5 @@
#pragma mark -
#pragma mark Paddle
- (void) setPaddleDirectWithScalar:(float)scalar;
- (void) setPaddleRelativeWithInteger:(NSInteger)value;
@end

View File

@ -664,29 +664,6 @@
#pragma mark -
#pragma mark Paddle
- (void) setPaddleDirectWithScalar:(float)scalar
{
// Clamp the input value.
if (scalar < -1.0f)
{
scalar = -1.0f;
}
if (scalar > 1.0f)
{
scalar = 1.0f;
}
// Normalize the input value for the paddle.
const float paddleValue = 256.0f * scalar;
[[self deviceManager] setPaddleValue:(UInt16)paddleValue];
}
- (void) setPaddleRelativeWithInteger:(NSInteger)value
{
NSInteger paddleValue = [[self deviceManager] paddleValue] + value;
[[self deviceManager] setPaddleValue:(UInt16)paddleValue];
}
#pragma mark -
#pragma mark NSTableViewDelegate Protocol

View File

@ -416,35 +416,33 @@
}
#pragma mark InputHIDManagerTarget Protocol
- (BOOL) handleHIDQueue:(IOHIDQueueRef)hidQueue
- (BOOL) handleHIDQueue:(IOHIDQueueRef)hidQueue hidManager:(InputHIDManager *)hidManager
{
BOOL isHandled = NO;
NSString *cmdTagTarget = [self configInputTargetID];
if ([self configInputTargetID] == nil)
if (cmdTagTarget == nil)
{
ClearHIDQueue(hidQueue);
return isHandled;
}
InputAttributesList inputList = InputManagerEncodeHIDQueue(hidQueue);
CommandAttributes cmdAttr = [[hidManager inputManager] defaultCommandAttributesForCommandTag:[cmdTagTarget cStringUsingEncoding:NSUTF8StringEncoding]];
bool forceDigitalInput = !cmdAttr.allowAnalogInput;
InputAttributesList inputList = InputManagerEncodeHIDQueue(hidQueue, [hidManager inputManager], forceDigitalInput);
const size_t inputCount = inputList.size();
for (size_t i = 0; i < inputCount; i++)
{
const InputAttributes &inputAttr = inputList[i];
char inputKey[INPUT_HANDLER_STRING_LENGTH*2];
strlcpy(inputKey, inputAttr.deviceCode, INPUT_HANDLER_STRING_LENGTH*2);
strlcat(inputKey, ":", INPUT_HANDLER_STRING_LENGTH*2);
strlcat(inputKey, inputAttr.elementCode, INPUT_HANDLER_STRING_LENGTH*2);
NSString *inputKeyStr = [NSString stringWithCString:inputKey encoding:NSUTF8StringEncoding];
NSDate *inputOnDate = [configInputList valueForKey:inputKeyStr];
NSString *inputKey = [NSString stringWithFormat:@"%s:%s", inputAttr.deviceCode, inputAttr.elementCode];
NSDate *inputOnDate = [configInputList valueForKey:inputKey];
if (inputAttr.state == INPUT_ATTRIBUTE_STATE_ON)
{
if (inputOnDate == nil)
{
[configInputList setValue:[NSDate date] forKey:inputKeyStr];
[configInputList setValue:[NSDate date] forKey:inputKey];
}
}
else
@ -454,11 +452,11 @@
if (([inputOnDate timeIntervalSinceNow] * -1.0) < INPUT_HOLD_TIME)
{
// If the button isn't held for at least INPUT_HOLD_TIME seconds, then reject the input.
[configInputList setValue:nil forKey:inputKeyStr];
[configInputList setValue:nil forKey:inputKey];
}
else
{
isHandled = [self addMappingUsingInputAttributes:&inputAttr commandTag:[self configInputTargetID]];
isHandled = [self addMappingUsingInputAttributes:&inputAttr commandTag:cmdTagTarget];
break;
}
}

View File

@ -149,6 +149,9 @@ extern ADDON_CFLASH_MODE CFlash_Mode;
extern std::string CFlash_Path;
inline bool CFlash_IsUsingPath() { return CFlash_Mode==ADDON_CFLASH_MODE_Path || CFlash_Mode==ADDON_CFLASH_MODE_RomPath; }
u16 Paddle_GetValue();
void Paddle_SetValue(u16 theValue);
extern void guitarGrip_setKey(bool green, bool red, bool yellow, bool blue); // Guitar grip keys
extern void piano_setKey(bool c, bool cs, bool d, bool ds, bool e, bool f, bool fs, bool g, bool gs, bool a, bool as, bool b, bool hic); //piano keys
#endif //__SLOT_H__