[Scummvm-git-logs] scummvm branch-2-7 -> 50c315e3167253e4bc604226646f9038bbc23158

criezy noreply at scummvm.org
Thu Apr 27 21:33:16 UTC 2023


This automated email contains information about 26 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
4d774e2fc3 TVOS: Add Apple TV OS as a separate dist
a836661511 CREATE_PROJECT: Add Apple TV OS XCode target
0a9239ad7c IOS7: Put iOS specific code within platform specific macros
255852c8e3 IOS7: Implement support for Apple TV remote
694345d8f8 IOS7: Implement keyboard support for Apple TV OS
1ff4fe8149 IOS7: Forward backward key presses when textField is empty
a7c2a8b2d9 IOS7: Replace UIAlertView with UIAlertAction
314590e654 IOS7: Show inputAccessoryView when hardware keyboad is connected
80cb6427e1 IOS7: Trigger joystick presses only once for buttons A and B
2c351f85ee IOS7: Check keyboard visible if inputView being first responder
eb4028880e IOS7: Suspend application if menu key pressed and no game is running
1ace0305ce IOS7: Add general handling of the menu button on game controllers
a5cc5e17b8 IOS7: Fix compiler warnings
c38c1512a9 IOS7: Add AppleTV support to configure
2c60b9a4dc DOCS: Add draft documentation of Apple TV platform
4a864d8039 DOCS: Fix formatting in the tvOS documentation
5bc748a659 CREATE_PROJECT: Add option to use XCFramework in iOS, tvOS and macOS
fb79d61a31 DOCPORTAL: Update ios7 and tvos instructions
07652d9d82 IOS7: Fix detection of orientation on some devices
1675496f01 IOS7: Remove checks that @available can be used
5bfa6feaa1 IOS7: Fix missing override keyword
f1f808f7a4 IOS7: Remove support for non-sandboxed mode
aaf6ed536f IOS7: Cleanup code to access Document and app bundle paths
c1bcb0fd09 IOS7: Create log file in Document folder
e3b643d9a6 IOS7: Fix orientation detection when the view becomes visible
50c315e316 IOS7: Add check of size for log file to make sure it does not grow too much


Commit: 4d774e2fc320ba4032eb50442ac78fb1655950b2
    https://github.com/scummvm/scummvm/commit/4d774e2fc320ba4032eb50442ac78fb1655950b2
Author: Lars Sundström (l.sundstrom at gmail.com)
Date: 2023-04-27T21:13:27+01:00

Commit Message:
TVOS: Add Apple TV OS as a separate dist

The Apple TV OS requires a different type of storyboard than iOS. Also,
the Info.plist file differ since the tvOS platform doesn't handle
different orientations.

The Apple TV OS also need a different set of icons with different
resolutions more suitable for TV screens.

The application icons are required to be of layered type, which means
that a single PNG file is not accepted as an icon file. The icons must
have at least two layers, hence the ScummVM icon is defined by a back
image with just the background color and a front image with the ScummVM
logo.

The icons are then put together when archiving the application in Xcode
to an Assets.car file. However the linux builds are not building the
application using Xcode. Therefore a pre-compiled Assets.car file
containing the image assets (icons, splash screen etc) is added to the
tvos folder. This file is copied to the application bundle. If the icons
are changed in the future a new Assets.car file has to be compiled. This
can only be done on a computer with Xcode installed. To compile run the
following command in the tvos folder:
xcrun actool ./Images.xcassets --compile build --platform appletvos \
--minimum-deployment-target 9.0 --app-icon AppIcon \
--output-partial-info-plist build/partial.plist \
--launch-image LaunchImage

The partial.plist file generated will show what to add to the Info.plist
and if something must be changed in the ports.mk section for the
tvosbundle.

Changed paths:
  A dists/tvos/Assets.car
  A dists/tvos/Images.xcassets/AppIcon.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Content.imageset/Contents.json
  A dists/tvos/Images.xcassets/AppIcon.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Content.imageset/ScummVMAppStoreBack at 1x.png
  A dists/tvos/Images.xcassets/AppIcon.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Contents.json
  A dists/tvos/Images.xcassets/AppIcon.brandassets/App Icon - App Store.imagestack/Contents.json
  A dists/tvos/Images.xcassets/AppIcon.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Content.imageset/Contents.json
  A dists/tvos/Images.xcassets/AppIcon.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Content.imageset/ScummVMAppStoreFront at 1x.png
  A dists/tvos/Images.xcassets/AppIcon.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Contents.json
  A dists/tvos/Images.xcassets/AppIcon.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json
  A dists/tvos/Images.xcassets/AppIcon.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Contents.json
  A dists/tvos/Images.xcassets/AppIcon.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/Contents.json
  A dists/tvos/Images.xcassets/AppIcon.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/ScummVMBack at 1x.png
  A dists/tvos/Images.xcassets/AppIcon.brandassets/App Icon.imagestack/Back.imagestacklayer/Contents.json
  A dists/tvos/Images.xcassets/AppIcon.brandassets/App Icon.imagestack/Contents.json
  A dists/tvos/Images.xcassets/AppIcon.brandassets/App Icon.imagestack/Front.imagestacklayer/Content.imageset/Contents.json
  A dists/tvos/Images.xcassets/AppIcon.brandassets/App Icon.imagestack/Front.imagestacklayer/Content.imageset/ScummVMFront at 1x.png
  A dists/tvos/Images.xcassets/AppIcon.brandassets/App Icon.imagestack/Front.imagestacklayer/Contents.json
  A dists/tvos/Images.xcassets/AppIcon.brandassets/App Icon.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json
  A dists/tvos/Images.xcassets/AppIcon.brandassets/App Icon.imagestack/Middle.imagestacklayer/Contents.json
  A dists/tvos/Images.xcassets/AppIcon.brandassets/Contents.json
  A dists/tvos/Images.xcassets/AppIcon.brandassets/Top Shelf Image Wide.imageset/Contents.json
  A dists/tvos/Images.xcassets/AppIcon.brandassets/Top Shelf Image Wide.imageset/ScummVMTopShelfWide at 1x.png
  A dists/tvos/Images.xcassets/AppIcon.brandassets/Top Shelf Image.imageset/Contents.json
  A dists/tvos/Images.xcassets/AppIcon.brandassets/Top Shelf Image.imageset/ScummVMTopShelf at 1x.png
  A dists/tvos/Images.xcassets/Contents.json
  A dists/tvos/Images.xcassets/LaunchImage.launchimage/Contents.json
  A dists/tvos/Images.xcassets/LaunchImage.launchimage/ScummVMLaunchImage at 1x.png
  A dists/tvos/Info.plist
  A dists/tvos/Info.plist.in
  A dists/tvos/LaunchScreen_tvos.storyboard
    devtools/update-version.pl


diff --git a/devtools/update-version.pl b/devtools/update-version.pl
index 29f89ce766f..0a4c9e9ff1c 100755
--- a/devtools/update-version.pl
+++ b/devtools/update-version.pl
@@ -39,6 +39,7 @@ my @subs_files = qw(
 	dists/macosx/dockplugin/Info.plist
 	dists/iphone/Info.plist
 	dists/ios7/Info.plist
+	dists/tvos/Info.plist
 	dists/irix/scummvm.spec
 	dists/wii/meta.xml
 	dists/openpandora/PXML.xml
diff --git a/dists/tvos/Assets.car b/dists/tvos/Assets.car
new file mode 100644
index 00000000000..3fd882b153e
Binary files /dev/null and b/dists/tvos/Assets.car differ
diff --git a/dists/tvos/Images.xcassets/AppIcon.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Content.imageset/Contents.json b/dists/tvos/Images.xcassets/AppIcon.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Content.imageset/Contents.json
new file mode 100644
index 00000000000..2f76df8af96
--- /dev/null
+++ b/dists/tvos/Images.xcassets/AppIcon.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Content.imageset/Contents.json	
@@ -0,0 +1,17 @@
+{
+  "images" : [
+    {
+      "filename" : "ScummVMAppStoreBack at 1x.png",
+      "idiom" : "tv",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "tv",
+      "scale" : "2x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/dists/tvos/Images.xcassets/AppIcon.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Content.imageset/ScummVMAppStoreBack at 1x.png b/dists/tvos/Images.xcassets/AppIcon.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Content.imageset/ScummVMAppStoreBack at 1x.png
new file mode 100644
index 00000000000..405e1d2bfc3
Binary files /dev/null and b/dists/tvos/Images.xcassets/AppIcon.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Content.imageset/ScummVMAppStoreBack at 1x.png differ
diff --git a/dists/tvos/Images.xcassets/AppIcon.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Contents.json b/dists/tvos/Images.xcassets/AppIcon.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Contents.json
new file mode 100644
index 00000000000..73c00596a7f
--- /dev/null
+++ b/dists/tvos/Images.xcassets/AppIcon.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Contents.json	
@@ -0,0 +1,6 @@
+{
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/dists/tvos/Images.xcassets/AppIcon.brandassets/App Icon - App Store.imagestack/Contents.json b/dists/tvos/Images.xcassets/AppIcon.brandassets/App Icon - App Store.imagestack/Contents.json
new file mode 100644
index 00000000000..de59d885ae8
--- /dev/null
+++ b/dists/tvos/Images.xcassets/AppIcon.brandassets/App Icon - App Store.imagestack/Contents.json	
@@ -0,0 +1,17 @@
+{
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  },
+  "layers" : [
+    {
+      "filename" : "Front.imagestacklayer"
+    },
+    {
+      "filename" : "Middle.imagestacklayer"
+    },
+    {
+      "filename" : "Back.imagestacklayer"
+    }
+  ]
+}
diff --git a/dists/tvos/Images.xcassets/AppIcon.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Content.imageset/Contents.json b/dists/tvos/Images.xcassets/AppIcon.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Content.imageset/Contents.json
new file mode 100644
index 00000000000..a67e7022813
--- /dev/null
+++ b/dists/tvos/Images.xcassets/AppIcon.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Content.imageset/Contents.json	
@@ -0,0 +1,17 @@
+{
+  "images" : [
+    {
+      "filename" : "ScummVMAppStoreFront at 1x.png",
+      "idiom" : "tv",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "tv",
+      "scale" : "2x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/dists/tvos/Images.xcassets/AppIcon.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Content.imageset/ScummVMAppStoreFront at 1x.png b/dists/tvos/Images.xcassets/AppIcon.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Content.imageset/ScummVMAppStoreFront at 1x.png
new file mode 100644
index 00000000000..4ba46552303
Binary files /dev/null and b/dists/tvos/Images.xcassets/AppIcon.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Content.imageset/ScummVMAppStoreFront at 1x.png differ
diff --git a/dists/tvos/Images.xcassets/AppIcon.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Contents.json b/dists/tvos/Images.xcassets/AppIcon.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Contents.json
new file mode 100644
index 00000000000..73c00596a7f
--- /dev/null
+++ b/dists/tvos/Images.xcassets/AppIcon.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Contents.json	
@@ -0,0 +1,6 @@
+{
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/dists/tvos/Images.xcassets/AppIcon.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json b/dists/tvos/Images.xcassets/AppIcon.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json
new file mode 100644
index 00000000000..795cce17243
--- /dev/null
+++ b/dists/tvos/Images.xcassets/AppIcon.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json	
@@ -0,0 +1,16 @@
+{
+  "images" : [
+    {
+      "idiom" : "tv",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "tv",
+      "scale" : "2x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/dists/tvos/Images.xcassets/AppIcon.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Contents.json b/dists/tvos/Images.xcassets/AppIcon.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Contents.json
new file mode 100644
index 00000000000..73c00596a7f
--- /dev/null
+++ b/dists/tvos/Images.xcassets/AppIcon.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Contents.json	
@@ -0,0 +1,6 @@
+{
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/dists/tvos/Images.xcassets/AppIcon.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/Contents.json b/dists/tvos/Images.xcassets/AppIcon.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/Contents.json
new file mode 100644
index 00000000000..177e692a508
--- /dev/null
+++ b/dists/tvos/Images.xcassets/AppIcon.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/Contents.json	
@@ -0,0 +1,17 @@
+{
+  "images" : [
+    {
+      "filename" : "ScummVMBack at 1x.png",
+      "idiom" : "tv",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "tv",
+      "scale" : "2x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/dists/tvos/Images.xcassets/AppIcon.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/ScummVMBack at 1x.png b/dists/tvos/Images.xcassets/AppIcon.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/ScummVMBack at 1x.png
new file mode 100644
index 00000000000..c6b9f064607
Binary files /dev/null and b/dists/tvos/Images.xcassets/AppIcon.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/ScummVMBack at 1x.png differ
diff --git a/dists/tvos/Images.xcassets/AppIcon.brandassets/App Icon.imagestack/Back.imagestacklayer/Contents.json b/dists/tvos/Images.xcassets/AppIcon.brandassets/App Icon.imagestack/Back.imagestacklayer/Contents.json
new file mode 100644
index 00000000000..73c00596a7f
--- /dev/null
+++ b/dists/tvos/Images.xcassets/AppIcon.brandassets/App Icon.imagestack/Back.imagestacklayer/Contents.json	
@@ -0,0 +1,6 @@
+{
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/dists/tvos/Images.xcassets/AppIcon.brandassets/App Icon.imagestack/Contents.json b/dists/tvos/Images.xcassets/AppIcon.brandassets/App Icon.imagestack/Contents.json
new file mode 100644
index 00000000000..de59d885ae8
--- /dev/null
+++ b/dists/tvos/Images.xcassets/AppIcon.brandassets/App Icon.imagestack/Contents.json	
@@ -0,0 +1,17 @@
+{
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  },
+  "layers" : [
+    {
+      "filename" : "Front.imagestacklayer"
+    },
+    {
+      "filename" : "Middle.imagestacklayer"
+    },
+    {
+      "filename" : "Back.imagestacklayer"
+    }
+  ]
+}
diff --git a/dists/tvos/Images.xcassets/AppIcon.brandassets/App Icon.imagestack/Front.imagestacklayer/Content.imageset/Contents.json b/dists/tvos/Images.xcassets/AppIcon.brandassets/App Icon.imagestack/Front.imagestacklayer/Content.imageset/Contents.json
new file mode 100644
index 00000000000..7e049ff60cd
--- /dev/null
+++ b/dists/tvos/Images.xcassets/AppIcon.brandassets/App Icon.imagestack/Front.imagestacklayer/Content.imageset/Contents.json	
@@ -0,0 +1,17 @@
+{
+  "images" : [
+    {
+      "filename" : "ScummVMFront at 1x.png",
+      "idiom" : "tv",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "tv",
+      "scale" : "2x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/dists/tvos/Images.xcassets/AppIcon.brandassets/App Icon.imagestack/Front.imagestacklayer/Content.imageset/ScummVMFront at 1x.png b/dists/tvos/Images.xcassets/AppIcon.brandassets/App Icon.imagestack/Front.imagestacklayer/Content.imageset/ScummVMFront at 1x.png
new file mode 100644
index 00000000000..25cd718935a
Binary files /dev/null and b/dists/tvos/Images.xcassets/AppIcon.brandassets/App Icon.imagestack/Front.imagestacklayer/Content.imageset/ScummVMFront at 1x.png differ
diff --git a/dists/tvos/Images.xcassets/AppIcon.brandassets/App Icon.imagestack/Front.imagestacklayer/Contents.json b/dists/tvos/Images.xcassets/AppIcon.brandassets/App Icon.imagestack/Front.imagestacklayer/Contents.json
new file mode 100644
index 00000000000..73c00596a7f
--- /dev/null
+++ b/dists/tvos/Images.xcassets/AppIcon.brandassets/App Icon.imagestack/Front.imagestacklayer/Contents.json	
@@ -0,0 +1,6 @@
+{
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/dists/tvos/Images.xcassets/AppIcon.brandassets/App Icon.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json b/dists/tvos/Images.xcassets/AppIcon.brandassets/App Icon.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json
new file mode 100644
index 00000000000..795cce17243
--- /dev/null
+++ b/dists/tvos/Images.xcassets/AppIcon.brandassets/App Icon.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json	
@@ -0,0 +1,16 @@
+{
+  "images" : [
+    {
+      "idiom" : "tv",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "tv",
+      "scale" : "2x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/dists/tvos/Images.xcassets/AppIcon.brandassets/App Icon.imagestack/Middle.imagestacklayer/Contents.json b/dists/tvos/Images.xcassets/AppIcon.brandassets/App Icon.imagestack/Middle.imagestacklayer/Contents.json
new file mode 100644
index 00000000000..73c00596a7f
--- /dev/null
+++ b/dists/tvos/Images.xcassets/AppIcon.brandassets/App Icon.imagestack/Middle.imagestacklayer/Contents.json	
@@ -0,0 +1,6 @@
+{
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/dists/tvos/Images.xcassets/AppIcon.brandassets/Contents.json b/dists/tvos/Images.xcassets/AppIcon.brandassets/Contents.json
new file mode 100644
index 00000000000..f47ba43daac
--- /dev/null
+++ b/dists/tvos/Images.xcassets/AppIcon.brandassets/Contents.json
@@ -0,0 +1,32 @@
+{
+  "assets" : [
+    {
+      "filename" : "App Icon - App Store.imagestack",
+      "idiom" : "tv",
+      "role" : "primary-app-icon",
+      "size" : "1280x768"
+    },
+    {
+      "filename" : "App Icon.imagestack",
+      "idiom" : "tv",
+      "role" : "primary-app-icon",
+      "size" : "400x240"
+    },
+    {
+      "filename" : "Top Shelf Image Wide.imageset",
+      "idiom" : "tv",
+      "role" : "top-shelf-image-wide",
+      "size" : "2320x720"
+    },
+    {
+      "filename" : "Top Shelf Image.imageset",
+      "idiom" : "tv",
+      "role" : "top-shelf-image",
+      "size" : "1920x720"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/dists/tvos/Images.xcassets/AppIcon.brandassets/Top Shelf Image Wide.imageset/Contents.json b/dists/tvos/Images.xcassets/AppIcon.brandassets/Top Shelf Image Wide.imageset/Contents.json
new file mode 100644
index 00000000000..0c885bb8003
--- /dev/null
+++ b/dists/tvos/Images.xcassets/AppIcon.brandassets/Top Shelf Image Wide.imageset/Contents.json	
@@ -0,0 +1,17 @@
+{
+  "images" : [
+    {
+      "filename" : "ScummVMTopShelfWide at 1x.png",
+      "idiom" : "tv",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "tv",
+      "scale" : "2x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/dists/tvos/Images.xcassets/AppIcon.brandassets/Top Shelf Image Wide.imageset/ScummVMTopShelfWide at 1x.png b/dists/tvos/Images.xcassets/AppIcon.brandassets/Top Shelf Image Wide.imageset/ScummVMTopShelfWide at 1x.png
new file mode 100644
index 00000000000..410928e124d
Binary files /dev/null and b/dists/tvos/Images.xcassets/AppIcon.brandassets/Top Shelf Image Wide.imageset/ScummVMTopShelfWide at 1x.png differ
diff --git a/dists/tvos/Images.xcassets/AppIcon.brandassets/Top Shelf Image.imageset/Contents.json b/dists/tvos/Images.xcassets/AppIcon.brandassets/Top Shelf Image.imageset/Contents.json
new file mode 100644
index 00000000000..dca2306b264
--- /dev/null
+++ b/dists/tvos/Images.xcassets/AppIcon.brandassets/Top Shelf Image.imageset/Contents.json	
@@ -0,0 +1,17 @@
+{
+  "images" : [
+    {
+      "filename" : "ScummVMTopShelf at 1x.png",
+      "idiom" : "tv",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "tv",
+      "scale" : "2x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/dists/tvos/Images.xcassets/AppIcon.brandassets/Top Shelf Image.imageset/ScummVMTopShelf at 1x.png b/dists/tvos/Images.xcassets/AppIcon.brandassets/Top Shelf Image.imageset/ScummVMTopShelf at 1x.png
new file mode 100644
index 00000000000..8ba5899f5a9
Binary files /dev/null and b/dists/tvos/Images.xcassets/AppIcon.brandassets/Top Shelf Image.imageset/ScummVMTopShelf at 1x.png differ
diff --git a/dists/tvos/Images.xcassets/Contents.json b/dists/tvos/Images.xcassets/Contents.json
new file mode 100644
index 00000000000..73c00596a7f
--- /dev/null
+++ b/dists/tvos/Images.xcassets/Contents.json
@@ -0,0 +1,6 @@
+{
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/dists/tvos/Images.xcassets/LaunchImage.launchimage/Contents.json b/dists/tvos/Images.xcassets/LaunchImage.launchimage/Contents.json
new file mode 100644
index 00000000000..a813397ef82
--- /dev/null
+++ b/dists/tvos/Images.xcassets/LaunchImage.launchimage/Contents.json
@@ -0,0 +1,23 @@
+{
+  "images" : [
+    {
+      "extent" : "full-screen",
+      "idiom" : "tv",
+      "minimum-system-version" : "11.0",
+      "orientation" : "landscape",
+      "scale" : "2x"
+    },
+    {
+      "extent" : "full-screen",
+      "filename" : "ScummVMLaunchImage at 1x.png",
+      "idiom" : "tv",
+      "minimum-system-version" : "9.0",
+      "orientation" : "landscape",
+      "scale" : "1x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/dists/tvos/Images.xcassets/LaunchImage.launchimage/ScummVMLaunchImage at 1x.png b/dists/tvos/Images.xcassets/LaunchImage.launchimage/ScummVMLaunchImage at 1x.png
new file mode 100644
index 00000000000..b45bd1b37d1
Binary files /dev/null and b/dists/tvos/Images.xcassets/LaunchImage.launchimage/ScummVMLaunchImage at 1x.png differ
diff --git a/dists/tvos/Info.plist b/dists/tvos/Info.plist
new file mode 100644
index 00000000000..bf93f76be75
--- /dev/null
+++ b/dists/tvos/Info.plist
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>en</string>
+	<key>CFBundleExecutable</key>
+	<string>$(EXECUTABLE_NAME)</string>
+	<key>CFBundleIcons</key>
+	<dict/>
+	<key>CFBundleIdentifier</key>
+	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundleName</key>
+	<string>ScummVM</string>
+	<key>CFBundlePackageType</key>
+	<string>APPL</string>
+	<key>CFBundleShortVersionString</key>
+	<string>2.7.0git</string>
+	<key>CFBundleSignature</key>
+	<string>????</string>
+	<key>CFBundleVersion</key>
+	<string>2.7.0git</string>
+	<key>GCSupportedGameControllers</key>
+	<array>
+		<dict>
+			<key>ProfileName</key>
+			<string>ExtendedGamepad</string>
+		</dict>
+	</array>
+	<key>GCSupportsControllerUserInteraction</key>
+	<true/>
+	<key>LSSupportsOpeningDocumentsInPlace</key>
+	<true/>
+	<key>UIApplicationExitsOnSuspend</key>
+	<false/>
+	<key>UIApplicationSupportsIndirectInputEvents</key>
+	<true/>
+	<key>UIFileSharingEnabled</key>
+	<true/>
+	<key>UILaunchImages</key>
+	<array/>
+	<key>UILaunchStoryboardName</key>
+	<string></string>
+	<key>UIPrerenderedIcon</key>
+	<true/>
+	<key>UIRequiresFullScreen</key>
+	<true/>
+	<key>UIStatusBarHidden</key>
+	<true/>
+</dict>
+</plist>
diff --git a/dists/tvos/Info.plist.in b/dists/tvos/Info.plist.in
new file mode 100644
index 00000000000..5603246fcd8
--- /dev/null
+++ b/dists/tvos/Info.plist.in
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>en</string>
+	<key>CFBundleExecutable</key>
+	<string>$(EXECUTABLE_NAME)</string>
+	<key>CFBundleIcons</key>
+	<dict/>
+	<key>CFBundleIdentifier</key>
+	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundleName</key>
+	<string>ScummVM</string>
+	<key>CFBundlePackageType</key>
+	<string>APPL</string>
+	<key>CFBundleShortVersionString</key>
+	<string>2.7.0git</string>
+	<key>CFBundleSignature</key>
+	<string>????</string>
+	<key>CFBundleVersion</key>
+	<string>2.7.0git</string>
+	<key>GCSupportedGameControllers</key>
+	<array>
+		<dict>
+			<key>ProfileName</key>
+			<string>ExtendedGamepad</string>
+		</dict>
+	</array>
+	<key>GCSupportsControllerUserInteraction</key>
+	<true/>
+	<key>LSSupportsOpeningDocumentsInPlace</key>
+	<true/>
+	<key>UIApplicationExitsOnSuspend</key>
+	<false/>
+	<key>UIApplicationSupportsIndirectInputEvents</key>
+	<true/>
+	<key>UIFileSharingEnabled</key>
+	<true/>
+	<key>UILaunchImages</key>
+	<array/>
+	<key>UILaunchStoryboardName</key>
+	<string>LaunchScreen_tvos</string>
+	<key>UIPrerenderedIcon</key>
+	<true/>
+	<key>UIRequiresFullScreen</key>
+	<true/>
+	<key>UIStatusBarHidden</key>
+	<true/>
+</dict>
+</plist>
diff --git a/dists/tvos/LaunchScreen_tvos.storyboard b/dists/tvos/LaunchScreen_tvos.storyboard
new file mode 100644
index 00000000000..de7eeef3ea4
--- /dev/null
+++ b/dists/tvos/LaunchScreen_tvos.storyboard
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder.AppleTV.Storyboard" version="3.0" toolsVersion="21507" targetRuntime="AppleTV" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
+    <device id="appleTV" appearance="light"/>
+    <dependencies>
+        <deployment identifier="tvOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21505"/>
+        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <scenes>
+        <!--View Controller-->
+        <scene sceneID="tne-QT-ifu">
+            <objects>
+                <viewController id="BYZ-38-t0r" sceneMemberID="viewController">
+                    <layoutGuides>
+                        <viewControllerLayoutGuide type="top" id="MKS-xh-tX1"/>
+                        <viewControllerLayoutGuide type="bottom" id="fWP-k2-16V"/>
+                    </layoutGuides>
+                    <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
+                        <rect key="frame" x="0.0" y="0.0" width="1920" height="1080"/>
+                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                        <viewLayoutGuide key="safeArea" id="wu6-TO-1qx"/>
+                        <color key="backgroundColor" red="0.93520456549999997" green="0.48712334977416927" blue="0.12821434333899484" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
+                    </view>
+                </viewController>
+                <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
+            </objects>
+            <point key="canvasLocation" x="24" y="-62"/>
+        </scene>
+    </scenes>
+</document>


Commit: a836661511151c90f4eba23fa03a3d100be31a92
    https://github.com/scummvm/scummvm/commit/a836661511151c90f4eba23fa03a3d100be31a92
Author: Lars Sundström (l.sundstrom at gmail.com)
Date: 2023-04-27T21:14:19+01:00

Commit Message:
CREATE_PROJECT: Add Apple TV OS XCode target

Add Apple TV OS as a new target to the xcode project creator utility.
Make sure that TV OS specific files are not part of the iOS and macOS
targets and the other way around.
The TV OS project will utilize the same source code files as the iOS
project but will instead use the tvos dist files.

Changed paths:
    devtools/create_project/xcode.cpp


diff --git a/devtools/create_project/xcode.cpp b/devtools/create_project/xcode.cpp
index 868a2f5240e..34093d88864 100644
--- a/devtools/create_project/xcode.cpp
+++ b/devtools/create_project/xcode.cpp
@@ -42,6 +42,7 @@ namespace CreateProjectTool {
 
 #define IOS_TARGET 0
 #define OSX_TARGET 1
+#define TVOS_TARGET 2
 
 #define ADD_DEFINE(defines, name) \
 	defines.push_back(name);
@@ -107,6 +108,10 @@ bool targetIsIOS(const std::string &targetName) {
 	return targetName.length() > 4 && targetName.substr(targetName.length() - 4) == "-iOS";
 }
 
+bool targetIsTVOS(const std::string &targetName) {
+	return targetName.length() > 5 && targetName.substr(targetName.length() - 5) == "-tvOS";
+}
+
 bool shouldSkipFileForTarget(const std::string &fileID, const std::string &targetName, const std::string &fileName) {
 	// Rules:
 	// - if the parent directory is "backends/platform/ios7", the file belongs to the iOS target.
@@ -116,11 +121,20 @@ bool shouldSkipFileForTarget(const std::string &fileID, const std::string &targe
 	std::string name, ext;
 	splitFilename(fileName, name, ext);
 
-	if (targetIsIOS(targetName)) {
-		// iOS target: we skip all files with the "_osx" suffix
+	if (targetIsIOS(targetName) || targetIsTVOS(targetName)) {
+		// iOS & tvOS target: we skip all files with the "_osx" suffix
 		if (name.length() > 4 && name.substr(name.length() - 4) == "_osx") {
 			return true;
 		}
+		if (targetIsIOS(targetName)) {
+			// skip tvos dist files
+			if (fileID.find("dists/tvos/") != std::string::npos)
+				return true;
+		} else {
+			// skip ios dist files
+			if (fileID.find("dists/ios7/") != std::string::npos)
+				return true;
+		}
 		// We don't need SDL for the iOS target
 		static const std::string sdl_directory = "/sdl/";
 		static const std::string surfacesdl_directory = "/surfacesdl/";
@@ -141,6 +155,10 @@ bool shouldSkipFileForTarget(const std::string &fileID, const std::string &targe
 		if (name.length() > 4 && name.substr(name.length() - 4) == "_ios") {
 			return true;
 		}
+		// macOS target: we skip all files with the "_tvos" suffix
+		if (name.length() > 5 && name.substr(name.length() - 5) == "_tvos") {
+			return true;
+		}
 		// macOS target: we skip all files with the "ios7_" prefix
 		if (name.length() > 5 && name.substr(0, 5) == "ios7_") {
 			return true;
@@ -278,6 +296,7 @@ XcodeProvider::XcodeProvider(StringList &global_warnings, std::map<std::string,
 
 void XcodeProvider::addResourceFiles(const BuildSetup &setup, StringList &includeList, StringList &excludeList) {
 	includeList.push_back(setup.srcDir + "/dists/ios7/Info.plist");
+	includeList.push_back(setup.srcDir + "/dists/tvos/Info.plist");
 
 	ValueList &resources = getResourceFiles(setup);
 	for (ValueList::iterator it = resources.begin(); it != resources.end(); ++it) {
@@ -299,6 +318,7 @@ void XcodeProvider::createWorkspace(const BuildSetup &setup) {
 	setupDefines(setup);
 	_targets.push_back(PROJECT_DESCRIPTION "-iOS");
 	_targets.push_back(PROJECT_DESCRIPTION "-macOS");
+	_targets.push_back(PROJECT_DESCRIPTION "-tvOS");
 	setupCopyFilesBuildPhase();
 	setupFrameworksBuildPhase(setup);
 	setupNativeTarget();
@@ -750,6 +770,107 @@ void XcodeProvider::setupFrameworksBuildPhase(const BuildSetup &setup) {
 	framework_OSX->_properties["files"] = osx_files;
 
 	_frameworksBuildPhase.add(framework_OSX);
+
+	//////////////////////////////////////////////////////////////////////////
+	// ScummVM-tvOS
+	Object *framework_tvOS = new Object(this, "PBXFrameworksBuildPhase_" + _targets[TVOS_TARGET], "PBXFrameworksBuildPhase", "PBXFrameworksBuildPhase", "", "Frameworks");
+
+	framework_tvOS->addProperty("buildActionMask", "2147483647", "", kSettingsNoValue);
+	framework_tvOS->addProperty("runOnlyForDeploymentPostprocessing", "0", "", kSettingsNoValue);
+
+	// List of frameworks
+	Property tvOS_files;
+	tvOS_files._hasOrder = true;
+	tvOS_files._flags = kSettingsAsList;
+
+	ValueList frameworks_tvOS;
+	frameworks_tvOS.push_back("CoreAudio.framework");
+	frameworks_tvOS.push_back("CoreGraphics.framework");
+	frameworks_tvOS.push_back("CoreFoundation.framework");
+	frameworks_tvOS.push_back("Foundation.framework");
+	frameworks_tvOS.push_back("GameController.framework");
+	frameworks_tvOS.push_back("UIKit.framework");
+	frameworks_tvOS.push_back("SystemConfiguration.framework");
+	frameworks_tvOS.push_back("AudioToolbox.framework");
+	frameworks_tvOS.push_back("QuartzCore.framework");
+	frameworks_tvOS.push_back("OpenGLES.framework");
+
+	if (CONTAINS_DEFINE(setup.defines, "USE_FAAD")) {
+		frameworks_tvOS.push_back("libfaad.a");
+	}
+	if (CONTAINS_DEFINE(setup.defines, "USE_FLAC")) {
+		frameworks_tvOS.push_back("libFLAC.a");
+	}
+	if (CONTAINS_DEFINE(setup.defines, "USE_FREETYPE2")) {
+		frameworks_tvOS.push_back("libfreetype.a");
+		frameworks_tvOS.push_back("libbz2.a");
+	}
+	if (CONTAINS_DEFINE(setup.defines, "USE_JPEG")) {
+		frameworks_tvOS.push_back("libjpeg.a");
+	}
+	if (CONTAINS_DEFINE(setup.defines, "USE_PNG")) {
+		frameworks_tvOS.push_back("libpng.a");
+	}
+	if (CONTAINS_DEFINE(setup.defines, "USE_GIF")) {
+		frameworks_tvOS.push_back("libgif.a");
+	}
+	if (CONTAINS_DEFINE(setup.defines, "USE_OGG")) {
+		frameworks_tvOS.push_back("libogg.a");
+	}
+	if (CONTAINS_DEFINE(setup.defines, "USE_VORBIS")) {
+		frameworks_tvOS.push_back("libvorbis.a");
+		frameworks_tvOS.push_back("libvorbisfile.a");
+	}
+	if (CONTAINS_DEFINE(setup.defines, "USE_TREMOR")) {
+		frameworks_tvOS.push_back("libvorbisidec.a");
+	}
+	if (CONTAINS_DEFINE(setup.defines, "USE_THEORADEC")) {
+		frameworks_tvOS.push_back("libtheoradec.a");
+	}
+	if (CONTAINS_DEFINE(setup.defines, "USE_MAD")) {
+		frameworks_tvOS.push_back("libmad.a");
+	}
+	if (CONTAINS_DEFINE(setup.defines, "USE_MPEG2")) {
+		frameworks_tvOS.push_back("libmpeg2.a");
+	}
+	if (CONTAINS_DEFINE(setup.defines, "USE_FRIBIDI")) {
+		frameworks_tvOS.push_back("libfribidi.a");
+	}
+	if (CONTAINS_DEFINE(setup.defines, "USE_FLUIDSYNTH") &&
+		!CONTAINS_DEFINE(setup.defines, "USE_FLUIDLITE")) {
+		frameworks_tvOS.push_back("libfluidsynth.a");
+		frameworks_tvOS.push_back("libglib-2.0.a");
+		frameworks_tvOS.push_back("libintl.a");
+		frameworks_tvOS.push_back("libffi.a");
+		frameworks_tvOS.push_back("CoreMIDI.framework");
+		frameworks_tvOS.push_back("libiconv.tbd");
+	}
+	if (CONTAINS_DEFINE(setup.defines, "USE_ZLIB")) {
+		frameworks_tvOS.push_back("libz.tbd");
+	}
+	if (CONTAINS_DEFINE(setup.defines, "USE_LIBCURL")) {
+		frameworks_tvOS.push_back("libcurl.a");
+		frameworks_tvOS.push_back("Security.framework");
+	}
+	if (CONTAINS_DEFINE(setup.defines, "USE_SDL_NET")) {
+		if (setup.useSDL2)
+			frameworks_tvOS.push_back("libSDL2_net.a");
+		else
+			frameworks_tvOS.push_back("libSDL_net.a");
+	}
+
+	for (ValueList::iterator framework = frameworks_tvOS.begin(); framework != frameworks_tvOS.end(); framework++) {
+		std::string id = "Frameworks_" + *framework + "_appletv";
+		std::string comment = *framework + " in Frameworks";
+
+		ADD_SETTING_ORDER_NOVALUE(tvOS_files, getHash(id), comment, order++);
+		ADD_BUILD_FILE(id, *framework, getHash(*framework), comment);
+		ADD_FILE_REFERENCE(*framework, *framework, properties[*framework]);
+	}
+
+	framework_tvOS->_properties["files"] = tvOS_files;
+
+	_frameworksBuildPhase.add(framework_tvOS);
 }
 
 void XcodeProvider::setupNativeTarget() {
@@ -818,6 +939,7 @@ void XcodeProvider::setupProject() {
 	targets._flags = kSettingsAsList;
 	targets._settings[getHash("PBXNativeTarget_" + _targets[IOS_TARGET])] = Setting("", _targets[IOS_TARGET], kSettingsNoValue, 0, 0);
 	targets._settings[getHash("PBXNativeTarget_" + _targets[OSX_TARGET])] = Setting("", _targets[OSX_TARGET], kSettingsNoValue, 0, 1);
+	targets._settings[getHash("PBXNativeTarget_" + _targets[TVOS_TARGET])] = Setting("", _targets[TVOS_TARGET], kSettingsNoValue, 0, 2);
 	project->_properties["targets"] = targets;
 
 	// Force list even when there is only a single target
@@ -866,6 +988,7 @@ XcodeProvider::ValueList& XcodeProvider::getResourceFiles(const BuildSetup &setu
 		files.push_back("dists/engine-data/wintermute.zip");
 		files.push_back("dists/engine-data/xeen.ccs");
 		files.push_back("dists/ios7/LaunchScreen_ios.storyboard");
+		files.push_back("dists/tvos/LaunchScreen_tvos.storyboard");
 		files.push_back("dists/pred.dic");
 		files.push_back("dists/networking/wwwroot.zip");
 		if (CONTAINS_DEFINE(setup.defines, "ENABLE_GRIME")) {
@@ -1291,6 +1414,85 @@ void XcodeProvider::setupBuildConfiguration(const BuildSetup &setup) {
 	_buildConfiguration.add(scummvmOSX_Debug_Object);
 	_buildConfiguration.add(scummvmOSX_Release_Object);
 
+	///****************************************
+	// * ScummVM - tvOS Target
+	// ****************************************/
+
+	// Debug
+	Object *tvOS_Debug_Object = new Object(this, "XCBuildConfiguration_" PROJECT_DESCRIPTION "-tvOS_Debug", _targets[TVOS_TARGET] /* ScummVM-tvOS */, "XCBuildConfiguration", "PBXNativeTarget", "Debug");
+	Property tvOS_Debug;
+	ADD_SETTING_QUOTE(tvOS_Debug, "CODE_SIGN_IDENTITY", "iPhone Developer");
+	ADD_SETTING_QUOTE_VAR(tvOS_Debug, "CODE_SIGN_IDENTITY[sdk=appletvos*]", "iPhone Developer");
+	ADD_SETTING(tvOS_Debug, "COPY_PHASE_STRIP", "NO");
+	ADD_SETTING_QUOTE(tvOS_Debug, "DEBUG_INFORMATION_FORMAT", "dwarf");
+	ValueList tvOS_FrameworkSearchPaths;
+	tvOS_FrameworkSearchPaths.push_back("$(inherited)");
+	tvOS_FrameworkSearchPaths.push_back("\"$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks\"");
+	ADD_SETTING_LIST(tvOS_Debug, "FRAMEWORK_SEARCH_PATHS", tvOS_FrameworkSearchPaths, kSettingsAsList, 5);
+	ADD_SETTING(tvOS_Debug, "GCC_DYNAMIC_NO_PIC", "NO");
+	ADD_SETTING(tvOS_Debug, "GCC_ENABLE_CPP_EXCEPTIONS", "NO");
+	ADD_SETTING(tvOS_Debug, "GCC_OPTIMIZATION_LEVEL", "0");
+	ADD_SETTING(tvOS_Debug, "GCC_PRECOMPILE_PREFIX_HEADER", "NO");
+	ADD_SETTING(tvOS_Debug, "GCC_WARN_64_TO_32_BIT_CONVERSION", "NO");
+	ADD_SETTING_QUOTE(tvOS_Debug, "GCC_PREFIX_HEADER", "");
+	ADD_SETTING(tvOS_Debug, "GCC_UNROLL_LOOPS", "YES");
+	ValueList tvOS_HeaderSearchPaths;
+	tvOS_HeaderSearchPaths.push_back("$(SRCROOT)/engines/");
+	tvOS_HeaderSearchPaths.push_back("$(SRCROOT)");
+	for (StringList::const_iterator i = setup.includeDirs.begin(); i != setup.includeDirs.end(); ++i)
+		tvOS_HeaderSearchPaths.push_back("\"" + *i + "\"");
+	tvOS_HeaderSearchPaths.push_back("\"" + projectOutputDirectory + "\"");
+	tvOS_HeaderSearchPaths.push_back("\"" + projectOutputDirectory + "/include\"");
+	if (CONTAINS_DEFINE(setup.defines, "USE_SDL_NET")) {
+		if (setup.useSDL2)
+			tvOS_HeaderSearchPaths.push_back("\"" + projectOutputDirectory + "/include/SDL2\"");
+		else
+			tvOS_HeaderSearchPaths.push_back("\"" + projectOutputDirectory + "include/SDL\"");
+	}
+	ADD_SETTING_LIST(tvOS_Debug, "HEADER_SEARCH_PATHS", tvOS_HeaderSearchPaths, kSettingsAsList | kSettingsQuoteVariable, 5);
+	ADD_SETTING_QUOTE(tvOS_Debug, "INFOPLIST_FILE", "$(SRCROOT)/dists/tvos/Info.plist");
+	ValueList tvOS_LibPaths;
+	for (StringList::const_iterator i = setup.libraryDirs.begin(); i != setup.libraryDirs.end(); ++i)
+		tvOS_LibPaths.push_back("\"" + *i + "\"");
+	tvOS_LibPaths.push_back("$(inherited)");
+	tvOS_LibPaths.push_back("\"" + projectOutputDirectory + "/lib\"");
+	ADD_SETTING_LIST(tvOS_Debug, "LIBRARY_SEARCH_PATHS", tvOS_LibPaths, kSettingsAsList, 5);
+	ADD_SETTING(tvOS_Debug, "ONLY_ACTIVE_ARCH", "YES");
+	ADD_SETTING(tvOS_Debug, "PRODUCT_NAME", PROJECT_NAME);
+	ADD_SETTING(tvOS_Debug, "PRODUCT_BUNDLE_IDENTIFIER", "\"org.scummvm.${PRODUCT_NAME}\"");
+	ADD_SETTING(tvOS_Debug, "TVOS_DEPLOYMENT_TARGET", "9.0");
+	ADD_SETTING_QUOTE_VAR(tvOS_Debug, "PROVISIONING_PROFILE[sdk=appletvos*]", "");
+	ADD_SETTING(tvOS_Debug, "SDKROOT", "appletvos");
+	ADD_SETTING_QUOTE(tvOS_Debug, "TARGETED_DEVICE_FAMILY", "3");
+	ValueList scummvmTVOS_defines;
+	ADD_DEFINE(scummvmTVOS_defines, "\"$(inherited)\"");
+	ADD_DEFINE(scummvmTVOS_defines, "IPHONE");
+	ADD_DEFINE(scummvmTVOS_defines, "IPHONE_IOS7");
+	ADD_DEFINE(scummvmTVOS_defines, "IPHONE_SANDBOXED");
+	if (CONTAINS_DEFINE(setup.defines, "USE_SDL_NET"))
+		ADD_DEFINE(scummvmTVOS_defines, "WITHOUT_SDL");
+	ADD_SETTING_LIST(tvOS_Debug, "GCC_PREPROCESSOR_DEFINITIONS", scummvmTVOS_defines, kSettingsNoQuote | kSettingsAsList, 5);
+	ADD_SETTING(tvOS_Debug, "ASSETCATALOG_COMPILER_APPICON_NAME", "AppIcon");
+	ADD_SETTING(tvOS_Debug, "ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME", "LaunchImage");
+	tvOS_Debug_Object->addProperty("name", "Debug", "", kSettingsNoValue);
+	tvOS_Debug_Object->_properties["buildSettings"] = tvOS_Debug;
+
+	// Release
+	Object *tvOS_Release_Object = new Object(this, "XCBuildConfiguration_" PROJECT_DESCRIPTION "-tvOS_Release", _targets[TVOS_TARGET] /* ScummVM-tvOS */, "XCBuildConfiguration", "PBXNativeTarget", "Release");
+	Property tvOS_Release(tvOS_Debug);
+	ADD_SETTING(tvOS_Release, "GCC_OPTIMIZATION_LEVEL", "3");
+	ADD_SETTING(tvOS_Release, "COPY_PHASE_STRIP", "YES");
+	REMOVE_SETTING(tvOS_Release, "GCC_DYNAMIC_NO_PIC");
+	ADD_SETTING(tvOS_Release, "WRAPPER_EXTENSION", "app");
+	REMOVE_SETTING(tvOS_Release, "DEBUG_INFORMATION_FORMAT");
+	ADD_SETTING_QUOTE(tvOS_Release, "DEBUG_INFORMATION_FORMAT", "dwarf-with-dsym");
+
+	tvOS_Release_Object->addProperty("name", "Release", "", kSettingsNoValue);
+	tvOS_Release_Object->_properties["buildSettings"] = tvOS_Release;
+
+	_buildConfiguration.add(tvOS_Debug_Object);
+	_buildConfiguration.add(tvOS_Release_Object);
+
 	// Warning: This assumes we have all configurations with a Debug & Release pair
 	for (std::vector<Object *>::iterator config = _buildConfiguration._objects.begin(); config != _buildConfiguration._objects.end(); config++) {
 
@@ -1314,16 +1516,24 @@ void XcodeProvider::setupBuildConfiguration(const BuildSetup &setup) {
 void XcodeProvider::setupImageAssetCatalog(const BuildSetup &setup) {
 	const std::string filename = "Images.xcassets";
 	const std::string absoluteCatalogPath = _projectRoot + "/dists/ios7/" + filename;
+	const std::string absoluteCatalogPathTVOS = _projectRoot + "/dists/tvos/" + filename;
 	const std::string id = "FileReference_" + absoluteCatalogPath;
+	const std::string idTVOS = "FileReference_" + absoluteCatalogPathTVOS;
 	Group *group = touchGroupsForPath(absoluteCatalogPath);
+	Group *groupTVOS = touchGroupsForPath(absoluteCatalogPathTVOS);
 	group->addChildFile(filename);
+	groupTVOS->addChildFile(filename);
 	addBuildFile(absoluteCatalogPath, filename, getHash(id), "Image Asset Catalog");
+	addBuildFile(absoluteCatalogPathTVOS, filename, getHash(idTVOS), "Image Asset Catalog");
 }
 
 void XcodeProvider::setupAdditionalSources(std::string targetName, Property &files, int &order) {
 	if (targetIsIOS(targetName)) {
 		const std::string absoluteCatalogPath = _projectRoot + "/dists/ios7/Images.xcassets";
 		ADD_SETTING_ORDER_NOVALUE(files, getHash(absoluteCatalogPath), "Image Asset Catalog", order++);
+	} else if (targetIsTVOS(targetName)) {
+		const std::string absoluteCatalogPath = _projectRoot + "/dists/tvos/Images.xcassets";
+		ADD_SETTING_ORDER_NOVALUE(files, getHash(absoluteCatalogPath), "Image Asset Catalog", order++);
 	}
 }
 


Commit: 0a9239ad7cbc08df749721c8f2115e78c9cbc8b8
    https://github.com/scummvm/scummvm/commit/0a9239ad7cbc08df749721c8f2115e78c9cbc8b8
Author: Lars Sundström (l.sundstrom at gmail.com)
Date: 2023-04-27T21:16:10+01:00

Commit Message:
IOS7: Put iOS specific code within platform specific macros

iOS and tvOS shares a lot of code. However some there are parts that are
specific to iOS, for instance handling of UI device orientation and
certain types of gestures.

Currently there are also some limitations on the Apple TV that needs to
be flagged to the  engine. There is no support for virtual keyboard, no
clipboard support and no possibility to open URLs.

Put code specific for iOS within the ObjC platfrom macro TARGET_OS_IOS.
The code specific for tvOS are put within the macro TARGET_OS_TV.

Changed paths:
    backends/platform/ios7/ios7_app_delegate.mm
    backends/platform/ios7/ios7_keyboard.mm
    backends/platform/ios7/ios7_osys_main.cpp
    backends/platform/ios7/ios7_osys_misc.mm
    backends/platform/ios7/ios7_osys_video.mm
    backends/platform/ios7/ios7_video.h
    backends/platform/ios7/ios7_video.mm


diff --git a/backends/platform/ios7/ios7_app_delegate.mm b/backends/platform/ios7/ios7_app_delegate.mm
index 831e319877f..4a8140a383b 100644
--- a/backends/platform/ios7/ios7_app_delegate.mm
+++ b/backends/platform/ios7/ios7_app_delegate.mm
@@ -59,17 +59,21 @@
 	_controller = [[iOS7ScummVMViewController alloc] init];
 
 	_view = [[iPhoneView alloc] initWithFrame:rect];
+#if TARGET_OS_IOS
 	_view.multipleTouchEnabled = YES;
+#endif
 	_controller.view = _view;
 
 	[_window setRootViewController:_controller];
 	[_window makeKeyAndVisible];
 
+#if TARGET_OS_IOS
 	[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
 	[[NSNotificationCenter defaultCenter] addObserver:self
 	                                         selector:@selector(didRotate:)
 	                                             name:@"UIDeviceOrientationDidChangeNotification"
 	                                           object:nil];
+#endif
 
 	// Force creation of the shared instance on the main thread
 	iOS7_buildSharedOSystemInstance();
@@ -93,8 +97,10 @@
 
 	// Make sure we have the correct orientation in case the orientation was changed while
 	// the app was inactive.
+#if TARGET_OS_IOS
 	UIDeviceOrientation screenOrientation = [[UIDevice currentDevice] orientation];
 	[_view deviceOrientationChanged:screenOrientation];
+#endif
 }
 
 - (void)applicationDidEnterBackground:(UIApplication *)application {
@@ -119,8 +125,10 @@
 }
 
 - (void)didRotate:(NSNotification *)notification {
+#if TARGET_OS_IOS
 	UIDeviceOrientation screenOrientation = [[UIDevice currentDevice] orientation];
 	[_view deviceOrientationChanged:screenOrientation];
+#endif
 }
 
 + (iOS7AppDelegate *)iOS7AppDelegate {
@@ -145,7 +153,12 @@
 @end
 
 const char *iOS7_getDocumentsDir() {
-	NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
+	NSArray *paths;
+#if TARGET_OS_IOS
+	paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
+#else
+	paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
+#endif
 	NSString *documentsDirectory = [paths objectAtIndex:0];
 	return [documentsDirectory UTF8String];
 }
diff --git a/backends/platform/ios7/ios7_keyboard.mm b/backends/platform/ios7/ios7_keyboard.mm
index e378eb1e0e3..0ee0fb9d523 100644
--- a/backends/platform/ios7/ios7_keyboard.mm
+++ b/backends/platform/ios7/ios7_keyboard.mm
@@ -30,7 +30,9 @@
 
 @interface TextInputHandler : UITextView {
 	SoftKeyboard *softKeyboard;
+#if TARGET_OS_IOS
 	UIToolbar *toolbar;
+#endif
 	UIScrollView *scrollView;
 }
 
@@ -51,7 +53,7 @@
 	[self setAutocorrectionType:UITextAutocorrectionTypeNo];
 	[self setAutocapitalizationType:UITextAutocapitalizationTypeNone];
 	[self setEnablesReturnKeyAutomatically:NO];
-
+#if TARGET_OS_IOS
 	// Hide the input assistent bar. The API is only available since IOS 9.0.
 	// The code only compils with the iOS 9.0+ SDK, and only works on iOS 9.0
 	// or above.
@@ -118,11 +120,14 @@
 	[scrollView addSubview:toolbar];
 	self.inputAccessoryView = scrollView;
 
+#endif
 	return self;
 }
 
 -(void)dealloc {
+#if TARGET_OS_IOS
 	[toolbar release];
+#endif
 	[scrollView release];
 	[super dealloc];
 }
@@ -133,9 +138,11 @@
 //	self.inputAccessoryView = scrollView;
 //	[self reloadInputViews];
 	// We need at least a width of 768 pt for the toolbar. If we add more buttons this may need to be increased.
+#if TARGET_OS_IOS
 	toolbar.frame = CGRectMake(0, 0, MAX(768, [[UIScreen mainScreen] bounds].size.width), toolbar.frame.size.height);
 	toolbar.bounds = toolbar.frame;
 	scrollView.contentSize = toolbar.frame.size;
+#endif
 }
 
 - (void)detachAccessoryView {
@@ -276,7 +283,9 @@
 	inputDelegate = nil;
 	inputView = [[TextInputHandler alloc] initWithKeyboard:self];
 	inputView.delegate = self;
+#if TARGET_OS_IOS
 	[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(prepareKeyboard:) name:UIKeyboardWillShowNotification object:nil];
+#endif
 	return self;
 }
 
@@ -314,6 +323,7 @@
 }
 
 - (void)prepareKeyboard:(NSNotification *)notification {
+#if TARGET_OS_IOS
 	// Check if a hardware keyboard is connected, and only show the accessory view if there isn't one.
 	// If there is a hardware keyboard, the software one will only contains the text assistance bar
 	// and will be small (less than 100 pt, but use a bit more in case it changes with future iOS versions).
@@ -326,6 +336,7 @@
 		[inputView detachAccessoryView];
 	else
 		[inputView attachAccessoryView];
+#endif
 }
 
 - (void)showKeyboard {
diff --git a/backends/platform/ios7/ios7_osys_main.cpp b/backends/platform/ios7/ios7_osys_main.cpp
index 1ca10a81f23..d157d93f47d 100644
--- a/backends/platform/ios7/ios7_osys_main.cpp
+++ b/backends/platform/ios7/ios7_osys_main.cpp
@@ -168,7 +168,9 @@ bool OSystem_iOS7::hasFeature(Feature f) {
 	case kFeatureCursorPalette:
 	case kFeatureFilteringMode:
 	case kFeatureVirtualKeyboard:
+#if TARGET_OS_IOS
 	case kFeatureClipboardSupport:
+#endif
 	case kFeatureOpenUrl:
 	case kFeatureNoQuit:
 		return true;
diff --git a/backends/platform/ios7/ios7_osys_misc.mm b/backends/platform/ios7/ios7_osys_misc.mm
index 7f5109641cb..d0885120963 100644
--- a/backends/platform/ios7/ios7_osys_misc.mm
+++ b/backends/platform/ios7/ios7_osys_misc.mm
@@ -142,13 +142,18 @@ Common::String OSystem_iOS7::getSystemLanguage() const {
 }
 
 bool OSystem_iOS7::hasTextInClipboard() {
+#if TARGET_OS_IOS
 	return [[UIPasteboard generalPasteboard] containsPasteboardTypes:UIPasteboardTypeListString];
+#else
+	return false;
+#endif
 }
 
 Common::U32String OSystem_iOS7::getTextFromClipboard() {
 	if (!hasTextInClipboard())
 		return Common::U32String();
 
+#if TARGET_OS_IOS
 	UIPasteboard *pb = [UIPasteboard generalPasteboard];
 	NSString *str = pb.string;
 	if (str == nil)
@@ -174,9 +179,13 @@ Common::U32String OSystem_iOS7::getTextFromClipboard() {
 	delete[] text;
 
 	return u32String;
+#else
+	return Common::U32String();
+#endif
 }
 
 bool OSystem_iOS7::setTextInClipboard(const Common::U32String &text) {
+#if TARGET_OS_IOS
 #ifdef SCUMM_LITTLE_ENDIAN
 	NSStringEncoding stringEncoding = NSUTF32LittleEndianStringEncoding;
 #else
@@ -187,6 +196,9 @@ bool OSystem_iOS7::setTextInClipboard(const Common::U32String &text) {
 	[pb setString:nsstring];
 	[nsstring release];
 	return true;
+#else
+	return false;
+#endif
 }
 
 bool OSystem_iOS7::openUrl(const Common::String &url) {
diff --git a/backends/platform/ios7/ios7_osys_video.mm b/backends/platform/ios7/ios7_osys_video.mm
index 7c321839e12..7ac0b815973 100644
--- a/backends/platform/ios7/ios7_osys_video.mm
+++ b/backends/platform/ios7/ios7_osys_video.mm
@@ -28,6 +28,7 @@
 #include "graphics/blit.h"
 #include "backends/platform/ios7/ios7_app_delegate.h"
 
+#if TARGET_OS_IOS
 @interface iOS7AlertHandler : NSObject<UIAlertViewDelegate>
 @end
 
@@ -49,8 +50,10 @@ static void displayAlert(void *ctx) {
 	[alert show];
 	[alert autorelease];
 }
+#endif
 
 void OSystem_iOS7::fatalError() {
+#if TARGET_OS_IOS
 	if (_lastErrorMessage.size()) {
 		dispatch_async_f(dispatch_get_main_queue(), (void *)_lastErrorMessage.c_str(), displayAlert);
 		for(;;);
@@ -58,6 +61,7 @@ void OSystem_iOS7::fatalError() {
 	else {
 		OSystem::fatalError();
 	}
+#endif
 }
 
 void OSystem_iOS7::logMessage(LogMessageType::Type type, const char *message) {
diff --git a/backends/platform/ios7/ios7_video.h b/backends/platform/ios7/ios7_video.h
index 2bd6accaece..d0b34bc8a79 100644
--- a/backends/platform/ios7/ios7_video.h
+++ b/backends/platform/ios7/ios7_video.h
@@ -116,7 +116,9 @@ uint getSizeNextPOT(uint size);
 - (void)updateMouseCursorScaling;
 - (void)updateMouseCursor;
 
+#if TARGET_OS_IOS
 - (void)deviceOrientationChanged:(UIDeviceOrientation)orientation;
+#endif
 
 - (void)showKeyboard;
 - (void)hideKeyboard;
diff --git a/backends/platform/ios7/ios7_video.mm b/backends/platform/ios7/ios7_video.mm
index da29d0376c3..2b8ac9da2ba 100644
--- a/backends/platform/ios7/ios7_video.mm
+++ b/backends/platform/ios7/ios7_video.mm
@@ -54,7 +54,11 @@ void printOglError(const char *file, int line) {
 }
 
 bool iOS7_isBigDevice() {
+#if TARGET_OS_IOS
 	return UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad;
+#elif TARGET_OS_TV
+	return true;
+#endif
 }
 
 static inline void execute_on_main_thread(void (^block)(void)) {
@@ -338,6 +342,7 @@ uint getSizeNextPOT(uint size) {
 }
 
 - (void)setupGestureRecognizers {
+#if TARGET_OS_IOS
 	UIPinchGestureRecognizer *pinchKeyboard = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(keyboardPinch:)];
 
 	UISwipeGestureRecognizer *swipeRight = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(twoFingersSwipeRight:)];
@@ -415,6 +420,7 @@ uint getSizeNextPOT(uint size) {
 	[swipeUp3 release];
 	[swipeDown3 release];
 	[doubleTapTwoFingers release];
+#endif
 }
 
 - (id)initWithFrame:(struct CGRect)frame {
@@ -424,7 +430,7 @@ uint getSizeNextPOT(uint size) {
 
 	[self setupGestureRecognizers];
 
-	if (@available(iOS 14.0, *)) {
+	if (@available(iOS 14.0, tvOS 14.0, *)) {
 		_controllers.push_back([[MouseController alloc] initWithView:self]);
 		_controllers.push_back([[GamepadController alloc] initWithView:self]);
 	}
@@ -752,14 +758,15 @@ uint getSizeNextPOT(uint size) {
 	// available when running on iOS 11+ if it has been compiled on iOS 11+
 #ifdef __IPHONE_11_0
 #if __has_builtin(__builtin_available)
-	if ( @available(iOS 11,*) ) {
+	if ( @available(iOS 11, tvOS 11, *) ) {
 #else
 	if ( [[[UIApplication sharedApplication] keyWindow] respondsToSelector:@selector(safeAreaInsets)] ) {
 #endif
 		CGRect screenSize = [[UIScreen mainScreen] bounds];
+		CGRect newFrame = screenSize;
+#if TARGET_OS_IOS
 		UIEdgeInsets inset = [[[UIApplication sharedApplication] keyWindow] safeAreaInsets];
 		UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
-		CGRect newFrame = screenSize;
 		if ( orientation == UIInterfaceOrientationPortrait ) {
 			newFrame = CGRectMake(screenSize.origin.x, screenSize.origin.y + inset.top, screenSize.size.width, screenSize.size.height - inset.top);
 		} else if ( orientation == UIInterfaceOrientationLandscapeLeft ) {
@@ -767,6 +774,7 @@ uint getSizeNextPOT(uint size) {
 		} else if ( orientation == UIInterfaceOrientationLandscapeRight ) {
 			newFrame = CGRectMake(screenSize.origin.x + inset.left, screenSize.origin.y, screenSize.size.width - inset.left, screenSize.size.height);
 		}
+#endif
 		self.frame = newFrame;
 	}
 #endif
@@ -866,7 +874,7 @@ uint getSizeNextPOT(uint size) {
 }
 
 - (BOOL)isMouseControllerConnected {
-	if (@available(iOS 14.0, *)) {
+	if (@available(iOS 14.0, tvOS 14.0, *)) {
 		return [self isControllerTypeConnected:MouseController.class];
 	} else {
 		// Fallback on earlier versions
@@ -875,7 +883,7 @@ uint getSizeNextPOT(uint size) {
 }
 
 - (BOOL)isGamepadControllerConnected {
-	if (@available(iOS 14.0, *)) {
+	if (@available(iOS 14.0, tvOS 14.0, *)) {
 		return [self isControllerTypeConnected:GamepadController.class];
 	} else {
 		// Fallback on earlier versions
@@ -883,6 +891,7 @@ uint getSizeNextPOT(uint size) {
 	}
 }
 
+#if TARGET_OS_IOS
 - (void)deviceOrientationChanged:(UIDeviceOrientation)orientation {
 	[self addEvent:InternalEvent(kInputOrientationChanged, orientation, 0)];
 
@@ -893,6 +902,7 @@ uint getSizeNextPOT(uint size) {
 		[self showKeyboard];
 	}
 }
+#endif
 
 - (void)showKeyboard {
 	[_keyboardView showKeyboard];
@@ -940,12 +950,14 @@ uint getSizeNextPOT(uint size) {
 	}
 }
 
+#if TARGET_OS_IOS
 - (void)keyboardPinch:(UIPinchGestureRecognizer *)recognizer {
 	if ([recognizer scale] < 0.8)
 		[self showKeyboard];
 	else if ([recognizer scale] > 1.25)
 		[self hideKeyboard];
 }
+#endif
 
 - (void)twoFingersSwipeRight:(UISwipeGestureRecognizer *)recognizer {
 	[self addEvent:InternalEvent(kInputSwipe, kUIViewSwipeRight, 2)];


Commit: 255852c8e35674cd8fdfd1004edb519f0eab87b9
    https://github.com/scummvm/scummvm/commit/255852c8e35674cd8fdfd1004edb519f0eab87b9
Author: Lars Sundström (l.sundstrom at gmail.com)
Date: 2023-04-27T21:16:53+01:00

Commit Message:
IOS7: Implement support for Apple TV remote

The Apple TV remote has a touch area which functions as a touch
controller. It also has a few buttons that can be programmed for
different actions.

The "touchpad mode" is not really relevant for the Apple TV remote.
However the pointer should be moved when swiping on the touch area
on the remote. Since we don't want to generate actions on touchBegan
and touchEnded for the remote, make sure these are only triggered if
the touch is made on direct contact with the screen, UITouchTypeDirect.

Implement the button handling by implement the microGamepad profile in
the GamepadController class. Only buttons A, X and the menu buttons are
relevant since the touch area is using the touch controller class.
The tvOS simulator however doesn't call the lambda functions defined for
the microGamepad buttons, hence the implementation of the "pressesBegan"
and "pressesEnded" which is called instead when running the simulator.

Implement common handling of the menu button. If the menu button is
pressed the soft keyboard will be shown. If pressing the menu button
again the soft keyboard will be hidden. If pressing the menu button
a third time the application will be suspended.

Implement new gesture recognizers that can be used with the Apple TV
remote. Up/down/left/right actions are triggered on press on the arrow
buttons, or tap on the edges of the touch area.

A long press, 5 seconds, of "Play/Pause" button toggles Mouse-click-and-
drag mode needed by some games.

Changed paths:
    backends/platform/ios7/ios7_gamepad_controller.mm
    backends/platform/ios7/ios7_touch_controller.mm
    backends/platform/ios7/ios7_video.mm
    dists/tvos/Info.plist
    dists/tvos/Info.plist.in


diff --git a/backends/platform/ios7/ios7_gamepad_controller.mm b/backends/platform/ios7/ios7_gamepad_controller.mm
index e7b34758d1a..9f3c0826109 100644
--- a/backends/platform/ios7/ios7_gamepad_controller.mm
+++ b/backends/platform/ios7/ios7_gamepad_controller.mm
@@ -27,10 +27,6 @@
 #include "backends/platform/ios7/ios7_video.h"
 #include <GameController/GameController.h>
 
-// This value will be multiplied with the x and y values of a thumbstick
-// value (-1, 1). Should ideally be configurable through ScummVM settings
-#define GAMEPAD_SENSITIVITY 20
-
 @implementation GamepadController {
 	GCController *_controller;
 }
@@ -50,10 +46,25 @@
 }
 
 - (void)controllerDidConnect:(NSNotification *)notification {
-	[self setIsConnected:YES];
 	_controller = (GCController*)notification.object;
 
+#if TARGET_OS_TV
+	if (_controller.microGamepad != nil) {
+		[self setIsConnected:YES];
+
+		_controller.microGamepad.buttonA.valueChangedHandler = ^(GCControllerButtonInput * _Nonnull button, float value, BOOL pressed) {
+			[self handleJoystickButtonAction:Common::JOYSTICK_BUTTON_A isPressed:pressed];
+		};
+
+		_controller.microGamepad.buttonX.valueChangedHandler = ^(GCControllerButtonInput * _Nonnull button, float value, BOOL pressed) {
+			// Map button X to button B because B is mapped to left button
+			[self handleJoystickButtonAction:Common::JOYSTICK_BUTTON_B isPressed:pressed];
+		};
+	}
+#endif
 	if (_controller.extendedGamepad != nil) {
+		[self setIsConnected:YES];
+
 		_controller.extendedGamepad.leftThumbstick.valueChangedHandler = ^(GCControllerDirectionPad * _Nonnull dpad, float xValue, float yValue) {
 			// Convert the given axis values in float (-1 to 1) to ScummVM Joystick
 			// Axis value as integers (0 to int16_max)
@@ -105,12 +116,6 @@
 		_controller.extendedGamepad.rightShoulder.valueChangedHandler = ^(GCControllerButtonInput * _Nonnull button, float value, BOOL pressed) {
 			[self handleJoystickButtonAction:Common::JOYSTICK_BUTTON_RIGHT_SHOULDER isPressed:pressed];
 		};
-#ifdef __IPHONE_13_0
-		_controller.extendedGamepad.buttonMenu.valueChangedHandler = ^(GCControllerButtonInput * _Nonnull button, float value, BOOL pressed) {
-			[[self view] addEvent:InternalEvent(kInputMainMenu, 0, 0)];
-
-		};
-#endif
 	}
 }
 
diff --git a/backends/platform/ios7/ios7_touch_controller.mm b/backends/platform/ios7/ios7_touch_controller.mm
index 6e567b4aaea..e68fbe4d2e8 100644
--- a/backends/platform/ios7/ios7_touch_controller.mm
+++ b/backends/platform/ios7/ios7_touch_controller.mm
@@ -59,23 +59,21 @@
 	NSSet *allTouches = [event allTouches];
 	if (allTouches.count == 1) {
 		_firstTouch = [allTouches anyObject];
-		if (_firstTouch.type == UITouchTypeDirect) {
-			if (iOS7_touchpadModeEnabled()) {
-				// In touchpad mode the action should occur on the current pointer position
-				[self handleMouseButtonAction:kGameControllerMouseButtonLeft isPressed:YES at:[[self view] pointerPosition]];
-			} else {
-				// Only move the pointer to the new position if not in touchpadMode else it's very hard to click on items
-				[self handlePointerMoveTo:[_firstTouch locationInView: [self view]]];
-				[self handleMouseButtonAction:kGameControllerMouseButtonLeft isPressed:YES at:[_firstTouch locationInView:[self view]]];
-			}
+		if (iOS7_touchpadModeEnabled()) {
+			// In touchpad mode the action should occur on the current pointer position
+			[self handleMouseButtonAction:kGameControllerMouseButtonLeft isPressed:YES at:[[self view] pointerPosition]];
+		} else if (_firstTouch.type == UITouchTypeDirect) {
+			// Only move the pointer to the new position if not in touchpadMode else it's very hard to click on items
+			[self handlePointerMoveTo:[_firstTouch locationInView: [self view]]];
+			[self handleMouseButtonAction:kGameControllerMouseButtonLeft isPressed:YES at:[_firstTouch locationInView:[self view]]];
 		}
 	} else if (allTouches.count == 2) {
 		_secondTouch = [self secondTouchOtherTouchThan:_firstTouch in:allTouches];
-		if (_secondTouch && _secondTouch.type == UITouchTypeDirect) {
+		if (_secondTouch) {
 			if (iOS7_touchpadModeEnabled()) {
 				// In touchpad mode the action should occur on the current pointer position
 				[self handleMouseButtonAction:kGameControllerMouseButtonRight isPressed:YES at:[[self view] pointerPosition]];
-			} else {
+			} else if (_secondTouch.type == UITouchTypeDirect) {
 				[self handleMouseButtonAction:kGameControllerMouseButtonRight isPressed:YES at:[_secondTouch locationInView:[self view]]];
 			}
 		}
@@ -87,18 +85,16 @@
 	for (UITouch *touch in allTouches) {
 		if (touch == _firstTouch ||
 			touch == _secondTouch) {
-			if (touch.type == UITouchTypeDirect) {
-				if (iOS7_touchpadModeEnabled()) {
-					// Calculate new position for the pointer based on delta of the current and previous location of the touch
-					CGPoint pointerLocation = [[self view] pointerPosition];
-					CGPoint touchLocation = [touch locationInView:[self view]];
-					CGPoint previousTouchLocation = [touch previousLocationInView:[self view]];
-					pointerLocation.y += touchLocation.y - previousTouchLocation.y;
-					pointerLocation.x += touchLocation.x - previousTouchLocation.x;
-					[self handlePointerMoveTo:pointerLocation];
-				} else {
-					[self handlePointerMoveTo:[touch locationInView: [self view]]];
-				}
+			if (iOS7_touchpadModeEnabled() || _firstTouch.type == UITouchTypeIndirect) {
+				// Calculate new position for the pointer based on delta of the current and previous location of the touch
+				CGPoint pointerLocation = [[self view] pointerPosition];
+				CGPoint touchLocation = [touch locationInView:[self view]];
+				CGPoint previousTouchLocation = [touch previousLocationInView:[self view]];
+				pointerLocation.y += touchLocation.y - previousTouchLocation.y;
+				pointerLocation.x += touchLocation.x - previousTouchLocation.x;
+				[self handlePointerMoveTo:pointerLocation];
+			} else if (_firstTouch.type == UITouchTypeDirect) {
+				[self handlePointerMoveTo:[touch locationInView: [self view]]];
 			}
 		}
 	}
@@ -108,12 +104,16 @@
 	NSSet *allTouches = [event allTouches];
 	if (allTouches.count == 1) {
 		UITouch *touch = [allTouches anyObject];
-		if (touch.type == UITouchTypeDirect) {
+		if (iOS7_touchpadModeEnabled()) {
+			[self handleMouseButtonAction:kGameControllerMouseButtonLeft isPressed:NO at:[[self view] pointerPosition]];
+		} else if (touch.type == UITouchTypeDirect) {
 			[self handleMouseButtonAction:kGameControllerMouseButtonLeft isPressed:NO at:[touch locationInView:[self view]]];
 		}
 	} else if (allTouches.count == 2) {
 		UITouch *touch = [[allTouches allObjects] objectAtIndex:1];
-		if (touch.type == UITouchTypeDirect) {
+		if (iOS7_touchpadModeEnabled()) {
+			[self handleMouseButtonAction:kGameControllerMouseButtonRight isPressed:NO at:[[self view] pointerPosition]];
+		} else if (touch.type == UITouchTypeDirect) {
 			[self handleMouseButtonAction:kGameControllerMouseButtonRight isPressed:NO at:[touch locationInView:[self view]]];
 		}
 	}
diff --git a/backends/platform/ios7/ios7_video.mm b/backends/platform/ios7/ios7_video.mm
index 2b8ac9da2ba..d12c81ccd0c 100644
--- a/backends/platform/ios7/ios7_video.mm
+++ b/backends/platform/ios7/ios7_video.mm
@@ -22,6 +22,7 @@
 // Disable symbol overrides so that we can use system headers.
 #define FORBIDDEN_SYMBOL_ALLOW_ALL
 
+#include "common/events.h"
 #include "backends/platform/ios7/ios7_video.h"
 #include "backends/platform/ios7/ios7_touch_controller.h"
 #include "backends/platform/ios7/ios7_mouse_controller.h"
@@ -420,6 +421,34 @@ uint getSizeNextPOT(uint size) {
 	[swipeUp3 release];
 	[swipeDown3 release];
 	[doubleTapTwoFingers release];
+#elif TARGET_OS_TV
+	UITapGestureRecognizer *tapUpGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(threeFingersSwipeUp:)];
+	[tapUpGestureRecognizer setAllowedPressTypes:@[@(UIPressTypeUpArrow)]];
+
+	UITapGestureRecognizer *tapDownGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(threeFingersSwipeDown:)];
+	[tapDownGestureRecognizer setAllowedPressTypes:@[@(UIPressTypeDownArrow)]];
+
+	UITapGestureRecognizer *tapLeftGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(threeFingersSwipeLeft:)];
+	[tapLeftGestureRecognizer setAllowedPressTypes:@[@(UIPressTypeLeftArrow)]];
+
+	UITapGestureRecognizer *tapRightGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(threeFingersSwipeRight:)];
+	[tapRightGestureRecognizer setAllowedPressTypes:@[@(UIPressTypeRightArrow)]];
+
+	UILongPressGestureRecognizer *longPressGestureRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(showKeyboard)];
+	[longPressGestureRecognizer setAllowedPressTypes:@[[NSNumber numberWithInteger:UIPressTypePlayPause]]];
+	[longPressGestureRecognizer setMinimumPressDuration:1.0];
+
+	[self addGestureRecognizer:tapUpGestureRecognizer];
+	[self addGestureRecognizer:tapDownGestureRecognizer];
+	[self addGestureRecognizer:tapLeftGestureRecognizer];
+	[self addGestureRecognizer:tapRightGestureRecognizer];
+	[self addGestureRecognizer:longPressGestureRecognizer];
+
+	[tapUpGestureRecognizer release];
+	[tapDownGestureRecognizer release];
+	[tapLeftGestureRecognizer release];
+	[tapRightGestureRecognizer release];
+	[longPressGestureRecognizer release];
 #endif
 }
 
@@ -950,6 +979,58 @@ uint getSizeNextPOT(uint size) {
 	}
 }
 
+#if TARGET_OS_TV
+// UIKit calls these methods when a button is pressed by the user.
+// These methods are used to determine which button was pressed and
+// to take any needed actions. The default implementation of these
+// methods forwardsm the message up the responder chain.
+// Button presses are already handled by the GameController class for
+// connected game controllers (including the Apple TV remote).
+// The Apple TV remote is not registered as a micro game controller
+// when running the application in tvOS simulator, hence these methods
+// only needs to be implemented for the tvOS simulator to handle presses
+// on the Apple TV remote.
+-(void)pressesBegan:(NSSet<UIPress *> *)presses withEvent:(UIPressesEvent *)event {
+#if TARGET_OS_SIMULATOR
+	UIPress *press = [presses anyObject];
+	if (press.type == UIPressTypeMenu) {
+		// Trigger on pressesEnded
+	} else if (press.type == UIPressTypeSelect || press.type == UIPressTypePlayPause) {
+		[self addEvent:InternalEvent(kInputJoystickButtonDown, press.type == UIPressTypeSelect ? Common::JOYSTICK_BUTTON_A : Common::JOYSTICK_BUTTON_B, 0)];
+	}
+	else {
+		[super pressesBegan:presses withEvent:event];
+	}
+#endif
+}
+
+-(void)pressesEnded:(NSSet<UIPress *> *)presses withEvent:(UIPressesEvent *)event {
+#if TARGET_OS_SIMULATOR
+	UIPress *press = [presses anyObject];
+	if (press.type == UIPressTypeMenu) {
+		[self handleMainMenuKey];
+	} else if (press.type == UIPressTypeSelect || press.type == UIPressTypePlayPause) {
+		[self addEvent:InternalEvent(kInputJoystickButtonUp, press.type == UIPressTypeSelect ? Common::JOYSTICK_BUTTON_A : Common::JOYSTICK_BUTTON_B, 0)];
+	}
+	else {
+		[super pressesEnded:presses withEvent:event];
+	}
+#endif
+}
+
+-(void)pressesChanged:(NSSet<UIPress *> *)presses withEvent:(UIPressesEvent *)event {
+#if TARGET_OS_SIMULATOR
+	[super pressesChanged:presses withEvent:event];
+#endif
+}
+
+-(void)pressesCancelled:(NSSet<UIPress *> *)presses withEvent:(UIPressesEvent *)event {
+#if TARGET_OS_SIMULATOR
+	[super pressesCancelled:presses withEvent:event];
+#endif
+}
+#endif
+
 #if TARGET_OS_IOS
 - (void)keyboardPinch:(UIPinchGestureRecognizer *)recognizer {
 	if ([recognizer scale] < 0.8)
diff --git a/dists/tvos/Info.plist b/dists/tvos/Info.plist
index bf93f76be75..394b91bc925 100644
--- a/dists/tvos/Info.plist
+++ b/dists/tvos/Info.plist
@@ -28,6 +28,10 @@
 			<key>ProfileName</key>
 			<string>ExtendedGamepad</string>
 		</dict>
+		<dict>
+			<key>ProfileName</key>
+			<string>MicroGamepad</string>
+		</dict>
 	</array>
 	<key>GCSupportsControllerUserInteraction</key>
 	<true/>
diff --git a/dists/tvos/Info.plist.in b/dists/tvos/Info.plist.in
index 5603246fcd8..b32a3444b08 100644
--- a/dists/tvos/Info.plist.in
+++ b/dists/tvos/Info.plist.in
@@ -28,6 +28,10 @@
 			<key>ProfileName</key>
 			<string>ExtendedGamepad</string>
 		</dict>
+		<dict>
+			<key>ProfileName</key>
+			<string>MicroGamepad</string>
+		</dict>
 	</array>
 	<key>GCSupportsControllerUserInteraction</key>
 	<true/>


Commit: 694345d8f83a922b9605a7af9f0741d02b090f70
    https://github.com/scummvm/scummvm/commit/694345d8f83a922b9605a7af9f0741d02b090f70
Author: Lars Sundström (l.sundstrom at gmail.com)
Date: 2023-04-27T21:17:09+01:00

Commit Message:
IOS7: Implement keyboard support for Apple TV OS

The UITextView is becoming focused by default in iOS and brings up the
keyboard for user input. This is not the case in tvOS. UITextView in
tvOS is not becoming focused by default and if manually setting it to
focused it will still not bring up the keyboard screen.

The UITextField is however becoming focused in both iOS and tvOS and
requires basically the same implementation. So the UITextView is
replaced with UITextField to bring up keyboard in both iOS and tvOS.

The UIToolbar class is not supported in tvOS. Instead implement the
toolbar as a UITabBar. The UITabBar is set directly as the
inputAccessoryView to the keyboard view in tvOS while in iOS it's put in
a UIScrollView (as the previous UIToolbar) to be able to scale the
inputAccessoryView better for small screens.

The UITabBar behaves a little bit different on iOS and tvOS where in
tvOS the delegate function
-(void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item
is called when navigated to a specific toolbar item, while in iOS called
when clicking on an item. To get the tvOS to trigger action on presses,
add a gesture recognizer to handle touch events.

Since the keyboard view on Apple TV always full screen prompted texts
gets hidden behind the keyboard. Delay the showing of the keyboard to
allow the user to understand what's requested as input.

Changed paths:
    backends/platform/ios7/ios7_keyboard.h
    backends/platform/ios7/ios7_keyboard.mm
    backends/platform/ios7/ios7_osys_video.mm


diff --git a/backends/platform/ios7/ios7_keyboard.h b/backends/platform/ios7/ios7_keyboard.h
index 3fe443dfa36..7efcb84ebc5 100644
--- a/backends/platform/ios7/ios7_keyboard.h
+++ b/backends/platform/ios7/ios7_keyboard.h
@@ -27,14 +27,14 @@
 
 @class TextInputHandler;
 
- at interface SoftKeyboard : UIView<UITextViewDelegate> {
+ at interface SoftKeyboard : UIView<UITextFieldDelegate> {
 	id inputDelegate;
 	TextInputHandler *inputView;
 }
 
 - (id)initWithFrame:(CGRect)frame;
 - (void)dealloc;
-- (UITextView *)inputView;
+- (UITextField *)inputView;
 - (void)setInputDelegate:(id)delegate;
 - (void)handleKeyPress:(unichar)c;
 - (void)handleMainMenuKey;
diff --git a/backends/platform/ios7/ios7_keyboard.mm b/backends/platform/ios7/ios7_keyboard.mm
index 0ee0fb9d523..5db19e1a02d 100644
--- a/backends/platform/ios7/ios7_keyboard.mm
+++ b/backends/platform/ios7/ios7_keyboard.mm
@@ -28,11 +28,9 @@
 - (void)setEnablesReturnKeyAutomatically:(BOOL)val;
 @end
 
- at interface TextInputHandler : UITextView {
+ at interface TextInputHandler : UITextField<UITabBarDelegate> {
 	SoftKeyboard *softKeyboard;
-#if TARGET_OS_IOS
-	UIToolbar *toolbar;
-#endif
+	UITabBar *toolbar;
 	UIScrollView *scrollView;
 }
 
@@ -69,47 +67,66 @@
 			item.trailingBarButtonGroups = @[];
 		}
 	}
+#endif
 #endif
 
-	toolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 0.0f, 0.0f)];
+	toolbar = [[UITabBar alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 0.0f, 0.0f)];
 	toolbar.barTintColor = keyboard.backgroundColor;
 	toolbar.tintColor = keyboard.tintColor;
 	toolbar.translucent = NO;
+	toolbar.delegate = self;
 
 	toolbar.items = @[
 		// GMM button
-		[[[UIBarButtonItem alloc] initWithTitle:@"\u2630" style:UIBarButtonItemStylePlain target:self action:@selector(mainMenuKey)] autorelease],
+		[[[UITabBarItem alloc] initWithTitle:@"\u2630" image:nil tag:1] autorelease],
 		// Escape key
-		[[[UIBarButtonItem alloc] initWithTitle:@"Esc" style:UIBarButtonItemStylePlain target:self action:@selector(escapeKey)] autorelease],
+		[[[UITabBarItem alloc] initWithTitle:@"Esc" image:nil tag:2] autorelease],
 		// Tab key
-		[[[UIBarButtonItem alloc] initWithTitle:@"Tab" style:UIBarButtonItemStylePlain target:self action:@selector(tabKey)] autorelease],
+		[[[UITabBarItem alloc] initWithTitle:@"Tab" image:nil tag:3] autorelease],
 		// Return key
-		[[[UIBarButtonItem alloc] initWithTitle:@"\u23ce" style:UIBarButtonItemStylePlain target:self action:@selector(returnKey)] autorelease],
+		[[[UITabBarItem alloc] initWithTitle:@"\u23ce" image:nil tag:4] autorelease],
 		// Function keys
-		[[[UIBarButtonItem alloc] initWithTitle:@"F1" style:UIBarButtonItemStylePlain target:self action:@selector(fn1Key)] autorelease],
-		[[[UIBarButtonItem alloc] initWithTitle:@"F2" style:UIBarButtonItemStylePlain target:self action:@selector(fn2Key)] autorelease],
-		[[[UIBarButtonItem alloc] initWithTitle:@"F3" style:UIBarButtonItemStylePlain target:self action:@selector(fn3Key)] autorelease],
-		[[[UIBarButtonItem alloc] initWithTitle:@"F4" style:UIBarButtonItemStylePlain target:self action:@selector(fn4Key)] autorelease],
-		[[[UIBarButtonItem alloc] initWithTitle:@"F5" style:UIBarButtonItemStylePlain target:self action:@selector(fn5Key)] autorelease],
-		[[[UIBarButtonItem alloc] initWithTitle:@"F6" style:UIBarButtonItemStylePlain target:self action:@selector(fn6Key)] autorelease],
-		[[[UIBarButtonItem alloc] initWithTitle:@"F7" style:UIBarButtonItemStylePlain target:self action:@selector(fn7Key)] autorelease],
-		[[[UIBarButtonItem alloc] initWithTitle:@"F8" style:UIBarButtonItemStylePlain target:self action:@selector(fn8Key)] autorelease],
-		[[[UIBarButtonItem alloc] initWithTitle:@"F9" style:UIBarButtonItemStylePlain target:self action:@selector(fn9Key)] autorelease],
-		[[[UIBarButtonItem alloc] initWithTitle:@"F10" style:UIBarButtonItemStylePlain target:self action:@selector(fn10Key)] autorelease],
-		[[[UIBarButtonItem alloc] initWithTitle:@"F11" style:UIBarButtonItemStylePlain target:self action:@selector(fn11Key)] autorelease],
-		[[[UIBarButtonItem alloc] initWithTitle:@"F12" style:UIBarButtonItemStylePlain target:self action:@selector(fn12Key)] autorelease],
+		[[[UITabBarItem alloc] initWithTitle:@"F1" image:nil tag:5] autorelease],
+		[[[UITabBarItem alloc] initWithTitle:@"F2" image:nil tag:6] autorelease],
+		[[[UITabBarItem alloc] initWithTitle:@"F3" image:nil tag:7] autorelease],
+		[[[UITabBarItem alloc] initWithTitle:@"F4" image:nil tag:8] autorelease],
+		[[[UITabBarItem alloc] initWithTitle:@"F5" image:nil tag:9] autorelease],
+		[[[UITabBarItem alloc] initWithTitle:@"F6" image:nil tag:10] autorelease],
+		[[[UITabBarItem alloc] initWithTitle:@"F7" image:nil tag:11] autorelease],
+		[[[UITabBarItem alloc] initWithTitle:@"F8" image:nil tag:12] autorelease],
+		[[[UITabBarItem alloc] initWithTitle:@"F9" image:nil tag:13] autorelease],
+		[[[UITabBarItem alloc] initWithTitle:@"F10" image:nil tag:14] autorelease],
+		[[[UITabBarItem alloc] initWithTitle:@"F11" image:nil tag:15] autorelease],
+		[[[UITabBarItem alloc] initWithTitle:@"F12" image:nil tag:16] autorelease],
 		// Arrow keys
-		[[[UIBarButtonItem alloc] initWithTitle:@"\u2190" style:UIBarButtonItemStylePlain target:self action:@selector(leftArrowKey)] autorelease],
-		[[[UIBarButtonItem alloc] initWithTitle:@"\u2191" style:UIBarButtonItemStylePlain target:self action:@selector(upArrowKey)] autorelease],
-		[[[UIBarButtonItem alloc] initWithTitle:@"\u2192" style:UIBarButtonItemStylePlain target:self action:@selector(rightArrowKey)] autorelease],
-		[[[UIBarButtonItem alloc] initWithTitle:@"\u2193" style:UIBarButtonItemStylePlain target:self action:@selector(downArrowKey)] autorelease],
-		// Spacer at the end
-		[[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil] autorelease],
+		[[[UITabBarItem alloc] initWithTitle:@"\u2190" image:nil tag:17] autorelease],
+		[[[UITabBarItem alloc] initWithTitle:@"\u2191" image:nil tag:18] autorelease],
+		[[[UITabBarItem alloc] initWithTitle:@"\u2192" image:nil tag:19] autorelease],
+		[[[UITabBarItem alloc] initWithTitle:@"\u2193" image:nil tag:20] autorelease]
 	];
 
+	// Increase the font size on the UITabBarItems to make them readable on small displays
+	for (UITabBarItem *item in toolbar.items) {
+		[item setTitleTextAttributes: [NSDictionary dictionaryWithObjectsAndKeys: [UIFont fontWithName:@"Helvetica" size:20.0], NSFontAttributeName, nil] forState:UIControlStateNormal];
+	}
+
+#if TARGET_OS_TV
+	// In tvOS a UITabBarItem is selected when moving to the selected item, in other words
+	// no click is required. This is not a great user experience since the user needs to
+	// scroll to the wanted UITabBarItem causing the delegate function
+	// tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item to be called multiple
+	// times. Instead add a tap gesture on the UITabBar and let the delegate function set
+	// the selected item. Then trigger the action when the user press the button.
+	UITapGestureRecognizer *tapGesture = [[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(selectUITabBarItem:)] autorelease];
+	[toolbar addGestureRecognizer:tapGesture];
+#endif
+
 	self.inputAccessoryView = toolbar;
 	[toolbar sizeToFit];
 
+#if TARGET_OS_IOS
+	// In tvOS the UITabBar is scrollable but not in iOS. In iOS the UITabBar must be
+	// put in a UIScrollView to be scrollable.
 	scrollView = [[UIScrollView alloc] init];
 	scrollView.frame = toolbar.frame;
 	scrollView.bounds = toolbar.bounds;
@@ -125,22 +142,96 @@
 }
 
 -(void)dealloc {
-#if TARGET_OS_IOS
 	[toolbar release];
-#endif
 	[scrollView release];
 	[super dealloc];
 }
 
+-(void)selectUITabBarItem:(UITapGestureRecognizer *)recognizer {
+	switch ([[toolbar selectedItem] tag]) {
+	case 1:
+		[self mainMenuKey];
+		break;
+	case 2:
+		[self escapeKey];
+		break;
+	case 3:
+		[self tabKey];
+		break;
+	case 4:
+		[self returnKey];
+		break;
+	case 5:
+		[self fn1Key];
+		break;
+	case 6:
+		[self fn2Key];
+		break;
+	case 7:
+		[self fn3Key];
+		break;
+	case 8:
+		[self fn4Key];
+		break;
+	case 9:
+		[self fn5Key];
+		break;
+	case 10:
+		[self fn6Key];
+		break;
+	case 11:
+		[self fn7Key];
+		break;
+	case 12:
+		[self fn8Key];
+		break;
+	case 13:
+		[self fn9Key];
+		break;
+	case 14:
+		[self fn10Key];
+		break;
+	case 15:
+		[self fn11Key];
+		break;
+	case 16:
+		[self fn12Key];
+		break;
+	case 17:
+		[self leftArrowKey];
+		break;
+	case 18:
+		[self upArrowKey];
+		break;
+	case 19:
+		[self rightArrowKey];
+		break;
+	case 20:
+		[self downArrowKey];
+		break;
+	default:
+		break;
+	}
+}
+
+-(void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item {
+#if TARGET_OS_IOS
+	// In iOS the UITabBarItem is selected on touch. Trigger the action
+	// on the selected item.
+	[self selectUITabBarItem:nil];
+#endif
+}
+
 - (void)attachAccessoryView {
 	self.inputAccessoryView.hidden = NO;
 	// Alternatively we could add/remove instead of show/hide the inpute accessory view
 //	self.inputAccessoryView = scrollView;
 //	[self reloadInputViews];
-	// We need at least a width of 768 pt for the toolbar. If we add more buttons this may need to be increased.
-#if TARGET_OS_IOS
-	toolbar.frame = CGRectMake(0, 0, MAX(768, [[UIScreen mainScreen] bounds].size.width), toolbar.frame.size.height);
+	// We need at least a width of 1024 pt for the toolbar. If we add more buttons this may need to be increased.
+	toolbar.frame = CGRectMake(0, 0, MAX(1024, [[UIScreen mainScreen] bounds].size.width), toolbar.frame.size.height);
 	toolbar.bounds = toolbar.frame;
+	toolbar.selectedItem = nil;
+#if TARGET_OS_IOS
 	scrollView.contentSize = toolbar.frame.size;
 #endif
 }
@@ -283,6 +374,9 @@
 	inputDelegate = nil;
 	inputView = [[TextInputHandler alloc] initWithKeyboard:self];
 	inputView.delegate = self;
+	inputView.clearsOnBeginEditing = YES;
+	[inputView layoutIfNeeded];
+
 #if TARGET_OS_IOS
 	[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(prepareKeyboard:) name:UIKeyboardWillShowNotification object:nil];
 #endif
@@ -294,7 +388,7 @@
 	[super dealloc];
 }
 
-- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
+- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)text {
 	unichar c;
 	if (text.length) {
 		c = [text characterAtIndex:0];
@@ -306,7 +400,14 @@
 	return YES;
 }
 
-- (UITextView *)inputView {
+- (void)textFieldDidBeginEditing:(UITextField *)textField {
+	[inputView attachAccessoryView];
+}
+- (void)textFieldDidEndEditing:(UITextField *)textField {
+	[inputView detachAccessoryView];
+}
+
+-(UITextField *)inputView {
 	return inputView;
 }
 
diff --git a/backends/platform/ios7/ios7_osys_video.mm b/backends/platform/ios7/ios7_osys_video.mm
index 7ac0b815973..ce3702f184b 100644
--- a/backends/platform/ios7/ios7_osys_video.mm
+++ b/backends/platform/ios7/ios7_osys_video.mm
@@ -605,9 +605,18 @@ void OSystem_iOS7::updateMouseTexture() {
 
 void OSystem_iOS7::setShowKeyboard(bool show) {
 	if (show) {
+#if TARGET_OS_IOS
 		execute_on_main_thread(^ {
 			[[iOS7AppDelegate iPhoneView] showKeyboard];
 		});
+#elif TARGET_OS_TV
+		// Delay the showing of keyboard 1 second so the user
+		// is able to see the message
+		dispatch_time_t delay = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC));
+		dispatch_after(delay, dispatch_get_main_queue(), ^(void){
+			[[iOS7AppDelegate iPhoneView] showKeyboard];
+		});
+#endif
 	} else {
 		// Do not hide the keyboard in portrait mode as it is shown automatically and not
 		// just when asked with the kFeatureVirtualKeyboard.


Commit: 1ff4fe81493aba9ed6cf478aed8b013f1007c76b
    https://github.com/scummvm/scummvm/commit/1ff4fe81493aba9ed6cf478aed8b013f1007c76b
Author: Lars Sundström (l.sundstrom at gmail.com)
Date: 2023-04-27T21:17:22+01:00

Commit Message:
IOS7: Forward backward key presses when textField is empty

There's a difference between UITextFields and UITextViews that the
delegate function textView:shouldChangeTextInRange:replacementText:
is called when pressing the backward button on a keyboard also when
the textView is empty. This is not the case for UITextFields, the
function textField:shouldChangeTextInRange:replacementText: is not
called if the textField is empty which is problematic in the cases
where there's already text in the open dialog (e.g. the save dialog
when the user wants to overwrite an existing slot). There's currently
no possibility to propagate existing text elements from dialog into
the textField. To be able to handle the cases where the user wants to
delete existing texts when the textField is empty the inputView has
to implement the UITextInput protocol function deleteBackward that is
called every time the backward key is pressed.

Changed paths:
    backends/platform/ios7/ios7_keyboard.mm


diff --git a/backends/platform/ios7/ios7_keyboard.mm b/backends/platform/ios7/ios7_keyboard.mm
index 5db19e1a02d..632eb14e7c4 100644
--- a/backends/platform/ios7/ios7_keyboard.mm
+++ b/backends/platform/ios7/ios7_keyboard.mm
@@ -28,7 +28,7 @@
 - (void)setEnablesReturnKeyAutomatically:(BOOL)val;
 @end
 
- at interface TextInputHandler : UITextField<UITabBarDelegate> {
+ at interface TextInputHandler : UITextField<UITabBarDelegate, UITextInput> {
 	SoftKeyboard *softKeyboard;
 	UITabBar *toolbar;
 	UIScrollView *scrollView;
@@ -147,6 +147,34 @@
 	[super dealloc];
 }
 
+/* There's a difference between UITextFields and UITextViews that the
+ * delegate function textView:shouldChangeTextInRange:replacementText:
+ * is called when pressing the backward button on a keyboard also when
+ * the textView is empty. This is not the case for UITextFields, the
+ * function textField:shouldChangeTextInRange:replacementText: is not
+ * called if the textField is empty which is problematic in the cases
+ * where there's already text in the open dialog (e.g. the save dialog
+ * when the user wants to overwrite an existing slot). There's currently
+ * no possibility to propagate existing text elements from dialog into
+ * the textField. To be able to handle the cases where the user wants to
+ * delete existing texts when the textField is empty the inputView has
+ * to implement the UITextInput protocol function deleteBackward that is
+ * called every time the backward key is pressed. */
+-(void)deleteBackward {
+	if ([self hasText]) {
+		/* If the textField has text the backward key presses will be
+		 * forwarded to the EventManager in the delegate function
+		 * textField:shouldChangeTextInRange:replacementText:
+		 * call the super class to delete characters in the textField */
+		[super deleteBackward];
+	} else {
+		/* Forward the key press to the EventManager also in the cases
+		 * where the textField is empty to remove prefilled characters
+		 * in dialogs. */
+		[softKeyboard handleKeyPress:'\b'];
+	}
+}
+
 -(void)selectUITabBarItem:(UITapGestureRecognizer *)recognizer {
 	switch ([[toolbar selectedItem] tag]) {
 	case 1:


Commit: a7c2a8b2d91af4a34c6ce463c21de89212774fb6
    https://github.com/scummvm/scummvm/commit/a7c2a8b2d91af4a34c6ce463c21de89212774fb6
Author: Lars Sundström (l.sundstrom at gmail.com)
Date: 2023-04-27T21:17:36+01:00

Commit Message:
IOS7: Replace UIAlertView with UIAlertAction

The UIAlertView was deprecated in iOS 9 and therefore not supported in
tvOS. Replace the UIAlertView with the suggested UIAlertAction, which is
supported by both iOS and tvOS.

Define a macro to find the root view controller of a view. Use the view
controller of the iPhoneView to present the alert.

Changed paths:
    backends/platform/ios7/ios7_osys_video.mm


diff --git a/backends/platform/ios7/ios7_osys_video.mm b/backends/platform/ios7/ios7_osys_video.mm
index ce3702f184b..1b41104a8c8 100644
--- a/backends/platform/ios7/ios7_osys_video.mm
+++ b/backends/platform/ios7/ios7_osys_video.mm
@@ -28,32 +28,29 @@
 #include "graphics/blit.h"
 #include "backends/platform/ios7/ios7_app_delegate.h"
 
-#if TARGET_OS_IOS
- at interface iOS7AlertHandler : NSObject<UIAlertViewDelegate>
- at end
-
- at implementation iOS7AlertHandler
+#define UIViewParentController(__view) ({ \
+	UIResponder *__responder = __view; \
+	while ([__responder isKindOfClass:[UIView class]]) \
+		__responder = [__responder nextResponder]; \
+	(UIViewController *)__responder; \
+})
 
-- (void)alertView:(UIAlertView *)alertView willDismissWithButtonIndex:(NSInteger)buttonIndex {
-	OSystem_iOS7::sharedInstance()->quit();
-	abort();
-}
+static void displayAlert(void *ctx) {
+	UIAlertController* alert = [UIAlertController alertControllerWithTitle:@"Fatal Error"
+								message:[NSString stringWithCString:(const char *)ctx 	encoding:NSUTF8StringEncoding]
+								preferredStyle:UIAlertControllerStyleAlert];
 
- at end
+	UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault
+	   handler:^(UIAlertAction * action) {
+		OSystem_iOS7::sharedInstance()->quit();
+		abort();
+	}];
 
-static void displayAlert(void *ctx) {
-	UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Fatal Error"
-	                                                message:[NSString stringWithCString:(const char *)ctx encoding:NSUTF8StringEncoding]
-	                                               delegate:[[iOS7AlertHandler alloc] init]
-	                                      cancelButtonTitle:@"OK"
-	                                      otherButtonTitles:nil];
-	[alert show];
-	[alert autorelease];
+	[alert addAction:defaultAction];
+	[UIViewParentController([iOS7AppDelegate iPhoneView]) presentViewController:alert animated:YES completion:nil];
 }
-#endif
 
 void OSystem_iOS7::fatalError() {
-#if TARGET_OS_IOS
 	if (_lastErrorMessage.size()) {
 		dispatch_async_f(dispatch_get_main_queue(), (void *)_lastErrorMessage.c_str(), displayAlert);
 		for(;;);
@@ -61,7 +58,6 @@ void OSystem_iOS7::fatalError() {
 	else {
 		OSystem::fatalError();
 	}
-#endif
 }
 
 void OSystem_iOS7::logMessage(LogMessageType::Type type, const char *message) {


Commit: 314590e65411883c29198b5636947f027a13f04e
    https://github.com/scummvm/scummvm/commit/314590e65411883c29198b5636947f027a13f04e
Author: Lars Sundström (l.sundstrom at gmail.com)
Date: 2023-04-27T21:17:48+01:00

Commit Message:
IOS7: Show inputAccessoryView when hardware keyboad is connected

The inputAccessoryView is only shown if no hardware keyboard is
connected. Some hardware keyboards doesn't necessary have all keys,
e.g. the Apple magic keyboard to the iPads which lacks the escape
key and all function keys.

To give the user the possibility to use these buttons, always show
the inputAccessoryView.

Changed paths:
    backends/platform/ios7/ios7_keyboard.h
    backends/platform/ios7/ios7_keyboard.mm


diff --git a/backends/platform/ios7/ios7_keyboard.h b/backends/platform/ios7/ios7_keyboard.h
index 7efcb84ebc5..d33cdc980e7 100644
--- a/backends/platform/ios7/ios7_keyboard.h
+++ b/backends/platform/ios7/ios7_keyboard.h
@@ -39,7 +39,6 @@
 - (void)handleKeyPress:(unichar)c;
 - (void)handleMainMenuKey;
 
-- (void)prepareKeyboard:(NSNotification *)notification;
 - (void)showKeyboard;
 - (void)hideKeyboard;
 
diff --git a/backends/platform/ios7/ios7_keyboard.mm b/backends/platform/ios7/ios7_keyboard.mm
index 632eb14e7c4..95d5460b7a1 100644
--- a/backends/platform/ios7/ios7_keyboard.mm
+++ b/backends/platform/ios7/ios7_keyboard.mm
@@ -405,9 +405,6 @@
 	inputView.clearsOnBeginEditing = YES;
 	[inputView layoutIfNeeded];
 
-#if TARGET_OS_IOS
-	[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(prepareKeyboard:) name:UIKeyboardWillShowNotification object:nil];
-#endif
 	return self;
 }
 
@@ -451,23 +448,6 @@
 	[inputDelegate handleMainMenuKey];
 }
 
-- (void)prepareKeyboard:(NSNotification *)notification {
-#if TARGET_OS_IOS
-	// Check if a hardware keyboard is connected, and only show the accessory view if there isn't one.
-	// If there is a hardware keyboard, the software one will only contains the text assistance bar
-	// and will be small (less than 100 pt, but use a bit more in case it changes with future iOS versions).
-	// This only works with iOS 9 and above. For ealier version the keyboard size is fixed and instead it
-	// only shows part of the keyboard (which could be detected with the origin position, but that would
-	// depend on the current orientation and screen resolution).
-	NSDictionary* info = [notification userInfo];
-	CGRect keyboardEndFrame = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
-	if (keyboardEndFrame.size.height < 140)
-		[inputView detachAccessoryView];
-	else
-		[inputView attachAccessoryView];
-#endif
-}
-
 - (void)showKeyboard {
 	[inputView becomeFirstResponder];
 }


Commit: 80cb6427e1e2d2d69c3c25b932ae4a05cdcfbef6
    https://github.com/scummvm/scummvm/commit/80cb6427e1e2d2d69c3c25b932ae4a05cdcfbef6
Author: Lars Sundström (l.sundstrom at gmail.com)
Date: 2023-04-27T21:17:58+01:00

Commit Message:
IOS7: Trigger joystick presses only once for buttons A and B

All buttons and triggers on MFi game controllers are pressure sensitive
which means that when pressing buttons the registered
valueChangedHandler function is called multiple times providing updates
on the pressure value the button is pressed with. This causes multiple
kInputJoystickButtonDown events to be sent to the EventManager.
In adventure games the pressure value is not relevant and could cause
problems for the user that it triggers multiple presses on e.g. the B
button which often is mapped to the right mouse button. In some games
a click on the right mouse button changes what action that should be
performed.

Keep track on if the joystick buttons A or B (often mapped as left and
right mouse buttons) are being pressed. If the button is already
pressed do not add a new event until the button isn't pressed anymore.

To not interfere with any open dialog, don't send key events while the
keyboard is visible.

Changed paths:
    backends/platform/ios7/ios7_game_controller.mm


diff --git a/backends/platform/ios7/ios7_game_controller.mm b/backends/platform/ios7/ios7_game_controller.mm
index 1c0c365ad6b..4c17e058c0f 100644
--- a/backends/platform/ios7/ios7_game_controller.mm
+++ b/backends/platform/ios7/ios7_game_controller.mm
@@ -117,7 +117,30 @@
 }
 
 - (void)handleJoystickButtonAction:(int)button isPressed:(bool)pressed {
-	[view addEvent:InternalEvent(pressed ? kInputJoystickButtonDown : kInputJoystickButtonUp, button, 0)];
+	bool addEvent = true;
+	if (button == Common::JOYSTICK_BUTTON_A) {
+		if (_firstButtonPressed) {
+			if (pressed) {
+				addEvent = false;
+			}
+		}
+		_firstButtonPressed = pressed;
+	} else if (button == Common::JOYSTICK_BUTTON_B) {
+		if (_secondButtonPressed) {
+			if (pressed) {
+				addEvent = false;
+			}
+		}
+		_secondButtonPressed = pressed;
+	}
+	// Do not send button presses if keyboard is shown because if e.g.
+	// the "Do you want to quit?" dialog is shown the wait for user
+	// input will end (treating the button push as a mouse click) while
+	// the user tried to select the "y" or "n" character on the tvOS
+	// keyboard.
+	if (addEvent && ![view isKeyboardShown]) {
+		[view addEvent:InternalEvent(pressed ? kInputJoystickButtonDown : kInputJoystickButtonUp, button, 0)];
+	}
 }
 
 @end


Commit: 2c351f85ee072ada40be299a32db8e4a7a72ba43
    https://github.com/scummvm/scummvm/commit/2c351f85ee072ada40be299a32db8e4a7a72ba43
Author: Lars Sundström (l.sundstrom at gmail.com)
Date: 2023-04-27T21:18:08+01:00

Commit Message:
IOS7: Check keyboard visible if inputView being first responder

The keyboard can be presented and dismissed without being triggered by
the showKeyboard/hideKeyboard functions e.g. by pressing the menu button
on the Apple TV remote while the keyboard is shown.
If the keyboard visibility is not set entirely by the showKeyboard/
hideKeyboard functions that means that the _keyboardVisible state
variable can be out of sync.

Check if the keyboard is shown based on if the inputView is the first
responder or not. The check has to be made on the main thread.

Changed paths:
    backends/platform/ios7/ios7_keyboard.h
    backends/platform/ios7/ios7_keyboard.mm
    backends/platform/ios7/ios7_osys_video.mm
    backends/platform/ios7/ios7_video.h
    backends/platform/ios7/ios7_video.mm


diff --git a/backends/platform/ios7/ios7_keyboard.h b/backends/platform/ios7/ios7_keyboard.h
index d33cdc980e7..3e6f7c7930c 100644
--- a/backends/platform/ios7/ios7_keyboard.h
+++ b/backends/platform/ios7/ios7_keyboard.h
@@ -41,6 +41,7 @@
 
 - (void)showKeyboard;
 - (void)hideKeyboard;
+- (BOOL)isKeyboardShown;
 
 @end
 
diff --git a/backends/platform/ios7/ios7_keyboard.mm b/backends/platform/ios7/ios7_keyboard.mm
index 95d5460b7a1..a20568eb767 100644
--- a/backends/platform/ios7/ios7_keyboard.mm
+++ b/backends/platform/ios7/ios7_keyboard.mm
@@ -456,4 +456,7 @@
 	[inputView endEditing:YES];
 }
 
+- (BOOL)isKeyboardShown {
+	return [inputView isFirstResponder];
+}
 @end
diff --git a/backends/platform/ios7/ios7_osys_video.mm b/backends/platform/ios7/ios7_osys_video.mm
index 1b41104a8c8..b1495b15edf 100644
--- a/backends/platform/ios7/ios7_osys_video.mm
+++ b/backends/platform/ios7/ios7_osys_video.mm
@@ -625,5 +625,9 @@ void OSystem_iOS7::setShowKeyboard(bool show) {
 }
 
 bool OSystem_iOS7::isKeyboardShown() const {
-	return [[iOS7AppDelegate iPhoneView] isKeyboardShown];
+	__block bool isShown = false;
+	execute_on_main_thread(^{
+		isShown = [[iOS7AppDelegate iPhoneView] isKeyboardShown];
+	});
+	return isShown;
 }
diff --git a/backends/platform/ios7/ios7_video.h b/backends/platform/ios7/ios7_video.h
index d0b34bc8a79..922f037e125 100644
--- a/backends/platform/ios7/ios7_video.h
+++ b/backends/platform/ios7/ios7_video.h
@@ -50,7 +50,6 @@ uint getSizeNextPOT(uint size);
 	Common::List<InternalEvent> _events;
 	NSLock *_eventLock;
 	SoftKeyboard *_keyboardView;
-	BOOL _keyboardVisible;
 	Common::List<GameController*> _controllers;
 
 	UIBackgroundTaskIdentifier _backgroundSaveStateTask;
diff --git a/backends/platform/ios7/ios7_video.mm b/backends/platform/ios7/ios7_video.mm
index d12c81ccd0c..7ec9eb9ad91 100644
--- a/backends/platform/ios7/ios7_video.mm
+++ b/backends/platform/ios7/ios7_video.mm
@@ -468,7 +468,6 @@ uint getSizeNextPOT(uint size) {
 	[self setContentScaleFactor:[[UIScreen mainScreen] scale]];
 
 	_keyboardView = nil;
-	_keyboardVisible = NO;
 	_screenTexture = 0;
 	_overlayTexture = 0;
 	_mouseCursorTexture = 0;
@@ -935,16 +934,14 @@ uint getSizeNextPOT(uint size) {
 
 - (void)showKeyboard {
 	[_keyboardView showKeyboard];
-	_keyboardVisible = YES;
 }
 
 - (void)hideKeyboard {
 	[_keyboardView hideKeyboard];
-	_keyboardVisible = NO;
 }
 
 - (BOOL)isKeyboardShown {
-	return _keyboardVisible;
+	return [_keyboardView isKeyboardShown];
 }
 
 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {


Commit: eb4028880e648da49e7d494d7b90ceae36d8d3cd
    https://github.com/scummvm/scummvm/commit/eb4028880e648da49e7d494d7b90ceae36d8d3cd
Author: Lars Sundström (l.sundstrom at gmail.com)
Date: 2023-04-27T21:18:23+01:00

Commit Message:
IOS7: Suspend application if menu key pressed and no game is running

Add isInGame property to track if the launcher is shown of if a game is
running. Handle press on menu key different depending on if launcher is
shown or not. If launcher is shown suspend the application to return to
Apple TV Home Screen since that is the parent view of the launcher. If
in game pause the game and show menu. This is according to Apple
guidelines which can ge read here:
https://developer.apple.com/design/human-interface-guidelines/inputs/remotes

Changed paths:
    backends/platform/ios7/ios7_osys_video.mm
    backends/platform/ios7/ios7_video.h
    backends/platform/ios7/ios7_video.mm


diff --git a/backends/platform/ios7/ios7_osys_video.mm b/backends/platform/ios7/ios7_osys_video.mm
index b1495b15edf..e4a3e5b0ce5 100644
--- a/backends/platform/ios7/ios7_osys_video.mm
+++ b/backends/platform/ios7/ios7_osys_video.mm
@@ -84,6 +84,7 @@ void OSystem_iOS7::engineInit() {
 	dispatch_async(dispatch_get_main_queue(), ^{
 		[[UIApplication sharedApplication] setIdleTimerDisabled:YES];
 	});
+	[[iOS7AppDelegate iPhoneView] setIsInGame:YES];
 }
 
 void OSystem_iOS7::engineDone() {
@@ -92,6 +93,7 @@ void OSystem_iOS7::engineDone() {
 	dispatch_async(dispatch_get_main_queue(), ^{
 		[[UIApplication sharedApplication] setIdleTimerDisabled:NO];
 	});
+	[[iOS7AppDelegate iPhoneView] setIsInGame:NO];
 }
 
 void OSystem_iOS7::initVideoContext() {
diff --git a/backends/platform/ios7/ios7_video.h b/backends/platform/ios7/ios7_video.h
index 922f037e125..d0d9509feae 100644
--- a/backends/platform/ios7/ios7_video.h
+++ b/backends/platform/ios7/ios7_video.h
@@ -94,6 +94,7 @@ uint getSizeNextPOT(uint size);
 }
 
 @property (nonatomic, assign) CGPoint pointerPosition;
+ at property (nonatomic, assign) BOOL isInGame;
 
 - (id)initWithFrame:(struct CGRect)frame;
 
diff --git a/backends/platform/ios7/ios7_video.mm b/backends/platform/ios7/ios7_video.mm
index 7ec9eb9ad91..0a40b46e2db 100644
--- a/backends/platform/ios7/ios7_video.mm
+++ b/backends/platform/ios7/ios7_video.mm
@@ -1082,7 +1082,11 @@ uint getSizeNextPOT(uint size) {
 }
 
 - (void)handleMainMenuKey {
-	[self addEvent:InternalEvent(kInputMainMenu, 0, 0)];
+	if ([self isInGame]) {
+		[self addEvent:InternalEvent(kInputMainMenu, 0, 0)];
+	} else {
+		[[UIApplication sharedApplication] performSelector:@selector(suspend)];
+	}
 }
 
 - (void)applicationSuspend {


Commit: 1ace0305ceaaa0c04d3845f70ff482fbb7beaed6
    https://github.com/scummvm/scummvm/commit/1ace0305ceaaa0c04d3845f70ff482fbb7beaed6
Author: Lars Sundström (l.sundstrom at gmail.com)
Date: 2023-04-27T21:18:34+01:00

Commit Message:
IOS7: Add general handling of the menu button on game controllers

Expose the handleMainMenuKey function and call that when pressing the
menu button on game controllers.

Changed paths:
    backends/platform/ios7/ios7_game_controller.h
    backends/platform/ios7/ios7_game_controller.mm
    backends/platform/ios7/ios7_gamepad_controller.mm
    backends/platform/ios7/ios7_video.h


diff --git a/backends/platform/ios7/ios7_game_controller.h b/backends/platform/ios7/ios7_game_controller.h
index f219710cd66..7a061d1f8c0 100644
--- a/backends/platform/ios7/ios7_game_controller.h
+++ b/backends/platform/ios7/ios7_game_controller.h
@@ -50,6 +50,7 @@ typedef enum {
 - (void)handleJoystickAxisMotionX:(int)x andY:(int)y forJoystick:(GameControllerJoystick)joystick;
 - (void)handleJoystickButtonAction:(int)button isPressed:(bool)pressed;
 
+- (void)handleMainMenu:(BOOL)pressed;
 @end
 
 #endif /* BACKENDS_PLATFORM_IOS7_IOS7_GAME_CONTROLLER_H */
diff --git a/backends/platform/ios7/ios7_game_controller.mm b/backends/platform/ios7/ios7_game_controller.mm
index 4c17e058c0f..35af7994c65 100644
--- a/backends/platform/ios7/ios7_game_controller.mm
+++ b/backends/platform/ios7/ios7_game_controller.mm
@@ -143,4 +143,9 @@
 	}
 }
 
+- (void)handleMainMenu:(BOOL)pressed {
+	if (!pressed) { // released
+		[view handleMainMenuKey];
+	}
+}
 @end
diff --git a/backends/platform/ios7/ios7_gamepad_controller.mm b/backends/platform/ios7/ios7_gamepad_controller.mm
index 9f3c0826109..75b26a71903 100644
--- a/backends/platform/ios7/ios7_gamepad_controller.mm
+++ b/backends/platform/ios7/ios7_gamepad_controller.mm
@@ -60,6 +60,12 @@
 			// Map button X to button B because B is mapped to left button
 			[self handleJoystickButtonAction:Common::JOYSTICK_BUTTON_B isPressed:pressed];
 		};
+
+		if (@available(iOS 13.0, tvOS 13.0, *)) {
+			_controller.microGamepad.buttonMenu.valueChangedHandler = ^(GCControllerButtonInput * _Nonnull button, float value, BOOL pressed) {
+				[self handleMainMenu:pressed];
+			};
+		}
 	}
 #endif
 	if (_controller.extendedGamepad != nil) {
@@ -116,6 +122,14 @@
 		_controller.extendedGamepad.rightShoulder.valueChangedHandler = ^(GCControllerButtonInput * _Nonnull button, float value, BOOL pressed) {
 			[self handleJoystickButtonAction:Common::JOYSTICK_BUTTON_RIGHT_SHOULDER isPressed:pressed];
 		};
+
+#ifdef __IPHONE_13_0
+		if (@available(iOS 13.0, tvOS 13.0, *)) {
+			_controller.extendedGamepad.buttonMenu.valueChangedHandler = ^(GCControllerButtonInput * _Nonnull button, float value, BOOL pressed) {
+				[self handleMainMenu:pressed];
+			};
+		}
+#endif
 	}
 }
 
diff --git a/backends/platform/ios7/ios7_video.h b/backends/platform/ios7/ios7_video.h
index d0d9509feae..d848f4705e3 100644
--- a/backends/platform/ios7/ios7_video.h
+++ b/backends/platform/ios7/ios7_video.h
@@ -124,6 +124,8 @@ uint getSizeNextPOT(uint size);
 - (void)hideKeyboard;
 - (BOOL)isKeyboardShown;
 
+- (void)handleMainMenuKey;
+
 - (void)applicationSuspend;
 - (void)applicationResume;
 


Commit: a5cc5e17b8ff9df5e86cd631125145e104f41bc4
    https://github.com/scummvm/scummvm/commit/a5cc5e17b8ff9df5e86cd631125145e104f41bc4
Author: Lars Sundström (l.sundstrom at gmail.com)
Date: 2023-04-27T21:18:43+01:00

Commit Message:
IOS7: Fix compiler warnings

This commit fixes the compiler warnings regarding:
- The local declaration of 'view' hides instance variable [-Wshadow-ivar]
- Some of the gamepad controller buttons is only available in specific
versions of iOS and tvOS.
- Use of non-standard escape character '\E'. \E is a GNU shortcut.

Changed paths:
    backends/platform/ios7/ios7_game_controller.h
    backends/platform/ios7/ios7_game_controller.mm
    backends/platform/ios7/ios7_gamepad_controller.mm
    backends/platform/ios7/ios7_video.mm


diff --git a/backends/platform/ios7/ios7_game_controller.h b/backends/platform/ios7/ios7_game_controller.h
index 7a061d1f8c0..21d03b04ebb 100644
--- a/backends/platform/ios7/ios7_game_controller.h
+++ b/backends/platform/ios7/ios7_game_controller.h
@@ -43,7 +43,7 @@ typedef enum {
 @property (nonatomic, readwrite, retain) iPhoneView *view;
 @property (nonatomic, assign) BOOL isConnected;
 
-- (id)initWithView:(iPhoneView *)view;
+- (id)initWithView:(iPhoneView *)v;
 
 - (void)handlePointerMoveTo:(CGPoint)point;
 - (void)handleMouseButtonAction:(GameControllerMouseButton)button isPressed:(bool)pressed at:(CGPoint)point;
diff --git a/backends/platform/ios7/ios7_game_controller.mm b/backends/platform/ios7/ios7_game_controller.mm
index 35af7994c65..0695df281a8 100644
--- a/backends/platform/ios7/ios7_game_controller.mm
+++ b/backends/platform/ios7/ios7_game_controller.mm
@@ -35,10 +35,10 @@
 
 @synthesize view;
 
-- (id)initWithView:(iPhoneView *)view {
+- (id)initWithView:(iPhoneView *)v {
 	self = [super init];
 	if (self) {
-		[self setView:view];
+		[self setView:v];
 	}
 	_firstButtonPressed = _secondButtonPressed = NO;
 	return self;
diff --git a/backends/platform/ios7/ios7_gamepad_controller.mm b/backends/platform/ios7/ios7_gamepad_controller.mm
index 75b26a71903..07af27f7d34 100644
--- a/backends/platform/ios7/ios7_gamepad_controller.mm
+++ b/backends/platform/ios7/ios7_gamepad_controller.mm
@@ -107,13 +107,17 @@
 			[self handleJoystickButtonAction:Common::JOYSTICK_BUTTON_Y isPressed:pressed];
 		};
 #ifdef __IPHONE_12_1
-		_controller.extendedGamepad.leftThumbstickButton.valueChangedHandler = ^(GCControllerButtonInput * _Nonnull button, float value, BOOL pressed) {
-			[self handleJoystickButtonAction:Common::JOYSTICK_BUTTON_LEFT_STICK isPressed:pressed];
-		};
+		if (@available(iOS 12.1, tvOS 12.1, *)) {
+			_controller.extendedGamepad.leftThumbstickButton.valueChangedHandler = ^(GCControllerButtonInput * _Nonnull button, float value, BOOL pressed) {
+				[self handleJoystickButtonAction:Common::JOYSTICK_BUTTON_LEFT_STICK isPressed:pressed];
+			};
+		}
 
-		_controller.extendedGamepad.rightThumbstickButton.valueChangedHandler = ^(GCControllerButtonInput * _Nonnull button, float value, BOOL pressed) {
-			[self handleJoystickButtonAction:Common::JOYSTICK_BUTTON_RIGHT_STICK isPressed:pressed];
-		};
+		if (@available(iOS 12.1, tvOS 12.1, *)) {
+			_controller.extendedGamepad.rightThumbstickButton.valueChangedHandler = ^(GCControllerButtonInput * _Nonnull button, float value, BOOL pressed) {
+				[self handleJoystickButtonAction:Common::JOYSTICK_BUTTON_RIGHT_STICK isPressed:pressed];
+			};
+		}
 #endif
 		_controller.extendedGamepad.leftShoulder.valueChangedHandler = ^(GCControllerButtonInput * _Nonnull button, float value, BOOL pressed) {
 			[self handleJoystickButtonAction:Common::JOYSTICK_BUTTON_LEFT_SHOULDER isPressed:pressed];
diff --git a/backends/platform/ios7/ios7_video.mm b/backends/platform/ios7/ios7_video.mm
index 0a40b46e2db..cd52295aabd 100644
--- a/backends/platform/ios7/ios7_video.mm
+++ b/backends/platform/ios7/ios7_video.mm
@@ -1075,7 +1075,7 @@ uint getSizeNextPOT(uint size) {
 
 - (void)handleKeyPress:(unichar)c {
 	if (c == '`') {
-		[self addEvent:InternalEvent(kInputKeyPressed, '\E', 0)];
+		[self addEvent:InternalEvent(kInputKeyPressed, '\033', 0)];
 	} else {
 		[self addEvent:InternalEvent(kInputKeyPressed, c, 0)];
 	}


Commit: c38c1512a957a439b71bb546caa5c0bea4e68335
    https://github.com/scummvm/scummvm/commit/c38c1512a957a439b71bb546caa5c0bea4e68335
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-04-27T21:24:16+01:00

Commit Message:
IOS7: Add AppleTV support to configure

Changed paths:
    configure
    dists/tvos/Info.plist
    dists/tvos/Info.plist.in
    ports.mk


diff --git a/configure b/configure
index 7bf16385f42..090b8dfa0e7 100755
--- a/configure
+++ b/configure
@@ -853,6 +853,7 @@ Special configuration feature:
                                            psp for PlayStation Portable
                                            samsungtv for Samsung TV
                                            switch for Nintendo Switch
+                                           tvos for Apple TV (tvOS 9.0+)
                                            wasm32-unknown-emscripten for WebAssembly
                                            wii for Nintendo Wii
 
@@ -1737,6 +1738,12 @@ switch)
 	datadir='${datarootdir}'
 	docdir='${prefix}/doc'
 	;;
+tvos)
+	_host_os=iphone
+	# Remains of configure not knowing about arm64
+	_host_cpu=aarch64
+	_host_alias=arm64-apple-darwin11
+	;;
 wasm32-*)
 	_endian=little # the endian check below fails, but emscripten is always little endian anyway
 	_host_os=emscripten
@@ -3771,6 +3778,13 @@ if test -n "$_host"; then
 			_mt32emu=no
 			_port_mk="backends/platform/psp/psp.mk"
 			;;
+		tvos)
+			add_line_to_config_mk 'IPHONE = 1'
+			append_var DEFINES "-DIPHONE -DIPHONE_IOS7 -DIPHONE_SANDBOXED"
+			_backend="ios7"
+			_seq_midi=no
+			_timidity=no
+			;;
 		samsungtv)
 			append_var DEFINES "-DSAMSUNGTV"
 			append_var DEFINES "-DDISABLE_COMMAND_LINE"
@@ -3874,7 +3888,11 @@ case $_backend in
 		append_var LIBS "-framework QuartzCore -framework CoreFoundation -framework Foundation"
 		append_var LIBS "-framework AudioToolbox -framework CoreAudio -framework SystemConfiguration "
 		append_var LIBS "-framework GameController -framework Accelerate"
-		if test "$_host_cpu" = 'aarch64' ; then
+		if test "$_host" = 'tvos'; then
+			append_var LDFLAGS "-mtvos-version-min=9 -arch arm64"
+			append_var CFLAGS "-mtvos-version-min=9 -arch arm64"
+			append_var CXXFLAGS "-mtvos-version-min=9 -arch arm64"
+		elif test "$_host_cpu" = 'aarch64' ; then
 			append_var LDFLAGS "-miphoneos-version-min=7.1 -arch arm64"
 			append_var CFLAGS "-miphoneos-version-min=7.1 -arch arm64"
 			append_var CXXFLAGS "-miphoneos-version-min=7.1 -arch arm64"
diff --git a/dists/tvos/Info.plist b/dists/tvos/Info.plist
index 394b91bc925..b32a3444b08 100644
--- a/dists/tvos/Info.plist
+++ b/dists/tvos/Info.plist
@@ -46,7 +46,7 @@
 	<key>UILaunchImages</key>
 	<array/>
 	<key>UILaunchStoryboardName</key>
-	<string></string>
+	<string>LaunchScreen_tvos</string>
 	<key>UIPrerenderedIcon</key>
 	<true/>
 	<key>UIRequiresFullScreen</key>
diff --git a/dists/tvos/Info.plist.in b/dists/tvos/Info.plist.in
index b32a3444b08..217894c02fd 100644
--- a/dists/tvos/Info.plist.in
+++ b/dists/tvos/Info.plist.in
@@ -17,11 +17,11 @@
 	<key>CFBundlePackageType</key>
 	<string>APPL</string>
 	<key>CFBundleShortVersionString</key>
-	<string>2.7.0git</string>
+	<string>@VERSION@</string>
 	<key>CFBundleSignature</key>
 	<string>????</string>
 	<key>CFBundleVersion</key>
-	<string>2.7.0git</string>
+	<string>@VERSION@</string>
 	<key>GCSupportedGameControllers</key>
 	<array>
 		<dict>
diff --git a/ports.mk b/ports.mk
index 969faf682ac..82aa475098b 100644
--- a/ports.mk
+++ b/ports.mk
@@ -239,22 +239,6 @@ ios7bundle: iphone
 			print "\t\t</dict>";\
 			print "\t</dict>";\
 			s=2}\
-		/<key>CFBundleIcons~ipad<\/key>/ {\
-			print $$0;\
-			print "\t<dict>";\
-			print "\t\t<key>CFBundlePrimaryIcon</key>";\
-			print "\t\t<dict>";\
-			print "\t\t\t<key>CFBundleIconFiles</key>";\
-			print "\t\t\t<array>";\
-			print "\t\t\t\t<string>AppIcon29x29</string>";\
-			print "\t\t\t\t<string>AppIcon40x40</string>";\
-			print "\t\t\t\t<string>AppIcon60x60</string>";\
-			print "\t\t\t\t<string>AppIcon76x76</string>";\
-			print "\t\t\t\t<string>AppIcon83.5x83.5</string>";\
-			print "\t\t\t</array>";\
-			print "\t\t</dict>";\
-			print "\t</dict>";\
-			s=2}\
 		/<key>UILaunchImages<\/key>/ {\
 			print $$0;\
 			print "\t<array>";\
@@ -359,6 +343,74 @@ endif
 	cp $(srcdir)/dists/ios7/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-750x1334.png $(bundle_name)/LaunchImage-800-667h at 2x.png
 	codesign -s - --deep --force $(bundle_name)
 
+tvosbundle: iphone
+	mkdir -p $(bundle_name)
+	awk 'BEGIN {s=0}\
+		/<key>CFBundleIcons<\/key>/ {\
+			print $$0;\
+			print "\t<dict>";\
+			print "\t\t<key>CFBundlePrimaryIcon</key>";\
+			print "\t\t<string>App Icon</string>";\
+			print "\t</dict>";\
+			s=2}\
+		/<key>TVTopShelfImage<\/key>/ {\
+			print $$0;\
+			print "\t<dict>";\
+			print "\t\t<key>TVTopShelfPrimaryImageWide</key>";\
+			print "\t\t<string>Top Shelf Image</string>";\
+			print "\t\t<key>TVTopShelfPrimaryImage</key>";\
+			print "\t\t<string>Top Shelf Image Wide</string>";\
+			print "\t</dict>";\
+			s=2}\
+		/<key>UILaunchImages<\/key>/ {\
+			print $$0;\
+			print "\t<array>";\
+			print "\t\t<dict>";\
+			print "\t\t\t<key>UILaunchImageMinimumOSVersion</key>";\
+			print "\t\t\t<string>9.0</string>";\
+			print "\t\t\t<key>UILaunchImageName</key>";\
+			print "\t\t\t<string>LaunchImage</string>";\
+			print "\t\t\t<key>UILaunchImageOrientation</key>";\
+			print "\t\t\t<string>Landscape</string>";\
+			print "\t\t\t<key>UILaunchImageSize</key>";\
+			print "\t\t\t<string>{1920, 1080}</string>";\
+			print "\t\t</dict>";\
+			print "\t\t<dict>";\
+			print "\t\t\t<key>UILaunchImageMinimumOSVersion</key>";\
+			print "\t\t\t<string>11.0</string>";\
+			print "\t\t\t<key>UILaunchImageName</key>";\
+			print "\t\t\t<string>LaunchImage</string>";\
+			print "\t\t\t<key>UILaunchImageOrientation</key>";\
+			print "\t\t\t<string>Landscape</string>";\
+			print "\t\t\t<key>UILaunchImageSize</key>";\
+			print "\t\t\t<string>{1920, 1080}</string>";\
+			print "\t\t</dict>";\
+			print "\t</array>";\
+			s=2}\
+		s==0 {print $$0}\
+		s > 0 { s-- }' $(srcdir)/dists/tvos/Info.plist >$(bundle_name)/Info.plist
+	sed -i'' -e 's/$$(PRODUCT_BUNDLE_IDENTIFIER)/org.scummvm.scummvm/' $(bundle_name)/Info.plist
+	sed -i'' -e 's/$$(EXECUTABLE_NAME)/ScummVM/' $(bundle_name)/Info.plist
+	sed -i'' -e '/UILaunchStoryboardName/{N;d;}' $(bundle_name)/Info.plist
+	cp $(DIST_FILES_DOCS) $(bundle_name)/
+	cp $(DIST_FILES_THEMES) $(bundle_name)/
+ifdef DIST_FILES_NETWORKING
+	cp $(DIST_FILES_NETWORKING) $(bundle_name)/
+endif
+ifdef DIST_FILES_ENGINEDATA
+	cp $(DIST_FILES_ENGINEDATA) $(bundle_name)/
+endif
+ifdef DIST_FILES_VKEYBD
+	cp $(DIST_FILES_VKEYBD) $(bundle_name)/
+endif
+ifneq ($(DIST_FILES_SHADERS),)
+	cp $(DIST_FILES_SHADERS) $(bundle_name)/
+endif
+	$(STRIP) scummvm
+	chmod 755 scummvm
+	cp scummvm $(bundle_name)/ScummVM
+	cp -r $(srcdir)/dists/tvos/Assets.car $(bundle_name)/Assets.car
+	codesign -s - --deep --force $(bundle_name)
 
 ifndef WITHOUT_SDL
 OSX_STATIC_LIBS := `$(SDLCONFIG) --prefix=$(STATICLIBPATH) --static-libs`


Commit: 2c60b9a4dc8d7565ea77a026082115adc7d21c76
    https://github.com/scummvm/scummvm/commit/2c60b9a4dc8d7565ea77a026082115adc7d21c76
Author: Lars Sundström (l.sundstrom at gmail.com)
Date: 2023-04-27T21:25:25+01:00

Commit Message:
DOCS: Add draft documentation of Apple TV platform

Add basic documentation needed starting using or developing ScummVM on
the Apple TV.

Changed paths:
  A doc/docportal/other_platforms/tvos.rst


diff --git a/doc/docportal/other_platforms/tvos.rst b/doc/docportal/other_platforms/tvos.rst
new file mode 100644
index 00000000000..0f221bb7946
--- /dev/null
+++ b/doc/docportal/other_platforms/tvos.rst
@@ -0,0 +1,112 @@
+
+==============
+Apple TV OS
+==============
+
+---
+**NOTE**
+
+This page is under development. Only basic information is given to enable ScummVM on Apple TV.
+
+---
+
+This page contains all the information you need to get ScummVM up and running on an Apple TV.
+
+
+Installing ScummVM
+=====================
+There are two ways to install ScummVM on an Apple TV depending on if building the project or downloading a bundle.
+
+Building the project
+************************************
+
+Since the port for Apple TV shares the same code base as the iOS port the instructions for building the project is the same as for iOS. Follow the :doc:`./ios` with the differences that the `tvOS libraries <https://github.com/larsamannen/scummvm-tvos-libs-v1>`_ should be used instead and the ``ScummVM-tvOS`` target should be chosen in Xcode. Use the libraries in the ``appletv`` folder if building for real target and ``appletvsimulator`` if building for simulator. Note that the libraries are built without bitcode since it's not required since tvOS 16.
+
+Downloading and installing ScummVM
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Instructions will be added when packages are available for download.
+
+
+Transferring game files
+========================
+
+---
+**NOTE**
+
+Note that Apple TV applications doesn't have a ``Documents`` folder in which games can be stored. All games are stored in the ``cache`` folder which can be deleted when the system requires the needed space. This could happen if having limited available space and streaming high definition content or installing other applications. Please see https://developer.apple.com/library/archive/documentation/General/Conceptual/AppleTV_PG/OnDemandResources.html for more information.
+
+Make sure to make backups of savegames.
+
+---
+
+ScummVM has built-in cloud functionality, which lets you connect your Google Drive, OneDrive, Box or Dropbox account. For more information, see the :doc:`../use_scummvm/connect_cloud` page. ScummVM also has the ability to run a local web server. For more information, see the :doc:`../use_scummvm/LAN` page.
+
+.. note::
+
+ ScummVM's cloud functionality does not currently support iCloud, however you can upload game folders to your iCloud and then use the Files app on your iOS device to copy these folders into the local ScummVM folder.
+
+
+See :doc:`../use_scummvm/game_files` for more information about game file requirements.
+
+Controls
+============
+
+The Apple TV supports several controllers however no mouse support. External keyboards can be used to help entering text input. Usually the Apple TV remote controller will be used.
+
+Game controllers
+^^^^^^^^^^^^^^^^^^^^
+If running tvOS 14 and later there is support for connected gamepad controllers using the Apple Game Controller framework. "Micro Gamepad Controllers ""Extended Gamepad Controllers" are supported at the moment. For more information visit
+https://developer.apple.com/documentation/gamecontroller/gcmicrogamepad
+https://developer.apple.com/documentation/gamecontroller/gcextendedgamepad
+
+Key mappings on Apple TV remote (also remote app on iOS)
+^^^^^^^^^^^^^^^^^^^^
+
+.. csv-table::
+    :widths: 40 60
+    :header-rows: 1
+    :class: controls
+
+        Button, Action
+        Swipe on Touch area, Controls pointer
+        Press Touch area, Left mouse click
+        Play/Pause, Right mouse click
+        Back/Menu in game, Global Main menu
+        Back/Menu in launcher, Apple TV Home
+        Hold Play/Pause, Show keyboard with extra keys
+        Touch (not press) on top of Touch area, Up arrow key
+        Touch (not press) on left of Touch area, Left arrow key
+        Touch (not press) on right of Touch area, Right arrow key
+        Touch (not press) on bottom of Touch area, Down arrow key
+
+Key mappings on Extended gamepad controller
+^^^^^^^^^^^^^^^^^^^^
+
+.. csv-table::
+    :widths: 40 60
+    :header-rows: 1
+    :class: controls
+
+        Button, Action
+        Left analog joystick, Controls pointer
+        D-Pad, Up, Left, Right, Down arrow buttons
+        A, Left mouse click
+        B, Right mouse click
+        Hold X, Show keyboard with extra keys
+        Menu in game, Global Main menu
+        Menu in launcher, Apple TV Home
+        L1, show game original menu
+
+Paths
+=======
+
+Saved games
+**************
+
+``Savegames/`` in the cache root folder. Access this folder through :doc:`../use_scummvm/LAN`.
+
+Configuration file
+*********************
+
+``Preferences`` in the cache folder. Access this folder through :doc:`../use_scummvm/LAN`.


Commit: 4a864d8039acdaf05c2b8d1a8c916a7d05ae1f02
    https://github.com/scummvm/scummvm/commit/4a864d8039acdaf05c2b8d1a8c916a7d05ae1f02
Author: Cameron Cawley (ccawley2011 at gmail.com)
Date: 2023-04-27T21:25:46+01:00

Commit Message:
DOCS: Fix formatting in the tvOS documentation

Changed paths:
    doc/docportal/index.rst
    doc/docportal/other_platforms/tvos.rst


diff --git a/doc/docportal/index.rst b/doc/docportal/index.rst
index 7d2cff8a0f1..b5687485a8a 100644
--- a/doc/docportal/index.rst
+++ b/doc/docportal/index.rst
@@ -167,6 +167,8 @@ We also have guides on how to get ScummVM running on a wide range of other platf
       ^^^^^^^^^^^^^^^
       :doc:`other_platforms/ios`
 
+      :doc:`other_platforms/tvos`
+
       :doc:`other_platforms/android`
 
       ---
diff --git a/doc/docportal/other_platforms/tvos.rst b/doc/docportal/other_platforms/tvos.rst
index 0f221bb7946..5fdab31bf81 100644
--- a/doc/docportal/other_platforms/tvos.rst
+++ b/doc/docportal/other_platforms/tvos.rst
@@ -3,12 +3,9 @@
 Apple TV OS
 ==============
 
----
-**NOTE**
-
-This page is under development. Only basic information is given to enable ScummVM on Apple TV.
+.. note::
 
----
+ This page is under development. Only basic information is given to enable ScummVM on Apple TV.
 
 This page contains all the information you need to get ScummVM up and running on an Apple TV.
 
@@ -31,14 +28,11 @@ Instructions will be added when packages are available for download.
 Transferring game files
 ========================
 
----
-**NOTE**
-
-Note that Apple TV applications doesn't have a ``Documents`` folder in which games can be stored. All games are stored in the ``cache`` folder which can be deleted when the system requires the needed space. This could happen if having limited available space and streaming high definition content or installing other applications. Please see https://developer.apple.com/library/archive/documentation/General/Conceptual/AppleTV_PG/OnDemandResources.html for more information.
+.. note::
 
-Make sure to make backups of savegames.
+ Note that Apple TV applications doesn't have a ``Documents`` folder in which games can be stored. All games are stored in the ``cache`` folder which can be deleted when the system requires the needed space. This could happen if having limited available space and streaming high definition content or installing other applications. Please see https://developer.apple.com/library/archive/documentation/General/Conceptual/AppleTV_PG/OnDemandResources.html for more information.
 
----
+ Make sure to make backups of savegames.
 
 ScummVM has built-in cloud functionality, which lets you connect your Google Drive, OneDrive, Box or Dropbox account. For more information, see the :doc:`../use_scummvm/connect_cloud` page. ScummVM also has the ability to run a local web server. For more information, see the :doc:`../use_scummvm/LAN` page.
 
@@ -55,13 +49,13 @@ Controls
 The Apple TV supports several controllers however no mouse support. External keyboards can be used to help entering text input. Usually the Apple TV remote controller will be used.
 
 Game controllers
-^^^^^^^^^^^^^^^^^^^^
+********************
 If running tvOS 14 and later there is support for connected gamepad controllers using the Apple Game Controller framework. "Micro Gamepad Controllers ""Extended Gamepad Controllers" are supported at the moment. For more information visit
 https://developer.apple.com/documentation/gamecontroller/gcmicrogamepad
 https://developer.apple.com/documentation/gamecontroller/gcextendedgamepad
 
 Key mappings on Apple TV remote (also remote app on iOS)
-^^^^^^^^^^^^^^^^^^^^
+************************************************************
 
 .. csv-table::
     :widths: 40 60
@@ -81,7 +75,7 @@ Key mappings on Apple TV remote (also remote app on iOS)
         Touch (not press) on bottom of Touch area, Down arrow key
 
 Key mappings on Extended gamepad controller
-^^^^^^^^^^^^^^^^^^^^
+***********************************************
 
 .. csv-table::
     :widths: 40 60
@@ -90,7 +84,7 @@ Key mappings on Extended gamepad controller
 
         Button, Action
         Left analog joystick, Controls pointer
-        D-Pad, Up, Left, Right, Down arrow buttons
+        D-Pad, Up/Left/Right/Down arrow buttons
         A, Left mouse click
         B, Right mouse click
         Hold X, Show keyboard with extra keys


Commit: 5bc748a6593ebf55de15d9f9c04298acd84655e8
    https://github.com/scummvm/scummvm/commit/5bc748a6593ebf55de15d9f9c04298acd84655e8
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-04-27T21:35:02+01:00

Commit Message:
CREATE_PROJECT: Add option to use XCFramework in iOS, tvOS and macOS

The introduction of Apple M1 processor, which is based on the arm64
architecture, makes it impossible to use fat static libraries for iOS
and tvOS since building libraries for the simulators targeting the
arm64 architecture conflicts with the iOS and tvOS native arm64
libraries. It's not possible to have two arm64 libraries targeting
different platforms in the same fat library.

Apple resolves this problem with XCFrameworks. Each XCFramework
contain an Info.plist specifying which platforms and architectures it
targets.

The new iOS and tvOS library package, scummvm-ios7-libs-v3, utilize
the XCFramework format and includes pre-compiled libraries for both
iOS and tvOS with corresponding simulator.

Add the option to use XCFramework in create_project by passing the
switch '--use-xcframework'

Implement support to use XCFrameworks for iOS, tvOS and macOS. If not
passing '--use-xcframework' to create_project, legacy behaviour is
applied.

This commit also add support for mikmod for tvOS.

Changed paths:
    devtools/create_project/create_project.cpp
    devtools/create_project/create_project.h
    devtools/create_project/xcode.cpp
    devtools/create_project/xcode.h


diff --git a/devtools/create_project/create_project.cpp b/devtools/create_project/create_project.cpp
index 24a605dcab0..2f6c2526a63 100644
--- a/devtools/create_project/create_project.cpp
+++ b/devtools/create_project/create_project.cpp
@@ -303,6 +303,8 @@ int main(int argc, char *argv[]) {
 			setup.useWindowsUnicode = true;
 		} else if (!std::strcmp(argv[i], "--use-windows-ansi")) {
 			setup.useWindowsUnicode = false;
+		} else if (!std::strcmp(argv[i], "--use-xcframework")) {
+			setup.useXCFramework = true;
 		} else {
 			std::cerr << "ERROR: Unknown parameter \"" << argv[i] << "\"\n";
 			return -1;
diff --git a/devtools/create_project/create_project.h b/devtools/create_project/create_project.h
index d6407d31b18..01b54aeda2e 100644
--- a/devtools/create_project/create_project.h
+++ b/devtools/create_project/create_project.h
@@ -248,6 +248,7 @@ struct BuildSetup {
 	bool useCanonicalLibNames; ///< Whether to use canonical libraries names or default ones
 	bool useStaticDetection;   ///< Whether to link detection features inside the executable or not.
 	bool useWindowsUnicode;    ///< Whether to use Windows Unicode APIs or ANSI APIs.
+	bool useXCFramework;       ///< Whether to use Apple XCFrameworks instead of static libraries
 
 	BuildSetup() {
 		devTools = false;
@@ -258,6 +259,7 @@ struct BuildSetup {
 		useCanonicalLibNames = false;
 		useStaticDetection = true;
 		useWindowsUnicode = true;
+		useXCFramework = false;
 	}
 
 	bool featureEnabled(std::string feature) const;
diff --git a/devtools/create_project/xcode.cpp b/devtools/create_project/xcode.cpp
index 34093d88864..1d0c68f54aa 100644
--- a/devtools/create_project/xcode.cpp
+++ b/devtools/create_project/xcode.cpp
@@ -434,6 +434,8 @@ void XcodeProvider::setupCopyFilesBuildPhase() {
 
 #define DEF_LOCALLIB_STATIC(lib) DEF_LOCALLIB_STATIC_PATH(lib ".a", lib, false)
 
+#define DEF_LOCALXCFRAMEWORK(xcframework,path) { properties[xcframework".xcframework"] = FileProperty("wrapper.xcframework", xcframework".xcframework", path + "/frameworks/" + xcframework ".xcframework", "\"<group>\""); \
+	ADD_SETTING_ORDER_NOVALUE(children, getHash(xcframework".xcframework"), xcframework".xcframework", fwOrder++); }
 
 /**
  * Sets up the frameworks build phase.
@@ -450,6 +452,13 @@ void XcodeProvider::setupFrameworksBuildPhase(const BuildSetup &setup) {
 	children._hasOrder = true;
 	children._flags = kSettingsAsList;
 
+	std::string projectOutputDirectory;
+#ifdef POSIX
+	char tmpbuf[PATH_MAX];
+	char *rp = realpath(setup.outputDir.c_str(), tmpbuf);
+	projectOutputDirectory = rp;
+#endif
+
 	// Setup framework file properties
 	std::map<std::string, FileProperty> properties;
 	int fwOrder = 0;
@@ -478,9 +487,11 @@ void XcodeProvider::setupFrameworksBuildPhase(const BuildSetup &setup) {
 	// Local libraries
 	if (CONTAINS_DEFINE(setup.defines, "USE_FAAD")) {
 		DEF_LOCALLIB_STATIC("libfaad");
+		DEF_LOCALXCFRAMEWORK("faad", projectOutputDirectory);
 	}
 	if (CONTAINS_DEFINE(setup.defines, "USE_FLAC")) {
 		DEF_LOCALLIB_STATIC("libFLAC");
+		DEF_LOCALXCFRAMEWORK("FLAC", projectOutputDirectory);
 	}
 	if (CONTAINS_DEFINE(setup.defines, "USE_FLUIDLITE")) {
 		DEF_LOCALLIB_STATIC("libfluidlite");
@@ -489,43 +500,60 @@ void XcodeProvider::setupFrameworksBuildPhase(const BuildSetup &setup) {
 		DEF_LOCALLIB_STATIC("libffi");
 		DEF_LOCALLIB_STATIC("libglib-2.0");
 		DEF_SYSTBD("libffi");
+		DEF_LOCALXCFRAMEWORK("fluidsynth", projectOutputDirectory);
+		DEF_LOCALXCFRAMEWORK("ffi", projectOutputDirectory);
+		DEF_LOCALXCFRAMEWORK("intl", projectOutputDirectory);
+		DEF_LOCALXCFRAMEWORK("bz2", projectOutputDirectory);
+		DEF_LOCALXCFRAMEWORK("glib-2.0", projectOutputDirectory);
 	}
 	if (CONTAINS_DEFINE(setup.defines, "USE_FREETYPE2")) {
 		DEF_LOCALLIB_STATIC("libfreetype");
+		DEF_LOCALXCFRAMEWORK("freetype", projectOutputDirectory);
 	}
 	if (CONTAINS_DEFINE(setup.defines, "USE_JPEG")) {
 		DEF_LOCALLIB_STATIC("libjpeg");
+		DEF_LOCALXCFRAMEWORK("jpeg", projectOutputDirectory);
 	}
 	if (CONTAINS_DEFINE(setup.defines, "USE_LIBCURL")) {
 		DEF_LOCALLIB_STATIC("libcurl");
+		DEF_LOCALXCFRAMEWORK("curl", projectOutputDirectory);
 	}
 	if (CONTAINS_DEFINE(setup.defines, "USE_MAD")) {
 		DEF_LOCALLIB_STATIC("libmad");
+		DEF_LOCALXCFRAMEWORK("mad", projectOutputDirectory);
 	}
 	if (CONTAINS_DEFINE(setup.defines, "USE_MPEG2")) {
 		DEF_LOCALLIB_STATIC("libmpeg2");
+		DEF_LOCALXCFRAMEWORK("mpeg2", projectOutputDirectory);
 	}
 	if (CONTAINS_DEFINE(setup.defines, "USE_FRIBIDI")) {
 		DEF_LOCALLIB_STATIC("libfribidi");
+		DEF_LOCALXCFRAMEWORK("fribidi", projectOutputDirectory);
 	}
 	if (CONTAINS_DEFINE(setup.defines, "USE_PNG")) {
 		DEF_LOCALLIB_STATIC("libpng");
+		DEF_LOCALXCFRAMEWORK("png", projectOutputDirectory);
 	}
 	if (CONTAINS_DEFINE(setup.defines, "USE_GIF")) {
 		DEF_LOCALLIB_STATIC("libgif");
+		DEF_LOCALXCFRAMEWORK("gif", projectOutputDirectory);
 	}
 	if (CONTAINS_DEFINE(setup.defines, "USE_OGG")) {
 		DEF_LOCALLIB_STATIC("libogg");
+		DEF_LOCALXCFRAMEWORK("ogg", projectOutputDirectory);
 	}
 	if (CONTAINS_DEFINE(setup.defines, "USE_VORBIS")) {
 		DEF_LOCALLIB_STATIC("libvorbis");
 		DEF_LOCALLIB_STATIC("libvorbisfile");
+		DEF_LOCALXCFRAMEWORK("vorbis", projectOutputDirectory);
+		DEF_LOCALXCFRAMEWORK("vorbisfile", projectOutputDirectory);
 	}
 	if (CONTAINS_DEFINE(setup.defines, "USE_TREMOR")) {
 		DEF_LOCALLIB_STATIC("libvorbisidec");
 	}
 	if (CONTAINS_DEFINE(setup.defines, "USE_THEORADEC")) {
 		DEF_LOCALLIB_STATIC("libtheoradec");
+		DEF_LOCALXCFRAMEWORK("theoradec", projectOutputDirectory);
 	}
 	if (CONTAINS_DEFINE(setup.defines, "USE_RETROWAVE")) {
 		DEF_LOCALLIB_STATIC("libretrowave");
@@ -542,6 +570,7 @@ void XcodeProvider::setupFrameworksBuildPhase(const BuildSetup &setup) {
 		DEF_LOCALLIB_STATIC("libSDL2");
 		if (CONTAINS_DEFINE(setup.defines, "USE_SDL_NET")) {
 			DEF_LOCALLIB_STATIC("libSDL2_net");
+			DEF_LOCALXCFRAMEWORK("SDL2_net", projectOutputDirectory);
 		}
 	} else {
 		DEF_LOCALLIB_STATIC("libSDLmain");
@@ -586,50 +615,55 @@ void XcodeProvider::setupFrameworksBuildPhase(const BuildSetup &setup) {
 	frameworks_iOS.push_back("Accelerate.framework");
 
 	if (CONTAINS_DEFINE(setup.defines, "USE_FAAD")) {
-		frameworks_iOS.push_back("libfaad.a");
+		frameworks_iOS.push_back(getLibString("faad", setup.useXCFramework));
 	}
 	if (CONTAINS_DEFINE(setup.defines, "USE_FLAC")) {
-		frameworks_iOS.push_back("libFLAC.a");
+		frameworks_iOS.push_back(getLibString("FLAC", setup.useXCFramework));
 	}
 	if (CONTAINS_DEFINE(setup.defines, "USE_FREETYPE2")) {
-		frameworks_iOS.push_back("libfreetype.a");
+		frameworks_iOS.push_back(getLibString("freetype", setup.useXCFramework));
 	}
 	if (CONTAINS_DEFINE(setup.defines, "USE_JPEG")) {
-		frameworks_iOS.push_back("libjpeg.a");
+		frameworks_iOS.push_back(getLibString("jpeg", setup.useXCFramework));
 	}
 	if (CONTAINS_DEFINE(setup.defines, "USE_PNG")) {
-		frameworks_iOS.push_back("libpng.a");
+		frameworks_iOS.push_back(getLibString("png", setup.useXCFramework));
 	}
 	if (CONTAINS_DEFINE(setup.defines, "USE_GIF")) {
-		frameworks_iOS.push_back("libgif.a");
+		frameworks_iOS.push_back(getLibString("gif", setup.useXCFramework));
 	}
 	if (CONTAINS_DEFINE(setup.defines, "USE_OGG")) {
-		frameworks_iOS.push_back("libogg.a");
+		frameworks_iOS.push_back(getLibString("ogg", setup.useXCFramework));
 	}
 	if (CONTAINS_DEFINE(setup.defines, "USE_VORBIS")) {
-		frameworks_iOS.push_back("libvorbis.a");
-		frameworks_iOS.push_back("libvorbisfile.a");
+		frameworks_iOS.push_back(getLibString("vorbis", setup.useXCFramework));
+		frameworks_iOS.push_back(getLibString("vorbisfile", setup.useXCFramework));
 	}
 	if (CONTAINS_DEFINE(setup.defines, "USE_TREMOR")) {
-		frameworks_iOS.push_back("libvorbisidec.a");
+		frameworks_iOS.push_back(getLibString("vorbisidec", setup.useXCFramework));
 	}
 	if (CONTAINS_DEFINE(setup.defines, "USE_THEORADEC")) {
-		frameworks_iOS.push_back("libtheoradec.a");
+		frameworks_iOS.push_back(getLibString("theoradec", setup.useXCFramework));
 	}
 	if (CONTAINS_DEFINE(setup.defines, "USE_MAD")) {
-		frameworks_iOS.push_back("libmad.a");
+		frameworks_iOS.push_back(getLibString("mad", setup.useXCFramework));
 	}
 	if (CONTAINS_DEFINE(setup.defines, "USE_MPEG2")) {
-		frameworks_iOS.push_back("libmpeg2.a");
+		frameworks_iOS.push_back(getLibString("mpeg2", setup.useXCFramework));
 	}
 	if (CONTAINS_DEFINE(setup.defines, "USE_FRIBIDI")) {
-		frameworks_iOS.push_back("libfribidi.a");
+		frameworks_iOS.push_back(getLibString("fribidi", setup.useXCFramework));
 	}
 	if (CONTAINS_DEFINE(setup.defines, "USE_FLUIDSYNTH") &&
 		!CONTAINS_DEFINE(setup.defines, "USE_FLUIDLITE")) {
-		frameworks_iOS.push_back("libfluidsynth.a");
-		frameworks_iOS.push_back("libglib-2.0.a");
-		frameworks_iOS.push_back("libffi.a");
+		frameworks_iOS.push_back(getLibString("fluidsynth", setup.useXCFramework));
+		frameworks_iOS.push_back(getLibString("ffi", setup.useXCFramework));
+		frameworks_iOS.push_back(getLibString("glib-2.0", setup.useXCFramework));
+		if (setup.useXCFramework) {
+			// The libintl and libbz2 libs are not combined into glib-2.0 in the xcframework libs
+			frameworks_iOS.push_back(getLibString("intl", setup.useXCFramework));
+			frameworks_iOS.push_back(getLibString("bz2", setup.useXCFramework));
+		}
 		frameworks_iOS.push_back("CoreMIDI.framework");
 		frameworks_iOS.push_back("libiconv.tbd");
 	}
@@ -637,14 +671,15 @@ void XcodeProvider::setupFrameworksBuildPhase(const BuildSetup &setup) {
 		frameworks_iOS.push_back("libz.tbd");
 	}
 	if (CONTAINS_DEFINE(setup.defines, "USE_LIBCURL")) {
-		frameworks_iOS.push_back("libcurl.a");
+		frameworks_iOS.push_back(getLibString("curl", setup.useXCFramework));
 		frameworks_iOS.push_back("Security.framework");
 	}
 	if (CONTAINS_DEFINE(setup.defines, "USE_SDL_NET")) {
-		if (setup.useSDL2)
-			frameworks_iOS.push_back("libSDL2_net.a");
-		else
-			frameworks_iOS.push_back("libSDL_net.a");
+		if (setup.useSDL2) {
+			frameworks_iOS.push_back(getLibString("SDL2_net", setup.useXCFramework));
+		} else {
+			frameworks_iOS.push_back(getLibString("SDL_net", setup.useXCFramework));
+		}
 	}
 
 	for (ValueList::iterator framework = frameworks_iOS.begin(); framework != frameworks_iOS.end(); framework++) {
@@ -687,74 +722,74 @@ void XcodeProvider::setupFrameworksBuildPhase(const BuildSetup &setup) {
 	frameworks_osx.push_back("AudioUnit.framework");
 
 	if (CONTAINS_DEFINE(setup.defines, "USE_FAAD")) {
-		frameworks_osx.push_back("libfaad.a");
+		frameworks_osx.push_back(getLibString("faad", setup.useXCFramework));
 	}
 	if (CONTAINS_DEFINE(setup.defines, "USE_FLAC")) {
-		frameworks_osx.push_back("libFLAC.a");
+		frameworks_osx.push_back(getLibString("FLAC", setup.useXCFramework));
 	}
 	if (CONTAINS_DEFINE(setup.defines, "USE_FLUIDSYNTH") &&
 		!CONTAINS_DEFINE(setup.defines, "USE_FLUIDLITE")) {
-		frameworks_osx.push_back("libfluidsynth.a");
-		frameworks_osx.push_back("libglib-2.0.a");
+		frameworks_osx.push_back(getLibString("fluidsynth", setup.useXCFramework));
+		frameworks_osx.push_back(getLibString("glib-2.0", setup.useXCFramework));
 		frameworks_osx.push_back("libffi.tbd");
 	}
 	if (CONTAINS_DEFINE(setup.defines, "USE_FREETYPE2")) {
-		frameworks_osx.push_back("libfreetype.a");
+		frameworks_osx.push_back(getLibString("freetype", setup.useXCFramework));
 	}
 	if (CONTAINS_DEFINE(setup.defines, "USE_JPEG")) {
-		frameworks_osx.push_back("libjpeg.a");
+		frameworks_osx.push_back(getLibString("jpeg", setup.useXCFramework));
 	}
 	if (CONTAINS_DEFINE(setup.defines, "USE_LIBCURL")) {
-		frameworks_osx.push_back("libcurl.a");
+		frameworks_osx.push_back(getLibString("curl", setup.useXCFramework));
 	}
 	if (CONTAINS_DEFINE(setup.defines, "USE_MAD")) {
-		frameworks_osx.push_back("libmad.a");
+		frameworks_osx.push_back(getLibString("mad", setup.useXCFramework));
 	}
 	if (CONTAINS_DEFINE(setup.defines, "USE_MPEG2")) {
-		frameworks_osx.push_back("libmpeg2.a");
+		frameworks_osx.push_back(getLibString("mpeg2", setup.useXCFramework));
 	}
 	if (CONTAINS_DEFINE(setup.defines, "USE_FRIBIDI")) {
-		frameworks_osx.push_back("libfribidi.a");
+		frameworks_osx.push_back(getLibString("fribidi", setup.useXCFramework));
 	}
 	if (CONTAINS_DEFINE(setup.defines, "USE_PNG")) {
-		frameworks_osx.push_back("libpng.a");
+		frameworks_osx.push_back(getLibString("png", setup.useXCFramework));
 	}
 	if (CONTAINS_DEFINE(setup.defines, "USE_GIF")) {
-		frameworks_osx.push_back("libgif.a");
+		frameworks_osx.push_back(getLibString("gif", setup.useXCFramework));
 	}
 	if (CONTAINS_DEFINE(setup.defines, "USE_OGG")) {
-		frameworks_osx.push_back("libogg.a");
+		frameworks_osx.push_back(getLibString("ogg", setup.useXCFramework));
 	}
 	if (CONTAINS_DEFINE(setup.defines, "USE_VORBIS")) {
-		frameworks_osx.push_back("libvorbis.a");
-		frameworks_osx.push_back("libvorbisfile.a");
+		frameworks_osx.push_back(getLibString("vorbis", setup.useXCFramework));
+		frameworks_osx.push_back(getLibString("vorbisfile", setup.useXCFramework));
 	}
 	if (CONTAINS_DEFINE(setup.defines, "USE_TREMOR")) {
-		frameworks_osx.push_back("libvorbisidec.a");
+		frameworks_osx.push_back(getLibString("vorbisidec", setup.useXCFramework));
 	}
 	if (CONTAINS_DEFINE(setup.defines, "USE_THEORADEC")) {
-		frameworks_osx.push_back("libtheoradec.a");
+		frameworks_osx.push_back(getLibString("theoradec", setup.useXCFramework));
 	}
 	if (CONTAINS_DEFINE(setup.defines, "USE_RETROWAVE")) {
-		frameworks_osx.push_back("libretrowave.a");
+		frameworks_osx.push_back(getLibString("retrowave", setup.useXCFramework));
 	}
 	if (CONTAINS_DEFINE(setup.defines, "USE_ZLIB")) {
 		frameworks_osx.push_back("libz.tbd");
 	}
 	if (CONTAINS_DEFINE(setup.defines, "USE_DISCORD")) {
-		frameworks_osx.push_back("libdiscord-rpc.a");
+		frameworks_osx.push_back(getLibString("discord-rpc", setup.useXCFramework));
 	}
 
 	if (setup.useSDL2) {
-		frameworks_osx.push_back("libSDL2main.a");
-		frameworks_osx.push_back("libSDL2.a");
+		frameworks_osx.push_back(getLibString("SDL2main", setup.useXCFramework));
+		frameworks_osx.push_back(getLibString("SDL2", setup.useXCFramework));
 		if (CONTAINS_DEFINE(setup.defines, "USE_SDL_NET"))
-			frameworks_osx.push_back("libSDL2_net.a");
+			frameworks_osx.push_back(getLibString("SDL2_net", setup.useXCFramework));
 	} else {
-		frameworks_osx.push_back("libSDLmain.a");
-		frameworks_osx.push_back("libSDL.a");
+		frameworks_osx.push_back(getLibString("SDLmain", setup.useXCFramework));
+		frameworks_osx.push_back(getLibString("SDL", setup.useXCFramework));
 		if (CONTAINS_DEFINE(setup.defines, "USE_SDL_NET"))
-			frameworks_osx.push_back("libSDL_net.a");
+			frameworks_osx.push_back(getLibString("SDL_net", setup.useXCFramework));
 	}
 
 	order = 0;
@@ -796,52 +831,52 @@ void XcodeProvider::setupFrameworksBuildPhase(const BuildSetup &setup) {
 	frameworks_tvOS.push_back("OpenGLES.framework");
 
 	if (CONTAINS_DEFINE(setup.defines, "USE_FAAD")) {
-		frameworks_tvOS.push_back("libfaad.a");
+		frameworks_tvOS.push_back(getLibString("faad", setup.useXCFramework));
 	}
 	if (CONTAINS_DEFINE(setup.defines, "USE_FLAC")) {
-		frameworks_tvOS.push_back("libFLAC.a");
+		frameworks_tvOS.push_back(getLibString("FLAC", setup.useXCFramework));
 	}
 	if (CONTAINS_DEFINE(setup.defines, "USE_FREETYPE2")) {
-		frameworks_tvOS.push_back("libfreetype.a");
-		frameworks_tvOS.push_back("libbz2.a");
+		frameworks_tvOS.push_back(getLibString("freetype", setup.useXCFramework));
 	}
 	if (CONTAINS_DEFINE(setup.defines, "USE_JPEG")) {
-		frameworks_tvOS.push_back("libjpeg.a");
+		frameworks_tvOS.push_back(getLibString("jpeg", setup.useXCFramework));
 	}
 	if (CONTAINS_DEFINE(setup.defines, "USE_PNG")) {
-		frameworks_tvOS.push_back("libpng.a");
+		frameworks_tvOS.push_back(getLibString("png", setup.useXCFramework));
 	}
 	if (CONTAINS_DEFINE(setup.defines, "USE_GIF")) {
-		frameworks_tvOS.push_back("libgif.a");
+		frameworks_tvOS.push_back(getLibString("gif", setup.useXCFramework));
 	}
 	if (CONTAINS_DEFINE(setup.defines, "USE_OGG")) {
-		frameworks_tvOS.push_back("libogg.a");
+		frameworks_tvOS.push_back(getLibString("ogg", setup.useXCFramework));
 	}
 	if (CONTAINS_DEFINE(setup.defines, "USE_VORBIS")) {
-		frameworks_tvOS.push_back("libvorbis.a");
-		frameworks_tvOS.push_back("libvorbisfile.a");
+		frameworks_tvOS.push_back(getLibString("vorbis", setup.useXCFramework));
+		frameworks_tvOS.push_back(getLibString("vorbisfile", setup.useXCFramework));
 	}
 	if (CONTAINS_DEFINE(setup.defines, "USE_TREMOR")) {
-		frameworks_tvOS.push_back("libvorbisidec.a");
+		frameworks_tvOS.push_back(getLibString("vorbisidec", setup.useXCFramework));
 	}
 	if (CONTAINS_DEFINE(setup.defines, "USE_THEORADEC")) {
-		frameworks_tvOS.push_back("libtheoradec.a");
+		frameworks_tvOS.push_back(getLibString("theoradec", setup.useXCFramework));
 	}
 	if (CONTAINS_DEFINE(setup.defines, "USE_MAD")) {
-		frameworks_tvOS.push_back("libmad.a");
+		frameworks_tvOS.push_back(getLibString("mad", setup.useXCFramework));
 	}
 	if (CONTAINS_DEFINE(setup.defines, "USE_MPEG2")) {
-		frameworks_tvOS.push_back("libmpeg2.a");
+		frameworks_tvOS.push_back(getLibString("mpeg2", setup.useXCFramework));
 	}
 	if (CONTAINS_DEFINE(setup.defines, "USE_FRIBIDI")) {
-		frameworks_tvOS.push_back("libfribidi.a");
+		frameworks_tvOS.push_back(getLibString("fribidi", setup.useXCFramework));
 	}
 	if (CONTAINS_DEFINE(setup.defines, "USE_FLUIDSYNTH") &&
 		!CONTAINS_DEFINE(setup.defines, "USE_FLUIDLITE")) {
-		frameworks_tvOS.push_back("libfluidsynth.a");
-		frameworks_tvOS.push_back("libglib-2.0.a");
-		frameworks_tvOS.push_back("libintl.a");
-		frameworks_tvOS.push_back("libffi.a");
+		frameworks_tvOS.push_back(getLibString("fluidsynth", setup.useXCFramework));
+		frameworks_tvOS.push_back(getLibString("ffi", setup.useXCFramework));
+		frameworks_tvOS.push_back(getLibString("glib-2.0", setup.useXCFramework));
+		frameworks_tvOS.push_back(getLibString("intl", setup.useXCFramework));
+		frameworks_tvOS.push_back(getLibString("bz2", setup.useXCFramework));
 		frameworks_tvOS.push_back("CoreMIDI.framework");
 		frameworks_tvOS.push_back("libiconv.tbd");
 	}
@@ -849,14 +884,15 @@ void XcodeProvider::setupFrameworksBuildPhase(const BuildSetup &setup) {
 		frameworks_tvOS.push_back("libz.tbd");
 	}
 	if (CONTAINS_DEFINE(setup.defines, "USE_LIBCURL")) {
-		frameworks_tvOS.push_back("libcurl.a");
+		frameworks_tvOS.push_back(getLibString("curl", setup.useXCFramework));
 		frameworks_tvOS.push_back("Security.framework");
 	}
 	if (CONTAINS_DEFINE(setup.defines, "USE_SDL_NET")) {
-		if (setup.useSDL2)
-			frameworks_tvOS.push_back("libSDL2_net.a");
-		else
-			frameworks_tvOS.push_back("libSDL_net.a");
+		if (setup.useSDL2) {
+			frameworks_tvOS.push_back(getLibString("SDL2_net", setup.useXCFramework));
+		} else {
+			frameworks_tvOS.push_back(getLibString("SDL_net", setup.useXCFramework));
+		}
 	}
 
 	for (ValueList::iterator framework = frameworks_tvOS.begin(); framework != frameworks_tvOS.end(); framework++) {
@@ -1087,6 +1123,16 @@ XcodeProvider::ValueList& XcodeProvider::getResourceFiles(const BuildSetup &setu
 	return files;
 }
 
+std::string XcodeProvider::getLibString(std::string libName, bool xcframework) const {
+	std::string libString;
+	if (xcframework) {
+		libString = libName + std::string(".xcframework");
+	} else {
+		libString = std::string("lib") + libName + std::string(".a");
+	}
+	return libString;
+}
+
 void XcodeProvider::setupResourcesBuildPhase(const BuildSetup &setup) {
 	_resourcesBuildPhase._comment = "PBXResourcesBuildPhase";
 
@@ -1285,12 +1331,14 @@ void XcodeProvider::setupBuildConfiguration(const BuildSetup &setup) {
 	for (StringList::const_iterator i = setup.includeDirs.begin(); i != setup.includeDirs.end(); ++i)
 		iPhone_HeaderSearchPaths.push_back("\"" + *i + "\"");
 	iPhone_HeaderSearchPaths.push_back("\"" + projectOutputDirectory + "\"");
-	iPhone_HeaderSearchPaths.push_back("\"" + projectOutputDirectory + "/include\"");
-	if (CONTAINS_DEFINE(setup.defines, "USE_SDL_NET")) {
-		if (setup.useSDL2)
-			iPhone_HeaderSearchPaths.push_back("\"" + projectOutputDirectory + "/include/SDL2\"");
-		else
-			iPhone_HeaderSearchPaths.push_back("\"" + projectOutputDirectory + "include/SDL\"");
+	if (!setup.useXCFramework) {
+		iPhone_HeaderSearchPaths.push_back("\"" + projectOutputDirectory + "/include\"");
+		if (CONTAINS_DEFINE(setup.defines, "USE_SDL_NET")) {
+			if (setup.useSDL2)
+				iPhone_HeaderSearchPaths.push_back("\"" + projectOutputDirectory + "/include/SDL2\"");
+			else
+				iPhone_HeaderSearchPaths.push_back("\"" + projectOutputDirectory + "include/SDL\"");
+		}
 	}
 	ADD_SETTING_LIST(iPhone_Debug, "HEADER_SEARCH_PATHS", iPhone_HeaderSearchPaths, kSettingsAsList | kSettingsQuoteVariable, 5);
 	ADD_SETTING_QUOTE(iPhone_Debug, "INFOPLIST_FILE", "$(SRCROOT)/dists/ios7/Info.plist");
@@ -1298,7 +1346,8 @@ void XcodeProvider::setupBuildConfiguration(const BuildSetup &setup) {
 	for (StringList::const_iterator i = setup.libraryDirs.begin(); i != setup.libraryDirs.end(); ++i)
 		iPhone_LibPaths.push_back("\"" + *i + "\"");
 	iPhone_LibPaths.push_back("$(inherited)");
-	iPhone_LibPaths.push_back("\"" + projectOutputDirectory + "/lib\"");
+	if (!setup.useXCFramework)
+		iPhone_LibPaths.push_back("\"" + projectOutputDirectory + "/lib\"");
 	ADD_SETTING_LIST(iPhone_Debug, "LIBRARY_SEARCH_PATHS", iPhone_LibPaths, kSettingsAsList, 5);
 	ADD_SETTING(iPhone_Debug, "ONLY_ACTIVE_ARCH", "YES");
 	ADD_SETTING(iPhone_Debug, "PRODUCT_NAME", PROJECT_NAME);
diff --git a/devtools/create_project/xcode.h b/devtools/create_project/xcode.h
index 9429274e418..939c14c831e 100644
--- a/devtools/create_project/xcode.h
+++ b/devtools/create_project/xcode.h
@@ -325,6 +325,7 @@ private:
 
 	// Retrieve information
 	ValueList& getResourceFiles(const BuildSetup &setup) const;
+	std::string getLibString(std::string libName, bool xcframework) const;
 
 	// Hash generation
 	std::string getHash(std::string key);


Commit: fb79d61a315fb3b937ee101b1a5845061ef54802
    https://github.com/scummvm/scummvm/commit/fb79d61a315fb3b937ee101b1a5845061ef54802
Author: Lars Sundström (l.sundstrom at gmail.com)
Date: 2023-04-27T21:43:28+01:00

Commit Message:
DOCPORTAL: Update ios7 and tvos instructions

This updates the instructions for building the ios7 and tvos backends
using scummvm-ios7-libs-v3, utilizing the Apple XCFramework format for
the pre-compiled libraries.

Using scummvm-ios7-libs-v3 also enables use of the following
features:
 - faad
 - gif
 - mpeg2
 - theoradec

DOC

Changed paths:
    doc/docportal/other_platforms/ios.rst
    doc/docportal/other_platforms/tvos.rst


diff --git a/doc/docportal/other_platforms/ios.rst b/doc/docportal/other_platforms/ios.rst
index 7ce5a28d526..bf15949c8a4 100644
--- a/doc/docportal/other_platforms/ios.rst
+++ b/doc/docportal/other_platforms/ios.rst
@@ -20,7 +20,7 @@ What you'll need
 
 - A Mac computer with Xcode installed. Xcode is a free App, available from the Mac App Store.
 - An Apple Developer account. You can sign up for a free account on the `Apple Developer Member Center <https://developer.apple.com/membercenter/>`_ with your Apple ID.
-- The ScummVM `iOS Libraries <https://downloads.scummvm.org/frs/build/scummvm-ios7-libs-v2.zip>`_ downloaded, and the zip file extracted.
+- The ScummVM `iOS Libraries <https://downloads.scummvm.org/frs/build/scummvm-ios7-libs-v3.zip>`_ downloaded, and the zip file extracted.
 
 .. note::
 
@@ -47,11 +47,11 @@ Create a new directory called ``build`` at the same level as the repository you
 
     mkdir build
 
-Copy the contents of the ``scummvm-ios7-libs-v2`` folder you extracted earlier into the ``build`` directory, using either the Finder, or the command line as follows:
+Move the contents of the ``scummvm-ios7-libs-v3`` folder you extracted earlier into the ``build`` directory, using either the Finder, or the command line as follows:
 
 .. code-block::
 
-    cp -r ~/Downloads/scummvm-ios7-libs-v2/* ~/build/
+    mv ~/Downloads/frameworks ~/build/
 
 If your downloaded iOS library folder is not in the Downloads folder as it is in the preceding example, change the path to where the folder actually is.
 
@@ -76,7 +76,7 @@ It's time to generate the Xcode project. Run the following on the command line:
 
 .. code::
 
-    ../scummvm/devtools/create_project/xcode/build/Release/create_project ../scummvm --xcode --enable-fluidsynth --disable-nasm --disable-opengl --disable-theoradec --disable-mpeg2 --disable-taskbar --disable-tts --disable-fribidi
+    ../scummvm/devtools/create_project/xcode/build/Release/create_project ../scummvm --xcode --use-xcframework --enable-faad --enable-fluidsynth --enable-gif --enable-mpeg2 --disable-nasm --disable-opengl --disable-taskbar --disable-tts
 
 The resulting directory structure looks like this:
 
@@ -85,8 +85,7 @@ The resulting directory structure looks like this:
     Home
      |--scummvm
      '--build
-         |-- include
-         |-- lib
+         |-- frameworks
          |-- engines
          '-- scummvm.xcodeproj
 
diff --git a/doc/docportal/other_platforms/tvos.rst b/doc/docportal/other_platforms/tvos.rst
index 5fdab31bf81..35655153a53 100644
--- a/doc/docportal/other_platforms/tvos.rst
+++ b/doc/docportal/other_platforms/tvos.rst
@@ -17,7 +17,7 @@ There are two ways to install ScummVM on an Apple TV depending on if building th
 Building the project
 ************************************
 
-Since the port for Apple TV shares the same code base as the iOS port the instructions for building the project is the same as for iOS. Follow the :doc:`./ios` with the differences that the `tvOS libraries <https://github.com/larsamannen/scummvm-tvos-libs-v1>`_ should be used instead and the ``ScummVM-tvOS`` target should be chosen in Xcode. Use the libraries in the ``appletv`` folder if building for real target and ``appletvsimulator`` if building for simulator. Note that the libraries are built without bitcode since it's not required since tvOS 16.
+Since the port for Apple TV shares the same code base as the iOS port the instructions for building the project is the same as for iOS. Follow the :doc:`./ios` with the difference that the ``ScummVM-tvOS`` target should be chosen in Xcode.
 
 Downloading and installing ScummVM
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^


Commit: 07652d9d82561caacea84a8adbe45d7da6c02bd2
    https://github.com/scummvm/scummvm/commit/07652d9d82561caacea84a8adbe45d7da6c02bd2
Author: Thierry Crozat (criezy at scummvm.org)
Date: 2023-04-27T21:43:40+01:00

Commit Message:
IOS7: Fix detection of orientation on some devices

The main change in to use the interface orientation and not the device
orientation. This may be different for example when locking the orientation.
This also changes the way orientation changes are detected using the
documented method. However this means dropping support for iOS 7 as this
method is only available since iOS 8, and alternative methods available in
iOS 7 have been deprecated in iOS 13.

Another change is to properly detect the interface orientation instead of
infering it from the view bounds, which was incorrect on some devices.

Changed paths:
    backends/platform/ios7/ios7_app_delegate.mm
    backends/platform/ios7/ios7_scummvm_view_controller.h
    backends/platform/ios7/ios7_scummvm_view_controller.mm
    backends/platform/ios7/ios7_video.h
    backends/platform/ios7/ios7_video.mm


diff --git a/backends/platform/ios7/ios7_app_delegate.mm b/backends/platform/ios7/ios7_app_delegate.mm
index 4a8140a383b..fe0797dade5 100644
--- a/backends/platform/ios7/ios7_app_delegate.mm
+++ b/backends/platform/ios7/ios7_app_delegate.mm
@@ -67,14 +67,6 @@
 	[_window setRootViewController:_controller];
 	[_window makeKeyAndVisible];
 
-#if TARGET_OS_IOS
-	[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
-	[[NSNotificationCenter defaultCenter] addObserver:self
-	                                         selector:@selector(didRotate:)
-	                                             name:@"UIDeviceOrientationDidChangeNotification"
-	                                           object:nil];
-#endif
-
 	// Force creation of the shared instance on the main thread
 	iOS7_buildSharedOSystemInstance();
 
@@ -98,8 +90,16 @@
 	// Make sure we have the correct orientation in case the orientation was changed while
 	// the app was inactive.
 #if TARGET_OS_IOS
-	UIDeviceOrientation screenOrientation = [[UIDevice currentDevice] orientation];
-	[_view deviceOrientationChanged:screenOrientation];
+	UIInterfaceOrientation interfaceOrientation = UIInterfaceOrientationUnknown;
+	if (@available(iOS 13.0, *)) {
+		interfaceOrientation = [[[_view window] windowScene] interfaceOrientation];
+	} else {
+		interfaceOrientation = [[UIApplication sharedApplication] statusBarOrientation];
+	}
+	if (interfaceOrientation != UIInterfaceOrientationUnknown) {
+		[_view interfaceOrientationChanged:interfaceOrientation];
+		[_controller setCurrentOrientation: interfaceOrientation];
+	}
 #endif
 }
 
@@ -124,13 +124,6 @@
 	_restoreState = YES;
 }
 
-- (void)didRotate:(NSNotification *)notification {
-#if TARGET_OS_IOS
-	UIDeviceOrientation screenOrientation = [[UIDevice currentDevice] orientation];
-	[_view deviceOrientationChanged:screenOrientation];
-#endif
-}
-
 + (iOS7AppDelegate *)iOS7AppDelegate {
 	UIApplication *app = [UIApplication sharedApplication];
 	// [UIApplication delegate] must be used from the main thread only
diff --git a/backends/platform/ios7/ios7_scummvm_view_controller.h b/backends/platform/ios7/ios7_scummvm_view_controller.h
index cc62c58ae85..9b6cf004d56 100644
--- a/backends/platform/ios7/ios7_scummvm_view_controller.h
+++ b/backends/platform/ios7/ios7_scummvm_view_controller.h
@@ -25,7 +25,15 @@
 #include <UIKit/UIKit.h>
 
 
- at interface iOS7ScummVMViewController : UIViewController
+ at interface iOS7ScummVMViewController : UIViewController {
+#if TARGET_OS_IOS
+	UIInterfaceOrientation currentOrientation;
+#endif
+}
+
+#if TARGET_OS_IOS
+-(void) setCurrentOrientation:(UIInterfaceOrientation)orientation;
+#endif
 
 @end
 
diff --git a/backends/platform/ios7/ios7_scummvm_view_controller.mm b/backends/platform/ios7/ios7_scummvm_view_controller.mm
index 0072f909b78..6d66b8c92ec 100644
--- a/backends/platform/ios7/ios7_scummvm_view_controller.mm
+++ b/backends/platform/ios7/ios7_scummvm_view_controller.mm
@@ -20,10 +20,19 @@
  */
 
 #include "backends/platform/ios7/ios7_scummvm_view_controller.h"
-
+#include "backends/platform/ios7/ios7_app_delegate.h"
+#include "backends/platform/ios7/ios7_video.h"
 
 @implementation iOS7ScummVMViewController
 
+- (id)init {
+	self = [super init];
+#if TARGET_OS_IOS
+	self->currentOrientation = UIInterfaceOrientationUnknown;
+#endif
+	return self;
+}
+
 - (BOOL)prefersStatusBarHidden {
 	return YES;
 }
@@ -37,4 +46,43 @@
 	return YES;
 }
 
+#if TARGET_OS_IOS
+-(void) setCurrentOrientation:(UIInterfaceOrientation)orientation {
+	if (orientation != currentOrientation) {
+		currentOrientation = orientation;
+		[[iOS7AppDelegate iPhoneView] interfaceOrientationChanged:currentOrientation];
+	}
+}
+
+- (void)viewDidAppear:(BOOL)animated {
+	[super viewDidAppear:animated];
+
+	UIInterfaceOrientation orientationBefore = UIInterfaceOrientationUnknown;
+	if (@available(iOS 13.0, *)) {
+		orientationBefore = [[[[self view] window] windowScene] interfaceOrientation];
+	} else {
+		orientationBefore = [[UIApplication sharedApplication] statusBarOrientation];
+	}
+	if (currentOrientation != UIInterfaceOrientationUnknown)
+		[[iOS7AppDelegate iPhoneView] interfaceOrientationChanged:currentOrientation];
+}
+
+- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
+	[super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
+
+	[coordinator animateAlongsideTransition:nil completion:^(id<UIViewControllerTransitionCoordinatorContext> context) {
+		UIInterfaceOrientation orientationAfter = UIInterfaceOrientationUnknown;
+		if (@available(iOS 13.0, *)) {
+			orientationAfter = [[[[self view] window] windowScene] interfaceOrientation];
+		} else {
+			orientationAfter = [[UIApplication sharedApplication] statusBarOrientation];
+		}
+		if (orientationAfter != UIInterfaceOrientationUnknown && orientationAfter != currentOrientation) {
+			currentOrientation = orientationAfter;
+			[[iOS7AppDelegate iPhoneView] interfaceOrientationChanged:currentOrientation];
+		}
+	}];
+}
+#endif
+
 @end
diff --git a/backends/platform/ios7/ios7_video.h b/backends/platform/ios7/ios7_video.h
index d848f4705e3..e4dccf2fa3d 100644
--- a/backends/platform/ios7/ios7_video.h
+++ b/backends/platform/ios7/ios7_video.h
@@ -117,7 +117,7 @@ uint getSizeNextPOT(uint size);
 - (void)updateMouseCursor;
 
 #if TARGET_OS_IOS
-- (void)deviceOrientationChanged:(UIDeviceOrientation)orientation;
+- (void)interfaceOrientationChanged:(UIInterfaceOrientation)orientation;
 #endif
 
 - (void)showKeyboard;
diff --git a/backends/platform/ios7/ios7_video.mm b/backends/platform/ios7/ios7_video.mm
index cd52295aabd..1190c782c12 100644
--- a/backends/platform/ios7/ios7_video.mm
+++ b/backends/platform/ios7/ios7_video.mm
@@ -686,14 +686,23 @@ uint getSizeNextPOT(uint size) {
 		[self rebuildFrameBuffer];
 	}
 
-	BOOL isLandscape = (self.bounds.size.width > self.bounds.size.height); // UIDeviceOrientationIsLandscape([[UIDevice currentDevice] orientation]);
+#if TARGET_OS_IOS
+	UIInterfaceOrientation interfaceOrientation = UIInterfaceOrientationUnknown;
+	if (@available(iOS 13.0, *)) {
+		interfaceOrientation = [[[self window] windowScene] interfaceOrientation];
+	} else {
+		interfaceOrientation = [[UIApplication sharedApplication] statusBarOrientation];
+	}
+	BOOL isLandscape = UIInterfaceOrientationIsLandscape(interfaceOrientation);
+#else // TVOS
+	BOOL isLandscape = YES;
+#endif
 
 	int screenWidth, screenHeight;
 	if (isLandscape) {
 		screenWidth = MAX(_renderBufferWidth, _renderBufferHeight);
 		screenHeight = MIN(_renderBufferWidth, _renderBufferHeight);
-	}
-	else {
+	} else {
 		screenWidth = MIN(_renderBufferWidth, _renderBufferHeight);
 		screenHeight = MAX(_renderBufferWidth, _renderBufferHeight);
 	}
@@ -794,9 +803,16 @@ uint getSizeNextPOT(uint size) {
 		CGRect newFrame = screenSize;
 #if TARGET_OS_IOS
 		UIEdgeInsets inset = [[[UIApplication sharedApplication] keyWindow] safeAreaInsets];
-		UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
+		UIInterfaceOrientation orientation = UIInterfaceOrientationUnknown;
+		if (@available(iOS 13.0, *)) {
+			orientation = [[[self window] windowScene] interfaceOrientation];
+		} else {
+			orientation = [[UIApplication sharedApplication] statusBarOrientation];
+		}
 		if ( orientation == UIInterfaceOrientationPortrait ) {
 			newFrame = CGRectMake(screenSize.origin.x, screenSize.origin.y + inset.top, screenSize.size.width, screenSize.size.height - inset.top);
+		} else if ( orientation == UIInterfaceOrientationPortraitUpsideDown ) {
+			newFrame = CGRectMake(screenSize.origin.x, screenSize.origin.y, screenSize.size.width, screenSize.size.height - inset.top);
 		} else if ( orientation == UIInterfaceOrientationLandscapeLeft ) {
 			newFrame = CGRectMake(screenSize.origin.x, screenSize.origin.y, screenSize.size.width - inset.right, screenSize.size.height);
 		} else if ( orientation == UIInterfaceOrientationLandscapeRight ) {
@@ -920,11 +936,9 @@ uint getSizeNextPOT(uint size) {
 }
 
 #if TARGET_OS_IOS
-- (void)deviceOrientationChanged:(UIDeviceOrientation)orientation {
+- (void)interfaceOrientationChanged:(UIInterfaceOrientation)orientation {
 	[self addEvent:InternalEvent(kInputOrientationChanged, orientation, 0)];
-
-	BOOL isLandscape = (self.bounds.size.width > self.bounds.size.height);
-	if (isLandscape) {
+	if (UIInterfaceOrientationIsLandscape(orientation)) {
 		[self hideKeyboard];
 	} else {
 		[self showKeyboard];


Commit: 1675496f01c22ccd6aab96a2250cf3a8b35f8306
    https://github.com/scummvm/scummvm/commit/1675496f01c22ccd6aab96a2250cf3a8b35f8306
Author: Thierry Crozat (criezy at scummvm.org)
Date: 2023-04-27T21:43:40+01:00

Commit Message:
IOS7: Remove checks that @available can be used

This was used in the past to make sure the code can be compiled
with old compilers that do not support using @available. But we
already dropped support for those old compilers, and in many
places already used @available without checking first that it can
be used.

Changed paths:
    backends/platform/ios7/ios7_keyboard.mm
    backends/platform/ios7/ios7_video.mm


diff --git a/backends/platform/ios7/ios7_keyboard.mm b/backends/platform/ios7/ios7_keyboard.mm
index a20568eb767..40f7674158b 100644
--- a/backends/platform/ios7/ios7_keyboard.mm
+++ b/backends/platform/ios7/ios7_keyboard.mm
@@ -56,11 +56,7 @@
 	// The code only compils with the iOS 9.0+ SDK, and only works on iOS 9.0
 	// or above.
 #ifdef __IPHONE_9_0
-#if __has_builtin(__builtin_available)
 	if ( @available(iOS 9,*) ) {
-#else
-	if ( [self respondsToSelector:@selector(inputAssistantItem)] ) {
-#endif
 		UITextInputAssistantItem* item = [self inputAssistantItem];
 		if (item) {
 			item.leadingBarButtonGroups = @[];
diff --git a/backends/platform/ios7/ios7_video.mm b/backends/platform/ios7/ios7_video.mm
index 1190c782c12..25f97c15eda 100644
--- a/backends/platform/ios7/ios7_video.mm
+++ b/backends/platform/ios7/ios7_video.mm
@@ -794,11 +794,7 @@ uint getSizeNextPOT(uint size) {
 	// So for now disable this code when compiled with an older SDK, which means it is only
 	// available when running on iOS 11+ if it has been compiled on iOS 11+
 #ifdef __IPHONE_11_0
-#if __has_builtin(__builtin_available)
 	if ( @available(iOS 11, tvOS 11, *) ) {
-#else
-	if ( [[[UIApplication sharedApplication] keyWindow] respondsToSelector:@selector(safeAreaInsets)] ) {
-#endif
 		CGRect screenSize = [[UIScreen mainScreen] bounds];
 		CGRect newFrame = screenSize;
 #if TARGET_OS_IOS


Commit: 5bfa6feaa11b52b08e71e4702d1b374a1245072f
    https://github.com/scummvm/scummvm/commit/5bfa6feaa11b52b08e71e4702d1b374a1245072f
Author: Thierry Crozat (criezy at scummvm.org)
Date: 2023-04-27T21:43:40+01:00

Commit Message:
IOS7: Fix missing override keyword

Changed paths:
    backends/platform/ios7/ios7_osys_main.h


diff --git a/backends/platform/ios7/ios7_osys_main.h b/backends/platform/ios7/ios7_osys_main.h
index d0e5f45a3ae..ee3bbfacf82 100644
--- a/backends/platform/ios7/ios7_osys_main.h
+++ b/backends/platform/ios7/ios7_osys_main.h
@@ -218,7 +218,7 @@ public:
 
 	bool isConnectionLimited() override;
 
-	virtual Common::String getDefaultLogFileName() { return Common::String("/var/mobile/.scummvm.log"); }
+	virtual Common::String getDefaultLogFileName() override { return Common::String("/var/mobile/.scummvm.log"); }
 
 protected:
 	void initVideoContext();


Commit: f1f808f7a415eebd730ad82e27fb06c460c620ef
    https://github.com/scummvm/scummvm/commit/f1f808f7a415eebd730ad82e27fb06c460c620ef
Author: Thierry Crozat (criezy at scummvm.org)
Date: 2023-04-27T21:43:40+01:00

Commit Message:
IOS7: Remove support for non-sandboxed mode

Changed paths:
    audio/softsynth/fluidsynth.cpp
    backends/platform/ios7/ios7_app_delegate.mm
    backends/platform/ios7/ios7_osys_main.cpp
    backends/platform/ios7/ios7_osys_main.h
    backends/platform/ios7/ios7_osys_misc.mm
    configure
    devtools/create_project/xcode.cpp


diff --git a/audio/softsynth/fluidsynth.cpp b/audio/softsynth/fluidsynth.cpp
index 215bee4f578..f8bcc81b106 100644
--- a/audio/softsynth/fluidsynth.cpp
+++ b/audio/softsynth/fluidsynth.cpp
@@ -48,7 +48,7 @@
 #include "audio/mpu401.h"
 #include "audio/softsynth/emumidi.h"
 #include "gui/message.h"
-#if defined(IPHONE_IOS7) && defined(IPHONE_SANDBOXED)
+#if defined(IPHONE_IOS7)
 #include "backends/platform/ios7/ios7_common.h"
 #endif
 #ifdef __ANDROID__
@@ -438,7 +438,7 @@ int MidiDriver_FluidSynth::open() {
 	} else
 #endif // FS_HAS_STREAM_SUPPORT
 	{
-#if defined(IPHONE_IOS7) && defined(IPHONE_SANDBOXED)
+#if defined(IPHONE_IOS7)
 		// HACK: Due to the sandbox on non-jailbroken iOS devices, we need to deal
 		// with the chroot filesystem. All the path selected by the user are
 		// relative to the Document directory. So, we need to adjust the path to
diff --git a/backends/platform/ios7/ios7_app_delegate.mm b/backends/platform/ios7/ios7_app_delegate.mm
index fe0797dade5..55b6c8b7b24 100644
--- a/backends/platform/ios7/ios7_app_delegate.mm
+++ b/backends/platform/ios7/ios7_app_delegate.mm
@@ -43,7 +43,6 @@
 - (void)applicationDidFinishLaunching:(UIApplication *)application {
 	CGRect rect = [[UIScreen mainScreen] bounds];
 
-#ifdef IPHONE_SANDBOXED
 	// Create the directory for savegames
 	NSFileManager *fm = [NSFileManager defaultManager];
 	NSString *documentPath = [NSString stringWithUTF8String:iOS7_getDocumentsDir()];
@@ -51,7 +50,6 @@
 	if (![fm fileExistsAtPath:savePath]) {
 		[fm createDirectoryAtPath:savePath withIntermediateDirectories:YES attributes:nil error:nil];
 	}
-#endif
 
 	_window = [[UIWindow alloc] initWithFrame:rect];
 	[_window retain];
diff --git a/backends/platform/ios7/ios7_osys_main.cpp b/backends/platform/ios7/ios7_osys_main.cpp
index d157d93f47d..7d43e8d468d 100644
--- a/backends/platform/ios7/ios7_osys_main.cpp
+++ b/backends/platform/ios7/ios7_osys_main.cpp
@@ -59,7 +59,6 @@ AQCallbackStruct OSystem_iOS7::s_AudioQueue;
 SoundProc OSystem_iOS7::s_soundCallback = NULL;
 void *OSystem_iOS7::s_soundParam = NULL;
 
-#ifdef IPHONE_SANDBOXED
 class SandboxedSaveFileManager : public DefaultSaveFileManager {
 	Common::String _sandboxRootPath;
 public:
@@ -84,7 +83,6 @@ public:
 		}
 	}
 };
-#endif
 
 OSystem_iOS7::OSystem_iOS7() :
 	_mixer(NULL), _lastMouseTap(0), _queuedEventTime(0),
@@ -95,7 +93,7 @@ OSystem_iOS7::OSystem_iOS7() :
 	_mouseCursorPaletteEnabled(false), _gfxTransactionError(kTransactionSuccess) {
 	_queuedInputEvent.type = Common::EVENT_INVALID;
 	_touchpadModeEnabled = !iOS7_isBigDevice();
-#ifdef IPHONE_SANDBOXED
+
 	_chrootBasePath = iOS7_getDocumentsDir();
 	ChRootFilesystemFactory *chFsFactory = new ChRootFilesystemFactory(_chrootBasePath);
 	_fsFactory = chFsFactory;
@@ -107,9 +105,7 @@ OSystem_iOS7::OSystem_iOS7() :
 			chFsFactory->addVirtualDrive("appbundle:", Common::String((const char *)buf));
 		CFRelease(fileUrl);
 	}
-#else
-	_fsFactory = new POSIXFilesystemFactory();
-#endif
+
 	initVideoContext();
 
 	memset(_gamePalette, 0, sizeof(_gamePalette));
@@ -146,11 +142,7 @@ int OSystem_iOS7::timerHandler(int t) {
 }
 
 void OSystem_iOS7::initBackend() {
-#ifdef IPHONE_SANDBOXED
 	_savefileManager = new SandboxedSaveFileManager(_chrootBasePath, "/Savegames");
-#else
-	_savefileManager = new DefaultSaveFileManager(SCUMMVM_SAVE_PATH);
-#endif
 
 	_timerManager = new DefaultTimerManager();
 
@@ -354,12 +346,8 @@ OSystem_iOS7 *OSystem_iOS7::sharedInstance() {
 }
 
 Common::String OSystem_iOS7::getDefaultConfigFileName() {
-#ifdef IPHONE_SANDBOXED
 	Common::String path = "/Preferences";
 	return path;
-#else
-	return SCUMMVM_PREFS_PATH;
-#endif
 }
 
 void OSystem_iOS7::addSysArchivesToSearchSet(Common::SearchSet &s, int priority) {
@@ -371,12 +359,8 @@ void OSystem_iOS7::addSysArchivesToSearchSet(Common::SearchSet &s, int priority)
 		if (CFURLGetFileSystemRepresentation(fileUrl, true, buf, sizeof(buf))) {
 			// Success: Add it to the search path
 			Common::String bundlePath((const char *)buf);
-#ifdef IPHONE_SANDBOXED
 			POSIXFilesystemNode *posixNode = new POSIXFilesystemNode(bundlePath);
 			s.add("__IOS_BUNDLE__", new Common::FSDirectory(AbstractFSNode::makeFSNode(posixNode)), priority);
-#else
-			s.add("__IOS_BUNDLE__", new Common::FSDirectory(bundlePath), priority);
-#endif
 		}
 		CFRelease(fileUrl);
 	}
@@ -408,14 +392,7 @@ void iOS7_main(int argc, char **argv) {
 		//gDebugLevel = 10;
 	}
 
-#ifdef IPHONE_SANDBOXED
 	chdir(iOS7_getDocumentsDir());
-#else
-	system("mkdir " SCUMMVM_ROOT_PATH);
-	system("mkdir " SCUMMVM_SAVE_PATH);
-
-	chdir("/var/mobile/");
-#endif
 
 	g_system = OSystem_iOS7::sharedInstance();
 	assert(g_system);
diff --git a/backends/platform/ios7/ios7_osys_main.h b/backends/platform/ios7/ios7_osys_main.h
index ee3bbfacf82..4e0faab9d43 100644
--- a/backends/platform/ios7/ios7_osys_main.h
+++ b/backends/platform/ios7/ios7_osys_main.h
@@ -39,10 +39,6 @@
 #define WAVE_BUFFER_SIZE 2048
 #define AUDIO_SAMPLE_RATE 44100
 
-#define SCUMMVM_ROOT_PATH "/var/mobile/Library/ScummVM"
-#define SCUMMVM_SAVE_PATH SCUMMVM_ROOT_PATH "/Savegames"
-#define SCUMMVM_PREFS_PATH SCUMMVM_ROOT_PATH "/Preferences"
-
 typedef void (*SoundProc)(void *param, byte *buf, int len);
 typedef int (*TimerProc)(int interval);
 
@@ -111,9 +107,7 @@ protected:
 
 	Common::String _lastErrorMessage;
 
-#ifdef IPHONE_SANDBOXED
 	Common::String _chrootBasePath;
-#endif
 
 public:
 
diff --git a/backends/platform/ios7/ios7_osys_misc.mm b/backends/platform/ios7/ios7_osys_misc.mm
index d0885120963..e7193f16a5f 100644
--- a/backends/platform/ios7/ios7_osys_misc.mm
+++ b/backends/platform/ios7/ios7_osys_misc.mm
@@ -56,13 +56,8 @@ void OSystem_iOS7::updateStartSettings(const Common::String &executable, Common:
 
 		// If the bundle contains a scummvm.ini, use it as initial config
 		NSString *iniPath = [bundle pathForResource:@"scummvm" ofType:@"ini"];
-		if (iniPath && !settings.contains("initial-cfg")) {
-#ifdef IPHONE_SANDBOXED
+		if (iniPath && !settings.contains("initial-cfg"))
 			settings["initial-cfg"] = "appbundle:/scummvm.ini";
-#else
-			settings["initial-cfg"] = Common::String([iniPath fileSystemRepresentation]);
-#endif
-		}
 
 		// If a command was specified on the command line, do not override it
 		if (!command.empty())
@@ -73,11 +68,7 @@ void OSystem_iOS7::updateStartSettings(const Common::String &executable, Common:
 		if (autorunPath) {
 			Common::File autorun;
 			Common::String line;
-#ifdef IPHONE_SANDBOXED
 			if (autorun.open(Common::FSNode("appbundle:/scummvm-autorun"))) {
-#else
-			if (autorun.open(Common::FSNode([autorunPath fileSystemRepresentation]))) {
-#endif
 				while (!autorun.eos()) {
 					line = autorun.readLine();
 					if (!line.empty() && line[0] != '#')
@@ -94,11 +85,7 @@ void OSystem_iOS7::updateStartSettings(const Common::String &executable, Common:
 		if (exists && isDir) {
 			// Use auto-detection
 			command = "auto-detect";
-#ifdef IPHONE_SANDBOXED
 			settings["path"] = "appbundle:/game";
-#else
-			settings["path"] = [gamePath fileSystemRepresentation];
-#endif
 			return;
 		}
 
@@ -118,11 +105,7 @@ void OSystem_iOS7::updateStartSettings(const Common::String &executable, Common:
 		if (exists && isDir) {
 			// Detect and add games
 			command = "add";
-#ifdef IPHONE_SANDBOXED
 			settings["path"] = "appbundle:/games";
-#else
-			settings["path"] = [gamesPath fileSystemRepresentation];
-#endif
 			settings["recursive"] = "true";
 			settings["exit"] = "false";
 			return;
diff --git a/configure b/configure
index 090b8dfa0e7..8d74abd13ac 100755
--- a/configure
+++ b/configure
@@ -3520,7 +3520,7 @@ if test -n "$_host"; then
 			;;
 		ios7*)
 			add_line_to_config_mk 'IPHONE = 1'
-			append_var DEFINES "-DIPHONE -DIPHONE_IOS7 -DIPHONE_SANDBOXED"
+			append_var DEFINES "-DIPHONE -DIPHONE_IOS7"
 			_backend="ios7"
 			_seq_midi=no
 			_timidity=no
@@ -3780,7 +3780,7 @@ if test -n "$_host"; then
 			;;
 		tvos)
 			add_line_to_config_mk 'IPHONE = 1'
-			append_var DEFINES "-DIPHONE -DIPHONE_IOS7 -DIPHONE_SANDBOXED"
+			append_var DEFINES "-DIPHONE -DIPHONE_IOS7"
 			_backend="ios7"
 			_seq_midi=no
 			_timidity=no
diff --git a/devtools/create_project/xcode.cpp b/devtools/create_project/xcode.cpp
index 1d0c68f54aa..560ffc4e376 100644
--- a/devtools/create_project/xcode.cpp
+++ b/devtools/create_project/xcode.cpp
@@ -1265,7 +1265,6 @@ void XcodeProvider::setupBuildConfiguration(const BuildSetup &setup) {
 	REMOVE_DEFINE(scummvm_defines, "MACOSX");
 	REMOVE_DEFINE(scummvm_defines, "IPHONE");
 	REMOVE_DEFINE(scummvm_defines, "IPHONE_IOS7");
-	REMOVE_DEFINE(scummvm_defines, "IPHONE_SANDBOXED");
 	REMOVE_DEFINE(scummvm_defines, "SDL_BACKEND");
 	ADD_SETTING_LIST(scummvm_Debug, "GCC_PREPROCESSOR_DEFINITIONS", scummvm_defines, kSettingsNoQuote | kSettingsAsList, 5);
 	ADD_SETTING(scummvm_Debug, "GCC_WARN_ABOUT_RETURN_TYPE", "YES");
@@ -1360,7 +1359,6 @@ void XcodeProvider::setupBuildConfiguration(const BuildSetup &setup) {
 	ADD_DEFINE(scummvmIOS_defines, "\"$(inherited)\"");
 	ADD_DEFINE(scummvmIOS_defines, "IPHONE");
 	ADD_DEFINE(scummvmIOS_defines, "IPHONE_IOS7");
-	ADD_DEFINE(scummvmIOS_defines, "IPHONE_SANDBOXED");
 	if (CONTAINS_DEFINE(setup.defines, "USE_SDL_NET"))
 		ADD_DEFINE(scummvmIOS_defines, "WITHOUT_SDL");
 	ADD_SETTING_LIST(iPhone_Debug, "GCC_PREPROCESSOR_DEFINITIONS", scummvmIOS_defines, kSettingsNoQuote | kSettingsAsList, 5);
@@ -1517,7 +1515,6 @@ void XcodeProvider::setupBuildConfiguration(const BuildSetup &setup) {
 	ADD_DEFINE(scummvmTVOS_defines, "\"$(inherited)\"");
 	ADD_DEFINE(scummvmTVOS_defines, "IPHONE");
 	ADD_DEFINE(scummvmTVOS_defines, "IPHONE_IOS7");
-	ADD_DEFINE(scummvmTVOS_defines, "IPHONE_SANDBOXED");
 	if (CONTAINS_DEFINE(setup.defines, "USE_SDL_NET"))
 		ADD_DEFINE(scummvmTVOS_defines, "WITHOUT_SDL");
 	ADD_SETTING_LIST(tvOS_Debug, "GCC_PREPROCESSOR_DEFINITIONS", scummvmTVOS_defines, kSettingsNoQuote | kSettingsAsList, 5);
@@ -1603,7 +1600,6 @@ void XcodeProvider::setupDefines(const BuildSetup &setup) {
 	REMOVE_DEFINE(_defines, "MACOSX");
 	REMOVE_DEFINE(_defines, "IPHONE");
 	REMOVE_DEFINE(_defines, "IPHONE_IOS7");
-	REMOVE_DEFINE(_defines, "IPHONE_SANDBOXED");
 	REMOVE_DEFINE(_defines, "SDL_BACKEND");
 	ADD_DEFINE(_defines, "CONFIG_H");
 	ADD_DEFINE(_defines, "UNIX");


Commit: aaf6ed536ff2f3d4ddf7cd7ddee7bf9e88b52044
    https://github.com/scummvm/scummvm/commit/aaf6ed536ff2f3d4ddf7cd7ddee7bf9e88b52044
Author: Thierry Crozat (criezy at scummvm.org)
Date: 2023-04-27T21:43:40+01:00

Commit Message:
IOS7: Cleanup code to access Document and app bundle paths

Changed paths:
  A backends/platform/ios7/ios7_misc.mm
    backends/platform/ios7/ios7_app_delegate.mm
    backends/platform/ios7/ios7_common.h
    backends/platform/ios7/ios7_osys_main.cpp
    backends/platform/ios7/module.mk


diff --git a/backends/platform/ios7/ios7_app_delegate.mm b/backends/platform/ios7/ios7_app_delegate.mm
index 55b6c8b7b24..517e509e96c 100644
--- a/backends/platform/ios7/ios7_app_delegate.mm
+++ b/backends/platform/ios7/ios7_app_delegate.mm
@@ -45,7 +45,7 @@
 
 	// Create the directory for savegames
 	NSFileManager *fm = [NSFileManager defaultManager];
-	NSString *documentPath = [NSString stringWithUTF8String:iOS7_getDocumentsDir()];
+	NSString *documentPath = [NSString stringWithUTF8String:iOS7_getDocumentsDir().c_str()];
 	NSString *savePath = [documentPath stringByAppendingPathComponent:@"Savegames"];
 	if (![fm fileExistsAtPath:savePath]) {
 		[fm createDirectoryAtPath:savePath withIntermediateDirectories:YES attributes:nil error:nil];
@@ -142,14 +142,3 @@
 }
 
 @end
-
-const char *iOS7_getDocumentsDir() {
-	NSArray *paths;
-#if TARGET_OS_IOS
-	paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
-#else
-	paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
-#endif
-	NSString *documentsDirectory = [paths objectAtIndex:0];
-	return [documentsDirectory UTF8String];
-}
diff --git a/backends/platform/ios7/ios7_common.h b/backends/platform/ios7/ios7_common.h
index 6374e0114b6..50b46117af5 100644
--- a/backends/platform/ios7/ios7_common.h
+++ b/backends/platform/ios7/ios7_common.h
@@ -117,7 +117,8 @@ bool iOS7_isBigDevice();
 
 void iOS7_buildSharedOSystemInstance();
 void iOS7_main(int argc, char **argv);
-const char *iOS7_getDocumentsDir();
+Common::String iOS7_getDocumentsDir();
+Common::String iOS7_getAppBundleDir();
 bool iOS7_touchpadModeEnabled();
 
 uint getSizeNextPOT(uint size);
diff --git a/backends/platform/ios7/ios7_misc.mm b/backends/platform/ios7/ios7_misc.mm
new file mode 100644
index 00000000000..db9380ac208
--- /dev/null
+++ b/backends/platform/ios7/ios7_misc.mm
@@ -0,0 +1,44 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <Foundation/NSArray.h>
+#include <Foundation/NSURL.h>
+#include <Foundation/NSFileManager.h>
+#include <Foundation/NSBundle.h>
+#include <Foundation/NSPathUtilities.h>
+#include "backends/platform/ios7/ios7_common.h"
+#include <common/str.h>
+
+Common::String iOS7_getDocumentsDir() {
+#if TARGET_OS_IOS
+	NSURL *url = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] firstObject];
+#else
+	NSURL *url = [[[NSFileManager defaultManager] URLsForDirectory:NSCachesDirectory inDomains:NSUserDomainMask] firstObject];
+#endif
+	return Common::String([url fileSystemRepresentation]);
+}
+
+Common::String iOS7_getAppBundleDir() {
+	NSString *bundlePath = [[NSBundle mainBundle] resourcePath];
+	if (bundlePath == nil)
+		return Common::String();
+	return Common::String([bundlePath fileSystemRepresentation]);
+}
diff --git a/backends/platform/ios7/ios7_osys_main.cpp b/backends/platform/ios7/ios7_osys_main.cpp
index 7d43e8d468d..e27a095ef9e 100644
--- a/backends/platform/ios7/ios7_osys_main.cpp
+++ b/backends/platform/ios7/ios7_osys_main.cpp
@@ -98,13 +98,9 @@ OSystem_iOS7::OSystem_iOS7() :
 	ChRootFilesystemFactory *chFsFactory = new ChRootFilesystemFactory(_chrootBasePath);
 	_fsFactory = chFsFactory;
 	// Add virtual drive for bundle path
-	CFURLRef fileUrl = CFBundleCopyResourcesDirectoryURL(CFBundleGetMainBundle());
-	if (fileUrl) {
-		UInt8 buf[MAXPATHLEN];
-		if (CFURLGetFileSystemRepresentation(fileUrl, true, buf, sizeof(buf)))
-			chFsFactory->addVirtualDrive("appbundle:", Common::String((const char *)buf));
-		CFRelease(fileUrl);
-	}
+	Common::String appBubdlePath = iOS7_getAppBundleDir();
+	if (!appBubdlePath.empty())
+		chFsFactory->addVirtualDrive("appbundle:", appBubdlePath);
 
 	initVideoContext();
 
@@ -392,7 +388,7 @@ void iOS7_main(int argc, char **argv) {
 		//gDebugLevel = 10;
 	}
 
-	chdir(iOS7_getDocumentsDir());
+	chdir(iOS7_getDocumentsDir().c_str());
 
 	g_system = OSystem_iOS7::sharedInstance();
 	assert(g_system);
diff --git a/backends/platform/ios7/module.mk b/backends/platform/ios7/module.mk
index 2075dfe6e25..ddda4a6f5ed 100644
--- a/backends/platform/ios7/module.mk
+++ b/backends/platform/ios7/module.mk
@@ -6,6 +6,7 @@ MODULE_OBJS := \
 	ios7_osys_sound.o \
 	ios7_osys_video.o \
 	ios7_osys_misc.o \
+	ios7_misc.o \
 	ios7_main.o \
 	ios7_video.o \
 	ios7_keyboard.o \


Commit: c1bcb0fd092d965f41e70c4b79635f02354b832d
    https://github.com/scummvm/scummvm/commit/c1bcb0fd092d965f41e70c4b79635f02354b832d
Author: Thierry Crozat (criezy at scummvm.org)
Date: 2023-04-27T21:43:40+01:00

Commit Message:
IOS7: Create log file in Document folder

Previously no log file was used as it attempted to create it in
a directory not accessible by the application. The commit also fixes
accessing the log file from the Options dialog (it needs the
sandboxed path and not the full path).

Changed paths:
    backends/platform/ios7/ios7_osys_main.cpp
    backends/platform/ios7/ios7_osys_main.h


diff --git a/backends/platform/ios7/ios7_osys_main.cpp b/backends/platform/ios7/ios7_osys_main.cpp
index e27a095ef9e..a1cce91824f 100644
--- a/backends/platform/ios7/ios7_osys_main.cpp
+++ b/backends/platform/ios7/ios7_osys_main.cpp
@@ -374,8 +374,9 @@ void iOS7_buildSharedOSystemInstance() {
 void iOS7_main(int argc, char **argv) {
 
 	//OSystem_iOS7::migrateApp();
+	Common::String logFilePath = iOS7_getDocumentsDir() + "/scummvm.log";
 
-	FILE *newfp = fopen("/var/mobile/.scummvm.log", "a");
+	FILE *newfp = fopen(logFilePath.c_str(), "a");
 	if (newfp != NULL) {
 		fclose(stdout);
 		fclose(stderr);
diff --git a/backends/platform/ios7/ios7_osys_main.h b/backends/platform/ios7/ios7_osys_main.h
index 4e0faab9d43..e023e617c64 100644
--- a/backends/platform/ios7/ios7_osys_main.h
+++ b/backends/platform/ios7/ios7_osys_main.h
@@ -212,7 +212,7 @@ public:
 
 	bool isConnectionLimited() override;
 
-	virtual Common::String getDefaultLogFileName() override { return Common::String("/var/mobile/.scummvm.log"); }
+	virtual Common::String getDefaultLogFileName() override { return Common::String("/scummvm.log"); }
 
 protected:
 	void initVideoContext();


Commit: e3b643d9a6dddfb1ff3bb95e80c7157fe135347b
    https://github.com/scummvm/scummvm/commit/e3b643d9a6dddfb1ff3bb95e80c7157fe135347b
Author: Thierry Crozat (criezy at scummvm.org)
Date: 2023-04-27T21:43:40+01:00

Commit Message:
IOS7: Fix orientation detection when the view becomes visible

Changed paths:
    backends/platform/ios7/ios7_scummvm_view_controller.mm


diff --git a/backends/platform/ios7/ios7_scummvm_view_controller.mm b/backends/platform/ios7/ios7_scummvm_view_controller.mm
index 6d66b8c92ec..4b9e3b389d2 100644
--- a/backends/platform/ios7/ios7_scummvm_view_controller.mm
+++ b/backends/platform/ios7/ios7_scummvm_view_controller.mm
@@ -57,14 +57,16 @@
 - (void)viewDidAppear:(BOOL)animated {
 	[super viewDidAppear:animated];
 
-	UIInterfaceOrientation orientationBefore = UIInterfaceOrientationUnknown;
+	UIInterfaceOrientation orientation = UIInterfaceOrientationUnknown;
 	if (@available(iOS 13.0, *)) {
-		orientationBefore = [[[[self view] window] windowScene] interfaceOrientation];
+		orientation = [[[[self view] window] windowScene] interfaceOrientation];
 	} else {
-		orientationBefore = [[UIApplication sharedApplication] statusBarOrientation];
+		orientation = [[UIApplication sharedApplication] statusBarOrientation];
+	}
+	if (orientation != UIInterfaceOrientationUnknown && orientation != currentOrientation) {
+		currentOrientation = orientation;
+		[[iOS7AppDelegate iPhoneView] interfaceOrientationChanged:orientation];
 	}
-	if (currentOrientation != UIInterfaceOrientationUnknown)
-		[[iOS7AppDelegate iPhoneView] interfaceOrientationChanged:currentOrientation];
 }
 
 - (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {


Commit: 50c315e3167253e4bc604226646f9038bbc23158
    https://github.com/scummvm/scummvm/commit/50c315e3167253e4bc604226646f9038bbc23158
Author: Thierry Crozat (criezy at scummvm.org)
Date: 2023-04-27T21:43:40+01:00

Commit Message:
IOS7: Add check of size for log file to make sure it does not grow too much

Changed paths:
    backends/platform/ios7/ios7_osys_main.cpp
    backends/platform/ios7/ios7_osys_main.h


diff --git a/backends/platform/ios7/ios7_osys_main.cpp b/backends/platform/ios7/ios7_osys_main.cpp
index a1cce91824f..3511ed83b16 100644
--- a/backends/platform/ios7/ios7_osys_main.cpp
+++ b/backends/platform/ios7/ios7_osys_main.cpp
@@ -374,19 +374,31 @@ void iOS7_buildSharedOSystemInstance() {
 void iOS7_main(int argc, char **argv) {
 
 	//OSystem_iOS7::migrateApp();
-	Common::String logFilePath = iOS7_getDocumentsDir() + "/scummvm.log";
 
-	FILE *newfp = fopen(logFilePath.c_str(), "a");
-	if (newfp != NULL) {
-		fclose(stdout);
-		fclose(stderr);
-		*stdout = *newfp;
-		*stderr = *newfp;
-		setbuf(stdout, NULL);
-		setbuf(stderr, NULL);
-
-		//extern int gDebugLevel;
-		//gDebugLevel = 10;
+	Common::String logFilePath = iOS7_getDocumentsDir() + "/scummvm.log";
+	FILE *logFile = fopen(logFilePath.c_str(), "a");
+	if (logFile != nullptr) {
+		// We check for log file size; if it's too big, we rewrite it.
+		// This happens only upon app launch
+		// NOTE: We don't check for file size each time we write a log message.
+		long sz = ftell(logFile);
+		if (sz > MAX_IOS7_SCUMMVM_LOG_FILESIZE_IN_BYTES) {
+			fclose(logFile);
+			fprintf(stdout, "Default log file is bigger than %dKB. It will be overwritten!", MAX_IOS7_SCUMMVM_LOG_FILESIZE_IN_BYTES / 1024);
+
+			// Create the log file from scratch overwriting the previous one
+			logFile = fopen(logFilePath.c_str(), "w");
+			if (logFile == nullptr)
+				fprintf(stdout, "Could not open default log file for rewrite!");
+		}
+		if (logFile != NULL) {
+			fclose(stdout);
+			fclose(stderr);
+			*stdout = *logFile;
+			*stderr = *logFile;
+			setbuf(stdout, NULL);
+			setbuf(stderr, NULL);
+		}
 	}
 
 	chdir(iOS7_getDocumentsDir().c_str());
@@ -398,9 +410,9 @@ void iOS7_main(int argc, char **argv) {
 	scummvm_main(argc, (const char *const *) argv);
 	g_system->quit();       // TODO: Consider removing / replacing this!
 
-	if (newfp != NULL) {
+	if (logFile != NULL) {
 		//*stdout = NULL;
 		//*stderr = NULL;
-		fclose(newfp);
+		fclose(logFile);
 	}
 }
diff --git a/backends/platform/ios7/ios7_osys_main.h b/backends/platform/ios7/ios7_osys_main.h
index e023e617c64..825cf47bb49 100644
--- a/backends/platform/ios7/ios7_osys_main.h
+++ b/backends/platform/ios7/ios7_osys_main.h
@@ -38,6 +38,7 @@
 #define AUDIO_BUFFERS 3
 #define WAVE_BUFFER_SIZE 2048
 #define AUDIO_SAMPLE_RATE 44100
+#define MAX_IOS7_SCUMMVM_LOG_FILESIZE_IN_BYTES (100*1024)
 
 typedef void (*SoundProc)(void *param, byte *buf, int len);
 typedef int (*TimerProc)(int interval);




More information about the Scummvm-git-logs mailing list