SameBoy | Accurate GB/GBC emulator |
| download: https://git.y1.nz/archives/sameboy.tar.gz | |
| README | Files | Log | Refs | LICENSE |
iOS/GCControllerGetElements.m
1 #import "GCControllerGetElements.h"
2 #import <objc/runtime.h>
3
4 static NSDictionary <NSNumber *, GCControllerElement *> *GCControllerGetElementsLegacy(GCExtendedGamepad *self)
5 {
6 if (!self) return nil;
7 NSMutableDictionary <NSNumber *, GCControllerElement *> *ret = [NSMutableDictionary dictionary];
8 if (self.dpad) ret[@(GBUsageDpad)] = self.dpad;
9 if (self.buttonA) ret[@(GBUsageButtonA)] = self.buttonA;
10 if (self.buttonB) ret[@(GBUsageButtonB)] = self.buttonB;
11 if (self.buttonX) ret[@(GBUsageButtonX)] = self.buttonX;
12 if (self.buttonY) ret[@(GBUsageButtonY)] = self.buttonY;
13 if (@available(iOS 13.0, *)) {
14 if (self.buttonMenu) ret[@(GBUsageButtonMenu)] = self.buttonMenu;
15 if (self.buttonOptions) ret[@(GBUsageButtonOptions)] = self.buttonOptions;
16 }
17 // Can't be used
18 /* if (@available(iOS 14.0, *)) {
19 if (self.buttonHome) ret[@(GBUsageButtonHome)] = self.buttonHome;
20 } */
21 if (self.leftThumbstick) ret[@(GBUsageLeftThumbstick)] = self.leftThumbstick;
22 if (self.rightThumbstick) ret[@(GBUsageRightThumbstick)] = self.rightThumbstick;
23 if (self.leftShoulder) ret[@(GBUsageLeftShoulder)] = self.leftShoulder;
24 if (self.rightShoulder) ret[@(GBUsageRightShoulder)] = self.rightShoulder;
25 if (self.leftTrigger) ret[@(GBUsageLeftTrigger)] = self.leftTrigger;
26 if (self.rightTrigger) ret[@(GBUsageRightTrigger)] = self.rightTrigger;
27 if (@available(iOS 12.1, *)) {
28 if (self.leftThumbstickButton) ret[@(GBUsageLeftThumbstickButton)] = self.leftThumbstickButton;
29 if (self.rightThumbstickButton) ret[@(GBUsageRightThumbstickButton)] = self.rightThumbstickButton;
30 }
31 return ret;
32 }
33
34 API_AVAILABLE(ios(14.0))
35 static NSDictionary <NSNumber *, GCControllerElement *> *GCControllerGetElementsModern(GCPhysicalInputProfile *self)
36 {
37 static NSDictionary * nameToUsage = nil;
38 static dispatch_once_t onceToken;
39 dispatch_once(&onceToken, ^{
40 nameToUsage = @{
41 GCInputButtonA: @(GBUsageButtonA),
42 GCInputButtonB: @(GBUsageButtonB),
43 GCInputButtonX: @(GBUsageButtonX),
44 GCInputButtonY: @(GBUsageButtonY),
45
46 GCInputLeftThumbstick: @(GBUsageLeftThumbstick),
47 GCInputRightThumbstick: @(GBUsageRightThumbstick),
48 GCInputLeftThumbstickButton: @(GBUsageLeftThumbstickButton),
49 GCInputRightThumbstickButton: @(GBUsageRightThumbstickButton),
50 GCInputLeftShoulder: @(GBUsageLeftShoulder),
51 GCInputRightShoulder: @(GBUsageRightShoulder),
52 GCInputLeftTrigger: @(GBUsageLeftTrigger),
53 GCInputRightTrigger: @(GBUsageRightTrigger),
54
55 GCInputButtonMenu: @(GBUsageButtonMenu),
56 GCInputButtonOptions: @(GBUsageButtonOptions),
57 GCInputDualShockTouchpadButton: @(GBUsageTouchpadButton),
58 };
59 });
60
61 NSArray<NSString *> *elementNames = [self.elements.allKeys sortedArrayUsingSelector:@selector(compare:)];
62
63 NSMutableDictionary <NSNumber *, GCControllerElement *> *ret = [NSMutableDictionary dictionary];
64 GBControllerUsage miscUsage = GBUsageMiscStartIndex;
65 for (NSString *name in elementNames) {
66 if ([name isEqualToString:GCInputButtonHome]) continue;
67 GCControllerElement *input = self.elements[name];
68 NSNumber *_usage = nameToUsage[name];
69 GBControllerUsage usage;
70 if (_usage) {
71 usage = _usage.unsignedIntValue;
72 // These get weird mappings by default
73 if ([self.device.vendorName isEqualToString:@"Joy-Con (L)"] ||
74 [self.device.vendorName isEqualToString:@"Joy-Con (R)"]) {
75 switch (usage) {
76 case GBUsageButtonA: usage = GBUsageButtonB; break;
77 case GBUsageButtonB: usage = GBUsageButtonY; break;
78 case GBUsageButtonX: usage = GBUsageButtonA; break;
79 case GBUsageButtonY: usage = GBUsageButtonX; break;
80 default: break;
81 }
82 }
83 }
84 else if ([input isKindOfClass:[GCControllerDirectionPad class]] && !ret[@(GBUsageDpad)]) {
85 usage = GBUsageDpad;
86 }
87 else {
88 usage = miscUsage++;
89 }
90 if ([ret.allValues containsObject:input]) {
91 NSNumber *alias = [ret allKeysForObject:input][0];
92 if (alias.unsignedIntValue >= GBUsageMiscStartIndex) {
93 [ret removeObjectForKey:alias];
94 }
95 else {
96 continue;
97 }
98 }
99 ret[@(usage)] = input;
100 }
101
102 return ret;
103 }
104
105 NSDictionary <NSNumber *, GCControllerElement *> *GCControllerGetElements(GCController *self)
106 {
107 NSDictionary <NSNumber *, GCControllerElement *> *ret = nil;
108 ret = objc_getAssociatedObject(self, GCControllerGetElements);
109 if (ret) return ret;
110 if (@available(iOS 14.0, *)) {
111 ret = GCControllerGetElementsModern(self.physicalInputProfile);
112 }
113 else {
114 ret = GCControllerGetElementsLegacy(self.extendedGamepad);
115 }
116 objc_setAssociatedObject(self, GCControllerGetElements, ret, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
117 return ret;
118 }
This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.