From 9e1fcf40319bf61250b0fbe5bf1c5c85ca44eb8f Mon Sep 17 00:00:00 2001
From: Yoshi Sugawara <yoshi.sugawara@gmail.com>
Date: Wed, 5 Jun 2019 06:20:51 -1000
Subject: [PATCH 1/2] iOS: Support L3/R3 in iOS 12.1, Options buttons in
 mfi/PS4/XBox One controllers in iOS 13

---
 input/drivers_joypad/mfi_joypad.m             | 135 +++++++++++-------
 .../RetroArch_iOS11.xcodeproj/project.pbxproj |   1 +
 2 files changed, 87 insertions(+), 49 deletions(-)

diff --git a/input/drivers_joypad/mfi_joypad.m b/input/drivers_joypad/mfi_joypad.m
index ae9ee26948..061832bf77 100644
--- a/input/drivers_joypad/mfi_joypad.m
+++ b/input/drivers_joypad/mfi_joypad.m
@@ -65,12 +65,18 @@ static void apple_gamecontroller_joypad_poll_internal(GCController *controller)
     buttons            = &mfi_buttons[slot];
 
     /* retain the values from the paused controller handler and pass them through */
-    pause              = *buttons & (1 << RETRO_DEVICE_ID_JOYPAD_START);
-    select             = *buttons & (1 << RETRO_DEVICE_ID_JOYPAD_SELECT);
-    l3                 = *buttons & ( 1 << RETRO_DEVICE_ID_JOYPAD_L3 );
-    r3                 = *buttons & ( 1 << RETRO_DEVICE_ID_JOYPAD_R3 );
-    *buttons           = 0 | pause | select | l3 | r3;
-
+    if (@available(iOS 13, *)) {
+        // The menu button can be pressed/unpressed like any other button in iOS 13
+        // so no need to passthrough anything
+        *buttons = 0;
+    } else {
+        // Use the paused controller handler for iOS versions below 13
+        pause              = *buttons & (1 << RETRO_DEVICE_ID_JOYPAD_START);
+        select             = *buttons & (1 << RETRO_DEVICE_ID_JOYPAD_SELECT);
+        l3                 = *buttons & ( 1 << RETRO_DEVICE_ID_JOYPAD_L3 );
+        r3                 = *buttons & ( 1 << RETRO_DEVICE_ID_JOYPAD_R3 );
+        *buttons           = 0 | pause | select | l3 | r3;
+    }
     memset(mfi_axes[slot], 0, sizeof(mfi_axes[0]));
 
     if (controller.extendedGamepad)
@@ -89,6 +95,31 @@ static void apple_gamecontroller_joypad_poll_internal(GCController *controller)
         *buttons             |= gp.rightShoulder.pressed   ? (1 << RETRO_DEVICE_ID_JOYPAD_R)     : 0;
         *buttons             |= gp.leftTrigger.pressed     ? (1 << RETRO_DEVICE_ID_JOYPAD_L2)    : 0;
         *buttons             |= gp.rightTrigger.pressed    ? (1 << RETRO_DEVICE_ID_JOYPAD_R2)    : 0;
+        if (@available(iOS 12.1, *)) {
+            *buttons         |= gp.leftThumbstickButton.pressed ? (1 << RETRO_DEVICE_ID_JOYPAD_L3) : 0;
+            *buttons         |= gp.rightThumbstickButton.pressed ? (1 << RETRO_DEVICE_ID_JOYPAD_R3) : 0;
+        }
+        if (@available(iOS 13, *)) {
+            // Support "Options" button present in PS4 / XBox One controllers
+            *buttons         |= gp.buttonOptions.pressed ? (1 << RETRO_DEVICE_ID_JOYPAD_SELECT) : 0;
+            
+            // Support buttons that aren't supported by older mFi controller via "hotkey" combinations:
+            //
+            // LS + Menu => Select
+            // LT + Menu => L3
+            // RT + Menu => R3
+            if ( gp.buttonMenu.pressed ) {
+                if ( gp.leftShoulder.pressed ) {
+                    *buttons     |= 1 << RETRO_DEVICE_ID_JOYPAD_SELECT;
+                } else if ( gp.leftTrigger.pressed ) {
+                    *buttons     |= 1 << RETRO_DEVICE_ID_JOYPAD_L3;
+                } else if ( gp.rightTrigger.pressed ) {
+                    *buttons     |= 1 << RETRO_DEVICE_ID_JOYPAD_R3;
+                } else {
+                    *buttons     |= 1 << RETRO_DEVICE_ID_JOYPAD_START;
+                }
+            }
+        }
         mfi_axes[slot][0]     = gp.leftThumbstick.xAxis.value * 32767.0f;
         mfi_axes[slot][1]     = gp.leftThumbstick.yAxis.value * 32767.0f;
         mfi_axes[slot][2]     = gp.rightThumbstick.xAxis.value * 32767.0f;
@@ -128,51 +159,57 @@ static void apple_gamecontroller_joypad_register(GCGamepad *gamepad)
         apple_gamecontroller_joypad_poll_internal(updateGamepad.controller);
     };
 
-    gamepad.controller.controllerPausedHandler = ^(GCController *controller)
-    {
-        uint32_t slot      = (uint32_t)controller.playerIndex;
-
-        // Support buttons that aren't supported by the mFi controller via "hotkey" combinations:
-        //
-        // LS + Menu => Select
-        // LT + Menu => L3
-        // RT + Menu => R3
-        // Note that these are just button presses, and it does not simulate holding down the button
-        if ( controller.gamepad.leftShoulder.pressed || controller.extendedGamepad.leftShoulder.pressed ) {
-            mfi_buttons[slot] &= ~(1 << RETRO_DEVICE_ID_JOYPAD_START);
-            mfi_buttons[slot] &= ~(1 << RETRO_DEVICE_ID_JOYPAD_L);
-            mfi_buttons[slot] |= (1 << RETRO_DEVICE_ID_JOYPAD_SELECT);
+    if (@available(iOS 13, *)) {
+        // controllerPausedHandler is deprecated in favor of being able to deal with the menu
+        // button as any other button
+        return;
+    } else {
+        gamepad.controller.controllerPausedHandler = ^(GCController *controller)
+        {
+            uint32_t slot      = (uint32_t)controller.playerIndex;
+            
+            // Support buttons that aren't supported by the mFi controller via "hotkey" combinations:
+            //
+            // LS + Menu => Select
+            // LT + Menu => L3
+            // RT + Menu => R3
+            // Note that these are just button presses, and it does not simulate holding down the button
+            if ( controller.gamepad.leftShoulder.pressed || controller.extendedGamepad.leftShoulder.pressed ) {
+                mfi_buttons[slot] &= ~(1 << RETRO_DEVICE_ID_JOYPAD_START);
+                mfi_buttons[slot] &= ~(1 << RETRO_DEVICE_ID_JOYPAD_L);
+                mfi_buttons[slot] |= (1 << RETRO_DEVICE_ID_JOYPAD_SELECT);
+                dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
+                    mfi_buttons[slot] &= ~(1 << RETRO_DEVICE_ID_JOYPAD_SELECT);
+                });
+                return;
+            }
+            if ( controller.extendedGamepad.leftTrigger.pressed ) {
+                mfi_buttons[slot] &= ~(1 << RETRO_DEVICE_ID_JOYPAD_L2);
+                mfi_buttons[slot] &= ~(1 << RETRO_DEVICE_ID_JOYPAD_START);
+                mfi_buttons[slot] |= (1 << RETRO_DEVICE_ID_JOYPAD_L3);
+                dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
+                    mfi_buttons[slot] &= ~(1 << RETRO_DEVICE_ID_JOYPAD_L3);
+                });
+                return;
+            }
+            if ( controller.extendedGamepad.rightTrigger.pressed ) {
+                mfi_buttons[slot] &= ~(1 << RETRO_DEVICE_ID_JOYPAD_R2);
+                mfi_buttons[slot] &= ~(1 << RETRO_DEVICE_ID_JOYPAD_START);
+                mfi_buttons[slot] |= (1 << RETRO_DEVICE_ID_JOYPAD_R3);
+                dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
+                    mfi_buttons[slot] &= ~(1 << RETRO_DEVICE_ID_JOYPAD_R3);
+                });
+                return;
+            }
+            
+            mfi_buttons[slot] |= (1 << RETRO_DEVICE_ID_JOYPAD_START);
+            
             dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
-                mfi_buttons[slot] &= ~(1 << RETRO_DEVICE_ID_JOYPAD_SELECT);
+                mfi_buttons[slot] &= ~(1 << RETRO_DEVICE_ID_JOYPAD_START);
             });
-            return;
-        }
-        if ( controller.extendedGamepad.leftTrigger.pressed ) {
-            mfi_buttons[slot] &= ~(1 << RETRO_DEVICE_ID_JOYPAD_L2);
-            mfi_buttons[slot] &= ~(1 << RETRO_DEVICE_ID_JOYPAD_START);
-            mfi_buttons[slot] |= (1 << RETRO_DEVICE_ID_JOYPAD_L3);
-            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
-                mfi_buttons[slot] &= ~(1 << RETRO_DEVICE_ID_JOYPAD_L3);
-            });
-            return;
-        }
-        if ( controller.extendedGamepad.rightTrigger.pressed ) {
-            mfi_buttons[slot] &= ~(1 << RETRO_DEVICE_ID_JOYPAD_R2);
-            mfi_buttons[slot] &= ~(1 << RETRO_DEVICE_ID_JOYPAD_START);
-            mfi_buttons[slot] |= (1 << RETRO_DEVICE_ID_JOYPAD_R3);
-            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
-                mfi_buttons[slot] &= ~(1 << RETRO_DEVICE_ID_JOYPAD_R3);
-            });
-            return;
-        }
-
-        mfi_buttons[slot] |= (1 << RETRO_DEVICE_ID_JOYPAD_START);
-
-        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
-            mfi_buttons[slot] &= ~(1 << RETRO_DEVICE_ID_JOYPAD_START);
-        });
-
-    };
+            
+        };
+    }
 }
 
 static void apple_gamecontroller_joypad_connect(GCController *controller)
diff --git a/pkg/apple/RetroArch_iOS11.xcodeproj/project.pbxproj b/pkg/apple/RetroArch_iOS11.xcodeproj/project.pbxproj
index a456aaab2b..174a7b3b26 100644
--- a/pkg/apple/RetroArch_iOS11.xcodeproj/project.pbxproj
+++ b/pkg/apple/RetroArch_iOS11.xcodeproj/project.pbxproj
@@ -418,6 +418,7 @@
 			developmentRegion = English;
 			hasScannedForEncodings = 0;
 			knownRegions = (
+				English,
 				en,
 				Base,
 			);

From 222d3297d2cb41f1b1706b02c79c26f05e9df410 Mon Sep 17 00:00:00 2001
From: Yoshi Sugawara <yoshi.sugawara@gmail.com>
Date: Wed, 5 Jun 2019 06:50:02 -1000
Subject: [PATCH 2/2] use preprocessor macros to support compiling using Xcode
 11/iOS 13 and older versions of Xcode

---
 input/drivers_joypad/mfi_joypad.m | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/input/drivers_joypad/mfi_joypad.m b/input/drivers_joypad/mfi_joypad.m
index 061832bf77..25fb57dccc 100644
--- a/input/drivers_joypad/mfi_joypad.m
+++ b/input/drivers_joypad/mfi_joypad.m
@@ -95,10 +95,14 @@ static void apple_gamecontroller_joypad_poll_internal(GCController *controller)
         *buttons             |= gp.rightShoulder.pressed   ? (1 << RETRO_DEVICE_ID_JOYPAD_R)     : 0;
         *buttons             |= gp.leftTrigger.pressed     ? (1 << RETRO_DEVICE_ID_JOYPAD_L2)    : 0;
         *buttons             |= gp.rightTrigger.pressed    ? (1 << RETRO_DEVICE_ID_JOYPAD_R2)    : 0;
+#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 120100 || __TV_OS_VERSION_MAX_ALLOWED >= 120100
         if (@available(iOS 12.1, *)) {
             *buttons         |= gp.leftThumbstickButton.pressed ? (1 << RETRO_DEVICE_ID_JOYPAD_L3) : 0;
             *buttons         |= gp.rightThumbstickButton.pressed ? (1 << RETRO_DEVICE_ID_JOYPAD_R3) : 0;
         }
+#endif
+
+#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000 || __TV_OS_VERSION_MAX_ALLOWED >= 130000
         if (@available(iOS 13, *)) {
             // Support "Options" button present in PS4 / XBox One controllers
             *buttons         |= gp.buttonOptions.pressed ? (1 << RETRO_DEVICE_ID_JOYPAD_SELECT) : 0;
@@ -120,6 +124,8 @@ static void apple_gamecontroller_joypad_poll_internal(GCController *controller)
                 }
             }
         }
+#endif
+
         mfi_axes[slot][0]     = gp.leftThumbstick.xAxis.value * 32767.0f;
         mfi_axes[slot][1]     = gp.leftThumbstick.yAxis.value * 32767.0f;
         mfi_axes[slot][2]     = gp.rightThumbstick.xAxis.value * 32767.0f;