git.y1.nz

SameBoy

Accurate GB/GBC emulator
download: https://git.y1.nz/archives/sameboy.tar.gz
README | Files | Log | Refs | LICENSE

commit 690a263648238f8b4ec4d277329f792c671c0edb
parent 0ff882f3bc384ea7e1ad0bcde4d772a3e02e6f85
Author: Lior Halphon <LIJI32@gmail.com>
Date:   Thu, 29 Jul 2021 22:43:55 +0300

Major improvements to JoyKit, fixing Xbox and 8BitDo controllers as well as analog mappings in PS controllers in some situations

Diffstat:
MCocoa/GBPreferencesWindow.m24++++++++----------------
MCocoa/Preferences.xib4++--
MJoyKit/ControllerConfiguration.inc8++++----
MJoyKit/JOYAxis.h7+++++++
MJoyKit/JOYAxis.m45++++++++++++++++++++++++++++++++++++++++++---
MJoyKit/JOYButton.h10++++++++++
MJoyKit/JOYButton.m8+++++++-
MJoyKit/JOYController.h1-
MJoyKit/JOYController.m59++++++++++++++++++++++++++++++++++-------------------------
MJoyKit/JOYEmulatedButton.m3++-
MJoyKit/JOYHat.m2++
11 files changed, 118 insertions(+), 53 deletions(-)

diff --git a/Cocoa/GBPreferencesWindow.m b/Cocoa/GBPreferencesWindow.m @@ -491,16 +491,12 @@ [GBUnderclock] = JOYButtonUsageR1, }; - // Todo: JoyKit might need an API to match an axis to a button if (joystick_configuration_state == GBUnderclock) { + mapping[@"AnalogUnderclock"] = nil; + double max = 0; for (JOYAxis *axis in controller.axes) { - if (axis.value > 0.5 || - (axis.usage == JOYAxisUsageL1 && button.usage == JOYButtonUsageL1) || - (axis.usage == JOYAxisUsageL2 && button.usage == JOYButtonUsageL2) || - (axis.usage == JOYAxisUsageL3 && button.usage == JOYButtonUsageL3) || - (axis.usage == JOYAxisUsageR1 && button.usage == JOYButtonUsageR1) || - (axis.usage == JOYAxisUsageR2 && button.usage == JOYButtonUsageR2) || - (axis.usage == JOYAxisUsageR3 && button.usage == JOYButtonUsageR3)) { + if ((axis.value > 0.5 || (axis.equivalentButtonUsage == button.usage)) && axis.value >= max) { + max = axis.value; mapping[@"AnalogUnderclock"] = @(axis.uniqueID); break; } @@ -508,16 +504,12 @@ } if (joystick_configuration_state == GBTurbo) { + mapping[@"AnalogTurbo"] = nil; + double max = 0; for (JOYAxis *axis in controller.axes) { - if (axis.value > 0.5 || - (axis.usage == JOYAxisUsageL1 && button.usage == JOYButtonUsageL1) || - (axis.usage == JOYAxisUsageL2 && button.usage == JOYButtonUsageL2) || - (axis.usage == JOYAxisUsageL3 && button.usage == JOYButtonUsageL3) || - (axis.usage == JOYAxisUsageR1 && button.usage == JOYButtonUsageR1) || - (axis.usage == JOYAxisUsageR2 && button.usage == JOYButtonUsageR2) || - (axis.usage == JOYAxisUsageR3 && button.usage == JOYButtonUsageR3)) { + if ((axis.value > 0.5 || (axis.equivalentButtonUsage == button.usage)) && axis.value >= max) { + max = axis.value; mapping[@"AnalogTurbo"] = @(axis.uniqueID); - break; } } } diff --git a/Cocoa/Preferences.xib b/Cocoa/Preferences.xib @@ -736,9 +736,9 @@ </connections> </button> <button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="d2I-jU-sLb"> - <rect key="frame" x="195" y="13" width="72" height="32"/> + <rect key="frame" x="198" y="13" width="67" height="32"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> - <buttonCell key="cell" type="push" title="Clear" bezelStyle="rounded" alignment="center" enabled="NO" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="sug-xy-tbw"> + <buttonCell key="cell" type="push" title="Skip" bezelStyle="rounded" alignment="center" enabled="NO" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="sug-xy-tbw"> <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/> <font key="font" metaFont="system"/> </buttonCell> diff --git a/JoyKit/ControllerConfiguration.inc b/JoyKit/ControllerConfiguration.inc @@ -4,8 +4,6 @@ hacksByManufacturer = @{ @(0x045E): @{ // Microsoft - /* Generally untested, but Microsoft goes by the book when it comes to HID report descriptors, so - it should work out of the box. The hack is only here for automatic mapping */ JOYAxisGroups: @{ @(kHIDUsage_GD_X): @(0), @@ -13,7 +11,7 @@ hacksByManufacturer = @{ @(kHIDUsage_GD_Z): @(2), @(kHIDUsage_GD_Rx): @(1), @(kHIDUsage_GD_Ry): @(1), - @(kHIDUsage_GD_Rz): @(3), + @(kHIDUsage_GD_Rz): @(2), }, JOYButtonUsageMapping: @{ @@ -37,8 +35,10 @@ hacksByManufacturer = @{ JOYAxes2DUsageMapping: @{ AXES2D(1): @(JOYAxes2DUsageLeftStick), - AXES2D(4): @(JOYAxes2DUsageRightStick), + AXES2D(3): @(JOYAxes2DUsageRightStick), }, + + JOYEmulateAxisButtons: @YES, }, @(0x054C): @{ // Sony diff --git a/JoyKit/JOYAxis.h b/JoyKit/JOYAxis.h @@ -1,4 +1,5 @@ #import <Foundation/Foundation.h> +#import "JOYButton.h" typedef enum { JOYAxisUsageNone, @@ -8,11 +9,16 @@ typedef enum { JOYAxisUsageR1, JOYAxisUsageR2, JOYAxisUsageR3, + + JOYAxisUsageSlider, + JOYAxisUsageDial, JOYAxisUsageWheel, + JOYAxisUsageRudder, JOYAxisUsageThrottle, JOYAxisUsageAccelerator, JOYAxisUsageBrake, + JOYAxisUsageNonGenericMax, JOYAxisUsageGeneric0 = 0x10000, @@ -23,6 +29,7 @@ typedef enum { + (NSString *)usageToString: (JOYAxisUsage) usage; - (uint64_t)uniqueID; - (double)value; +- (JOYButtonUsage)equivalentButtonUsage; @property JOYAxisUsage usage; @end diff --git a/JoyKit/JOYAxis.m b/JoyKit/JOYAxis.m @@ -19,6 +19,8 @@ @"Analog R1", @"Analog R2", @"Analog R3", + @"Slider", + @"Dial", @"Wheel", @"Rudder", @"Throttle", @@ -57,10 +59,23 @@ if (element.usagePage == kHIDPage_GenericDesktop) { - uint16_t usage = element.usage; - _usage = JOYAxisUsageGeneric0 + usage - kHIDUsage_GD_X + 1; + switch (element.usage) { + case kHIDUsage_GD_Slider: _usage = JOYAxisUsageSlider; break; + case kHIDUsage_GD_Dial: _usage = JOYAxisUsageDial; break; + case kHIDUsage_GD_Wheel: _usage = JOYAxisUsageWheel; break; + default: + _usage = JOYAxisUsageGeneric0 + element.usage - kHIDUsage_GD_X + 1; + break; + } + } + else if (element.usagePage == kHIDPage_Simulation) { + switch (element.usage) { + case kHIDUsage_Sim_Accelerator: _usage = JOYAxisUsageAccelerator; break; + case kHIDUsage_Sim_Brake: _usage = JOYAxisUsageBrake; break; + case kHIDUsage_Sim_Rudder: _usage = JOYAxisUsageRudder; break; + case kHIDUsage_Sim_Throttle: _usage = JOYAxisUsageThrottle; break; + } } - _min = 1.0; return self; @@ -87,4 +102,28 @@ return old != _state; } +- (JOYButtonUsage)equivalentButtonUsage +{ + if (self.usage >= JOYAxisUsageGeneric0) { + return self.usage - JOYAxisUsageGeneric0 + JOYButtonUsageGeneric0; + } + switch (self.usage) { + case JOYAxisUsageL1: return JOYButtonUsageL1; + case JOYAxisUsageL2: return JOYButtonUsageL2; + case JOYAxisUsageL3: return JOYButtonUsageL3; + case JOYAxisUsageR1: return JOYButtonUsageR1; + case JOYAxisUsageR2: return JOYButtonUsageR2; + case JOYAxisUsageR3: return JOYButtonUsageR3; + case JOYAxisUsageSlider: return JOYButtonUsageSlider; + case JOYAxisUsageDial: return JOYButtonUsageDial; + case JOYAxisUsageWheel: return JOYButtonUsageWheel; + case JOYAxisUsageRudder: return JOYButtonUsageRudder; + case JOYAxisUsageThrottle: return JOYButtonUsageThrottle; + case JOYAxisUsageAccelerator: return JOYButtonUsageAccelerator; + case JOYAxisUsageBrake: return JOYButtonUsageBrake; + default: return JOYButtonUsageNone; + } +} + + @end diff --git a/JoyKit/JOYButton.h b/JoyKit/JOYButton.h @@ -26,6 +26,16 @@ typedef enum { JOYButtonUsageDPadRight, JOYButtonUsageDPadUp, JOYButtonUsageDPadDown, + + JOYButtonUsageSlider, + JOYButtonUsageDial, + JOYButtonUsageWheel, + + JOYButtonUsageRudder, + JOYButtonUsageThrottle, + JOYButtonUsageAccelerator, + JOYButtonUsageBrake, + JOYButtonUsageNonGenericMax, JOYButtonUsageGeneric0 = 0x10000, diff --git a/JoyKit/JOYButton.m b/JoyKit/JOYButton.m @@ -1,5 +1,6 @@ #import "JOYButton.h" #import "JOYElement.h" +#import <AppKit/AppKit.h> @implementation JOYButton { @@ -80,6 +81,12 @@ case kHIDUsage_GD_SystemMainMenu: _usage = JOYButtonUsageHome; break; } } + else if (element.usagePage == kHIDPage_Consumer) { + switch (element.usage) { + case kHIDUsage_Csmr_ACHome: _usage = JOYButtonUsageHome; break; + case kHIDUsage_Csmr_ACBack: _usage = JOYButtonUsageSelect; break; + } + } return self; } @@ -98,5 +105,4 @@ } return false; } - @end diff --git a/JoyKit/JOYController.h b/JoyKit/JOYController.h @@ -4,7 +4,6 @@ #import "JOYAxes2D.h" #import "JOYHat.h" -static NSString const *JOYAxesEmulateButtonsKey = @"JOYAxesEmulateButtons"; static NSString const *JOYAxes2DEmulateButtonsKey = @"JOYAxes2DEmulateButtons"; static NSString const *JOYHatsEmulateButtonsKey = @"JOYHatsEmulateButtons"; diff --git a/JoyKit/JOYController.m b/JoyKit/JOYController.m @@ -7,6 +7,9 @@ #import "JOYEmulatedButton.h" #include <IOKit/hid/IOHIDLib.h> +#include <AppKit/AppKit.h> +extern NSTextField *globalDebugField; + #define PWM_RESOLUTION 16 static NSString const *JOYAxisGroups = @"JOYAxisGroups"; @@ -27,6 +30,7 @@ static NSString const *JOYActivationReport = @"JOYActivationReport"; static NSString const *JOYIgnoredReports = @"JOYIgnoredReports"; static NSString const *JOYIsDualShock3 = @"JOYIsDualShock3"; static NSString const *JOYIsSony = @"JOYIsSony"; +static NSString const *JOYEmulateAxisButtons = @"JOYEmulateAxisButtons"; static NSMutableDictionary<id, JOYController *> *controllers; // Physical controllers static NSMutableArray<JOYController *> *exposedControllers; // Logical controllers @@ -36,7 +40,6 @@ static NSDictionary *hacksByManufacturer = nil; static NSMutableSet<id<JOYListener>> *listeners = nil; -static bool axesEmulateButtons = false; static bool axes2DEmulateButtons = false; static bool hatsEmulateButtons = false; @@ -234,29 +237,40 @@ typedef union { return; } - if (element.usagePage == kHIDPage_Button) { + NSDictionary *axisGroups = @{ + @(kHIDUsage_GD_X): @(0), + @(kHIDUsage_GD_Y): @(0), + @(kHIDUsage_GD_Z): @(1), + @(kHIDUsage_GD_Rx): @(2), + @(kHIDUsage_GD_Ry): @(2), + @(kHIDUsage_GD_Rz): @(1), + }; + + axisGroups = _hacks[JOYAxisGroups] ?: axisGroups; + + if (element.usagePage == kHIDPage_Button || + (element.usagePage == kHIDPage_Consumer && (element.usage == kHIDUsage_Csmr_ACHome || + element.usage == kHIDUsage_Csmr_ACBack))) { button: { JOYButton *button = [[JOYButton alloc] initWithElement: element]; [_buttons setObject:button forKey:element]; - NSNumber *replacementUsage = _hacks[JOYButtonUsageMapping][@(button.usage)]; + NSNumber *replacementUsage = element.usagePage == kHIDPage_Button? _hacks[JOYButtonUsageMapping][@(button.usage)] : nil; if (replacementUsage) { button.usage = [replacementUsage unsignedIntValue]; } return; } } + else if (element.usagePage == kHIDPage_Simulation) { + switch (element.usage) { + case kHIDUsage_Sim_Accelerator: + case kHIDUsage_Sim_Brake: + case kHIDUsage_Sim_Rudder: + case kHIDUsage_Sim_Throttle: + goto single; + } + } else if (element.usagePage == kHIDPage_GenericDesktop) { - NSDictionary *axisGroups = @{ - @(kHIDUsage_GD_X): @(0), - @(kHIDUsage_GD_Y): @(0), - @(kHIDUsage_GD_Z): @(1), - @(kHIDUsage_GD_Rx): @(2), - @(kHIDUsage_GD_Ry): @(2), - @(kHIDUsage_GD_Rz): @(1), - }; - - axisGroups = _hacks[JOYAxisGroups] ?: axisGroups; - switch (element.usage) { case kHIDUsage_GD_X: case kHIDUsage_GD_Y: @@ -318,30 +332,26 @@ typedef union { }*/ break; } - single: case kHIDUsage_GD_Slider: case kHIDUsage_GD_Dial: - case kHIDUsage_GD_Wheel: { + case kHIDUsage_GD_Wheel: + { single: { JOYAxis *axis = [[JOYAxis alloc] initWithElement: element]; [_axes setObject:axis forKey:element]; - NSNumber *replacementUsage = _hacks[JOYAxisUsageMapping][@(axis.usage)]; + NSNumber *replacementUsage = element.usagePage == kHIDPage_GenericDesktop? _hacks[JOYAxisUsageMapping][@(axis.usage)] : nil; if (replacementUsage) { axis.usage = [replacementUsage unsignedIntValue]; } - if (axesEmulateButtons && axis.usage >= JOYAxisUsageL1 && axis.usage <= JOYAxisUsageR3) { + if ([_hacks[JOYEmulateAxisButtons] boolValue]) { _axisEmulatedButtons[@(axis.uniqueID)] = - [[JOYEmulatedButton alloc] initWithUsage:axis.usage - JOYAxisUsageL1 + JOYButtonUsageL1 uniqueID:axis.uniqueID]; + [[JOYEmulatedButton alloc] initWithUsage:axis.equivalentButtonUsage uniqueID:axis.uniqueID]; } - if (axesEmulateButtons && axis.usage >= JOYAxisUsageGeneric0) { - _axisEmulatedButtons[@(axis.uniqueID)] = - [[JOYEmulatedButton alloc] initWithUsage:axis.usage - JOYAxisUsageGeneric0 + JOYButtonUsageGeneric0 uniqueID:axis.uniqueID]; - } break; - } + }} case kHIDUsage_GD_DPadUp: case kHIDUsage_GD_DPadDown: case kHIDUsage_GD_DPadRight: @@ -1030,7 +1040,6 @@ typedef union { + (void)startOnRunLoop:(NSRunLoop *)runloop withOptions: (NSDictionary *)options { - axesEmulateButtons = [options[JOYAxesEmulateButtonsKey] boolValue]; axes2DEmulateButtons = [options[JOYAxes2DEmulateButtonsKey] boolValue]; hatsEmulateButtons = [options[JOYHatsEmulateButtonsKey] boolValue]; diff --git a/JoyKit/JOYEmulatedButton.m b/JoyKit/JOYEmulatedButton.m @@ -1,4 +1,5 @@ #import "JOYEmulatedButton.h" +#import <AppKit/AppKit.h> @interface JOYButton () { @@ -28,7 +29,7 @@ - (bool)updateStateFromAxis:(JOYAxis *)axis { bool old = _state; - _state = [axis value] > 0.5; + _state = [axis value] > 0.8; return _state != old; } diff --git a/JoyKit/JOYHat.m b/JoyKit/JOYHat.m @@ -1,5 +1,6 @@ #import "JOYHat.h" #import "JOYElement.h" +#import <AppKit/AppKit.h> @implementation JOYHat { @@ -27,6 +28,7 @@ if (!self) return self; _element = element; + _state = -1; return self; }

This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.