aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohannes Schickel2016-01-07 10:38:31 +0100
committerJohannes Schickel2016-01-07 10:38:31 +0100
commitbd1039b93ef3cb1541e9df91879c704aa894ddd9 (patch)
tree06aad88a939836932c53c27681507283376ad159
parentcf5856492c6ce1820339dd76f9d3175f9f457215 (diff)
parentb5ef98637c54a453a6f0ac0ca8c501ceb59924d5 (diff)
downloadscummvm-rg350-bd1039b93ef3cb1541e9df91879c704aa894ddd9.tar.gz
scummvm-rg350-bd1039b93ef3cb1541e9df91879c704aa894ddd9.tar.bz2
scummvm-rg350-bd1039b93ef3cb1541e9df91879c704aa894ddd9.zip
Merge pull request #630 from bSr43/ios-fix
IOS: Fixes the iOS port
-rw-r--r--AUTHORS3
-rw-r--r--audio/softsynth/fluidsynth.cpp15
-rw-r--r--backends/fs/chroot/chroot-fs-factory.cpp60
-rw-r--r--backends/fs/chroot/chroot-fs-factory.h45
-rw-r--r--backends/fs/chroot/chroot-fs.cpp124
-rw-r--r--backends/fs/chroot/chroot-fs.h57
-rw-r--r--backends/module.mk2
-rw-r--r--backends/platform/ios7/README.md150
-rw-r--r--backends/platform/ios7/iOS7AppDelegate.h15
-rw-r--r--backends/platform/ios7/iOS7AppDelegate.mm95
-rw-r--r--backends/platform/ios7/iOS7ScummVMViewController.h28
-rw-r--r--backends/platform/ios7/iOS7ScummVMViewController.mm32
-rw-r--r--backends/platform/ios7/ios7_common.h131
-rw-r--r--backends/platform/ios7/ios7_keyboard.h44
-rw-r--r--backends/platform/ios7/ios7_keyboard.mm98
-rw-r--r--backends/platform/ios7/ios7_main.mm47
-rw-r--r--backends/platform/ios7/ios7_osys_events.cpp576
-rw-r--r--backends/platform/ios7/ios7_osys_main.cpp368
-rw-r--r--backends/platform/ios7/ios7_osys_main.h233
-rw-r--r--backends/platform/ios7/ios7_osys_sound.cpp105
-rw-r--r--backends/platform/ios7/ios7_osys_video.mm545
-rw-r--r--backends/platform/ios7/ios7_video.h131
-rw-r--r--backends/platform/ios7/ios7_video.mm1002
-rw-r--r--backends/platform/ios7/module.mk17
-rw-r--r--backends/platform/iphone/osys_main.cpp6
-rw-r--r--common/fs.h4
-rw-r--r--common/str.h1
-rwxr-xr-xconfigure74
-rw-r--r--devtools/create_project/codeblocks.cpp5
-rw-r--r--devtools/create_project/codeblocks.h2
-rw-r--r--devtools/create_project/create_project.cpp38
-rw-r--r--devtools/create_project/create_project.h18
-rw-r--r--devtools/create_project/msvc.cpp5
-rw-r--r--devtools/create_project/msvc.h2
-rw-r--r--devtools/create_project/xcode.cpp612
-rw-r--r--devtools/create_project/xcode.h26
-rw-r--r--devtools/create_project/xcode/create_project.xcodeproj/project.pbxproj22
-rwxr-xr-xdevtools/credits.pl3
-rwxr-xr-xdevtools/update-version.pl1
-rw-r--r--dists/ios7/Images.xcassets/AppIcon.appiconset/Contents.json86
-rw-r--r--dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-29.pngbin0 -> 3084 bytes
-rw-r--r--dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-29@2x.pngbin0 -> 6829 bytes
-rw-r--r--dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-29@3x.pngbin0 -> 12228 bytes
-rw-r--r--dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-40.pngbin0 -> 4356 bytes
-rw-r--r--dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-40@2x.pngbin0 -> 10744 bytes
-rw-r--r--dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-40@3x.pngbin0 -> 18115 bytes
-rw-r--r--dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-60@2x.pngbin0 -> 18115 bytes
-rw-r--r--dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-60@3x.pngbin0 -> 33953 bytes
-rw-r--r--dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-76.pngbin0 -> 10147 bytes
-rw-r--r--dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-76@2x.pngbin0 -> 26351 bytes
-rw-r--r--dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-83.5@2x.pngbin0 -> 24888 bytes
-rw-r--r--dists/ios7/Images.xcassets/Contents.json6
-rw-r--r--dists/ios7/Images.xcassets/LaunchImage.launchimage/Contents.json150
-rw-r--r--dists/ios7/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-1024x768.pngbin0 -> 239614 bytes
-rw-r--r--dists/ios7/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-1242x2208.pngbin0 -> 1624064 bytes
-rw-r--r--dists/ios7/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-1536x2048.pngbin0 -> 942974 bytes
-rw-r--r--dists/ios7/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-2048x1536.pngbin0 -> 1069512 bytes
-rw-r--r--dists/ios7/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-2208x1242.pngbin0 -> 2234609 bytes
-rw-r--r--dists/ios7/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-640x1136-1.pngbin0 -> 671669 bytes
-rw-r--r--dists/ios7/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-750x1334.pngbin0 -> 917056 bytes
-rw-r--r--dists/ios7/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-768x1024.pngbin0 -> 185340 bytes
-rw-r--r--dists/ios7/Info.plist52
-rw-r--r--dists/ios7/Info.plist.in52
-rw-r--r--dists/macosx/Info.plist28
-rw-r--r--dists/macosx/Info.plist.in28
-rw-r--r--gui/credits.h4
-rw-r--r--gui/module.mk10
-rw-r--r--ports.mk132
68 files changed, 4955 insertions, 335 deletions
diff --git a/AUTHORS b/AUTHORS
index f5d62c2e14..c973bc1709 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -287,8 +287,9 @@ ScummVM Team
GPH Devices (GP2X, GP2XWiz & Caanoo):
John Willis
- iPhone:
+ iPhone / iPad:
Oystein Eftevaag
+ Vincent Benony
LinuxMoto:
Lubomyr Lisen
diff --git a/audio/softsynth/fluidsynth.cpp b/audio/softsynth/fluidsynth.cpp
index 9b64d70f2b..4dc43499d3 100644
--- a/audio/softsynth/fluidsynth.cpp
+++ b/audio/softsynth/fluidsynth.cpp
@@ -31,6 +31,11 @@
#include "audio/musicplugin.h"
#include "audio/mpu401.h"
#include "audio/softsynth/emumidi.h"
+#if defined(IPHONE_IOS7) && defined(IPHONE_SANDBOXED)
+#include <string.h>
+#include <sys/syslimits.h>
+#include "backends/platform/ios7/ios7_common.h"
+#endif
#include <fluidsynth.h>
@@ -179,7 +184,17 @@ int MidiDriver_FluidSynth::open() {
const char *soundfont = ConfMan.get("soundfont").c_str();
+#if defined(IPHONE_IOS7) && defined(IPHONE_SANDBOXED)
+ // 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 reflect that.
+ Common::String soundfont_fullpath = iOS7_getDocumentsDir();
+ soundfont_fullpath += soundfont;
+ _soundFont = fluid_synth_sfload(_synth, soundfont_fullpath.c_str(), 1);
+#else
_soundFont = fluid_synth_sfload(_synth, soundfont, 1);
+#endif
+
if (_soundFont == -1)
error("Failed loading custom sound font '%s'", soundfont);
diff --git a/backends/fs/chroot/chroot-fs-factory.cpp b/backends/fs/chroot/chroot-fs-factory.cpp
new file mode 100644
index 0000000000..fa98ab75d3
--- /dev/null
+++ b/backends/fs/chroot/chroot-fs-factory.cpp
@@ -0,0 +1,60 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#if defined(POSIX)
+
+#define FORBIDDEN_SYMBOL_EXCEPTION_time_h
+#define FORBIDDEN_SYMBOL_EXCEPTION_unistd_h
+#define FORBIDDEN_SYMBOL_EXCEPTION_mkdir
+#define FORBIDDEN_SYMBOL_EXCEPTION_exit //Needed for IRIX's unistd.h
+
+#include "chroot-fs-factory.h"
+#include "backends/fs/chroot/chroot-fs.h"
+#include "backends/fs/posix/posix-fs-factory.h"
+
+ChRootFilesystemFactory::ChRootFilesystemFactory(Common::String root) {
+ _root = root;
+}
+
+AbstractFSNode *ChRootFilesystemFactory::makeRootFileNode() const {
+ return new ChRootFilesystemNode(_root, "/");
+}
+
+AbstractFSNode *ChRootFilesystemFactory::makeCurrentDirectoryFileNode() const {
+ char buf[MAXPATHLEN];
+ if (getcwd(buf, MAXPATHLEN) == NULL) {
+ return NULL;
+ }
+
+ if (Common::String(buf).hasPrefix(_root + Common::String("/"))) {
+ return new ChRootFilesystemNode(_root, buf + _root.size());
+ }
+
+ return new ChRootFilesystemNode(_root, "/");
+}
+
+AbstractFSNode *ChRootFilesystemFactory::makeFileNodePath(const Common::String &path) const {
+ assert(!path.empty());
+ return new ChRootFilesystemNode(_root, path);
+}
+
+#endif
diff --git a/backends/fs/chroot/chroot-fs-factory.h b/backends/fs/chroot/chroot-fs-factory.h
new file mode 100644
index 0000000000..23b3c8f44a
--- /dev/null
+++ b/backends/fs/chroot/chroot-fs-factory.h
@@ -0,0 +1,45 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * FIXME: Warning, using this factory in your backend may silently breaks some features. Instances are, for example, the FluidSynth code, and the POSIX plugin code.
+ */
+
+#ifndef BACKENDS_FS_CHROOT_CHROOT_FS_FACTORY_H
+#define BACKENDS_FS_CHROOT_CHROOT_FS_FACTORY_H
+
+#include "backends/fs/fs-factory.h"
+
+class ChRootFilesystemFactory : public FilesystemFactory {
+private:
+ Common::String _root;
+
+protected:
+ virtual AbstractFSNode *makeRootFileNode() const;
+ virtual AbstractFSNode *makeCurrentDirectoryFileNode() const;
+ virtual AbstractFSNode *makeFileNodePath(const Common::String &path) const;
+
+public:
+ ChRootFilesystemFactory(Common::String root);
+};
+
+#endif /* BACKENDS_FS_CHROOT_CHROOT_FS_FACTORY_H */
diff --git a/backends/fs/chroot/chroot-fs.cpp b/backends/fs/chroot/chroot-fs.cpp
new file mode 100644
index 0000000000..2cbb4af9d6
--- /dev/null
+++ b/backends/fs/chroot/chroot-fs.cpp
@@ -0,0 +1,124 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#if defined(POSIX)
+
+// Re-enable some forbidden symbols to avoid clashes with stat.h and unistd.h.
+// Also with clock() in sys/time.h in some Mac OS X SDKs.
+#define FORBIDDEN_SYMBOL_EXCEPTION_time_h
+#define FORBIDDEN_SYMBOL_EXCEPTION_unistd_h
+#define FORBIDDEN_SYMBOL_EXCEPTION_mkdir
+#define FORBIDDEN_SYMBOL_EXCEPTION_getenv
+#define FORBIDDEN_SYMBOL_EXCEPTION_exit //Needed for IRIX's unistd.h
+
+#include "backends/fs/chroot/chroot-fs.h"
+
+ChRootFilesystemNode::ChRootFilesystemNode(const Common::String &root, POSIXFilesystemNode *node) {
+ _root = Common::normalizePath(root, '/');
+ _realNode = node;
+}
+
+ChRootFilesystemNode::ChRootFilesystemNode(const Common::String &root, const Common::String &path) {
+ _root = Common::normalizePath(root, '/');
+ _realNode = new POSIXFilesystemNode(addPathComponent(root, path));
+}
+
+ChRootFilesystemNode::~ChRootFilesystemNode() {
+ delete _realNode;
+}
+
+bool ChRootFilesystemNode::exists() const {
+ return _realNode->exists();
+}
+
+Common::String ChRootFilesystemNode::getDisplayName() const {
+ return getName();
+}
+
+Common::String ChRootFilesystemNode::getName() const {
+ return _realNode->AbstractFSNode::getDisplayName();
+}
+
+Common::String ChRootFilesystemNode::getPath() const {
+ Common::String path = _realNode->getPath();
+ if (path.size() > _root.size()) {
+ return Common::String(path.c_str() + _root.size());
+ }
+ return Common::String("/");
+}
+
+bool ChRootFilesystemNode::isDirectory() const {
+ return _realNode->isDirectory();
+}
+
+bool ChRootFilesystemNode::isReadable() const {
+ return _realNode->isReadable();
+}
+
+bool ChRootFilesystemNode::isWritable() const {
+ return _realNode->isWritable();
+}
+
+AbstractFSNode *ChRootFilesystemNode::getChild(const Common::String &n) const {
+ return new ChRootFilesystemNode(_root, (POSIXFilesystemNode *)_realNode->getChild(n));
+}
+
+bool ChRootFilesystemNode::getChildren(AbstractFSList &list, ListMode mode, bool hidden) const {
+ AbstractFSList tmp;
+ if (!_realNode->getChildren(tmp, mode, hidden)) {
+ return false;
+ }
+
+ for (AbstractFSList::iterator i=tmp.begin(); i!=tmp.end(); ++i) {
+ list.push_back(new ChRootFilesystemNode(_root, (POSIXFilesystemNode *) *i));
+ }
+
+ return true;
+}
+
+AbstractFSNode *ChRootFilesystemNode::getParent() const {
+ if (getPath() == "/") return 0;
+ return new ChRootFilesystemNode(_root, (POSIXFilesystemNode *)_realNode->getParent());
+}
+
+Common::SeekableReadStream *ChRootFilesystemNode::createReadStream() {
+ return _realNode->createReadStream();
+}
+
+Common::WriteStream *ChRootFilesystemNode::createWriteStream() {
+ return _realNode->createWriteStream();
+}
+
+Common::String ChRootFilesystemNode::addPathComponent(const Common::String &path, const Common::String &component) {
+ const char sep = '/';
+ if (path.lastChar() == sep && component.firstChar() == sep) {
+ return Common::String::format("%s%s", path.c_str(), component.c_str() + 1);
+ }
+
+ if (path.lastChar() == sep || component.firstChar() == sep) {
+ return Common::String::format("%s%s", path.c_str(), component.c_str());
+ }
+
+ return Common::String::format("%s%c%s", path.c_str(), sep, component.c_str());
+}
+
+#endif
diff --git a/backends/fs/chroot/chroot-fs.h b/backends/fs/chroot/chroot-fs.h
new file mode 100644
index 0000000000..9ff913be31
--- /dev/null
+++ b/backends/fs/chroot/chroot-fs.h
@@ -0,0 +1,57 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef BACKENDS_FS_CHROOT_CHROOT_FS_H
+#define BACKENDS_FS_CHROOT_CHROOT_FS_H
+
+#include "backends/fs/posix/posix-fs.h"
+
+class ChRootFilesystemNode : public AbstractFSNode {
+ Common::String _root;
+ POSIXFilesystemNode *_realNode;
+
+ ChRootFilesystemNode(const Common::String &root, POSIXFilesystemNode *);
+
+public:
+ ChRootFilesystemNode(const Common::String &root, const Common::String &path);
+ virtual ~ChRootFilesystemNode();
+
+ virtual bool exists() const;
+ virtual Common::String getDisplayName() const;
+ virtual Common::String getName() const;
+ virtual Common::String getPath() const;
+ virtual bool isDirectory() const;
+ virtual bool isReadable() const;
+ virtual bool isWritable() const;
+
+ virtual AbstractFSNode *getChild(const Common::String &n) const;
+ virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const;
+ virtual AbstractFSNode *getParent() const;
+
+ virtual Common::SeekableReadStream *createReadStream();
+ virtual Common::WriteStream *createWriteStream();
+
+private:
+ static Common::String addPathComponent(const Common::String &path, const Common::String &component);
+};
+
+#endif /* BACKENDS_FS_CHROOT_CHROOT_FS_H */
diff --git a/backends/module.mk b/backends/module.mk
index 3d7dea1f26..3d412c031a 100644
--- a/backends/module.mk
+++ b/backends/module.mk
@@ -88,6 +88,8 @@ ifdef POSIX
MODULE_OBJS += \
fs/posix/posix-fs.o \
fs/posix/posix-fs-factory.o \
+ fs/chroot/chroot-fs-factory.o \
+ fs/chroot/chroot-fs.o \
plugins/posix/posix-provider.o \
saves/posix/posix-saves.o \
taskbar/unity/unity-taskbar.o
diff --git a/backends/platform/ios7/README.md b/backends/platform/ios7/README.md
new file mode 100644
index 0000000000..1f34c15cc6
--- /dev/null
+++ b/backends/platform/ios7/README.md
@@ -0,0 +1,150 @@
+# ScummVM for iOS 7.1+ #
+
+This is a quick fix of the latest ScummVM (1.8.0) for iOS 7.1. It has been tested on real iPhone 6S+, and iPad Pro, and also on all the available Xcode simulators.
+
+I tried to use all the latest iOS features to replace the old code. For instance, it uses gesture recognizers most of the time, it supports the new iPhones 6 / 6+ / 6s / 6s+ resolution, and you can copy your game files using iTunes.
+
+## Compilation ##
+
+First, clone the repository:
+```
+$ git clone -b ios-fix --recursive https://github.com/bSr43/scummvm.git
+```
+
+### Compilation from Xcode ###
+
+This is the recommended way to compile ScummVM, and the only one which makes it possible to run ScummVM on a non-jailbroken device!
+
+The next step is to compile the **create_project** tool. Open the Xcode project you'll found in the **devtools/create\_project/xcode/** directory. Once compiled, copy the binary somewhere in your *PATH*, and create a **build** directory somewhere on your harddisk. It is recommended to create this directory next to the cloned repository (they share the same parent).
+
+Execute the following commands in a terminal:
+```
+$ cd path_to_the_build_directory
+$ create_project path_to_scummvm_repository --xcode --enable-fluidsynth --disable-jpeg --disable-bink --disable-16bit --disable-mt32emu --disable-nasm --disable-opengl --disable-theora --disable-taskbar
+```
+
+This will create an Xcode project for ScummVM, for both the OS X, and the iOS target.
+
+Now, download the external libraries from http://bsr43.free.fr/scummvm/ScummVM-iOS-libraries.zip. Unzip the archive in your **build** directory. Please make sure that the **lib**, and **include** directories are at the root of the **build** directory, not in a subdirectory.
+
+Now, your **build** directory should contain:
+* a generated **engines** directory,
+* a generated **scummvm.xcodeproj** project,
+* an **include** directory,
+* a **lib** directory.
+
+You are ready to compile ScummVM: open the **scummvm.xcodeproj** project, and build it.
+
+### Compilation from command line ###
+
+For jailbroken devices, it is also possible to compile the project from command line. You'll need a working toolchain, and some tools, like **ldid**, to fake the code signature.
+
+Here is a script to download, and compile all the required tools. This script has been wrote for Debian 8.2, and should be run as root.
+
+```
+#!/bin/bash
+
+if [ $UID -ne 0 ]; then
+ echo "This script should be run by the root user"
+ exit 1
+fi
+
+# Install the Clang compiler
+apt-get install -y clang-3.4 libclang-3.4-dev llvm-3.4 libtool bison flex automake subversion git pkg-config wget libssl-dev uuid-dev libxml2-dev || exit 1
+
+# Add LLVM to the linker library path
+echo /usr/lib/llvm-3.4/lib > /etc/ld.so.conf.d/libllvm-3.4.conf
+ldconfig
+
+# Add symlinks for the LLVM headers
+ln -s /usr/lib/llvm-3.4/bin/llvm-config /usr/bin/llvm-config || exit 1
+ln -s /usr/include/llvm-3.4/llvm /usr/include/llvm || exit 1
+ln -s /usr/include/llvm-c-3.4/llvm-c /usr/include/llvm-c || exit 1
+ln -s /usr/bin/clang-3.4 /usr/bin/clang || exit 1
+ln -s /usr/bin/clang++-3.4 /usr/bin/clang++ || exit 1
+
+# Build the linker
+svn checkout http://ios-toolchain-based-on-clang-for-linux.googlecode.com/svn/trunk/cctools-porting || exit 1
+cd cctools-porting
+sed -i'' 's/proz -k=20 --no-curses/wget/g' cctools-ld64.sh
+./cctools-ld64.sh || exit 1
+
+cd cctools-855-ld64-236.3
+./autogen.sh || exit 1
+./configure --prefix=/usr/local --target=arm-apple-darwin11 || exit 1
+make || exit 1
+make install || exit 1
+cd ../..
+
+# Install ios-tools
+wget https://ios-toolchain-based-on-clang-for-linux.googlecode.com/files/iphonesdk-utils-2.0.tar.gz || exit 1
+tar xzf iphonesdk-utils-2.0.tar.gz
+cd iphonesdk-utils-2.0
+patch -p0 <<_EOF
+*** genLocalization2/getLocalizedStringFromFile.cpp 2015-04-02 04:45:39.309837816 +0530
+--- genLocalization2/getLocalizedStringFromFile.cpp 2015-04-02 04:45:11.525700021 +0530
+***************
+*** 113,115 ****
+ clang::HeaderSearch headerSearch(headerSearchOptions,
+- fileManager,
+ *pDiagnosticsEngine,
+--- 113,115 ----
+ clang::HeaderSearch headerSearch(headerSearchOptions,
++ sourceManager,
+ *pDiagnosticsEngine,
+***************
+*** 129,134 ****
+ false);
+- clang::HeaderSearch headerSearch(fileManager,
+ *pDiagnosticsEngine,
+ languageOptions,
+- pTargetInfo);
+ ApplyHeaderSearchOptions(headerSearch, headerSearchOptions, languageOptions, pTargetInfo->getTriple());
+--- 129,134 ----
+ false);
++ clang::HeaderSearch headerSearch(fileManager);/*,
+ *pDiagnosticsEngine,
+ languageOptions,
++ pTargetInfo);*/
+ ApplyHeaderSearchOptions(headerSearch, headerSearchOptions, languageOptio
+_EOF
+
+./autogen.sh || exit 1
+CC=clang CXX=clang++ ./configure --prefix=/usr/local || exit 1
+make || exit 1
+make install || exit 1
+
+# Install the iOS SDK 8.1
+mkdir -p /usr/share/ios-sdk
+cd /usr/share/ios-sdk
+wget http://iphone.howett.net/sdks/dl/iPhoneOS8.1.sdk.tbz2 || exit 1
+tar xjf iPhoneOS8.1.sdk.tbz2
+rm iPhoneOS8.1.sdk.tbz2
+```
+
+Now, in order to compile ScummVM, execute the following commands:
+```
+$ export SDKROOT=/usr/share/ios-sdk/iPhoneOS8.1.sdk
+$ export CC=ios-clang
+$ export CXX=ios-clang++
+$ ./configure --host=ios7 --disable-mt32emu --enable-release
+$ make ios7bundle
+```
+
+At the end of the compilation, you'll find a **ScummVM.app** application: copy it over SSH, and reboot your device.
+
+## Usage ##
+
+The game data files can be copied on the iOS device using iTunes. Once done, add your games in ScummVM as usual.
+
+Here is a list of the in-game gestures:
+
+|Gesture|Description|
+|-------|-----------|
+|Two fingers swipe down|Display the ScummVM menu for loading, saving, etc.|
+|Two fingers swipe right|Enable / disable the touchpad mode|
+|Two fingers swipe up|Enable / disable the mouse-click-and-drag mode|
+|Two fingers tap|Simulate a right click. You should tap with one finger, and then tap with another while keeping your first finger on the screen.|
+|Two fingers double-tap|Skip the cinematic / video|
+
+The iOS keyboard is visible when the device is in portrait mode, and hidden in landscape mode.
diff --git a/backends/platform/ios7/iOS7AppDelegate.h b/backends/platform/ios7/iOS7AppDelegate.h
new file mode 100644
index 0000000000..7f903a692d
--- /dev/null
+++ b/backends/platform/ios7/iOS7AppDelegate.h
@@ -0,0 +1,15 @@
+//
+// Created by Vincent Bénony on 07/12/2015.
+//
+
+#import <UIKit/UIKit.h>
+
+@class iPhoneView;
+
+
+@interface iOS7AppDelegate : NSObject<UIApplicationDelegate>
+
++ (iOS7AppDelegate *)iOS7AppDelegate;
++ (iPhoneView *)iPhoneView;
+
+@end
diff --git a/backends/platform/ios7/iOS7AppDelegate.mm b/backends/platform/ios7/iOS7AppDelegate.mm
new file mode 100644
index 0000000000..e9908ec146
--- /dev/null
+++ b/backends/platform/ios7/iOS7AppDelegate.mm
@@ -0,0 +1,95 @@
+//
+// Created by Vincent Bénony on 07/12/2015.
+//
+
+#define FORBIDDEN_SYMBOL_ALLOW_ALL
+#import "iOS7AppDelegate.h"
+#import "iOS7ScummVMViewController.h"
+#import "ios7_video.h"
+
+@implementation iOS7AppDelegate {
+ UIWindow *_window;
+ iOS7ScummVMViewController *_controller;
+ iPhoneView *_view;
+}
+
+- (id)init {
+ if (self = [super init]) {
+ _window = nil;
+ _view = nil;
+ }
+ return self;
+}
+
+- (void)mainLoop:(id)param {
+ @autoreleasepool {
+ iOS7_main(iOS7_argc, iOS7_argv);
+ }
+
+ exit(0);
+}
+
+- (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()];
+ NSString *savePath = [documentPath stringByAppendingPathComponent:@"Savegames"];
+ if (![fm fileExistsAtPath:savePath]) {
+ [fm createDirectoryAtPath:savePath withIntermediateDirectories:YES attributes:nil error:nil];
+ }
+#endif
+
+ _window = [[UIWindow alloc] initWithFrame:rect];
+ [_window retain];
+
+ _controller = [[iOS7ScummVMViewController alloc] init];
+
+ _view = [[iPhoneView alloc] initWithFrame:rect];
+ _view.multipleTouchEnabled = YES;
+ _controller.view = _view;
+
+ [_window setRootViewController:_controller];
+ [_window makeKeyAndVisible];
+
+ [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
+ [[NSNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(didRotate:)
+ name:@"UIDeviceOrientationDidChangeNotification"
+ object:nil];
+
+ [NSThread detachNewThreadSelector:@selector(mainLoop:) toTarget:self withObject:nil];
+}
+
+- (void)applicationWillResignActive:(UIApplication *)application {
+ [_view applicationSuspend];
+}
+
+- (void)applicationDidBecomeActive:(UIApplication *)application {
+ [_view applicationResume];
+}
+
+- (void)didRotate:(NSNotification *)notification {
+ UIDeviceOrientation screenOrientation = [[UIDevice currentDevice] orientation];
+ [_view deviceOrientationChanged:screenOrientation];
+}
+
++ (iOS7AppDelegate *)iOS7AppDelegate {
+ UIApplication *app = [UIApplication sharedApplication];
+ return (iOS7AppDelegate *) app.delegate;
+}
+
++ (iPhoneView *)iPhoneView {
+ iOS7AppDelegate *appDelegate = [self iOS7AppDelegate];
+ return appDelegate->_view;
+}
+
+@end
+
+const char *iOS7_getDocumentsDir() {
+ NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
+ NSString *documentsDirectory = [paths objectAtIndex:0];
+ return [documentsDirectory UTF8String];
+}
diff --git a/backends/platform/ios7/iOS7ScummVMViewController.h b/backends/platform/ios7/iOS7ScummVMViewController.h
new file mode 100644
index 0000000000..0322bc6f7f
--- /dev/null
+++ b/backends/platform/ios7/iOS7ScummVMViewController.h
@@ -0,0 +1,28 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#import <UIKit/UIKit.h>
+
+
+@interface iOS7ScummVMViewController : UIViewController
+
+@end
diff --git a/backends/platform/ios7/iOS7ScummVMViewController.mm b/backends/platform/ios7/iOS7ScummVMViewController.mm
new file mode 100644
index 0000000000..f92fd0115c
--- /dev/null
+++ b/backends/platform/ios7/iOS7ScummVMViewController.mm
@@ -0,0 +1,32 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#import "iOS7ScummVMViewController.h"
+
+
+@implementation iOS7ScummVMViewController
+
+- (BOOL)prefersStatusBarHidden {
+ return YES;
+}
+
+@end
diff --git a/backends/platform/ios7/ios7_common.h b/backends/platform/ios7/ios7_common.h
new file mode 100644
index 0000000000..a32a59a541
--- /dev/null
+++ b/backends/platform/ios7/ios7_common.h
@@ -0,0 +1,131 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef BACKENDS_PLATFORM_IPHONE_IPHONE_COMMON_H
+#define BACKENDS_PLATFORM_IPHONE_IPHONE_COMMON_H
+
+#include "graphics/surface.h"
+
+// #define ENABLE_IOS7_SCALERS
+
+
+enum InputEvent {
+ kInputMouseDown,
+ kInputMouseUp,
+ kInputMouseDragged,
+ kInputMouseSecondDragged,
+ kInputMouseSecondDown,
+ kInputMouseSecondUp,
+ kInputOrientationChanged,
+ kInputKeyPressed,
+ kInputApplicationSuspended,
+ kInputApplicationResumed,
+ kInputSwipe,
+ kInputTap
+};
+
+enum ScreenOrientation {
+ kScreenOrientationPortrait,
+ kScreenOrientationLandscape,
+ kScreenOrientationFlippedLandscape
+};
+
+enum UIViewSwipeDirection {
+ kUIViewSwipeUp = 1,
+ kUIViewSwipeDown = 2,
+ kUIViewSwipeLeft = 4,
+ kUIViewSwipeRight = 8
+};
+
+enum UIViewTapDescription {
+ kUIViewTapSingle = 1,
+ kUIViewTapDouble = 2
+};
+
+enum GraphicsModes {
+ kGraphicsModeLinear = 0,
+ kGraphicsModeNone = 1,
+
+ kGraphicsMode2xSaI,
+ kGraphicsModeSuper2xSaI,
+ kGraphicsModeSuperEagle,
+ kGraphicsModeAdvMame2x,
+ kGraphicsModeAdvMame3x,
+ kGraphicsModeHQ2x,
+ kGraphicsModeHQ3x,
+ kGraphicsModeTV2x,
+ kGraphicsModeDotMatrix
+};
+
+struct VideoContext {
+ VideoContext() : asprectRatioCorrection(), screenWidth(), screenHeight(), overlayVisible(false),
+ overlayWidth(), overlayHeight(), mouseX(), mouseY(),
+ mouseHotspotX(), mouseHotspotY(), mouseWidth(), mouseHeight(),
+ mouseIsVisible(), graphicsMode(kGraphicsModeNone), shakeOffsetY() {
+ }
+
+ // Game screen state
+ bool asprectRatioCorrection;
+ uint screenWidth, screenHeight;
+ Graphics::Surface screenTexture;
+
+ // Overlay state
+ bool overlayVisible;
+ uint overlayWidth, overlayHeight;
+ Graphics::Surface overlayTexture;
+
+ // Mouse cursor state
+ uint mouseX, mouseY;
+ int mouseHotspotX, mouseHotspotY;
+ uint mouseWidth, mouseHeight;
+ bool mouseIsVisible;
+ Graphics::Surface mouseTexture;
+
+ // Misc state
+ GraphicsModes graphicsMode;
+ int shakeOffsetY;
+};
+
+struct InternalEvent {
+ InternalEvent() : type(), value1(), value2() {}
+ InternalEvent(InputEvent t, int v1, int v2) : type(t), value1(v1), value2(v2) {}
+
+ InputEvent type;
+ int value1, value2;
+};
+
+// On the ObjC side
+
+extern int iOS7_argc;
+extern char **iOS7_argv;
+
+void iOS7_updateScreen();
+bool iOS7_fetchEvent(InternalEvent *event);
+bool iOS7_isBigDevice();
+
+void iOS7_main(int argc, char **argv);
+const char *iOS7_getDocumentsDir();
+bool iOS7_touchpadModeEnabled();
+
+uint getSizeNextPOT(uint size);
+
+#endif
diff --git a/backends/platform/ios7/ios7_keyboard.h b/backends/platform/ios7/ios7_keyboard.h
new file mode 100644
index 0000000000..ddd8f436e5
--- /dev/null
+++ b/backends/platform/ios7/ios7_keyboard.h
@@ -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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef BACKENDS_PLATFORM_IPHONE_IPHONE_KEYBOARD_H
+#define BACKENDS_PLATFORM_IPHONE_IPHONE_KEYBOARD_H
+
+#include <UIKit/UIKit.h>
+#include <UIKit/UITextView.h>
+
+@interface SoftKeyboard : UIView<UITextViewDelegate> {
+ id inputDelegate;
+ UITextView *inputView;
+}
+
+- (id)initWithFrame:(CGRect)frame;
+- (UITextView *)inputView;
+- (void)setInputDelegate:(id)delegate;
+- (void)handleKeyPress:(unichar)c;
+
+- (void)showKeyboard;
+- (void)hideKeyboard;
+
+@end
+
+#endif
diff --git a/backends/platform/ios7/ios7_keyboard.mm b/backends/platform/ios7/ios7_keyboard.mm
new file mode 100644
index 0000000000..7923a1cda9
--- /dev/null
+++ b/backends/platform/ios7/ios7_keyboard.mm
@@ -0,0 +1,98 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "ios7_keyboard.h"
+
+@interface UITextInputTraits
+- (void)setAutocorrectionType:(int)type;
+- (void)setAutocapitalizationType:(int)type;
+- (void)setEnablesReturnKeyAutomatically:(BOOL)val;
+@end
+
+@interface TextInputHandler : UITextView {
+ SoftKeyboard *softKeyboard;
+}
+
+- (id)initWithKeyboard:(SoftKeyboard *)keyboard;
+
+@end
+
+
+@implementation TextInputHandler
+
+- (id)initWithKeyboard:(SoftKeyboard *)keyboard {
+ self = [super initWithFrame:CGRectMake(0.0f, 0.0f, 0.0f, 0.0f)];
+ softKeyboard = keyboard;
+
+ [self setAutocorrectionType:UITextAutocorrectionTypeNo];
+ [self setAutocapitalizationType:UITextAutocapitalizationTypeNone];
+ [self setEnablesReturnKeyAutomatically:NO];
+
+ return self;
+}
+
+@end
+
+
+@implementation SoftKeyboard
+
+- (id)initWithFrame:(CGRect)frame {
+ self = [super initWithFrame:frame];
+ inputDelegate = nil;
+ inputView = [[TextInputHandler alloc] initWithKeyboard:self];
+ inputView.delegate = self;
+ return self;
+}
+
+- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
+ unichar c;
+ if (text.length) {
+ c = [text characterAtIndex:0];
+ }
+ else {
+ c = '\b';
+ }
+ [inputDelegate handleKeyPress:c];
+ return YES;
+}
+
+- (UITextView *)inputView {
+ return inputView;
+}
+
+- (void)setInputDelegate:(id)delegate {
+ inputDelegate = delegate;
+}
+
+- (void)handleKeyPress:(unichar)c {
+ [inputDelegate handleKeyPress:c];
+}
+
+- (void)showKeyboard {
+ [inputView becomeFirstResponder];
+}
+
+- (void)hideKeyboard {
+ [inputView endEditing:YES];
+}
+
+@end
diff --git a/backends/platform/ios7/ios7_main.mm b/backends/platform/ios7/ios7_main.mm
new file mode 100644
index 0000000000..96f41f4c02
--- /dev/null
+++ b/backends/platform/ios7/ios7_main.mm
@@ -0,0 +1,47 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+// Disable symbol overrides so that we can use system headers.
+#define FORBIDDEN_SYMBOL_ALLOW_ALL
+
+#include <UIKit/UIKit.h>
+#include <Foundation/NSThread.h>
+
+#include "ios7_video.h"
+
+
+int iOS7_argc;
+char **iOS7_argv;
+
+int main(int argc, char **argv) {
+ int returnCode;
+
+ @autoreleasepool {
+ iOS7_argc = argc;
+ iOS7_argv = argv;
+
+ returnCode = UIApplicationMain(argc, argv, @"UIApplication", @"iOS7AppDelegate");
+ }
+
+ return returnCode;
+}
+
diff --git a/backends/platform/ios7/ios7_osys_events.cpp b/backends/platform/ios7/ios7_osys_events.cpp
new file mode 100644
index 0000000000..7e805f34b7
--- /dev/null
+++ b/backends/platform/ios7/ios7_osys_events.cpp
@@ -0,0 +1,576 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+// Disable symbol overrides so that we can use system headers.
+#define FORBIDDEN_SYMBOL_ALLOW_ALL
+
+#include "gui/message.h"
+#include "common/translation.h"
+
+#include "ios7_osys_main.h"
+
+static const int kQueuedInputEventDelay = 50;
+
+bool OSystem_iOS7::pollEvent(Common::Event &event) {
+ //printf("pollEvent()\n");
+
+ long curTime = getMillis();
+
+ if (_timerCallback && (curTime >= _timerCallbackNext)) {
+ _timerCallback(_timerCallbackTimer);
+ _timerCallbackNext = curTime + _timerCallbackTimer;
+ }
+
+ if (_queuedInputEvent.type != Common::EVENT_INVALID && curTime >= _queuedEventTime) {
+ event = _queuedInputEvent;
+ _queuedInputEvent.type = Common::EVENT_INVALID;
+ return true;
+ }
+
+ InternalEvent internalEvent;
+
+ if (iOS7_fetchEvent(&internalEvent)) {
+ switch (internalEvent.type) {
+ case kInputMouseDown:
+ if (!handleEvent_mouseDown(event, internalEvent.value1, internalEvent.value2))
+ return false;
+ break;
+
+ case kInputMouseUp:
+ if (!handleEvent_mouseUp(event, internalEvent.value1, internalEvent.value2))
+ return false;
+ break;
+
+ case kInputMouseDragged:
+ if (!handleEvent_mouseDragged(event, internalEvent.value1, internalEvent.value2))
+ return false;
+ break;
+
+ case kInputOrientationChanged:
+ handleEvent_orientationChanged(internalEvent.value1);
+ return false;
+
+ case kInputApplicationSuspended:
+ handleEvent_applicationSuspended();
+ return false;
+
+ case kInputApplicationResumed:
+ handleEvent_applicationResumed();
+ return false;
+
+ case kInputMouseSecondDragged:
+ if (!handleEvent_mouseSecondDragged(event, internalEvent.value1, internalEvent.value2))
+ return false;
+ break;
+ case kInputMouseSecondDown:
+ _secondaryTapped = true;
+ if (!handleEvent_secondMouseDown(event, internalEvent.value1, internalEvent.value2))
+ return false;
+ break;
+ case kInputMouseSecondUp:
+ _secondaryTapped = false;
+ if (!handleEvent_secondMouseUp(event, internalEvent.value1, internalEvent.value2))
+ return false;
+ break;
+
+ case kInputKeyPressed:
+ handleEvent_keyPressed(event, internalEvent.value1);
+ break;
+
+ case kInputSwipe:
+ if (!handleEvent_swipe(event, internalEvent.value1, internalEvent.value2))
+ return false;
+ break;
+
+ case kInputTap:
+ if (!handleEvent_tap(event, (UIViewTapDescription) internalEvent.value1, internalEvent.value2))
+ return false;
+ break;
+
+ default:
+ break;
+ }
+
+ return true;
+ }
+ return false;
+}
+
+bool OSystem_iOS7::handleEvent_mouseDown(Common::Event &event, int x, int y) {
+ //printf("Mouse down at (%u, %u)\n", x, y);
+
+ // Workaround: kInputMouseSecondToggled isn't always sent when the
+ // secondary finger is lifted. Need to make sure we get out of that mode.
+ _secondaryTapped = false;
+
+ if (_touchpadModeEnabled) {
+ _lastPadX = x;
+ _lastPadY = y;
+ } else
+ warpMouse(x, y);
+
+ if (_mouseClickAndDragEnabled) {
+ event.type = Common::EVENT_LBUTTONDOWN;
+ event.mouse.x = _videoContext->mouseX;
+ event.mouse.y = _videoContext->mouseY;
+ return true;
+ } else {
+ _lastMouseDown = getMillis();
+ }
+ return false;
+}
+
+bool OSystem_iOS7::handleEvent_mouseUp(Common::Event &event, int x, int y) {
+ //printf("Mouse up at (%u, %u)\n", x, y);
+
+ if (_secondaryTapped) {
+ _secondaryTapped = false;
+ if (!handleEvent_secondMouseUp(event, x, y))
+ return false;
+ } else if (_mouseClickAndDragEnabled) {
+ event.type = Common::EVENT_LBUTTONUP;
+ event.mouse.x = _videoContext->mouseX;
+ event.mouse.y = _videoContext->mouseY;
+ } else {
+ if (getMillis() - _lastMouseDown < 250) {
+ event.type = Common::EVENT_LBUTTONDOWN;
+ event.mouse.x = _videoContext->mouseX;
+ event.mouse.y = _videoContext->mouseY;
+
+ _queuedInputEvent.type = Common::EVENT_LBUTTONUP;
+ _queuedInputEvent.mouse.x = _videoContext->mouseX;
+ _queuedInputEvent.mouse.y = _videoContext->mouseY;
+ _lastMouseTap = getMillis();
+ _queuedEventTime = _lastMouseTap + kQueuedInputEventDelay;
+ } else
+ return false;
+ }
+
+ return true;
+}
+
+bool OSystem_iOS7::handleEvent_secondMouseDown(Common::Event &event, int x, int y) {
+ _lastSecondaryDown = getMillis();
+ _gestureStartX = x;
+ _gestureStartY = y;
+
+ if (_mouseClickAndDragEnabled) {
+ event.type = Common::EVENT_LBUTTONUP;
+ event.mouse.x = _videoContext->mouseX;
+ event.mouse.y = _videoContext->mouseY;
+
+ _queuedInputEvent.type = Common::EVENT_RBUTTONDOWN;
+ _queuedInputEvent.mouse.x = _videoContext->mouseX;
+ _queuedInputEvent.mouse.y = _videoContext->mouseY;
+ } else
+ return false;
+
+ return true;
+}
+
+bool OSystem_iOS7::handleEvent_secondMouseUp(Common::Event &event, int x, int y) {
+ int curTime = getMillis();
+
+ if (curTime - _lastSecondaryDown < 400) {
+ //printf("Right tap!\n");
+ if (curTime - _lastSecondaryTap < 400 && !_videoContext->overlayVisible) {
+ //printf("Right escape!\n");
+ event.type = Common::EVENT_KEYDOWN;
+ _queuedInputEvent.type = Common::EVENT_KEYUP;
+
+ event.kbd.flags = _queuedInputEvent.kbd.flags = 0;
+ event.kbd.keycode = _queuedInputEvent.kbd.keycode = Common::KEYCODE_ESCAPE;
+ event.kbd.ascii = _queuedInputEvent.kbd.ascii = Common::ASCII_ESCAPE;
+ _queuedEventTime = curTime + kQueuedInputEventDelay;
+ _lastSecondaryTap = 0;
+ } else if (!_mouseClickAndDragEnabled) {
+ //printf("Rightclick!\n");
+ event.type = Common::EVENT_RBUTTONDOWN;
+ event.mouse.x = _videoContext->mouseX;
+ event.mouse.y = _videoContext->mouseY;
+ _queuedInputEvent.type = Common::EVENT_RBUTTONUP;
+ _queuedInputEvent.mouse.x = _videoContext->mouseX;
+ _queuedInputEvent.mouse.y = _videoContext->mouseY;
+ _lastSecondaryTap = curTime;
+ _queuedEventTime = curTime + kQueuedInputEventDelay;
+ } else {
+ //printf("Right nothing!\n");
+ return false;
+ }
+ }
+ if (_mouseClickAndDragEnabled) {
+ event.type = Common::EVENT_RBUTTONUP;
+ event.mouse.x = _videoContext->mouseX;
+ event.mouse.y = _videoContext->mouseY;
+ }
+
+ return true;
+}
+
+bool OSystem_iOS7::handleEvent_mouseDragged(Common::Event &event, int x, int y) {
+ if (_lastDragPosX == x && _lastDragPosY == y)
+ return false;
+
+ _lastDragPosX = x;
+ _lastDragPosY = y;
+
+ //printf("Mouse dragged at (%u, %u)\n", x, y);
+ int mouseNewPosX;
+ int mouseNewPosY;
+ if (_touchpadModeEnabled) {
+ int deltaX = _lastPadX - x;
+ int deltaY = _lastPadY - y;
+ _lastPadX = x;
+ _lastPadY = y;
+
+ mouseNewPosX = (int)(_videoContext->mouseX - deltaX / 0.5f);
+ mouseNewPosY = (int)(_videoContext->mouseY - deltaY / 0.5f);
+
+ int widthCap = _videoContext->overlayVisible ? _videoContext->overlayWidth : _videoContext->screenWidth;
+ int heightCap = _videoContext->overlayVisible ? _videoContext->overlayHeight : _videoContext->screenHeight;
+
+ if (mouseNewPosX < 0)
+ mouseNewPosX = 0;
+ else if (mouseNewPosX > widthCap)
+ mouseNewPosX = widthCap;
+
+ if (mouseNewPosY < 0)
+ mouseNewPosY = 0;
+ else if (mouseNewPosY > heightCap)
+ mouseNewPosY = heightCap;
+
+ } else {
+ mouseNewPosX = x;
+ mouseNewPosY = y;
+ }
+
+ event.type = Common::EVENT_MOUSEMOVE;
+ event.mouse.x = mouseNewPosX;
+ event.mouse.y = mouseNewPosY;
+ warpMouse(mouseNewPosX, mouseNewPosY);
+
+ return true;
+}
+
+bool OSystem_iOS7::handleEvent_mouseSecondDragged(Common::Event &event, int x, int y) {
+ if (_gestureStartX == -1 || _gestureStartY == -1) {
+ return false;
+ }
+
+ static const int kNeededLength = 100;
+ static const int kMaxDeviation = 20;
+
+ int vecX = (x - _gestureStartX);
+ int vecY = (y - _gestureStartY);
+
+ int absX = abs(vecX);
+ int absY = abs(vecY);
+
+ //printf("(%d, %d)\n", vecX, vecY);
+
+ if (absX >= kNeededLength || absY >= kNeededLength) { // Long enough gesture to react upon.
+ _gestureStartX = -1;
+ _gestureStartY = -1;
+
+ if (absX < kMaxDeviation && vecY >= kNeededLength) {
+ // Swipe down
+ event.type = Common::EVENT_MAINMENU;
+ _queuedInputEvent.type = Common::EVENT_INVALID;
+
+ _queuedEventTime = getMillis() + kQueuedInputEventDelay;
+ return true;
+ }
+
+ if (absX < kMaxDeviation && -vecY >= kNeededLength) {
+ // Swipe up
+ _mouseClickAndDragEnabled = !_mouseClickAndDragEnabled;
+ const char *dialogMsg;
+ if (_mouseClickAndDragEnabled) {
+ _touchpadModeEnabled = false;
+ dialogMsg = _("Mouse-click-and-drag mode enabled.");
+ } else
+ dialogMsg = _("Mouse-click-and-drag mode disabled.");
+ GUI::TimedMessageDialog dialog(dialogMsg, 1500);
+ dialog.runModal();
+ return false;
+ }
+
+ if (absY < kMaxDeviation && vecX >= kNeededLength) {
+ // Swipe right
+ _touchpadModeEnabled = !_touchpadModeEnabled;
+ const char *dialogMsg;
+ if (_touchpadModeEnabled)
+ dialogMsg = _("Touchpad mode enabled.");
+ else
+ dialogMsg = _("Touchpad mode disabled.");
+ GUI::TimedMessageDialog dialog(dialogMsg, 1500);
+ dialog.runModal();
+ return false;
+
+ }
+
+ if (absY < kMaxDeviation && -vecX >= kNeededLength) {
+ // Swipe left
+ return false;
+ }
+ }
+
+ return false;
+}
+
+void OSystem_iOS7::handleEvent_orientationChanged(int orientation) {
+ //printf("Orientation: %i\n", orientation);
+
+ ScreenOrientation newOrientation;
+ switch (orientation) {
+ case 1:
+ newOrientation = kScreenOrientationPortrait;
+ break;
+ case 3:
+ newOrientation = kScreenOrientationLandscape;
+ break;
+ case 4:
+ newOrientation = kScreenOrientationFlippedLandscape;
+ break;
+ default:
+ return;
+ }
+
+ if (_screenOrientation != newOrientation) {
+ _screenOrientation = newOrientation;
+ rebuildSurface();
+ }
+}
+
+void OSystem_iOS7::rebuildSurface() {
+ updateOutputSurface();
+
+ dirtyFullScreen();
+ if (_videoContext->overlayVisible) {
+ dirtyFullOverlayScreen();
+ }
+ updateScreen();
+}
+
+void OSystem_iOS7::handleEvent_applicationSuspended() {
+ suspendLoop();
+}
+
+void OSystem_iOS7::handleEvent_applicationResumed() {
+ rebuildSurface();
+}
+
+void OSystem_iOS7::handleEvent_keyPressed(Common::Event &event, int keyPressed) {
+ int ascii = keyPressed;
+ //printf("key: %i\n", keyPressed);
+
+ // We remap some of the iPhone keyboard keys.
+ // The first ten here are the row of symbols below the numeric keys.
+ switch (keyPressed) {
+ case 45:
+ keyPressed = Common::KEYCODE_F1;
+ ascii = Common::ASCII_F1;
+ break;
+ case 47:
+ keyPressed = Common::KEYCODE_F2;
+ ascii = Common::ASCII_F2;
+ break;
+ case 58:
+ keyPressed = Common::KEYCODE_F3;
+ ascii = Common::ASCII_F3;
+ break;
+ case 59:
+ keyPressed = Common::KEYCODE_F4;
+ ascii = Common::ASCII_F4;
+ break;
+ case 40:
+ keyPressed = Common::KEYCODE_F5;
+ ascii = Common::ASCII_F5;
+ break;
+ case 41:
+ keyPressed = Common::KEYCODE_F6;
+ ascii = Common::ASCII_F6;
+ break;
+ case 36:
+ keyPressed = Common::KEYCODE_F7;
+ ascii = Common::ASCII_F7;
+ break;
+ case 38:
+ keyPressed = Common::KEYCODE_F8;
+ ascii = Common::ASCII_F8;
+ break;
+ case 64:
+ keyPressed = Common::KEYCODE_F9;
+ ascii = Common::ASCII_F9;
+ break;
+ case 34:
+ keyPressed = Common::KEYCODE_F10;
+ ascii = Common::ASCII_F10;
+ break;
+ case 10:
+ keyPressed = Common::KEYCODE_RETURN;
+ ascii = Common::ASCII_RETURN;
+ break;
+ }
+ event.type = Common::EVENT_KEYDOWN;
+ _queuedInputEvent.type = Common::EVENT_KEYUP;
+
+ event.kbd.flags = _queuedInputEvent.kbd.flags = 0;
+ event.kbd.keycode = _queuedInputEvent.kbd.keycode = (Common::KeyCode)keyPressed;
+ event.kbd.ascii = _queuedInputEvent.kbd.ascii = ascii;
+ _queuedEventTime = getMillis() + kQueuedInputEventDelay;
+}
+
+bool OSystem_iOS7::handleEvent_swipe(Common::Event &event, int direction, int touches) {
+ if (touches == 1) {
+ Common::KeyCode keycode = Common::KEYCODE_INVALID;
+ switch (_screenOrientation) {
+ case kScreenOrientationPortrait:
+ switch ((UIViewSwipeDirection)direction) {
+ case kUIViewSwipeUp:
+ keycode = Common::KEYCODE_UP;
+ break;
+ case kUIViewSwipeDown:
+ keycode = Common::KEYCODE_DOWN;
+ break;
+ case kUIViewSwipeLeft:
+ keycode = Common::KEYCODE_LEFT;
+ break;
+ case kUIViewSwipeRight:
+ keycode = Common::KEYCODE_RIGHT;
+ break;
+ default:
+ return false;
+ }
+ break;
+ case kScreenOrientationLandscape:
+ switch ((UIViewSwipeDirection)direction) {
+ case kUIViewSwipeUp:
+ keycode = Common::KEYCODE_LEFT;
+ break;
+ case kUIViewSwipeDown:
+ keycode = Common::KEYCODE_RIGHT;
+ break;
+ case kUIViewSwipeLeft:
+ keycode = Common::KEYCODE_DOWN;
+ break;
+ case kUIViewSwipeRight:
+ keycode = Common::KEYCODE_UP;
+ break;
+ default:
+ return false;
+ }
+ break;
+ case kScreenOrientationFlippedLandscape:
+ switch ((UIViewSwipeDirection)direction) {
+ case kUIViewSwipeUp:
+ keycode = Common::KEYCODE_RIGHT;
+ break;
+ case kUIViewSwipeDown:
+ keycode = Common::KEYCODE_LEFT;
+ break;
+ case kUIViewSwipeLeft:
+ keycode = Common::KEYCODE_UP;
+ break;
+ case kUIViewSwipeRight:
+ keycode = Common::KEYCODE_DOWN;
+ break;
+ default:
+ return false;
+ }
+ break;
+ }
+
+ event.kbd.keycode = _queuedInputEvent.kbd.keycode = keycode;
+ event.kbd.ascii = _queuedInputEvent.kbd.ascii = 0;
+ event.type = Common::EVENT_KEYDOWN;
+ _queuedInputEvent.type = Common::EVENT_KEYUP;
+ event.kbd.flags = _queuedInputEvent.kbd.flags = 0;
+ _queuedEventTime = getMillis() + kQueuedInputEventDelay;
+
+ return true;
+ }
+ else if (touches == 2) {
+ switch ((UIViewSwipeDirection)direction) {
+ case kUIViewSwipeUp: {
+ _mouseClickAndDragEnabled = !_mouseClickAndDragEnabled;
+ const char *dialogMsg;
+ if (_mouseClickAndDragEnabled) {
+ _touchpadModeEnabled = false;
+ dialogMsg = _("Mouse-click-and-drag mode enabled.");
+ } else
+ dialogMsg = _("Mouse-click-and-drag mode disabled.");
+ GUI::TimedMessageDialog dialog(dialogMsg, 1500);
+ dialog.runModal();
+ return false;
+ }
+
+ case kUIViewSwipeDown: {
+ // Swipe down
+ event.type = Common::EVENT_MAINMENU;
+ _queuedInputEvent.type = Common::EVENT_INVALID;
+ _queuedEventTime = getMillis() + kQueuedInputEventDelay;
+ return true;
+ }
+
+ case kUIViewSwipeRight: {
+ // Swipe right
+ _touchpadModeEnabled = !_touchpadModeEnabled;
+ const char *dialogMsg;
+ if (_touchpadModeEnabled)
+ dialogMsg = _("Touchpad mode enabled.");
+ else
+ dialogMsg = _("Touchpad mode disabled.");
+ GUI::TimedMessageDialog dialog(dialogMsg, 1500);
+ dialog.runModal();
+ return false;
+ }
+
+ default:
+ break;
+ }
+ }
+ return false;
+}
+
+bool OSystem_iOS7::handleEvent_tap(Common::Event &event, UIViewTapDescription type, int touches) {
+ if (touches == 1) {
+ if (type == kUIViewTapDouble) {
+ event.type = Common::EVENT_RBUTTONDOWN;
+ _queuedInputEvent.type = Common::EVENT_RBUTTONUP;
+ _queuedEventTime = getMillis() + kQueuedInputEventDelay;
+ return true;
+ }
+ }
+ else if (touches == 2) {
+ if (type == kUIViewTapDouble) {
+ event.kbd.keycode = _queuedInputEvent.kbd.keycode = Common::KEYCODE_ESCAPE;
+ event.kbd.ascii = _queuedInputEvent.kbd.ascii = Common::ASCII_ESCAPE;
+ event.type = Common::EVENT_KEYDOWN;
+ _queuedInputEvent.type = Common::EVENT_KEYUP;
+ event.kbd.flags = _queuedInputEvent.kbd.flags = 0;
+ _queuedEventTime = getMillis() + kQueuedInputEventDelay;
+ return true;
+ }
+ }
+ return false;
+}
diff --git a/backends/platform/ios7/ios7_osys_main.cpp b/backends/platform/ios7/ios7_osys_main.cpp
new file mode 100644
index 0000000000..37fa34ce33
--- /dev/null
+++ b/backends/platform/ios7/ios7_osys_main.cpp
@@ -0,0 +1,368 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+// Disable symbol overrides so that we can use system headers.
+#define FORBIDDEN_SYMBOL_ALLOW_ALL
+
+#include <unistd.h>
+#include <pthread.h>
+#include <string.h>
+
+#include <sys/time.h>
+#include <QuartzCore/QuartzCore.h>
+
+#include "common/scummsys.h"
+#include "common/util.h"
+#include "common/rect.h"
+#include "common/file.h"
+#include "common/fs.h"
+
+#include "base/main.h"
+
+#include "backends/saves/default/default-saves.h"
+#include "backends/timer/default/default-timer.h"
+#include "backends/fs/chroot/chroot-fs-factory.h"
+#include "backends/fs/posix/posix-fs.h"
+#include "audio/mixer.h"
+#include "audio/mixer_intern.h"
+
+#include "graphics/scaler.h"
+#include "graphics/scaler/aspect.h"
+
+#include "ios7_osys_main.h"
+
+
+const OSystem::GraphicsMode OSystem_iOS7::s_supportedGraphicsModes[] = {
+ { "none", "No filtering", kGraphicsModeNone },
+ { "linear", "Linear filtering", kGraphicsModeLinear },
+
+#ifdef ENABLE_IOS7_SCALERS
+#ifdef USE_SCALERS
+// {"2x", "2x", GFX_DOUBLESIZE},
+// {"3x", "3x", GFX_TRIPLESIZE},
+ { "2xsai", "2xSAI", kGraphicsMode2xSaI},
+ {"super2xsai", "Super2xSAI", kGraphicsModeSuper2xSaI},
+ {"supereagle", "SuperEagle", kGraphicsModeSuperEagle},
+ {"advmame2x", "AdvMAME2x", kGraphicsModeAdvMame2x},
+ {"advmame3x", "AdvMAME3x", kGraphicsModeAdvMame3x},
+#ifdef USE_HQ_SCALERS
+ {"hq2x", "HQ2x", kGraphicsModeHQ2x},
+ {"hq3x", "HQ3x", kGraphicsModeHQ3x},
+#endif
+ {"tv2x", "TV2x", kGraphicsModeTV2x},
+ {"dotmatrix", "DotMatrix", kGraphicsModeDotMatrix},
+#endif
+#endif
+ { 0, 0, 0 }
+};
+
+AQCallbackStruct OSystem_iOS7::s_AudioQueue;
+SoundProc OSystem_iOS7::s_soundCallback = NULL;
+void *OSystem_iOS7::s_soundParam = NULL;
+
+OSystem_iOS7::OSystem_iOS7() :
+ _mixer(NULL), _lastMouseTap(0), _queuedEventTime(0),
+ _mouseNeedTextureUpdate(false), _secondaryTapped(false), _lastSecondaryTap(0),
+ _screenOrientation(kScreenOrientationFlippedLandscape), _mouseClickAndDragEnabled(false),
+ _gestureStartX(-1), _gestureStartY(-1), _fullScreenIsDirty(false), _fullScreenOverlayIsDirty(false),
+ _mouseDirty(false), _timeSuspended(0), _lastDragPosX(-1), _lastDragPosY(-1), _screenChangeCount(0),
+ _lastErrorMessage(NULL), _mouseCursorPaletteEnabled(false), _gfxTransactionError(kTransactionSuccess) {
+ _queuedInputEvent.type = Common::EVENT_INVALID;
+ _touchpadModeEnabled = !iOS7_isBigDevice();
+#ifdef IPHONE_SANDBOXED
+ _fsFactory = new ChRootFilesystemFactory(iOS7_getDocumentsDir());
+#else
+ _fsFactory = new POSIXFilesystemFactory();
+#endif
+ initVideoContext();
+
+ memset(_gamePalette, 0, sizeof(_gamePalette));
+ memset(_gamePaletteRGBA5551, 0, sizeof(_gamePaletteRGBA5551));
+ memset(_mouseCursorPalette, 0, sizeof(_mouseCursorPalette));
+}
+
+OSystem_iOS7::~OSystem_iOS7() {
+ AudioQueueDispose(s_AudioQueue.queue, true);
+
+ delete _mixer;
+ // Prevent accidental freeing of the screen texture here. This needs to be
+ // checked since we might use the screen texture as framebuffer in the case
+ // of hi-color games for example. Otherwise this can lead to a double free.
+ if (_framebuffer.getPixels() != _videoContext->screenTexture.getPixels())
+ _framebuffer.free();
+ _mouseBuffer.free();
+}
+
+bool OSystem_iOS7::touchpadModeEnabled() const {
+ return _touchpadModeEnabled;
+}
+
+int OSystem_iOS7::timerHandler(int t) {
+ DefaultTimerManager *tm = (DefaultTimerManager *)g_system->getTimerManager();
+ tm->handler();
+ return t;
+}
+
+void OSystem_iOS7::initBackend() {
+#ifdef IPHONE_SANDBOXED
+ _savefileManager = new DefaultSaveFileManager("/Savegames");
+#else
+ _savefileManager = new DefaultSaveFileManager(SCUMMVM_SAVE_PATH);
+#endif
+
+ _timerManager = new DefaultTimerManager();
+
+ gettimeofday(&_startTime, NULL);
+
+ setupMixer();
+
+ setTimerCallback(&OSystem_iOS7::timerHandler, 10);
+
+ EventsBaseBackend::initBackend();
+}
+
+bool OSystem_iOS7::hasFeature(Feature f) {
+ switch (f) {
+ case kFeatureCursorPalette:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+void OSystem_iOS7::setFeatureState(Feature f, bool enable) {
+ switch (f) {
+ case kFeatureCursorPalette:
+ if (_mouseCursorPaletteEnabled != enable) {
+ _mouseNeedTextureUpdate = true;
+ _mouseDirty = true;
+ _mouseCursorPaletteEnabled = enable;
+ }
+ break;
+ case kFeatureAspectRatioCorrection:
+ _videoContext->asprectRatioCorrection = enable;
+ break;
+
+ default:
+ break;
+ }
+}
+
+bool OSystem_iOS7::getFeatureState(Feature f) {
+ switch (f) {
+ case kFeatureCursorPalette:
+ return _mouseCursorPaletteEnabled;
+ case kFeatureAspectRatioCorrection:
+ return _videoContext->asprectRatioCorrection;
+
+ default:
+ return false;
+ }
+}
+
+void OSystem_iOS7::suspendLoop() {
+ bool done = false;
+ uint32 startTime = getMillis();
+
+ stopSoundsystem();
+
+ InternalEvent event;
+ while (!done) {
+ if (iOS7_fetchEvent(&event))
+ if (event.type == kInputApplicationResumed)
+ done = true;
+ usleep(100000);
+ }
+
+ startSoundsystem();
+
+ _timeSuspended += getMillis() - startTime;
+}
+
+uint32 OSystem_iOS7::getMillis(bool skipRecord) {
+ CFTimeInterval timeInSeconds = CACurrentMediaTime();
+ return (uint32) (timeInSeconds * 1000.0);
+}
+
+void OSystem_iOS7::delayMillis(uint msecs) {
+ //printf("delayMillis(%d)\n", msecs);
+ usleep(msecs * 1000);
+}
+
+OSystem::MutexRef OSystem_iOS7::createMutex(void) {
+ pthread_mutexattr_t attr;
+ pthread_mutexattr_init(&attr);
+ pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
+
+ pthread_mutex_t *mutex = (pthread_mutex_t *) malloc(sizeof(pthread_mutex_t));
+ if (pthread_mutex_init(mutex, &attr) != 0) {
+ printf("pthread_mutex_init() failed!\n");
+ free(mutex);
+ return NULL;
+ }
+
+ return (MutexRef)mutex;
+}
+
+void OSystem_iOS7::lockMutex(MutexRef mutex) {
+ if (pthread_mutex_lock((pthread_mutex_t *) mutex) != 0) {
+ printf("pthread_mutex_lock() failed!\n");
+ }
+}
+
+void OSystem_iOS7::unlockMutex(MutexRef mutex) {
+ if (pthread_mutex_unlock((pthread_mutex_t *) mutex) != 0) {
+ printf("pthread_mutex_unlock() failed!\n");
+ }
+}
+
+void OSystem_iOS7::deleteMutex(MutexRef mutex) {
+ if (pthread_mutex_destroy((pthread_mutex_t *) mutex) != 0) {
+ printf("pthread_mutex_destroy() failed!\n");
+ } else {
+ free(mutex);
+ }
+}
+
+
+void OSystem_iOS7::setTimerCallback(TimerProc callback, int interval) {
+ //printf("setTimerCallback()\n");
+
+ if (callback != NULL) {
+ _timerCallbackTimer = interval;
+ _timerCallbackNext = getMillis() + interval;
+ _timerCallback = callback;
+ } else
+ _timerCallback = NULL;
+}
+
+void OSystem_iOS7::quit() {
+}
+
+void OSystem_iOS7::getTimeAndDate(TimeDate &td) const {
+ time_t curTime = time(0);
+ struct tm t = *localtime(&curTime);
+ td.tm_sec = t.tm_sec;
+ td.tm_min = t.tm_min;
+ td.tm_hour = t.tm_hour;
+ td.tm_mday = t.tm_mday;
+ td.tm_mon = t.tm_mon;
+ td.tm_year = t.tm_year;
+ td.tm_wday = t.tm_wday;
+}
+
+Audio::Mixer *OSystem_iOS7::getMixer() {
+ assert(_mixer);
+ return _mixer;
+}
+
+OSystem_iOS7 *OSystem_iOS7::sharedInstance() {
+ static OSystem_iOS7 *instance = new OSystem_iOS7();
+ return instance;
+}
+
+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) {
+ // Get URL of the Resource directory of the .app bundle
+ CFURLRef fileUrl = CFBundleCopyResourcesDirectoryURL(CFBundleGetMainBundle());
+ if (fileUrl) {
+ // Try to convert the URL to an absolute path
+ UInt8 buf[MAXPATHLEN];
+ 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);
+ Common::FSNode *node = new Common::FSNode(posixNode);
+ s.add("__IOS_BUNDLE__", new Common::FSDirectory(*node), priority);
+#else
+ s.add("__IOS_BUNDLE__", new Common::FSDirectory(bundlePath), priority);
+#endif
+ }
+ CFRelease(fileUrl);
+ }
+}
+
+void OSystem_iOS7::logMessage(LogMessageType::Type type, const char *message) {
+ FILE *output = 0;
+
+ if (type == LogMessageType::kInfo || type == LogMessageType::kDebug)
+ output = stdout;
+ else
+ output = stderr;
+
+ if (type == LogMessageType::kError) {
+ free(_lastErrorMessage);
+ _lastErrorMessage = strdup(message);
+ }
+
+ fputs(message, output);
+ fflush(output);
+}
+
+bool iOS7_touchpadModeEnabled() {
+ OSystem_iOS7 *sys = (OSystem_iOS7 *) g_system;
+ return sys && sys->touchpadModeEnabled();
+}
+
+void iOS7_main(int argc, char **argv) {
+
+ //OSystem_iOS7::migrateApp();
+
+ FILE *newfp = fopen("/var/mobile/.scummvm.log", "a");
+ if (newfp != NULL) {
+ fclose(stdout);
+ fclose(stderr);
+ *stdout = *newfp;
+ *stderr = *newfp;
+ setbuf(stdout, NULL);
+ setbuf(stderr, NULL);
+
+ //extern int gDebugLevel;
+ //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);
+
+ // Invoke the actual ScummVM main entry point:
+ scummvm_main(argc, (const char *const *) argv);
+ g_system->quit(); // TODO: Consider removing / replacing this!
+}
diff --git a/backends/platform/ios7/ios7_osys_main.h b/backends/platform/ios7/ios7_osys_main.h
new file mode 100644
index 0000000000..eadb49e5ac
--- /dev/null
+++ b/backends/platform/ios7/ios7_osys_main.h
@@ -0,0 +1,233 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef BACKENDS_PLATFORM_IPHONE_OSYS_MAIN_H
+#define BACKENDS_PLATFORM_IPHONE_OSYS_MAIN_H
+
+#include "graphics/surface.h"
+#include "ios7_common.h"
+#include "backends/base-backend.h"
+#include "common/events.h"
+#include "audio/mixer_intern.h"
+#include "backends/fs/posix/posix-fs-factory.h"
+#include "graphics/colormasks.h"
+#include "graphics/palette.h"
+
+#include <AudioToolbox/AudioQueue.h>
+
+#define AUDIO_BUFFERS 3
+#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);
+
+struct AQCallbackStruct {
+ AudioQueueRef queue;
+ uint32 frameCount;
+ AudioQueueBufferRef buffers[AUDIO_BUFFERS];
+ AudioStreamBasicDescription dataFormat;
+};
+
+class OSystem_iOS7 : public EventsBaseBackend, public PaletteManager {
+protected:
+ static const OSystem::GraphicsMode s_supportedGraphicsModes[];
+ static AQCallbackStruct s_AudioQueue;
+ static SoundProc s_soundCallback;
+ static void *s_soundParam;
+
+ Audio::MixerImpl *_mixer;
+
+ VideoContext *_videoContext;
+
+ Graphics::Surface _framebuffer;
+
+ // For signaling that screen format set up might have failed.
+ TransactionError _gfxTransactionError;
+
+ // For use with the game texture
+ uint16 _gamePalette[256];
+ // For use with the mouse texture
+ uint16 _gamePaletteRGBA5551[256];
+
+ struct timeval _startTime;
+ uint32 _timeSuspended;
+
+ bool _mouseCursorPaletteEnabled;
+ uint16 _mouseCursorPalette[256];
+ Graphics::Surface _mouseBuffer;
+ uint16 _mouseKeyColor;
+ bool _mouseDirty;
+ bool _mouseNeedTextureUpdate;
+
+ long _lastMouseDown;
+ long _lastMouseTap;
+ long _queuedEventTime;
+ Common::Event _queuedInputEvent;
+ bool _secondaryTapped;
+ long _lastSecondaryDown;
+ long _lastSecondaryTap;
+ int _gestureStartX, _gestureStartY;
+ bool _mouseClickAndDragEnabled;
+ bool _touchpadModeEnabled;
+ int _lastPadX;
+ int _lastPadY;
+ int _lastDragPosX;
+ int _lastDragPosY;
+
+ int _timerCallbackNext;
+ int _timerCallbackTimer;
+ TimerProc _timerCallback;
+
+ Common::Array<Common::Rect> _dirtyRects;
+ Common::Array<Common::Rect> _dirtyOverlayRects;
+ ScreenOrientation _screenOrientation;
+ bool _fullScreenIsDirty;
+ bool _fullScreenOverlayIsDirty;
+ int _screenChangeCount;
+
+ char *_lastErrorMessage;
+
+public:
+
+ OSystem_iOS7();
+ virtual ~OSystem_iOS7();
+
+ static OSystem_iOS7 *sharedInstance();
+
+ virtual void initBackend();
+
+ virtual bool hasFeature(Feature f);
+ virtual void setFeatureState(Feature f, bool enable);
+ virtual bool getFeatureState(Feature f);
+ virtual const GraphicsMode *getSupportedGraphicsModes() const;
+ virtual int getDefaultGraphicsMode() const;
+ virtual bool setGraphicsMode(int mode);
+ virtual int getGraphicsMode() const;
+ virtual void initSize(uint width, uint height, const Graphics::PixelFormat *format);
+
+ virtual void beginGFXTransaction();
+ virtual TransactionError endGFXTransaction();
+
+ virtual int16 getHeight();
+ virtual int16 getWidth();
+
+ bool touchpadModeEnabled() const;
+
+#ifdef USE_RGB_COLOR
+ virtual Graphics::PixelFormat getScreenFormat() const { return _framebuffer.format; }
+ virtual Common::List<Graphics::PixelFormat> getSupportedFormats() const;
+#endif
+
+ virtual PaletteManager *getPaletteManager() { return this; }
+protected:
+ // PaletteManager API
+ virtual void setPalette(const byte *colors, uint start, uint num);
+ virtual void grabPalette(byte *colors, uint start, uint num);
+
+public:
+ virtual void copyRectToScreen(const void *buf, int pitch, int x, int y, int w, int h);
+ virtual void updateScreen();
+ virtual Graphics::Surface *lockScreen();
+ virtual void unlockScreen();
+ virtual void setShakePos(int shakeOffset);
+
+ virtual void showOverlay();
+ virtual void hideOverlay();
+ virtual void clearOverlay();
+ virtual void grabOverlay(void *buf, int pitch);
+ virtual void copyRectToOverlay(const void *buf, int pitch, int x, int y, int w, int h);
+ virtual int16 getOverlayHeight();
+ virtual int16 getOverlayWidth();
+ virtual Graphics::PixelFormat getOverlayFormat() const { return Graphics::createPixelFormat<5551>(); }
+
+ virtual bool showMouse(bool visible);
+
+ virtual void warpMouse(int x, int y);
+ virtual void setMouseCursor(const void *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor = 255, bool dontScale = false, const Graphics::PixelFormat *format = NULL);
+ virtual void setCursorPalette(const byte *colors, uint start, uint num);
+
+ virtual bool pollEvent(Common::Event &event);
+ virtual uint32 getMillis(bool skipRecord = false);
+ virtual void delayMillis(uint msecs);
+
+ virtual MutexRef createMutex(void);
+ virtual void lockMutex(MutexRef mutex);
+ virtual void unlockMutex(MutexRef mutex);
+ virtual void deleteMutex(MutexRef mutex);
+
+ static void mixCallback(void *sys, byte *samples, int len);
+ virtual void setupMixer(void);
+ virtual void setTimerCallback(TimerProc callback, int interval);
+ virtual int getScreenChangeID() const { return _screenChangeCount; }
+ virtual void quit();
+
+ virtual void addSysArchivesToSearchSet(Common::SearchSet &s, int priority = 0);
+ virtual void getTimeAndDate(TimeDate &t) const;
+
+ virtual Audio::Mixer *getMixer();
+
+ void startSoundsystem();
+ void stopSoundsystem();
+
+ virtual Common::String getDefaultConfigFileName();
+
+ virtual void logMessage(LogMessageType::Type type, const char *message);
+ virtual void fatalError() override;
+
+protected:
+ void initVideoContext();
+ void updateOutputSurface();
+
+ void internUpdateScreen();
+ void dirtyFullScreen();
+ void dirtyFullOverlayScreen();
+ void suspendLoop();
+ void drawDirtyRect(const Common::Rect &dirtyRect);
+ void updateMouseTexture();
+ static void AQBufferCallback(void *in, AudioQueueRef inQ, AudioQueueBufferRef outQB);
+ static int timerHandler(int t);
+
+ bool handleEvent_swipe(Common::Event &event, int direction, int touches);
+ bool handleEvent_tap(Common::Event &event, UIViewTapDescription type, int touches);
+ void handleEvent_keyPressed(Common::Event &event, int keyPressed);
+ void handleEvent_orientationChanged(int orientation);
+ void handleEvent_applicationSuspended();
+ void handleEvent_applicationResumed();
+
+ bool handleEvent_mouseDown(Common::Event &event, int x, int y);
+ bool handleEvent_mouseUp(Common::Event &event, int x, int y);
+
+ bool handleEvent_secondMouseDown(Common::Event &event, int x, int y);
+ bool handleEvent_secondMouseUp(Common::Event &event, int x, int y);
+
+ bool handleEvent_mouseDragged(Common::Event &event, int x, int y);
+ bool handleEvent_mouseSecondDragged(Common::Event &event, int x, int y);
+
+ void rebuildSurface();
+};
+
+#endif
diff --git a/backends/platform/ios7/ios7_osys_sound.cpp b/backends/platform/ios7/ios7_osys_sound.cpp
new file mode 100644
index 0000000000..0dc81a9385
--- /dev/null
+++ b/backends/platform/ios7/ios7_osys_sound.cpp
@@ -0,0 +1,105 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+// Disable symbol overrides so that we can use system headers.
+#define FORBIDDEN_SYMBOL_ALLOW_ALL
+
+#include "ios7_osys_main.h"
+
+void OSystem_iOS7::AQBufferCallback(void *in, AudioQueueRef inQ, AudioQueueBufferRef outQB) {
+ //printf("AQBufferCallback()\n");
+ if (s_AudioQueue.frameCount > 0 && s_soundCallback != NULL) {
+ outQB->mAudioDataByteSize = 4 * s_AudioQueue.frameCount;
+ s_soundCallback(s_soundParam, (byte *)outQB->mAudioData, outQB->mAudioDataByteSize);
+ AudioQueueEnqueueBuffer(inQ, outQB, 0, NULL);
+ } else {
+ AudioQueueStop(s_AudioQueue.queue, false);
+ }
+}
+
+void OSystem_iOS7::mixCallback(void *sys, byte *samples, int len) {
+ OSystem_iOS7 *this_ = (OSystem_iOS7 *)sys;
+ assert(this_);
+
+ if (this_->_mixer) {
+ this_->_mixer->mixCallback(samples, len);
+ }
+}
+
+void OSystem_iOS7::setupMixer() {
+ _mixer = new Audio::MixerImpl(this, AUDIO_SAMPLE_RATE);
+
+ s_soundCallback = mixCallback;
+ s_soundParam = this;
+
+ startSoundsystem();
+}
+
+void OSystem_iOS7::startSoundsystem() {
+ s_AudioQueue.dataFormat.mSampleRate = AUDIO_SAMPLE_RATE;
+ s_AudioQueue.dataFormat.mFormatID = kAudioFormatLinearPCM;
+ s_AudioQueue.dataFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
+ s_AudioQueue.dataFormat.mBytesPerPacket = 4;
+ s_AudioQueue.dataFormat.mFramesPerPacket = 1;
+ s_AudioQueue.dataFormat.mBytesPerFrame = 4;
+ s_AudioQueue.dataFormat.mChannelsPerFrame = 2;
+ s_AudioQueue.dataFormat.mBitsPerChannel = 16;
+ s_AudioQueue.frameCount = WAVE_BUFFER_SIZE;
+
+ if (AudioQueueNewOutput(&s_AudioQueue.dataFormat, AQBufferCallback, &s_AudioQueue, 0, kCFRunLoopCommonModes, 0, &s_AudioQueue.queue)) {
+ printf("Couldn't set the AudioQueue callback!\n");
+ _mixer->setReady(false);
+ return;
+ }
+
+ uint32 bufferBytes = s_AudioQueue.frameCount * s_AudioQueue.dataFormat.mBytesPerFrame;
+
+ for (int i = 0; i < AUDIO_BUFFERS; i++) {
+ if (AudioQueueAllocateBuffer(s_AudioQueue.queue, bufferBytes, &s_AudioQueue.buffers[i])) {
+ printf("Error allocating AudioQueue buffer!\n");
+ _mixer->setReady(false);
+ return;
+ }
+
+ AQBufferCallback(&s_AudioQueue, s_AudioQueue.queue, s_AudioQueue.buffers[i]);
+ }
+
+ AudioQueueSetParameter(s_AudioQueue.queue, kAudioQueueParam_Volume, 1.0);
+ if (AudioQueueStart(s_AudioQueue.queue, NULL)) {
+ printf("Error starting the AudioQueue!\n");
+ _mixer->setReady(false);
+ return;
+ }
+
+ _mixer->setReady(true);
+}
+
+void OSystem_iOS7::stopSoundsystem() {
+ AudioQueueStop(s_AudioQueue.queue, true);
+
+ for (int i = 0; i < AUDIO_BUFFERS; i++) {
+ AudioQueueFreeBuffer(s_AudioQueue.queue, s_AudioQueue.buffers[i]);
+ }
+
+ AudioQueueDispose(s_AudioQueue.queue, true);
+ _mixer->setReady(false);
+}
diff --git a/backends/platform/ios7/ios7_osys_video.mm b/backends/platform/ios7/ios7_osys_video.mm
new file mode 100644
index 0000000000..0d183ce834
--- /dev/null
+++ b/backends/platform/ios7/ios7_osys_video.mm
@@ -0,0 +1,545 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+// Disable symbol overrides so that we can use system headers.
+#define FORBIDDEN_SYMBOL_ALLOW_ALL
+
+#include "ios7_osys_main.h"
+#include "ios7_video.h"
+
+#include "graphics/conversion.h"
+#import "iOS7AppDelegate.h"
+
+@interface iOS7AlertHandler : NSObject<UIAlertViewDelegate>
+@end
+
+@implementation iOS7AlertHandler
+
+- (void)alertView:(UIAlertView *)alertView willDismissWithButtonIndex:(NSInteger)buttonIndex {
+ OSystem_iOS7::sharedInstance()->quit();
+ exit(1);
+}
+
+@end
+
+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];
+}
+
+void OSystem_iOS7::fatalError() {
+ if (_lastErrorMessage) {
+ dispatch_async_f(dispatch_get_main_queue(), _lastErrorMessage, displayAlert);
+ for(;;);
+ }
+ else {
+ OSystem::fatalError();
+ }
+}
+
+void OSystem_iOS7::initVideoContext() {
+ _videoContext = [[iOS7AppDelegate iPhoneView] getVideoContext];
+}
+
+const OSystem::GraphicsMode *OSystem_iOS7::getSupportedGraphicsModes() const {
+ return s_supportedGraphicsModes;
+}
+
+int OSystem_iOS7::getDefaultGraphicsMode() const {
+ return kGraphicsModeNone;
+}
+
+bool OSystem_iOS7::setGraphicsMode(int mode) {
+ switch (mode) {
+ case kGraphicsModeNone:
+ case kGraphicsModeLinear:
+ case kGraphicsMode2xSaI:
+ case kGraphicsModeSuper2xSaI:
+ case kGraphicsModeSuperEagle:
+ case kGraphicsModeAdvMame2x:
+ case kGraphicsModeAdvMame3x:
+ case kGraphicsModeHQ2x:
+ case kGraphicsModeHQ3x:
+ case kGraphicsModeTV2x:
+ case kGraphicsModeDotMatrix:
+ _videoContext->graphicsMode = (GraphicsModes)mode;
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+int OSystem_iOS7::getGraphicsMode() const {
+ return _videoContext->graphicsMode;
+}
+
+#ifdef USE_RGB_COLOR
+Common::List<Graphics::PixelFormat> OSystem_iOS7::getSupportedFormats() const {
+ Common::List<Graphics::PixelFormat> list;
+ // RGB565
+ list.push_back(Graphics::createPixelFormat<565>());
+ // CLUT8
+ list.push_back(Graphics::PixelFormat::createFormatCLUT8());
+ return list;
+}
+#endif
+
+void OSystem_iOS7::initSize(uint width, uint height, const Graphics::PixelFormat *format) {
+ //printf("initSize(%u, %u, %p)\n", width, height, (const void *)format);
+
+ _videoContext->screenWidth = width;
+ _videoContext->screenHeight = height;
+ _videoContext->shakeOffsetY = 0;
+
+ // In case we use the screen texture as frame buffer we reset the pixels
+ // pointer here to avoid freeing the screen texture.
+ if (_framebuffer.getPixels() == _videoContext->screenTexture.getPixels())
+ _framebuffer.setPixels(0);
+
+ // Create the screen texture right here. We need to do this here, since
+ // when a game requests hi-color mode, we actually set the framebuffer
+ // to the texture buffer to avoid an additional copy step.
+ [[iOS7AppDelegate iPhoneView] performSelectorOnMainThread:@selector(createScreenTexture) withObject:nil waitUntilDone: YES];
+
+ // In case the client code tries to set up a non supported mode, we will
+ // fall back to CLUT8 and set the transaction error accordingly.
+ if (format && format->bytesPerPixel != 1 && *format != _videoContext->screenTexture.format) {
+ format = 0;
+ _gfxTransactionError = kTransactionFormatNotSupported;
+ }
+
+ if (!format || format->bytesPerPixel == 1) {
+ _framebuffer.create(width, height, Graphics::PixelFormat::createFormatCLUT8());
+ } else {
+#if 0
+ printf("bytesPerPixel: %u RGBAlosses: %u,%u,%u,%u RGBAshifts: %u,%u,%u,%u\n", format->bytesPerPixel,
+ format->rLoss, format->gLoss, format->bLoss, format->aLoss,
+ format->rShift, format->gShift, format->bShift, format->aShift);
+#endif
+ // We directly draw on the screen texture in hi-color mode. Thus
+ // we copy over its settings here and just replace the width and
+ // height to avoid any problems.
+ _framebuffer = _videoContext->screenTexture;
+ _framebuffer.w = width;
+ _framebuffer.h = height;
+ }
+
+ _fullScreenIsDirty = false;
+ dirtyFullScreen();
+ _mouseCursorPaletteEnabled = false;
+}
+
+void OSystem_iOS7::beginGFXTransaction() {
+ _gfxTransactionError = kTransactionSuccess;
+}
+
+OSystem::TransactionError OSystem_iOS7::endGFXTransaction() {
+ _screenChangeCount++;
+ updateOutputSurface();
+ [[iOS7AppDelegate iPhoneView] performSelectorOnMainThread:@selector(setGraphicsMode) withObject:nil waitUntilDone: YES];
+
+ return _gfxTransactionError;
+}
+
+void OSystem_iOS7::updateOutputSurface() {
+ [[iOS7AppDelegate iPhoneView] performSelectorOnMainThread:@selector(initSurface) withObject:nil waitUntilDone: YES];
+}
+
+int16 OSystem_iOS7::getHeight() {
+ return _videoContext->screenHeight;
+}
+
+int16 OSystem_iOS7::getWidth() {
+ return _videoContext->screenWidth;
+}
+
+void OSystem_iOS7::setPalette(const byte *colors, uint start, uint num) {
+ //printf("setPalette(%p, %u, %u)\n", colors, start, num);
+ assert(start + num <= 256);
+ const byte *b = colors;
+
+ for (uint i = start; i < start + num; ++i) {
+ _gamePalette[i] = Graphics::RGBToColor<Graphics::ColorMasks<565> >(b[0], b[1], b[2]);
+ _gamePaletteRGBA5551[i] = Graphics::RGBToColor<Graphics::ColorMasks<5551> >(b[0], b[1], b[2]);
+ b += 3;
+ }
+
+ dirtyFullScreen();
+
+ // Automatically update the mouse texture when the palette changes while the
+ // cursor palette is disabled.
+ if (!_mouseCursorPaletteEnabled && _mouseBuffer.format.bytesPerPixel == 1)
+ _mouseDirty = _mouseNeedTextureUpdate = true;
+}
+
+void OSystem_iOS7::grabPalette(byte *colors, uint start, uint num) {
+ //printf("grabPalette(%p, %u, %u)\n", colors, start, num);
+ assert(start + num <= 256);
+ byte *b = colors;
+
+ for (uint i = start; i < start + num; ++i) {
+ Graphics::colorToRGB<Graphics::ColorMasks<565> >(_gamePalette[i], b[0], b[1], b[2]);
+ b += 3;
+ }
+}
+
+void OSystem_iOS7::copyRectToScreen(const void *buf, int pitch, int x, int y, int w, int h) {
+ //printf("copyRectToScreen(%p, %d, %i, %i, %i, %i)\n", buf, pitch, x, y, w, h);
+ //Clip the coordinates
+ const byte *src = (const byte *)buf;
+ if (x < 0) {
+ w += x;
+ src -= x;
+ x = 0;
+ }
+
+ if (y < 0) {
+ h += y;
+ src -= y * pitch;
+ y = 0;
+ }
+
+ if (w > (int)_framebuffer.w - x) {
+ w = _framebuffer.w - x;
+ }
+
+ if (h > (int)_framebuffer.h - y) {
+ h = _framebuffer.h - y;
+ }
+
+ if (w <= 0 || h <= 0)
+ return;
+
+ if (!_fullScreenIsDirty) {
+ _dirtyRects.push_back(Common::Rect(x, y, x + w, y + h));
+ }
+
+ byte *dst = (byte *)_framebuffer.getBasePtr(x, y);
+ if (_framebuffer.pitch == pitch && _framebuffer.w == w) {
+ memcpy(dst, src, h * pitch);
+ } else {
+ do {
+ memcpy(dst, src, w * _framebuffer.format.bytesPerPixel);
+ src += pitch;
+ dst += _framebuffer.pitch;
+ } while (--h);
+ }
+}
+
+void OSystem_iOS7::updateScreen() {
+ if (_dirtyRects.size() == 0 && _dirtyOverlayRects.size() == 0 && !_mouseDirty)
+ return;
+
+ //printf("updateScreen(): %i dirty rects.\n", _dirtyRects.size());
+
+ internUpdateScreen();
+ _mouseDirty = false;
+ _fullScreenIsDirty = false;
+ _fullScreenOverlayIsDirty = false;
+
+ iOS7_updateScreen();
+}
+
+void OSystem_iOS7::internUpdateScreen() {
+ if (_mouseNeedTextureUpdate) {
+ updateMouseTexture();
+ _mouseNeedTextureUpdate = false;
+ }
+
+ while (_dirtyRects.size()) {
+ Common::Rect dirtyRect = _dirtyRects.remove_at(_dirtyRects.size() - 1);
+
+ //printf("Drawing: (%i, %i) -> (%i, %i)\n", dirtyRect.left, dirtyRect.top, dirtyRect.right, dirtyRect.bottom);
+ drawDirtyRect(dirtyRect);
+ // TODO: Implement dirty rect code
+ //updateHardwareSurfaceForRect(dirtyRect);
+ }
+
+ if (_videoContext->overlayVisible) {
+ // TODO: Implement dirty rect code
+ _dirtyOverlayRects.clear();
+ /*while (_dirtyOverlayRects.size()) {
+ Common::Rect dirtyRect = _dirtyOverlayRects.remove_at(_dirtyOverlayRects.size() - 1);
+
+ //printf("Drawing: (%i, %i) -> (%i, %i)\n", dirtyRect.left, dirtyRect.top, dirtyRect.right, dirtyRect.bottom);
+ drawDirtyOverlayRect(dirtyRect);
+ }*/
+ }
+}
+
+void OSystem_iOS7::drawDirtyRect(const Common::Rect &dirtyRect) {
+ // We only need to do a color look up for CLUT8
+ if (_framebuffer.format.bytesPerPixel != 1)
+ return;
+
+ int h = dirtyRect.bottom - dirtyRect.top;
+ int w = dirtyRect.right - dirtyRect.left;
+
+ const byte *src = (const byte *)_framebuffer.getBasePtr(dirtyRect.left, dirtyRect.top);
+ byte *dstRaw = (byte *)_videoContext->screenTexture.getBasePtr(dirtyRect.left, dirtyRect.top);
+
+ // When we use CLUT8 do a color look up
+ for (int y = h; y > 0; y--) {
+ uint16 *dst = (uint16 *)dstRaw;
+ for (int x = w; x > 0; x--)
+ *dst++ = _gamePalette[*src++];
+
+ dstRaw += _videoContext->screenTexture.pitch;
+ src += _framebuffer.pitch - w;
+ }
+}
+
+Graphics::Surface *OSystem_iOS7::lockScreen() {
+ //printf("lockScreen()\n");
+ return &_framebuffer;
+}
+
+void OSystem_iOS7::unlockScreen() {
+ //printf("unlockScreen()\n");
+ dirtyFullScreen();
+}
+
+void OSystem_iOS7::setShakePos(int shakeOffset) {
+ //printf("setShakePos(%i)\n", shakeOffset);
+ _videoContext->shakeOffsetY = shakeOffset;
+ [[iOS7AppDelegate iPhoneView] performSelectorOnMainThread:@selector(setViewTransformation) withObject:nil waitUntilDone: YES];
+ // HACK: We use this to force a redraw.
+ _mouseDirty = true;
+}
+
+void OSystem_iOS7::showOverlay() {
+ //printf("showOverlay()\n");
+ _videoContext->overlayVisible = true;
+ dirtyFullOverlayScreen();
+ updateScreen();
+ [[iOS7AppDelegate iPhoneView] performSelectorOnMainThread:@selector(updateMouseCursorScaling) withObject:nil waitUntilDone: YES];
+ [[iOS7AppDelegate iPhoneView] performSelectorOnMainThread:@selector(clearColorBuffer) withObject:nil waitUntilDone: YES];
+}
+
+void OSystem_iOS7::hideOverlay() {
+ //printf("hideOverlay()\n");
+ _videoContext->overlayVisible = false;
+ _dirtyOverlayRects.clear();
+ dirtyFullScreen();
+ [[iOS7AppDelegate iPhoneView] performSelectorOnMainThread:@selector(updateMouseCursorScaling) withObject:nil waitUntilDone: YES];
+ [[iOS7AppDelegate iPhoneView] performSelectorOnMainThread:@selector(clearColorBuffer) withObject:nil waitUntilDone: YES];
+}
+
+void OSystem_iOS7::clearOverlay() {
+ //printf("clearOverlay()\n");
+ bzero(_videoContext->overlayTexture.getPixels(), _videoContext->overlayTexture.h * _videoContext->overlayTexture.pitch);
+ dirtyFullOverlayScreen();
+}
+
+void OSystem_iOS7::grabOverlay(void *buf, int pitch) {
+ //printf("grabOverlay()\n");
+ int h = _videoContext->overlayHeight;
+
+ byte *dst = (byte *)buf;
+ const byte *src = (const byte *)_videoContext->overlayTexture.getPixels();
+ do {
+ memcpy(dst, src, _videoContext->overlayWidth * sizeof(uint16));
+ src += _videoContext->overlayTexture.pitch;
+ dst += pitch;
+ } while (--h);
+}
+
+void OSystem_iOS7::copyRectToOverlay(const void *buf, int pitch, int x, int y, int w, int h) {
+ //printf("copyRectToOverlay(%p, pitch=%i, x=%i, y=%i, w=%i, h=%i)\n", (const void *)buf, pitch, x, y, w, h);
+ const byte *src = (const byte *)buf;
+
+ //Clip the coordinates
+ if (x < 0) {
+ w += x;
+ src -= x * sizeof(uint16);
+ x = 0;
+ }
+
+ if (y < 0) {
+ h += y;
+ src -= y * pitch;
+ y = 0;
+ }
+
+ if (w > (int)_videoContext->overlayWidth - x)
+ w = _videoContext->overlayWidth - x;
+
+ if (h > (int)_videoContext->overlayHeight - y)
+ h = _videoContext->overlayHeight - y;
+
+ if (w <= 0 || h <= 0)
+ return;
+
+ if (!_fullScreenOverlayIsDirty) {
+ _dirtyOverlayRects.push_back(Common::Rect(x, y, x + w, y + h));
+ }
+
+ byte *dst = (byte *)_videoContext->overlayTexture.getBasePtr(x, y);
+ do {
+ memcpy(dst, src, w * sizeof(uint16));
+ src += pitch;
+ dst += _videoContext->overlayTexture.pitch;
+ } while (--h);
+}
+
+int16 OSystem_iOS7::getOverlayHeight() {
+ return _videoContext->overlayHeight;
+}
+
+int16 OSystem_iOS7::getOverlayWidth() {
+ return _videoContext->overlayWidth;
+}
+
+bool OSystem_iOS7::showMouse(bool visible) {
+ //printf("showMouse(%d)\n", visible);
+ bool last = _videoContext->mouseIsVisible;
+ _videoContext->mouseIsVisible = visible;
+ _mouseDirty = true;
+
+ return last;
+}
+
+void OSystem_iOS7::warpMouse(int x, int y) {
+ //printf("warpMouse(%d, %d)\n", x, y);
+ _videoContext->mouseX = x;
+ _videoContext->mouseY = y;
+ [[iOS7AppDelegate iPhoneView] performSelectorOnMainThread:@selector(notifyMouseMove) withObject:nil waitUntilDone: YES];
+ _mouseDirty = true;
+}
+
+void OSystem_iOS7::dirtyFullScreen() {
+ if (!_fullScreenIsDirty) {
+ _dirtyRects.clear();
+ _dirtyRects.push_back(Common::Rect(0, 0, _videoContext->screenWidth, _videoContext->screenHeight));
+ _fullScreenIsDirty = true;
+ }
+}
+
+void OSystem_iOS7::dirtyFullOverlayScreen() {
+ if (!_fullScreenOverlayIsDirty) {
+ _dirtyOverlayRects.clear();
+ _dirtyOverlayRects.push_back(Common::Rect(0, 0, _videoContext->overlayWidth, _videoContext->overlayHeight));
+ _fullScreenOverlayIsDirty = true;
+ }
+}
+
+void OSystem_iOS7::setMouseCursor(const void *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, bool dontScale, const Graphics::PixelFormat *format) {
+ //printf("setMouseCursor(%p, %u, %u, %i, %i, %u, %d, %p)\n", (const void *)buf, w, h, hotspotX, hotspotY, keycolor, dontScale, (const void *)format);
+
+ const Graphics::PixelFormat pixelFormat = format ? *format : Graphics::PixelFormat::createFormatCLUT8();
+#if 0
+ printf("bytesPerPixel: %u RGBAlosses: %u,%u,%u,%u RGBAshifts: %u,%u,%u,%u\n", pixelFormat.bytesPerPixel,
+ pixelFormat.rLoss, pixelFormat.gLoss, pixelFormat.bLoss, pixelFormat.aLoss,
+ pixelFormat.rShift, pixelFormat.gShift, pixelFormat.bShift, pixelFormat.aShift);
+#endif
+ assert(pixelFormat.bytesPerPixel == 1 || pixelFormat.bytesPerPixel == 2);
+
+ if (_mouseBuffer.w != w || _mouseBuffer.h != h || _mouseBuffer.format != pixelFormat || !_mouseBuffer.getPixels())
+ _mouseBuffer.create(w, h, pixelFormat);
+
+ _videoContext->mouseWidth = w;
+ _videoContext->mouseHeight = h;
+
+ _videoContext->mouseHotspotX = hotspotX;
+ _videoContext->mouseHotspotY = hotspotY;
+
+ _mouseKeyColor = keycolor;
+
+ memcpy(_mouseBuffer.getPixels(), buf, h * _mouseBuffer.pitch);
+
+ _mouseDirty = true;
+ _mouseNeedTextureUpdate = true;
+}
+
+void OSystem_iOS7::setCursorPalette(const byte *colors, uint start, uint num) {
+ //printf("setCursorPalette(%p, %u, %u)\n", (const void *)colors, start, num);
+ assert(start + num <= 256);
+
+ for (uint i = start; i < start + num; ++i, colors += 3)
+ _mouseCursorPalette[i] = Graphics::RGBToColor<Graphics::ColorMasks<5551> >(colors[0], colors[1], colors[2]);
+
+ // FIXME: This is just stupid, our client code seems to assume that this
+ // automatically enables the cursor palette.
+ _mouseCursorPaletteEnabled = true;
+
+ if (_mouseCursorPaletteEnabled)
+ _mouseDirty = _mouseNeedTextureUpdate = true;
+}
+
+void OSystem_iOS7::updateMouseTexture() {
+ uint texWidth = getSizeNextPOT(_videoContext->mouseWidth);
+ uint texHeight = getSizeNextPOT(_videoContext->mouseHeight);
+
+ Graphics::Surface &mouseTexture = _videoContext->mouseTexture;
+ if (mouseTexture.w != texWidth || mouseTexture.h != texHeight)
+ mouseTexture.create(texWidth, texHeight, Graphics::createPixelFormat<5551>());
+
+ if (_mouseBuffer.format.bytesPerPixel == 1) {
+ const uint16 *palette;
+ if (_mouseCursorPaletteEnabled)
+ palette = _mouseCursorPalette;
+ else
+ palette = _gamePaletteRGBA5551;
+
+ uint16 *mouseBuf = (uint16 *)mouseTexture.getPixels();
+ for (uint x = 0; x < _videoContext->mouseWidth; ++x) {
+ for (uint y = 0; y < _videoContext->mouseHeight; ++y) {
+ const byte color = *(const byte *)_mouseBuffer.getBasePtr(x, y);
+ if (color != _mouseKeyColor)
+ mouseBuf[y * texWidth + x] = palette[color] | 0x1;
+ else
+ mouseBuf[y * texWidth + x] = 0x0;
+ }
+ }
+ } else {
+ if (crossBlit((byte *)mouseTexture.getPixels(), (const byte *)_mouseBuffer.getPixels(), mouseTexture.pitch,
+ _mouseBuffer.pitch, _mouseBuffer.w, _mouseBuffer.h, mouseTexture.format, _mouseBuffer.format)) {
+ if (!_mouseBuffer.format.aBits()) {
+ // Apply color keying since the original cursor had no alpha channel.
+ const uint16 *src = (const uint16 *)_mouseBuffer.getPixels();
+ uint8 *dstRaw = (uint8 *)mouseTexture.getPixels();
+
+ for (uint y = 0; y < _mouseBuffer.h; ++y, dstRaw += mouseTexture.pitch) {
+ uint16 *dst = (uint16 *)dstRaw;
+ for (uint x = 0; x < _mouseBuffer.w; ++x, ++dst) {
+ if (*src++ == _mouseKeyColor)
+ *dst &= ~1;
+ else
+ *dst |= 1;
+ }
+ }
+ }
+ } else {
+ // TODO: Log this!
+ // Make the cursor all transparent... we really need a better fallback ;-).
+ memset(mouseTexture.getPixels(), 0, mouseTexture.h * mouseTexture.pitch);
+ }
+ }
+
+ [[iOS7AppDelegate iPhoneView] performSelectorOnMainThread:@selector(updateMouseCursor) withObject:nil waitUntilDone: YES];
+}
diff --git a/backends/platform/ios7/ios7_video.h b/backends/platform/ios7/ios7_video.h
new file mode 100644
index 0000000000..ab261a977b
--- /dev/null
+++ b/backends/platform/ios7/ios7_video.h
@@ -0,0 +1,131 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef BACKENDS_PLATFORM_IPHONE_IPHONE_VIDEO_H
+#define BACKENDS_PLATFORM_IPHONE_IPHONE_VIDEO_H
+
+#include <UIKit/UIKit.h>
+#include <Foundation/Foundation.h>
+#include <QuartzCore/QuartzCore.h>
+
+#include <OpenGLES/EAGL.h>
+#include <OpenGLES/ES2/gl.h>
+#include <OpenGLES/ES2/glext.h>
+
+#include "ios7_keyboard.h"
+#include "ios7_common.h"
+
+#include "common/list.h"
+#import "graphics/scaler.h"
+
+typedef struct {
+ GLfloat x, y;
+ GLfloat u,v;
+} GLVertex;
+
+@interface iPhoneView : UIView {
+ VideoContext _videoContext;
+
+ Common::List<InternalEvent> _events;
+ NSLock *_eventLock;
+ SoftKeyboard *_keyboardView;
+
+ EAGLContext *_context;
+ GLuint _viewRenderbuffer;
+ GLuint _viewFramebuffer;
+ GLuint _screenTexture;
+ GLuint _overlayTexture;
+ GLuint _mouseCursorTexture;
+
+ GLuint _vertexShader;
+ GLuint _fragmentShader;
+
+ GLuint _vertexBuffer;
+
+ GLuint _screenSizeSlot;
+ GLuint _textureSlot;
+ GLuint _shakeSlot;
+
+ GLuint _positionSlot;
+ GLuint _textureCoordSlot;
+
+ GLint _renderBufferWidth;
+ GLint _renderBufferHeight;
+
+ GLVertex _gameScreenCoords[4];
+ CGRect _gameScreenRect;
+
+ GLVertex _overlayCoords[4];
+ CGRect _overlayRect;
+
+ GLVertex _mouseCoords[4];
+
+ GLint _mouseHotspotX, _mouseHotspotY;
+ GLint _mouseWidth, _mouseHeight;
+ GLfloat _mouseScaleX, _mouseScaleY;
+
+ int _scaledShakeOffsetY;
+
+ UITouch *_firstTouch;
+ UITouch *_secondTouch;
+
+#ifdef ENABLE_IOS7_SCALERS
+ uint8_t *_scalerMemorySrc;
+ uint8_t *_scalerMemoryDst;
+ size_t _scalerMemorySrcSize;
+ size_t _scalerMemoryDstSize;
+ int _scalerScale;
+ ScalerProc *_scaler;
+#endif
+}
+
+- (id)initWithFrame:(struct CGRect)frame;
+
+- (VideoContext *)getVideoContext;
+
+- (void)createScreenTexture;
+- (void)initSurface;
+- (void)setViewTransformation;
+
+- (void)setGraphicsMode;
+
+- (void)updateSurface;
+- (void)updateMainSurface;
+- (void)updateOverlaySurface;
+- (void)updateMouseSurface;
+- (void)clearColorBuffer;
+
+- (void)notifyMouseMove;
+- (void)updateMouseCursorScaling;
+- (void)updateMouseCursor;
+
+- (void)deviceOrientationChanged:(UIDeviceOrientation)orientation;
+
+- (void)applicationSuspend;
+
+- (void)applicationResume;
+
+- (bool)fetchEvent:(InternalEvent *)event;
+
+@end
+
+#endif
diff --git a/backends/platform/ios7/ios7_video.mm b/backends/platform/ios7/ios7_video.mm
new file mode 100644
index 0000000000..2cfc3e05f7
--- /dev/null
+++ b/backends/platform/ios7/ios7_video.mm
@@ -0,0 +1,1002 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+// Disable symbol overrides so that we can use system headers.
+#define FORBIDDEN_SYMBOL_ALLOW_ALL
+
+#include "ios7_video.h"
+
+#include "graphics/colormasks.h"
+#include "common/system.h"
+#import "iOS7AppDelegate.h"
+
+static int g_needsScreenUpdate = 0;
+
+#if 0
+static long g_lastTick = 0;
+static int g_frames = 0;
+#endif
+
+#define printOpenGLError() printOglError(__FILE__, __LINE__)
+
+int printOglError(const char *file, int line) {
+ int retCode = 0;
+
+ // returns 1 if an OpenGL error occurred, 0 otherwise.
+ GLenum glErr = glGetError();
+ while (glErr != GL_NO_ERROR) {
+ fprintf(stderr, "glError: %u (%s: %d)\n", glErr, file, line);
+ retCode = 1;
+ glErr = glGetError();
+ }
+ return retCode;
+}
+
+bool iOS7_isBigDevice() {
+ return UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad;
+}
+
+void iOS7_updateScreen() {
+ //printf("Mouse: (%i, %i)\n", mouseX, mouseY);
+ if (!g_needsScreenUpdate) {
+ g_needsScreenUpdate = 1;
+ [[iOS7AppDelegate iPhoneView] performSelectorOnMainThread:@selector(updateSurface) withObject:nil waitUntilDone: NO];
+ }
+}
+
+bool iOS7_fetchEvent(InternalEvent *event) {
+ return [[iOS7AppDelegate iPhoneView] fetchEvent:event];
+}
+
+uint getSizeNextPOT(uint size) {
+ if ((size & (size - 1)) || !size) {
+ int log = 0;
+
+ while (size >>= 1)
+ ++log;
+
+ size = (2 << log);
+ }
+
+ return size;
+}
+
+@implementation iPhoneView
+
++ (Class)layerClass {
+ return [CAEAGLLayer class];
+}
+
+- (VideoContext *)getVideoContext {
+ return &_videoContext;
+}
+
+- (void)createContext {
+ CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;
+
+ eaglLayer.opaque = YES;
+ eaglLayer.drawableProperties = @{
+ kEAGLDrawablePropertyRetainedBacking: @NO,
+ kEAGLDrawablePropertyColorFormat: kEAGLColorFormatRGB565
+ };
+
+ _context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
+
+ // In case creating the OpenGL ES context failed, we will error out here.
+ if (_context == nil) {
+ fprintf(stderr, "Could not create OpenGL ES context\n");
+ exit(-1);
+ }
+
+ if ([EAGLContext setCurrentContext:_context]) {
+ // glEnableClientState(GL_TEXTURE_COORD_ARRAY); printOpenGLError();
+ // glEnableClientState(GL_VERTEX_ARRAY); printOpenGLError();
+ [self setupOpenGL];
+ }
+}
+
+- (void)setupOpenGL {
+ [self setupFramebuffer];
+ [self createOverlaySurface];
+ [self compileShaders];
+ [self setupVBOs];
+ [self setupTextures];
+
+ [self finishGLSetup];
+}
+
+- (void)finishGLSetup {
+ glViewport(0, 0, _renderBufferWidth, _renderBufferHeight); printOpenGLError();
+ glClearColor(0.0f, 0.0f, 0.0f, 1.0f); printOpenGLError();
+
+ glUniform2f(_screenSizeSlot, _renderBufferWidth, _renderBufferHeight);
+
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+}
+
+- (void)freeOpenGL {
+ [self deleteTextures];
+ [self deleteVBOs];
+ [self deleteShaders];
+ [self deleteFramebuffer];
+}
+
+- (void)rebuildFrameBuffer {
+ [self deleteFramebuffer];
+ [self setupFramebuffer];
+ [self finishGLSetup];
+}
+
+- (void)setupFramebuffer {
+ glGenRenderbuffers(1, &_viewRenderbuffer);
+ printOpenGLError();
+ glBindRenderbuffer(GL_RENDERBUFFER, _viewRenderbuffer);
+ printOpenGLError();
+ [_context renderbufferStorage:GL_RENDERBUFFER fromDrawable:(id <EAGLDrawable>) self.layer];
+
+ glGenFramebuffers(1, &_viewFramebuffer);
+ printOpenGLError();
+ glBindFramebuffer(GL_FRAMEBUFFER, _viewFramebuffer);
+ printOpenGLError();
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, _viewRenderbuffer);
+ printOpenGLError();
+
+ // Retrieve the render buffer size. This *should* match the frame size,
+ // i.e. g_fullWidth and g_fullHeight.
+ glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &_renderBufferWidth);
+ printOpenGLError();
+ glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &_renderBufferHeight);
+ printOpenGLError();
+
+ if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
+ NSLog(@"Failed to make complete framebuffer object %x.", glCheckFramebufferStatus(GL_FRAMEBUFFER));
+ return;
+ }
+}
+
+- (void)createOverlaySurface {
+ uint overlayWidth = (uint) MAX(_renderBufferWidth, _renderBufferHeight);
+ uint overlayHeight = (uint) MIN(_renderBufferWidth, _renderBufferHeight);
+
+ if (iOS7_isBigDevice()) {
+ // On really big displays, like the iPad Pro, we scale the interface down
+ // so that the controls are not too small..
+ while (overlayHeight > 1024) {
+ overlayWidth /= 2;
+ overlayHeight /= 2;
+ }
+ }
+ else {
+ // On small devices, we force the user interface to use the small theme
+ while (overlayHeight > 480) {
+ overlayWidth /= 2;
+ overlayHeight /= 2;
+ }
+ }
+
+ _videoContext.overlayWidth = overlayWidth;
+ _videoContext.overlayHeight = overlayHeight;
+
+ uint overlayTextureWidthPOT = getSizeNextPOT(overlayWidth);
+ uint overlayTextureHeightPOT = getSizeNextPOT(overlayHeight);
+
+ // Since the overlay size won't change the whole run, we can
+ // precalculate the texture coordinates for the overlay texture here
+ // and just use it later on.
+ GLfloat u = _videoContext.overlayWidth / (GLfloat) overlayTextureWidthPOT;
+ GLfloat v = _videoContext.overlayHeight / (GLfloat) overlayTextureHeightPOT;
+ _overlayCoords[0].x = 0; _overlayCoords[0].y = 0; _overlayCoords[0].u = 0; _overlayCoords[0].v = 0;
+ _overlayCoords[1].x = 0; _overlayCoords[1].y = 0; _overlayCoords[1].u = u; _overlayCoords[1].v = 0;
+ _overlayCoords[2].x = 0; _overlayCoords[2].y = 0; _overlayCoords[2].u = 0; _overlayCoords[2].v = v;
+ _overlayCoords[3].x = 0; _overlayCoords[3].y = 0; _overlayCoords[3].u = u; _overlayCoords[3].v = v;
+
+ _videoContext.overlayTexture.create((uint16) overlayTextureWidthPOT, (uint16) overlayTextureHeightPOT, Graphics::createPixelFormat<5551>());
+}
+
+- (void)deleteFramebuffer {
+ glDeleteRenderbuffers(1, &_viewRenderbuffer);
+ glDeleteFramebuffers(1, &_viewFramebuffer);
+}
+
+- (void)setupVBOs {
+ glGenBuffers(1, &_vertexBuffer);
+ glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);
+}
+
+- (void)deleteVBOs {
+ glDeleteBuffers(1, &_vertexBuffer);
+}
+
+- (GLuint)compileShader:(const char*)shaderPrg withType:(GLenum)shaderType {
+ GLuint shaderHandle = glCreateShader(shaderType);
+
+ int shaderPrgLength = strlen(shaderPrg);
+ glShaderSource(shaderHandle, 1, &shaderPrg, &shaderPrgLength);
+
+ glCompileShader(shaderHandle);
+
+ GLint compileSuccess;
+ glGetShaderiv(shaderHandle, GL_COMPILE_STATUS, &compileSuccess);
+ if (compileSuccess == GL_FALSE) {
+ GLchar messages[256];
+ glGetShaderInfoLog(shaderHandle, sizeof(messages), 0, &messages[0]);
+ NSString *messageString = [NSString stringWithUTF8String:messages];
+ NSLog(@"%@", messageString);
+ exit(1);
+ }
+
+ return shaderHandle;
+}
+
+- (void)compileShaders {
+ const char *vertexPrg =
+ "uniform vec2 ScreenSize;"
+ "uniform float Shake;"
+ ""
+ "attribute vec2 Position;"
+ "attribute vec2 TexCoord;"
+ ""
+ "varying vec4 DestColor;"
+ "varying vec2 o_TexCoord;"
+ ""
+ "void main(void) {"
+ " DestColor = vec4(Position.x, Position.y, 0, 1);"
+ " o_TexCoord = TexCoord;"
+ " gl_Position = vec4((Position.x / ScreenSize.x) * 2.0 - 1.0, (1.0 - (Position.y + Shake) / ScreenSize.y) * 2.0 - 1.0, 0, 1);"
+ "}";
+
+ const char *fragmentPrg =
+ "uniform sampler2D Texture;"
+ ""
+ "varying lowp vec4 DestColor;"
+ "varying lowp vec2 o_TexCoord;"
+ ""
+ "void main(void) {"
+ " gl_FragColor = texture2D(Texture, o_TexCoord);"
+ "}";
+
+ _vertexShader = [self compileShader:vertexPrg withType:GL_VERTEX_SHADER];
+ _fragmentShader = [self compileShader:fragmentPrg withType:GL_FRAGMENT_SHADER];
+
+ GLuint programHandle = glCreateProgram();
+ glAttachShader(programHandle, _vertexShader);
+ glAttachShader(programHandle, _fragmentShader);
+ glLinkProgram(programHandle);
+
+ GLint linkSuccess;
+ glGetProgramiv(programHandle, GL_LINK_STATUS, &linkSuccess);
+ if (linkSuccess == GL_FALSE) {
+ printOpenGLError();
+ exit(1);
+ }
+
+ glUseProgram(programHandle);
+
+ _screenSizeSlot = (GLuint) glGetUniformLocation(programHandle, "ScreenSize");
+ _textureSlot = (GLuint) glGetUniformLocation(programHandle, "Texture");
+ _shakeSlot = (GLuint) glGetUniformLocation(programHandle, "Shake");
+
+ _positionSlot = (GLuint) glGetAttribLocation(programHandle, "Position");
+ _textureCoordSlot = (GLuint) glGetAttribLocation(programHandle, "TexCoord");
+
+ glEnableVertexAttribArray(_positionSlot);
+ glEnableVertexAttribArray(_textureCoordSlot);
+
+ glUniform1i(_textureSlot, 0); printOpenGLError();
+}
+
+- (void)deleteShaders {
+ glDeleteShader(_vertexShader);
+ glDeleteShader(_fragmentShader);
+}
+
+- (void)setupTextures {
+ glGenTextures(1, &_screenTexture); printOpenGLError();
+ glGenTextures(1, &_overlayTexture); printOpenGLError();
+ glGenTextures(1, &_mouseCursorTexture); printOpenGLError();
+
+ [self setGraphicsMode];
+}
+
+- (void)deleteTextures {
+ if (_screenTexture) {
+ glDeleteTextures(1, &_screenTexture); printOpenGLError();
+ _screenTexture = 0;
+ }
+ if (_overlayTexture) {
+ glDeleteTextures(1, &_overlayTexture); printOpenGLError();
+ _overlayTexture = 0;
+ }
+ if (_mouseCursorTexture) {
+ glDeleteTextures(1, &_mouseCursorTexture); printOpenGLError();
+ _mouseCursorTexture = 0;
+ }
+}
+
+- (void)setupGestureRecognizers {
+ UISwipeGestureRecognizer *swipeRight = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(twoFingersSwipeRight:)];
+ swipeRight.direction = UISwipeGestureRecognizerDirectionRight;
+ swipeRight.numberOfTouchesRequired = 2;
+ swipeRight.delaysTouchesBegan = NO;
+ swipeRight.delaysTouchesEnded = NO;
+
+ UISwipeGestureRecognizer *swipeLeft = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(twoFingersSwipeLeft:)];
+ swipeLeft.direction = UISwipeGestureRecognizerDirectionLeft;
+ swipeLeft.numberOfTouchesRequired = 2;
+ swipeLeft.delaysTouchesBegan = NO;
+ swipeLeft.delaysTouchesEnded = NO;
+
+ UISwipeGestureRecognizer *swipeUp = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(twoFingersSwipeUp:)];
+ swipeUp.direction = UISwipeGestureRecognizerDirectionUp;
+ swipeUp.numberOfTouchesRequired = 2;
+ swipeUp.delaysTouchesBegan = NO;
+ swipeUp.delaysTouchesEnded = NO;
+
+ UISwipeGestureRecognizer *swipeDown = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(twoFingersSwipeDown:)];
+ swipeDown.direction = UISwipeGestureRecognizerDirectionDown;
+ swipeDown.numberOfTouchesRequired = 2;
+ swipeDown.delaysTouchesBegan = NO;
+ swipeDown.delaysTouchesEnded = NO;
+
+ UITapGestureRecognizer *doubleTapTwoFingers = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(twoFingersDoubleTap:)];
+ doubleTapTwoFingers.numberOfTapsRequired = 2;
+ doubleTapTwoFingers.numberOfTouchesRequired = 2;
+ doubleTapTwoFingers.delaysTouchesBegan = NO;
+ doubleTapTwoFingers.delaysTouchesEnded = NO;
+
+ [self addGestureRecognizer:swipeRight];
+ [self addGestureRecognizer:swipeLeft];
+ [self addGestureRecognizer:swipeUp];
+ [self addGestureRecognizer:swipeDown];
+ [self addGestureRecognizer:doubleTapTwoFingers];
+
+ [swipeRight release];
+ [swipeLeft release];
+ [swipeUp release];
+ [swipeDown release];
+ [doubleTapTwoFingers release];
+}
+
+- (id)initWithFrame:(struct CGRect)frame {
+ self = [super initWithFrame: frame];
+
+#if defined(USE_SCALERS) || defined(USE_HQ_SCALERS)
+ InitScalers(565);
+#endif
+
+ [self setupGestureRecognizers];
+
+ [self setContentScaleFactor:[[UIScreen mainScreen] scale]];
+
+#ifdef ENABLE_IOS7_SCALERS
+ _scalerMemorySrc = NULL;
+ _scalerMemoryDst = NULL;
+ _scalerMemorySrcSize = 0;
+ _scalerMemoryDstSize = 0;
+ _scaler = NULL;
+ _scalerScale = 1;
+#endif
+
+ _keyboardView = nil;
+ _screenTexture = 0;
+ _overlayTexture = 0;
+ _mouseCursorTexture = 0;
+
+ _scaledShakeOffsetY = 0;
+
+ _firstTouch = NULL;
+ _secondTouch = NULL;
+
+ _eventLock = [[NSLock alloc] init];
+
+ memset(_gameScreenCoords, 0, sizeof(GLVertex) * 4);
+ memset(_overlayCoords, 0, sizeof(GLVertex) * 4);
+ memset(_mouseCoords, 0, sizeof(GLVertex) * 4);
+
+ // Initialize the OpenGL ES context
+ [self createContext];
+
+ return self;
+}
+
+- (void)dealloc {
+ [_keyboardView release];
+
+ _videoContext.screenTexture.free();
+ _videoContext.overlayTexture.free();
+ _videoContext.mouseTexture.free();
+
+#ifdef ENABLE_IOS7_SCALERS
+ free(_scalerMemorySrc);
+ free(_scalerMemoryDst);
+#endif
+
+ [_eventLock release];
+ [super dealloc];
+}
+
+- (void)setFilterModeForTexture:(GLuint)tex {
+ if (!tex)
+ return;
+
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, tex); printOpenGLError();
+
+ GLint filter = GL_LINEAR;
+
+ switch (_videoContext.graphicsMode) {
+ case kGraphicsModeNone:
+ filter = GL_NEAREST;
+ break;
+
+ case kGraphicsModeLinear:
+ case kGraphicsMode2xSaI:
+ case kGraphicsModeSuper2xSaI:
+ case kGraphicsModeSuperEagle:
+ case kGraphicsModeAdvMame2x:
+ case kGraphicsModeAdvMame3x:
+ case kGraphicsModeHQ2x:
+ case kGraphicsModeHQ3x:
+ case kGraphicsModeTV2x:
+ case kGraphicsModeDotMatrix:
+ filter = GL_LINEAR;
+ break;
+ }
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter); printOpenGLError();
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); printOpenGLError();
+ // We use GL_CLAMP_TO_EDGE here to avoid artifacts when linear filtering
+ // is used. If we would not use this for example the cursor in Loom would
+ // have a line/border artifact on the right side of the covered rect.
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); printOpenGLError();
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); printOpenGLError();
+}
+
+#ifdef ENABLE_IOS7_SCALERS
+- (void)setScaler {
+ ScalerProc *scaler = NULL;
+ int scalerScale = 1;
+
+ switch (_videoContext.graphicsMode) {
+ case kGraphicsModeLinear:
+ break;
+
+ case kGraphicsModeNone:
+ break;
+#ifdef USE_SCALERS
+ case kGraphicsMode2xSaI:
+ scaler = _2xSaI;
+ scalerScale = 2;
+ break;
+
+ case kGraphicsModeSuper2xSaI:
+ scaler = Super2xSaI;
+ scalerScale = 2;
+ break;
+
+ case kGraphicsModeSuperEagle:
+ scaler = SuperEagle;
+ scalerScale = 2;
+ break;
+
+ case kGraphicsModeAdvMame2x:
+ scaler = AdvMame2x;
+ scalerScale = 2;
+ break;
+
+ case kGraphicsModeAdvMame3x:
+ scaler = AdvMame3x;
+ scalerScale = 3;
+ break;
+
+#ifdef USE_HQ_SCALERS
+ case kGraphicsModeHQ2x:
+ scaler = HQ2x;
+ scalerScale = 2;
+ break;
+
+ case kGraphicsModeHQ3x:
+ scaler = HQ3x;
+ scalerScale = 3;
+ break;
+#endif
+
+ case kGraphicsModeTV2x:
+ scaler = TV2x;
+ scalerScale = 2;
+ break;
+
+ case kGraphicsModeDotMatrix:
+ scaler = DotMatrix;
+ scalerScale = 2;
+ break;
+#endif
+
+ default:
+ break;
+ }
+
+ _scaler = scaler;
+ _scalerScale = scalerScale;
+}
+#endif
+
+- (void)setGraphicsMode {
+ [self setFilterModeForTexture:_screenTexture];
+ [self setFilterModeForTexture:_overlayTexture];
+ [self setFilterModeForTexture:_mouseCursorTexture];
+#ifdef ENABLE_IOS7_SCALERS
+ [self setScaler];
+#endif
+}
+
+- (void)updateSurface {
+ if (!g_needsScreenUpdate) {
+ return;
+ }
+ g_needsScreenUpdate = 0;
+
+ glClear(GL_COLOR_BUFFER_BIT); printOpenGLError();
+
+ [self updateMainSurface];
+
+ if (_videoContext.overlayVisible)
+ [self updateOverlaySurface];
+
+ if (_videoContext.mouseIsVisible)
+ [self updateMouseSurface];
+
+ [_context presentRenderbuffer:GL_RENDERBUFFER];
+ glFinish();
+}
+
+- (void)notifyMouseMove {
+ const GLint mouseX = (GLint)(_videoContext.mouseX * _mouseScaleX) - _mouseHotspotX;
+ const GLint mouseY = (GLint)(_videoContext.mouseY * _mouseScaleY) - _mouseHotspotY;
+
+ _mouseCoords[0].x = _mouseCoords[2].x = mouseX;
+ _mouseCoords[0].y = _mouseCoords[1].y = mouseY;
+ _mouseCoords[1].x = _mouseCoords[3].x = mouseX + _mouseWidth;
+ _mouseCoords[2].y = _mouseCoords[3].y = mouseY + _mouseHeight;
+}
+
+- (void)updateMouseCursorScaling {
+ CGRect *rect;
+ int maxWidth, maxHeight;
+
+ if (!_videoContext.overlayVisible) {
+ rect = &_gameScreenRect;
+ maxWidth = _videoContext.screenWidth;
+ maxHeight = _videoContext.screenHeight;
+ } else {
+ rect = &_overlayRect;
+ maxWidth = _videoContext.overlayWidth;
+ maxHeight = _videoContext.overlayHeight;
+ }
+
+ if (!maxWidth || !maxHeight) {
+ printf("WARNING: updateMouseCursorScaling called when screen was not ready (%d)!\n", _videoContext.overlayVisible);
+ return;
+ }
+
+ _mouseScaleX = CGRectGetWidth(*rect) / (GLfloat)maxWidth;
+ _mouseScaleY = CGRectGetHeight(*rect) / (GLfloat)maxHeight;
+
+ _mouseWidth = (GLint)(_videoContext.mouseWidth * _mouseScaleX);
+ _mouseHeight = (GLint)(_videoContext.mouseHeight * _mouseScaleY);
+
+ _mouseHotspotX = (GLint)(_videoContext.mouseHotspotX * _mouseScaleX);
+ _mouseHotspotY = (GLint)(_videoContext.mouseHotspotY * _mouseScaleY);
+
+ // We subtract the screen offset to the hotspot here to simplify the
+ // screen offset handling in the mouse code. Note the subtraction here
+ // makes sure that the offset actually gets added to the mouse position,
+ // since the hotspot offset is substracted from the position.
+ _mouseHotspotX -= (GLint)CGRectGetMinX(*rect);
+ _mouseHotspotY -= (GLint)CGRectGetMinY(*rect);
+
+ // FIXME: For now we also adapt the mouse position here. In reality we
+ // would be better off to also adjust the event position when switching
+ // from overlay to game screen or vica versa.
+ [self notifyMouseMove];
+}
+
+- (void)updateMouseCursor {
+ [self updateMouseCursorScaling];
+
+ _mouseCoords[1].u = _mouseCoords[3].u = (_videoContext.mouseWidth - 1) / (GLfloat)_videoContext.mouseTexture.w;
+ _mouseCoords[2].v = _mouseCoords[3].v = (_videoContext.mouseHeight - 1) / (GLfloat)_videoContext.mouseTexture.h;
+
+ [self setFilterModeForTexture:_mouseCursorTexture];
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, _videoContext.mouseTexture.w, _videoContext.mouseTexture.h, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, _videoContext.mouseTexture.getPixels()); printOpenGLError();
+}
+
+- (void)updateMainSurface {
+ glBufferData(GL_ARRAY_BUFFER, sizeof(GLVertex) * 4, _gameScreenCoords, GL_STATIC_DRAW);
+ glVertexAttribPointer(_positionSlot, 2, GL_FLOAT, GL_FALSE, sizeof(GLVertex), 0);
+ glVertexAttribPointer(_textureCoordSlot, 2, GL_FLOAT, GL_FALSE, sizeof(GLVertex), (GLvoid *) (sizeof(GLfloat) * 2));
+
+ [self setFilterModeForTexture:_screenTexture];
+
+ // Unfortunately we have to update the whole texture every frame, since glTexSubImage2D is actually slower in all cases
+ // due to the iPhone internals having to convert the whole texture back from its internal format when used.
+ // In the future we could use several tiled textures instead.
+#ifdef ENABLE_IOS7_SCALERS
+ if (_scaler) {
+ size_t neededSrcMemorySize = (size_t) (_videoContext.screenTexture.pitch * (_videoContext.screenTexture.h + 4));
+ size_t neededDstMemorySize = (size_t) (_videoContext.screenTexture.pitch * (_videoContext.screenTexture.h + 4) * _scalerScale * _scalerScale);
+ if (neededSrcMemorySize != _scalerMemorySrcSize) {
+ _scalerMemorySrc = (uint8_t *) realloc(_scalerMemorySrc, neededSrcMemorySize);
+ _scalerMemorySrcSize = neededSrcMemorySize;
+ }
+ if (neededDstMemorySize != _scalerMemoryDstSize) {
+ _scalerMemoryDst = (uint8_t *) realloc(_scalerMemoryDst, neededDstMemorySize);
+ _scalerMemoryDstSize = neededDstMemorySize;
+ }
+
+ // Clear two lines before
+ memset(_scalerMemorySrc, 0, (size_t) (_videoContext.screenTexture.pitch * 2));
+ // Copy original buffer
+ memcpy(_scalerMemorySrc + _videoContext.screenTexture.pitch * 2, _videoContext.screenTexture.getPixels(), _videoContext.screenTexture.pitch * _videoContext.screenTexture.h);
+ // Clear two lines after
+ memset(_scalerMemorySrc + _videoContext.screenTexture.pitch * (2 + _videoContext.screenTexture.h), 0, (size_t) (_videoContext.screenTexture.pitch * 2));
+ // Apply scaler
+ _scaler(_scalerMemorySrc + _videoContext.screenTexture.pitch * 2,
+ _videoContext.screenTexture.pitch,
+ _scalerMemoryDst,
+ (uint32) (_videoContext.screenTexture.pitch * _scalerScale),
+ _videoContext.screenTexture.w,
+ _videoContext.screenTexture.h);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, _videoContext.screenTexture.w * _scalerScale, _videoContext.screenTexture.h * _scalerScale, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, _scalerMemoryDst); printOpenGLError();
+ }
+ else {
+#endif
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, _videoContext.screenTexture.w, _videoContext.screenTexture.h, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, _videoContext.screenTexture.getPixels()); printOpenGLError();
+#ifdef ENABLE_IOS7_SCALERS
+ }
+#endif
+
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); printOpenGLError();
+}
+
+- (void)updateOverlaySurface {
+ glBufferData(GL_ARRAY_BUFFER, sizeof(GLVertex) * 4, _overlayCoords, GL_STATIC_DRAW);
+ glVertexAttribPointer(_positionSlot, 2, GL_FLOAT, GL_FALSE, sizeof(GLVertex), 0);
+ glVertexAttribPointer(_textureCoordSlot, 2, GL_FLOAT, GL_FALSE, sizeof(GLVertex), (GLvoid *) (sizeof(GLfloat) * 2));
+
+ [self setFilterModeForTexture:_overlayTexture];
+
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, _videoContext.overlayTexture.w, _videoContext.overlayTexture.h, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, _videoContext.overlayTexture.getPixels()); printOpenGLError();
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); printOpenGLError();
+}
+
+- (void)updateMouseSurface {
+ glBufferData(GL_ARRAY_BUFFER, sizeof(GLVertex) * 4, _mouseCoords, GL_STATIC_DRAW);
+ glVertexAttribPointer(_positionSlot, 2, GL_FLOAT, GL_FALSE, sizeof(GLVertex), 0);
+ glVertexAttribPointer(_textureCoordSlot, 2, GL_FLOAT, GL_FALSE, sizeof(GLVertex), (GLvoid *) (sizeof(GLfloat) * 2));
+
+ glBindTexture(GL_TEXTURE_2D, _mouseCursorTexture); printOpenGLError();
+
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); printOpenGLError();
+}
+
+- (void)createScreenTexture {
+ const uint screenTexWidth = getSizeNextPOT(_videoContext.screenWidth);
+ const uint screenTexHeight = getSizeNextPOT(_videoContext.screenHeight);
+
+ _gameScreenCoords[1].u = _gameScreenCoords[3].u = _videoContext.screenWidth / (GLfloat)screenTexWidth;
+ _gameScreenCoords[2].v = _gameScreenCoords[3].v = _videoContext.screenHeight / (GLfloat)screenTexHeight;
+
+ _videoContext.screenTexture.create((uint16) screenTexWidth, (uint16) screenTexHeight, Graphics::createPixelFormat<565>());
+}
+
+- (void)initSurface {
+ if (_context) {
+ [self rebuildFrameBuffer];
+ }
+
+ BOOL isLandscape = (self.bounds.size.width > self.bounds.size.height); // UIDeviceOrientationIsLandscape([[UIDevice currentDevice] orientation]);
+
+ int screenWidth, screenHeight;
+ if (isLandscape) {
+ screenWidth = MAX(_renderBufferWidth, _renderBufferHeight);
+ screenHeight = MIN(_renderBufferWidth, _renderBufferHeight);
+ }
+ else {
+ screenWidth = MIN(_renderBufferWidth, _renderBufferHeight);
+ screenHeight = MAX(_renderBufferWidth, _renderBufferHeight);
+ }
+
+ glBindRenderbuffer(GL_RENDERBUFFER, _viewRenderbuffer); printOpenGLError();
+
+ [self clearColorBuffer];
+
+ GLfloat adjustedWidth = _videoContext.screenWidth;
+ GLfloat adjustedHeight = _videoContext.screenHeight;
+ if (_videoContext.asprectRatioCorrection) {
+ if (_videoContext.screenWidth == 320 && _videoContext.screenHeight == 200)
+ adjustedHeight = 240;
+ else if (_videoContext.screenWidth == 640 && _videoContext.screenHeight == 400)
+ adjustedHeight = 480;
+ }
+
+ float overlayPortraitRatio;
+
+ if (isLandscape) {
+ GLfloat gameScreenRatio = adjustedWidth / adjustedHeight;
+ GLfloat screenRatio = (GLfloat)screenWidth / (GLfloat)screenHeight;
+
+ // These are the width/height according to the portrait layout!
+ int rectWidth, rectHeight;
+ int xOffset, yOffset;
+
+ if (gameScreenRatio < screenRatio) {
+ // When the game screen ratio is less than the screen ratio
+ // we need to scale the width, since the game screen was higher
+ // compared to the width than our output screen is.
+ rectWidth = (int)(screenHeight * gameScreenRatio);
+ rectHeight = screenHeight;
+ xOffset = (screenWidth - rectWidth) / 2;
+ yOffset = 0;
+ } else {
+ // When the game screen ratio is bigger than the screen ratio
+ // we need to scale the height, since the game screen was wider
+ // compared to the height than our output screen is.
+ rectWidth = screenWidth;
+ rectHeight = (int)(screenWidth / gameScreenRatio);
+ xOffset = 0;
+ yOffset = (screenHeight - rectHeight) / 2;
+ }
+
+ [_keyboardView hideKeyboard];
+
+ //printf("Rect: %i, %i, %i, %i\n", xOffset, yOffset, rectWidth, rectHeight);
+ _gameScreenRect = CGRectMake(xOffset, yOffset, rectWidth, rectHeight);
+ overlayPortraitRatio = 1.0f;
+ } else {
+ GLfloat ratio = adjustedHeight / adjustedWidth;
+ int height = (int)(screenWidth * ratio);
+ //printf("Making rect (%u, %u)\n", screenWidth, height);
+ _gameScreenRect = CGRectMake(0, 0, screenWidth, height);
+
+ CGRect keyFrame = CGRectMake(0.0f, 0.0f, 0.0f, 0.0f);
+ if (_keyboardView == nil) {
+ _keyboardView = [[SoftKeyboard alloc] initWithFrame:keyFrame];
+ [_keyboardView setInputDelegate:self];
+ [self addSubview:[_keyboardView inputView]];
+ [self addSubview: _keyboardView];
+ }
+
+ [_keyboardView showKeyboard];
+ overlayPortraitRatio = (_videoContext.overlayHeight * ratio) / _videoContext.overlayWidth;
+ }
+ _overlayRect = CGRectMake(0, 0, screenWidth, screenHeight * overlayPortraitRatio);
+
+ _gameScreenCoords[0].x = _gameScreenCoords[2].x = CGRectGetMinX(_gameScreenRect);
+ _gameScreenCoords[0].y = _gameScreenCoords[1].y = CGRectGetMinY(_gameScreenRect);
+ _gameScreenCoords[1].x = _gameScreenCoords[3].x = CGRectGetMaxX(_gameScreenRect);
+ _gameScreenCoords[2].y = _gameScreenCoords[3].y = CGRectGetMaxY(_gameScreenRect);
+
+ _overlayCoords[1].x = _overlayCoords[3].x = CGRectGetMaxX(_overlayRect);
+ _overlayCoords[2].y = _overlayCoords[3].y = CGRectGetMaxY(_overlayRect);
+
+ [self setViewTransformation];
+ [self updateMouseCursorScaling];
+}
+
+- (void)setViewTransformation {
+ // Scale the shake offset according to the overlay size. We need this to
+ // adjust the overlay mouse click coordinates when an offset is set.
+ _scaledShakeOffsetY = (int)(_videoContext.shakeOffsetY / (GLfloat)_videoContext.screenHeight * CGRectGetHeight(_overlayRect));
+
+ glUniform1f(_shakeSlot, _scaledShakeOffsetY);
+}
+
+- (void)clearColorBuffer {
+ // The color buffer is triple-buffered, so we clear it multiple times right away to avid doing any glClears later.
+ int clearCount = 5;
+ while (clearCount-- > 0) {
+ glClear(GL_COLOR_BUFFER_BIT); printOpenGLError();
+ [_context presentRenderbuffer:GL_RENDERBUFFER];
+ glFinish();
+ }
+}
+
+- (void)addEvent:(InternalEvent)event {
+ [_eventLock lock];
+ _events.push_back(event);
+ [_eventLock unlock];
+}
+
+- (bool)fetchEvent:(InternalEvent *)event {
+ [_eventLock lock];
+ if (_events.empty()) {
+ [_eventLock unlock];
+ return false;
+ }
+
+ *event = *_events.begin();
+ _events.pop_front();
+ [_eventLock unlock];
+ return true;
+}
+
+- (bool)getMouseCoords:(CGPoint)point eventX:(int *)x eventY:(int *)y {
+ // We scale the input according to our scale factor to get actual screen
+ // coordinates.
+ point.x *= self.contentScaleFactor;
+ point.y *= self.contentScaleFactor;
+
+ CGRect *area;
+ int width, height, offsetY;
+ if (_videoContext.overlayVisible) {
+ area = &_overlayRect;
+ width = _videoContext.overlayWidth;
+ height = _videoContext.overlayHeight;
+ offsetY = _scaledShakeOffsetY;
+ } else {
+ area = &_gameScreenRect;
+ width = _videoContext.screenWidth;
+ height = _videoContext.screenHeight;
+ offsetY = _videoContext.shakeOffsetY;
+ }
+
+ point.x = (point.x - CGRectGetMinX(*area)) / CGRectGetWidth(*area);
+ point.y = (point.y - CGRectGetMinY(*area)) / CGRectGetHeight(*area);
+
+ *x = (int)(point.x * width);
+ // offsetY describes the translation of the screen in the upward direction,
+ // thus we need to add it here.
+ *y = (int)(point.y * height + offsetY);
+
+ if (!iOS7_touchpadModeEnabled()) {
+ // Clip coordinates
+ if (*x < 0 || *x > width || *y < 0 || *y > height)
+ return false;
+ }
+
+ return true;
+}
+
+- (void)deviceOrientationChanged:(UIDeviceOrientation)orientation {
+ [self addEvent:InternalEvent(kInputOrientationChanged, orientation, 0)];
+}
+
+- (UITouch *)secondTouchOtherTouchThan:(UITouch *)touch in:(NSSet *)set {
+ NSArray *all = [set allObjects];
+ for (UITouch *t in all) {
+ if (t != touch) {
+ return t;
+ }
+ }
+ return nil;
+}
+
+- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
+ int x, y;
+
+ NSSet *allTouches = [event allTouches];
+ if (allTouches.count == 1) {
+ _firstTouch = [allTouches anyObject];
+ CGPoint point = [_firstTouch locationInView:self];
+ if (![self getMouseCoords:point eventX:&x eventY:&y])
+ return;
+
+ [self addEvent:InternalEvent(kInputMouseDown, x, y)];
+ }
+ else if (allTouches.count == 2) {
+ _secondTouch = [self secondTouchOtherTouchThan:_firstTouch in:allTouches];
+ if (_secondTouch) {
+ CGPoint point = [_secondTouch locationInView:self];
+ if (![self getMouseCoords:point eventX:&x eventY:&y])
+ return;
+
+ [self addEvent:InternalEvent(kInputMouseSecondDown, x, y)];
+ }
+ }
+}
+
+- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
+ int x, y;
+
+ NSSet *allTouches = [event allTouches];
+ for (UITouch *touch in allTouches) {
+ if (touch == _firstTouch) {
+ CGPoint point = [touch locationInView:self];
+ if (![self getMouseCoords:point eventX:&x eventY:&y])
+ return;
+
+ [self addEvent:InternalEvent(kInputMouseDragged, x, y)];
+ } else if (touch == _secondTouch) {
+ CGPoint point = [touch locationInView:self];
+ if (![self getMouseCoords:point eventX:&x eventY:&y])
+ return;
+
+ [self addEvent:InternalEvent(kInputMouseSecondDragged, x, y)];
+ }
+ }
+}
+
+- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
+ int x, y;
+
+ NSSet *allTouches = [event allTouches];
+ if (allTouches.count == 1) {
+ UITouch *touch = [allTouches anyObject];
+ CGPoint point = [touch locationInView:self];
+ if (![self getMouseCoords:point eventX:&x eventY:&y]) {
+ return;
+ }
+
+ [self addEvent:InternalEvent(kInputMouseUp, x, y)];
+ }
+ else if (allTouches.count == 2) {
+ UITouch *touch = [[allTouches allObjects] objectAtIndex:1];
+ CGPoint point = [touch locationInView:self];
+ if (![self getMouseCoords:point eventX:&x eventY:&y])
+ return;
+
+ [self addEvent:InternalEvent(kInputMouseSecondUp, x, y)];
+ }
+ _firstTouch = nil;
+ _secondTouch = nil;
+}
+
+- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
+ _firstTouch = nil;
+ _secondTouch = nil;
+}
+
+- (void)twoFingersSwipeRight:(UISwipeGestureRecognizer *)recognizer {
+ [self addEvent:InternalEvent(kInputSwipe, kUIViewSwipeRight, 2)];
+}
+
+- (void)twoFingersSwipeLeft:(UISwipeGestureRecognizer *)recognizer {
+ [self addEvent:InternalEvent(kInputSwipe, kUIViewSwipeLeft, 2)];
+}
+
+- (void)twoFingersSwipeUp:(UISwipeGestureRecognizer *)recognizer {
+ [self addEvent:InternalEvent(kInputSwipe, kUIViewSwipeUp, 2)];
+}
+
+- (void)twoFingersSwipeDown:(UISwipeGestureRecognizer *)recognizer {
+ [self addEvent:InternalEvent(kInputSwipe, kUIViewSwipeDown, 2)];
+}
+
+- (void)twoFingersDoubleTap:(UITapGestureRecognizer *)recognizer {
+ [self addEvent:InternalEvent(kInputTap, kUIViewTapDouble, 2)];
+}
+
+- (void)handleKeyPress:(unichar)c {
+ [self addEvent:InternalEvent(kInputKeyPressed, c, 0)];
+}
+
+- (void)applicationSuspend {
+ [self addEvent:InternalEvent(kInputApplicationSuspended, 0, 0)];
+}
+
+- (void)applicationResume {
+ [self addEvent:InternalEvent(kInputApplicationResumed, 0, 0)];
+}
+
+@end
diff --git a/backends/platform/ios7/module.mk b/backends/platform/ios7/module.mk
new file mode 100644
index 0000000000..5ee4c7a601
--- /dev/null
+++ b/backends/platform/ios7/module.mk
@@ -0,0 +1,17 @@
+MODULE := backends/platform/ios7
+
+MODULE_OBJS := \
+ ios7_osys_main.o \
+ ios7_osys_events.o \
+ ios7_osys_sound.o \
+ ios7_osys_video.o \
+ ios7_main.o \
+ ios7_video.o \
+ ios7_keyboard.o \
+ iOS7ScummVMViewController.o \
+ iOS7AppDelegate.o
+
+# We don't use rules.mk but rather manually update OBJS and MODULE_DIRS.
+MODULE_OBJS := $(addprefix $(MODULE)/, $(MODULE_OBJS))
+OBJS := $(MODULE_OBJS) $(OBJS)
+MODULE_DIRS += $(sort $(dir $(MODULE_OBJS)))
diff --git a/backends/platform/iphone/osys_main.cpp b/backends/platform/iphone/osys_main.cpp
index 0ce21b44c1..3f5e7692c7 100644
--- a/backends/platform/iphone/osys_main.cpp
+++ b/backends/platform/iphone/osys_main.cpp
@@ -90,7 +90,7 @@ int OSystem_IPHONE::timerHandler(int t) {
}
void OSystem_IPHONE::initBackend() {
-#ifdef IPHONE_OFFICIAL
+#ifdef IPHONE_SANDBOXED
_savefileManager = new DefaultSaveFileManager(iPhone_getDocumentsDir());
#else
_savefileManager = new DefaultSaveFileManager(SCUMMVM_SAVE_PATH);
@@ -252,7 +252,7 @@ OSystem *OSystem_IPHONE_create() {
}
Common::String OSystem_IPHONE::getDefaultConfigFileName() {
-#ifdef IPHONE_OFFICIAL
+#ifdef IPHONE_SANDBOXED
Common::String path = iPhone_getDocumentsDir();
path += "/Preferences";
return path;
@@ -305,7 +305,7 @@ void iphone_main(int argc, char *argv[]) {
//gDebugLevel = 10;
}
-#ifdef IPHONE_OFFICIAL
+#ifdef IPHONE_SANDBOXED
chdir(iPhone_getDocumentsDir());
#else
system("mkdir " SCUMMVM_ROOT_PATH);
diff --git a/common/fs.h b/common/fs.h
index b5b88ba8cb..66e98444d6 100644
--- a/common/fs.h
+++ b/common/fs.h
@@ -58,9 +58,11 @@ class FSList : public Array<FSNode> {};
class FSNode : public ArchiveMember {
private:
SharedPtr<AbstractFSNode> _realNode;
- FSNode(AbstractFSNode *realNode);
public:
+ // WARNING: Use this constructor with care! FSNode takes the ownership of the pointer and will delete it at some point.
+ FSNode(AbstractFSNode *realNode);
+
/**
* Flag to tell listDir() which kind of files to list.
*/
diff --git a/common/str.h b/common/str.h
index dede87a005..a30dae3513 100644
--- a/common/str.h
+++ b/common/str.h
@@ -180,6 +180,7 @@ public:
inline uint size() const { return _size; }
inline bool empty() const { return (_size == 0); }
+ char firstChar() const { return (_size > 0) ? _str[0] : 0; }
char lastChar() const { return (_size > 0) ? _str[_size - 1] : 0; }
char operator[](int idx) const {
diff --git a/configure b/configure
index abc38fe4e3..6afa8e16f9 100755
--- a/configure
+++ b/configure
@@ -834,7 +834,7 @@ Usage: $0 [OPTIONS]...
Configuration:
-h, --help display this help and exit
--backend=BACKEND backend to build (android, tizen, dc, dingux, ds, gcw0,
- gph, iphone, linuxmoto, maemo, n64, null, openpandora,
+ gph, iphone, ios7, linuxmoto, maemo, n64, null, openpandora,
ps2, psp, samsungtv, sdl, webos, wii, wince) [sdl]
Installation directories:
@@ -874,7 +874,8 @@ Special configuration feature:
gcw0 for GCW Zero
gp2x for GP2X
gp2xwiz for GP2X Wiz
- iphone for Apple iPhone
+ iphone for Apple iPhone (iOS <= 6)
+ ios7 for Apple iPhone / iPad (iOS >= 7)
linupy for Yopy PDA
maemo for Nokia Maemo
motoezx for MotoEZX
@@ -1359,6 +1360,11 @@ iphone)
_host_cpu=arm
_host_alias=arm-apple-darwin9
;;
+ios7)
+ _host_os=iphone
+ _host_cpu=arm
+ _host_alias=arm-apple-darwin11
+ ;;
linupy)
_host_os=linux
_host_cpu=arm
@@ -2062,21 +2068,28 @@ define_in_config_h_if_yes $_need_memalign 'SCUMM_NEED_ALIGNMENT'
echo_n "Checking host CPU architecture... "
case $_host_cpu in
arm*)
- echo "ARM"
- define_in_config_if_yes yes 'USE_ARM_SCALER_ASM'
- # FIXME: The following feature exhibits a bug. It produces distorted
- # sound since 9003ce517ff9906b0288f9f7c02197fd091d4554. The ARM
- # assembly will need to be properly adapted to the changes to the C
- # code in 8f5a7cde2f99de9fef849b0ff688906f05f4643e.
- # See bug #6957: "AUDIO: ARM ASM sound code causes distorted audio on 32 bit armv6"
- #define_in_config_if_yes yes 'USE_ARM_SOUND_ASM'
- define_in_config_if_yes yes 'USE_ARM_SMUSH_ASM'
- define_in_config_if_yes yes 'USE_ARM_GFX_ASM'
- # FIXME: The following feature exhibits a bug during the intro scene of Indy 4
- # (on Pandora and iPhone at least)
- #define_in_config_if_yes yes 'USE_ARM_COSTUME_ASM'
-
- append_var DEFINES "-DARM_TARGET"
+ case $_host_alias in
+ arm-apple-darwin11)
+ echo "Apple iOS 7+ - ARM assembly disabled"
+ ;;
+ *)
+ echo "ARM"
+ define_in_config_if_yes yes 'USE_ARM_SCALER_ASM'
+ # FIXME: The following feature exhibits a bug. It produces distorted
+ # sound since 9003ce517ff9906b0288f9f7c02197fd091d4554. The ARM
+ # assembly will need to be properly adapted to the changes to the C
+ # code in 8f5a7cde2f99de9fef849b0ff688906f05f4643e.
+ # See bug #6957: "AUDIO: ARM ASM sound code causes distorted audio on 32 bit armv6"
+ #define_in_config_if_yes yes 'USE_ARM_SOUND_ASM'
+ define_in_config_if_yes yes 'USE_ARM_SMUSH_ASM'
+ define_in_config_if_yes yes 'USE_ARM_GFX_ASM'
+ # FIXME: The following feature exhibits a bug during the intro scene of Indy 4
+ # (on Pandora and iPhone at least)
+ #define_in_config_if_yes yes 'USE_ARM_COSTUME_ASM'
+
+ append_var DEFINES "-DARM_TARGET"
+ ;;
+ esac
;;
i[3-6]86)
echo "x86"
@@ -2722,6 +2735,16 @@ if test -n "$_host"; then
_seq_midi=no
_timidity=no
;;
+ ios7)
+ append_var DEFINES "-DIPHONE"
+ append_var CFLAGS "-Wno-shift-count-overflow"
+ append_var CXXFLAGS "-Wno-shift-count-overflow"
+ _backend="ios7"
+ _build_scalers=no
+ _mt32emu=no
+ _seq_midi=no
+ _timidity=no
+ ;;
m68k-atari-mint)
append_var DEFINES "-DSYSTEM_NOT_SUPPORTING_D_TYPE"
_ranlib=m68k-atari-mint-ranlib
@@ -3015,6 +3038,19 @@ case $_backend in
append_var LIBS "-framework QuartzCore -framework CoreFoundation -framework Foundation"
append_var LIBS "-framework AudioToolbox -framework CoreAudio"
;;
+ ios7)
+ append_var LIBS "-lobjc -framework UIKit -framework CoreGraphics -framework OpenGLES"
+ append_var LIBS "-framework QuartzCore -framework CoreFoundation -framework Foundation"
+ append_var LIBS "-framework AudioToolbox -framework CoreAudio"
+ append_var LDFLAGS "-miphoneos-version-min=7.1 -arch armv7"
+ append_var CFLAGS "-miphoneos-version-min=7.1 -arch armv7"
+ append_var CXXFLAGS "-miphoneos-version-min=7.1 -arch armv7"
+ if test -n "$SDKROOT"; then
+ append_var LDFLAGS "-mlinker-version=134.9 -B/usr/local/bin/arm-apple-darwin11-"
+ append_var CFLAGS "-isysroot $SDKROOT -F$SDKROOT/System/Library/Frameworks"
+ append_var CXXFLAGS "-isysroot $SDKROOT -I$SDKROOT/usr/include/c++/4.2.1 -F$SDKROOT/System/Library/Frameworks"
+ fi
+ ;;
linuxmoto)
append_var DEFINES "-DLINUXMOTO"
;;
@@ -3146,7 +3182,7 @@ esac
# Enable 16bit support only for backends which support it
#
case $_backend in
- android | dingux | dc | gph | iphone | maemo | openpandora | psp | samsungtv | sdl | tizen | webos | wii)
+ android | dingux | dc | gph | iphone | ios7 | maemo | openpandora | psp | samsungtv | sdl | tizen | webos | wii)
if test "$_16bit" = auto ; then
_16bit=yes
else
@@ -3205,7 +3241,7 @@ case $_host_os in
amigaos* | cygwin* | dreamcast | ds | gamecube | mingw* | n64 | ps2 | ps3 | psp | wii | wince)
_posix=no
;;
- android | beos* | bsd* | darwin* | freebsd* | gnu* | gph-linux | haiku* | hpux* | iphone | irix*| k*bsd*-gnu* | linux* | maemo | mint* | netbsd* | openbsd* | solaris* | sunos* | uclinux* | webos)
+ android | beos* | bsd* | darwin* | freebsd* | gnu* | gph-linux | haiku* | hpux* | iphone | ios7 | irix*| k*bsd*-gnu* | linux* | maemo | mint* | netbsd* | openbsd* | solaris* | sunos* | uclinux* | webos)
_posix=yes
;;
os2-emx*)
diff --git a/devtools/create_project/codeblocks.cpp b/devtools/create_project/codeblocks.cpp
index 442a2b0025..e9dc8bf234 100644
--- a/devtools/create_project/codeblocks.cpp
+++ b/devtools/create_project/codeblocks.cpp
@@ -200,6 +200,11 @@ void CodeBlocksProvider::createProjectFile(const std::string &name, const std::s
}
+void CodeBlocksProvider::addResourceFiles(const BuildSetup &setup, StringList &includeList, StringList &excludeList) {
+ includeList.push_back(setup.srcDir + "/icons/" + setup.projectName + ".ico");
+ includeList.push_back(setup.srcDir + "/dists/" + setup.projectName + ".rc");
+}
+
void CodeBlocksProvider::writeWarnings(const std::string &name, std::ofstream &output) const {
// Global warnings
diff --git a/devtools/create_project/codeblocks.h b/devtools/create_project/codeblocks.h
index f65604d925..5baa21c242 100644
--- a/devtools/create_project/codeblocks.h
+++ b/devtools/create_project/codeblocks.h
@@ -37,6 +37,8 @@ protected:
void createOtherBuildFiles(const BuildSetup &) {}
+ void addResourceFiles(const BuildSetup &setup, StringList &includeList, StringList &excludeList);
+
void createProjectFile(const std::string &name, const std::string &uuid, const BuildSetup &setup, const std::string &moduleDir,
const StringList &includeList, const StringList &excludeList);
diff --git a/devtools/create_project/create_project.cpp b/devtools/create_project/create_project.cpp
index 0aba511491..65b7601a54 100644
--- a/devtools/create_project/create_project.cpp
+++ b/devtools/create_project/create_project.cpp
@@ -340,7 +340,13 @@ int main(int argc, char *argv[]) {
setup.defines.push_back("WIN32");
} else {
setup.defines.push_back("POSIX");
- setup.defines.push_back("MACOSX"); // This will break iOS, but allows OS X to catch up on browser_osx.
+ // Define both MACOSX, and IPHONE, but only one of them will be associated to the
+ // correct target by the Xcode project provider.
+ // This define will help catching up target dependend files, like "browser_osx.mm"
+ // The suffix ("_osx", or "_ios") will be used by the project provider to filter out
+ // the files, according to the target.
+ setup.defines.push_back("MACOSX");
+ setup.defines.push_back("IPHONE");
}
setup.defines.push_back("SDL_BACKEND");
if (!useSDL2) {
@@ -929,16 +935,17 @@ TokenList tokenize(const std::string &input, char separator) {
namespace {
const Feature s_features[] = {
// Libraries
- { "libz", "USE_ZLIB", "zlib", true, "zlib (compression) support" },
- { "mad", "USE_MAD", "libmad", true, "libmad (MP3) support" },
- { "vorbis", "USE_VORBIS", "libvorbisfile_static libvorbis_static libogg_static", true, "Ogg Vorbis support" },
- { "flac", "USE_FLAC", "libFLAC_static win_utf8_io_static", true, "FLAC support" },
- { "png", "USE_PNG", "libpng", true, "libpng support" },
- { "faad", "USE_FAAD", "libfaad", false, "AAC support" },
- { "mpeg2", "USE_MPEG2", "libmpeg2", false, "MPEG-2 support" },
- { "theora", "USE_THEORADEC", "libtheora_static", true, "Theora decoding support" },
- {"freetype", "USE_FREETYPE2", "freetype", true, "FreeType support" },
- { "jpeg", "USE_JPEG", "jpeg-static", true, "libjpeg support" },
+ { "libz", "USE_ZLIB", "zlib", true, "zlib (compression) support" },
+ { "mad", "USE_MAD", "libmad", true, "libmad (MP3) support" },
+ { "vorbis", "USE_VORBIS", "libvorbisfile_static libvorbis_static libogg_static", true, "Ogg Vorbis support" },
+ { "flac", "USE_FLAC", "libFLAC_static win_utf8_io_static", true, "FLAC support" },
+ { "png", "USE_PNG", "libpng", true, "libpng support" },
+ { "faad", "USE_FAAD", "libfaad", false, "AAC support" },
+ { "mpeg2", "USE_MPEG2", "libmpeg2", false, "MPEG-2 support" },
+ { "theora", "USE_THEORADEC", "libtheora_static", true, "Theora decoding support" },
+ { "freetype", "USE_FREETYPE2", "freetype", true, "FreeType support" },
+ { "jpeg", "USE_JPEG", "jpeg-static", true, "libjpeg support" },
+ {"fluidsynth", "USE_FLUIDSYNTH", "libfluidsynth", true, "FluidSynth support" },
// Feature flags
{ "bink", "USE_BINK", "", true, "Bink video support" },
@@ -1050,6 +1057,12 @@ void splitFilename(const std::string &fileName, std::string &name, std::string &
ext = (dot == std::string::npos) ? std::string() : fileName.substr(dot + 1);
}
+std::string basename(const std::string &fileName) {
+ const std::string::size_type slash = fileName.find_last_of('/');
+ if (slash == std::string::npos) return fileName;
+ return fileName.substr(slash + 1);
+}
+
bool producesObjectFile(const std::string &fileName) {
std::string n, ext;
splitFilename(fileName, n, ext);
@@ -1334,8 +1347,7 @@ void ProjectProvider::createProject(BuildSetup &setup) {
createModuleList(setup.srcDir + "/image", setup.defines, setup.testDirs, in, ex);
// Resource files
- in.push_back(setup.srcDir + "/icons/" + setup.projectName + ".ico");
- in.push_back(setup.srcDir + "/dists/" + setup.projectName + ".rc");
+ addResourceFiles(setup, in, ex);
// Various text files
in.push_back(setup.srcDir + "/AUTHORS");
diff --git a/devtools/create_project/create_project.h b/devtools/create_project/create_project.h
index 1a28946315..fb207f3f59 100644
--- a/devtools/create_project/create_project.h
+++ b/devtools/create_project/create_project.h
@@ -316,6 +316,17 @@ std::string convertPathToWin(const std::string &path);
void splitFilename(const std::string &fileName, std::string &name, std::string &ext);
/**
+ * Returns the basename of a path.
+ * examples:
+ * a/b/c/d.ext -> d.ext
+ * d.ext -> d.ext
+ *
+ * @param fileName Filename
+ * @return The basename
+ */
+std::string basename(const std::string &fileName);
+
+/**
* Checks whether the given file will produce an object file or not.
*
* @param fileName Name of the file.
@@ -419,6 +430,13 @@ protected:
virtual void createOtherBuildFiles(const BuildSetup &setup) = 0;
/**
+ * Add resources to the project
+ *
+ * @param setup Description of the desired build setup.
+ */
+ virtual void addResourceFiles(const BuildSetup &setup, StringList &includeList, StringList &excludeList) = 0;
+
+ /**
* Create a project file for the specified list of files.
*
* @param name Name of the project file.
diff --git a/devtools/create_project/msvc.cpp b/devtools/create_project/msvc.cpp
index dbfbcc128d..e6b47fe724 100644
--- a/devtools/create_project/msvc.cpp
+++ b/devtools/create_project/msvc.cpp
@@ -130,6 +130,11 @@ void MSVCProvider::createOtherBuildFiles(const BuildSetup &setup) {
createBuildProp(setup, false, true, "LLVM");
}
+void MSVCProvider::addResourceFiles(const BuildSetup &setup, StringList &includeList, StringList &excludeList) {
+ includeList.push_back(setup.srcDir + "/icons/" + setup.projectName + ".ico");
+ includeList.push_back(setup.srcDir + "/dists/" + setup.projectName + ".rc");
+}
+
void MSVCProvider::createGlobalProp(const BuildSetup &setup) {
std::ofstream properties((setup.outputDir + '/' + setup.projectDescription + "_Global" + getPropertiesExtension()).c_str());
if (!properties)
diff --git a/devtools/create_project/msvc.h b/devtools/create_project/msvc.h
index e75e131bd1..178ba8e216 100644
--- a/devtools/create_project/msvc.h
+++ b/devtools/create_project/msvc.h
@@ -39,6 +39,8 @@ protected:
void createOtherBuildFiles(const BuildSetup &setup);
+ void addResourceFiles(const BuildSetup &setup, StringList &includeList, StringList &excludeList);
+
/**
* Create the global project properties.
*
diff --git a/devtools/create_project/xcode.cpp b/devtools/create_project/xcode.cpp
index c5c433c82e..8274875ec5 100644
--- a/devtools/create_project/xcode.cpp
+++ b/devtools/create_project/xcode.cpp
@@ -26,26 +26,33 @@
#include <fstream>
#include <algorithm>
+#ifdef MACOSX
+#include <sstream>
+#include <iomanip>
+#include <CommonCrypto/CommonCrypto.h>
+#endif
+
namespace CreateProjectTool {
#define DEBUG_XCODE_HASH 0
-#ifdef ENABLE_IOS
#define IOS_TARGET 0
#define OSX_TARGET 1
-#define SIM_TARGET 2
-#else
-#define OSX_TARGET 0
-#endif
#define ADD_DEFINE(defines, name) \
defines.push_back(name);
+#define REMOVE_DEFINE(defines, name) \
+ { ValueList::iterator i = std::find(defines.begin(), defines.end(), name); if (i != defines.end()) defines.erase(i); }
+
+#define CONTAINS_DEFINE(defines, name) \
+ (std::find(defines.begin(), defines.end(), name) != defines.end())
+
#define ADD_SETTING(config, key, value) \
config._settings[key] = Setting(value, "", kSettingsNoQuote);
#define ADD_SETTING_ORDER(config, key, value, order) \
- config._settings[key] = Setting(value, "", kSettingsNoQuote, 0, order);
+ config.settings[key] = Setting(value, "", kSettingsNoQuote, 0, order);
#define ADD_SETTING_ORDER_NOVALUE(config, key, comment, order) \
config._settings[key] = Setting("", comment, kSettingsNoValue, 0, order);
@@ -69,6 +76,17 @@ namespace CreateProjectTool {
_buildFile._flags = kSettingsSingleItem; \
}
+#define ADD_FILE_REFERENCE(id, name, properties) { \
+ Object *fileRef = new Object(this, id, name, "PBXFileReference", "PBXFileReference", name); \
+ if (!properties._fileEncoding.empty()) fileRef->addProperty("fileEncoding", properties._fileEncoding, "", kSettingsNoValue); \
+ if (!properties._lastKnownFileType.empty()) fileRef->addProperty("lastKnownFileType", properties._lastKnownFileType, "", kSettingsNoValue|kSettingsQuoteVariable); \
+ if (!properties._fileName.empty()) fileRef->addProperty("name", properties._fileName, "", kSettingsNoValue|kSettingsQuoteVariable); \
+ if (!properties._filePath.empty()) fileRef->addProperty("path", properties._filePath, "", kSettingsNoValue|kSettingsQuoteVariable); \
+ if (!properties._sourceTree.empty()) fileRef->addProperty("sourceTree", properties._sourceTree, "", kSettingsNoValue); \
+ _fileReference.add(fileRef); \
+ _fileReference._flags = kSettingsSingleItem; \
+}
+
bool producesObjectFileOnOSX(const std::string &fileName) {
std::string n, ext;
splitFilename(fileName, n, ext);
@@ -81,9 +99,61 @@ bool producesObjectFileOnOSX(const std::string &fileName) {
return false;
}
+bool targetIsIOS(const std::string &targetName) {
+ return targetName.length() > 4 && targetName.substr(targetName.length() - 4) == "-iOS";
+}
+
+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.
+ // - if the parent directory is "/sdl", the file belongs to the OS X target.
+ // - if the file has a suffix, like "_osx", or "_ios", the file belongs to one of the target.
+ // - if the file is an OS X icon file (icns), it belongs to the OS X target.
+ std::string name, ext;
+ splitFilename(fileName, name, ext);
+ if (targetIsIOS(targetName)) {
+ // iOS target: we skip all files with the "_osx" suffix
+ if (name.length() > 4 && name.substr(name.length() - 4) == "_osx") {
+ 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/";
+ static const std::string doublebufferdl_directory = "/doublebuffersdl/";
+ if (fileID.find(sdl_directory) != std::string::npos
+ || fileID.find(surfacesdl_directory) != std::string::npos
+ || fileID.find(doublebufferdl_directory) != std::string::npos) {
+ return true;
+ }
+ if (ext == "icns") {
+ return true;
+ }
+ }
+ else {
+ // Ugly hack: explicitly remove the browser.cpp file.
+ // The problem is that we have only one project for two different targets,
+ // and the parsing of the "mk" files added this file for both targets...
+ if (fileID.length() > 12 && fileID.substr(fileID.length() - 12) == "/browser.cpp") {
+ return true;
+ }
+ // OS X target: we skip all files with the "_ios" suffix
+ if (name.length() > 4 && name.substr(name.length() - 4) == "_ios") {
+ return true;
+ }
+ // parent directory
+ const std::string directory = fileID.substr(0, fileID.length() - fileName.length());
+ static const std::string iphone_directory = "backends/platform/ios7";
+ if (directory.length() > iphone_directory.length() && directory.substr(directory.length() - iphone_directory.length()) == iphone_directory) {
+ return true;
+ }
+ }
+ return false;
+}
+
XcodeProvider::Group::Group(XcodeProvider *objectParent, const std::string &groupName, const std::string &uniqueName, const std::string &path) : Object(objectParent, uniqueName, groupName, "PBXGroup", "", groupName) {
+ bool path_is_absolute = (path.length() > 0 && path.at(0) == '/');
addProperty("name", _name, "", kSettingsNoValue | kSettingsQuoteVariable);
- addProperty("sourceTree", "<group>", "", kSettingsNoValue | kSettingsQuoteVariable);
+ addProperty("sourceTree", path_is_absolute ? "<absolute>" : "<group>", "", kSettingsNoValue | kSettingsQuoteVariable);
if (path != "") {
addProperty("path", path, "", kSettingsNoValue | kSettingsQuoteVariable);
@@ -93,7 +163,7 @@ XcodeProvider::Group::Group(XcodeProvider *objectParent, const std::string &grou
}
void XcodeProvider::Group::ensureChildExists(const std::string &name) {
- std::map<std::string, Group *>::iterator it = _childGroups.find(name);
+ std::map<std::string, Group*>::iterator it = _childGroups.find(name);
if (it == _childGroups.end()) {
Group *child = new Group(_parent, name, this->_treeName + '/' + name, name);
_childGroups[name] = child;
@@ -180,7 +250,7 @@ void XcodeProvider::addFileReference(const std::string &id, const std::string &n
void XcodeProvider::addProductFileReference(const std::string &id, const std::string &name) {
Object *fileRef = new Object(this, id, name, "PBXFileReference", "PBXFileReference", name);
- fileRef->addProperty("explicitFileType", "compiled.mach-o.executable", "", kSettingsNoValue | kSettingsQuoteVariable);
+ fileRef->addProperty("explicitFileType", "wrapper.application", "", kSettingsNoValue | kSettingsQuoteVariable);
fileRef->addProperty("includeInIndex", "0", "", kSettingsNoValue);
fileRef->addProperty("path", name, "", kSettingsNoValue | kSettingsQuoteVariable);
fileRef->addProperty("sourceTree", "BUILT_PRODUCTS_DIR", "", kSettingsNoValue);
@@ -201,6 +271,18 @@ XcodeProvider::XcodeProvider(StringList &global_warnings, std::map<std::string,
_rootSourceGroup = NULL;
}
+void XcodeProvider::addResourceFiles(const BuildSetup &setup, StringList &includeList, StringList &excludeList) {
+ includeList.push_back(setup.srcDir + "/dists/ios7/Info.plist");
+
+ ValueList &resources = getResourceFiles();
+ for (ValueList::iterator it = resources.begin(); it != resources.end(); ++it) {
+ includeList.push_back(setup.srcDir + "/" + *it);
+ }
+
+ StringList td;
+ createModuleList(setup.srcDir + "/backends/platform/ios7", setup.defines, td, includeList, excludeList);
+}
+
void XcodeProvider::createWorkspace(const BuildSetup &setup) {
// Create project folder
std::string workspace = setup.outputDir + '/' + PROJECT_NAME ".xcodeproj";
@@ -210,19 +292,15 @@ void XcodeProvider::createWorkspace(const BuildSetup &setup) {
// Setup global objects
setupDefines(setup);
-#ifdef ENABLE_IOS
- _targets.push_back(PROJECT_DESCRIPTION "-iPhone");
-#endif
+ _targets.push_back(PROJECT_DESCRIPTION "-iOS");
_targets.push_back(PROJECT_DESCRIPTION "-OS X");
-#ifdef ENABLE_IOS
- _targets.push_back(PROJECT_DESCRIPTION "-Simulator");
-#endif
setupCopyFilesBuildPhase();
- setupFrameworksBuildPhase();
+ setupFrameworksBuildPhase(setup);
setupNativeTarget();
setupProject();
setupResourcesBuildPhase();
- setupBuildConfiguration();
+ setupBuildConfiguration(setup);
+ setupImageAssetCatalog(setup);
}
// We are done with constructing all the object graph and we got through every project, output the main project file
@@ -323,15 +401,21 @@ void XcodeProvider::setupCopyFilesBuildPhase() {
#define DEF_SYSFRAMEWORK(framework) properties[framework".framework"] = FileProperty("wrapper.framework", framework".framework", "System/Library/Frameworks/" framework ".framework", "SDKROOT"); \
ADD_SETTING_ORDER_NOVALUE(children, getHash(framework".framework"), framework".framework", fwOrder++);
-#define DEF_LOCALLIB_STATIC(lib) properties[lib".a"] = FileProperty("archive.ar", lib".a", "/opt/local/lib/" lib ".a", "\"<group>\""); \
+#define DEF_SYSTBD(lib) properties[lib".tbd"] = FileProperty("sourcecode.text-based-dylib-definition", lib".tbd", "usr/lib/" lib ".tbd", "SDKROOT"); \
+ ADD_SETTING_ORDER_NOVALUE(children, getHash(lib".tbd"), lib".tbd", fwOrder++);
+
+#define DEF_LOCALLIB_STATIC_PATH(path,lib,absolute) properties[lib".a"] = FileProperty("archive.ar", lib ".a", path, (absolute ? "\"<absolute>\"" : "\"<group>\"")); \
ADD_SETTING_ORDER_NOVALUE(children, getHash(lib".a"), lib".a", fwOrder++);
+#define DEF_LOCALLIB_STATIC(lib) DEF_LOCALLIB_STATIC_PATH("/opt/local/lib/" lib ".a", lib, true)
+
+
/**
* Sets up the frameworks build phase.
*
* (each native target has different build rules)
*/
-void XcodeProvider::setupFrameworksBuildPhase() {
+void XcodeProvider::setupFrameworksBuildPhase(const BuildSetup &setup) {
_frameworksBuildPhase._comment = "PBXFrameworksBuildPhase";
// Just use a hardcoded id for the Frameworks-group
@@ -351,6 +435,8 @@ void XcodeProvider::setupFrameworksBuildPhase() {
DEF_SYSFRAMEWORK("Carbon");
DEF_SYSFRAMEWORK("Cocoa");
DEF_SYSFRAMEWORK("CoreAudio");
+ DEF_SYSFRAMEWORK("CoreMIDI");
+ DEF_SYSFRAMEWORK("CoreGraphics");
DEF_SYSFRAMEWORK("CoreFoundation");
DEF_SYSFRAMEWORK("CoreMIDI");
DEF_SYSFRAMEWORK("Foundation");
@@ -359,6 +445,8 @@ void XcodeProvider::setupFrameworksBuildPhase() {
DEF_SYSFRAMEWORK("QuartzCore");
DEF_SYSFRAMEWORK("QuickTime");
DEF_SYSFRAMEWORK("UIKit");
+ DEF_SYSTBD("libiconv");
+
// Optionals:
DEF_SYSFRAMEWORK("OpenGL");
@@ -369,53 +457,92 @@ void XcodeProvider::setupFrameworksBuildPhase() {
DEF_LOCALLIB_STATIC("libfreetype");
// DEF_LOCALLIB_STATIC("libmpeg2");
+ std::string absoluteOutputDir;
+#ifdef POSIX
+ char *c_path = realpath(setup.outputDir.c_str(), NULL);
+ absoluteOutputDir = c_path;
+ absoluteOutputDir += "/lib";
+ free(c_path);
+#else
+ absoluteOutputDir = "lib";
+#endif
+
+ DEF_LOCALLIB_STATIC_PATH(absoluteOutputDir + "/libFLACiOS.a", "libFLACiOS", true);
+ DEF_LOCALLIB_STATIC_PATH(absoluteOutputDir + "/libFreetype2.a", "libFreetype2", true);
+ DEF_LOCALLIB_STATIC_PATH(absoluteOutputDir + "/libogg.a", "libogg", true);
+ DEF_LOCALLIB_STATIC_PATH(absoluteOutputDir + "/libpng.a", "libpng", true);
+ DEF_LOCALLIB_STATIC_PATH(absoluteOutputDir + "/libvorbis.a", "libvorbis", true);
+ DEF_LOCALLIB_STATIC_PATH(absoluteOutputDir + "/libmad.a", "libmad", true);
+ DEF_LOCALLIB_STATIC_PATH(absoluteOutputDir + "/libfluidsynth.a", "libfluidsynth", true);
+ DEF_LOCALLIB_STATIC_PATH(absoluteOutputDir + "/libglib.a", "libglib", true);
+
frameworksGroup->_properties["children"] = children;
_groups.add(frameworksGroup);
// Force this to be added as a sub-group in the root.
_rootSourceGroup->addChildGroup(frameworksGroup);
- // Declare this here, as it's used across the three targets
+ // Declare this here, as it's used across all the targets
int order = 0;
-#ifdef ENABLE_IOS
+
//////////////////////////////////////////////////////////////////////////
- // iPhone
+ // ScummVM-iOS
Object *framework_iPhone = new Object(this, "PBXFrameworksBuildPhase_" + _targets[IOS_TARGET], "PBXFrameworksBuildPhase", "PBXFrameworksBuildPhase", "", "Frameworks");
framework_iPhone->addProperty("buildActionMask", "2147483647", "", kSettingsNoValue);
framework_iPhone->addProperty("runOnlyForDeploymentPostprocessing", "0", "", kSettingsNoValue);
// List of frameworks
- Property iPhone_files;
- iPhone_files._hasOrder = true;
- iPhone_files._flags = kSettingsAsList;
-
- ValueList frameworks_iPhone;
- frameworks_iPhone.push_back("CoreAudio.framework");
- frameworks_iPhone.push_back("CoreFoundation.framework");
- frameworks_iPhone.push_back("Foundation.framework");
- frameworks_iPhone.push_back("UIKit.framework");
- frameworks_iPhone.push_back("AudioToolbox.framework");
- frameworks_iPhone.push_back("QuartzCore.framework");
- frameworks_iPhone.push_back("libmad.a");
- //frameworks_iPhone.push_back("libmpeg2.a");
- frameworks_iPhone.push_back("libFLAC.a");
- frameworks_iPhone.push_back("libvorbisidec.a");
- frameworks_iPhone.push_back("OpenGLES.framework");
-
- for (ValueList::iterator framework = frameworks_iPhone.begin(); framework != frameworks_iPhone.end(); framework++) {
+ Property iOS_files;
+ iOS_files._hasOrder = true;
+ iOS_files._flags = kSettingsAsList;
+
+ ValueList frameworks_iOS;
+ frameworks_iOS.push_back("CoreAudio.framework");
+ frameworks_iOS.push_back("CoreGraphics.framework");
+ frameworks_iOS.push_back("CoreFoundation.framework");
+ frameworks_iOS.push_back("Foundation.framework");
+ frameworks_iOS.push_back("UIKit.framework");
+ frameworks_iOS.push_back("AudioToolbox.framework");
+ frameworks_iOS.push_back("QuartzCore.framework");
+ frameworks_iOS.push_back("OpenGLES.framework");
+
+ if (CONTAINS_DEFINE(setup.defines, "USE_FLAC")) {
+ frameworks_iOS.push_back("libFLACiOS.a");
+ }
+ if (CONTAINS_DEFINE(setup.defines, "USE_FREETYPE2")) {
+ frameworks_iOS.push_back("libFreetype2.a");
+ }
+ if (CONTAINS_DEFINE(setup.defines, "USE_PNG")) {
+ frameworks_iOS.push_back("libpng.a");
+ }
+ if (CONTAINS_DEFINE(setup.defines, "USE_VORBIS")) {
+ frameworks_iOS.push_back("libogg.a");
+ frameworks_iOS.push_back("libvorbis.a");
+ }
+ if (CONTAINS_DEFINE(setup.defines, "USE_MAD")) {
+ frameworks_iOS.push_back("libmad.a");
+ }
+ if (CONTAINS_DEFINE(setup.defines, "USE_FLUIDSYNTH")) {
+ frameworks_iOS.push_back("libfluidsynth.a");
+ frameworks_iOS.push_back("libglib.a");
+ frameworks_iOS.push_back("CoreMIDI.framework");
+ frameworks_iOS.push_back("libiconv.tbd");
+ }
+
+ for (ValueList::iterator framework = frameworks_iOS.begin(); framework != frameworks_iOS.end(); framework++) {
std::string id = "Frameworks_" + *framework + "_iphone";
std::string comment = *framework + " in Frameworks";
- ADD_SETTING_ORDER_NOVALUE(iPhone_files, getHash(id), comment, order++);
+ ADD_SETTING_ORDER_NOVALUE(iOS_files, getHash(id), comment, order++);
ADD_BUILD_FILE(id, *framework, getHash(*framework), comment);
- addFileReference(*framework, *framework, properties[*framework]);
+ ADD_FILE_REFERENCE(*framework, *framework, properties[*framework]);
}
- framework_iPhone->_properties["files"] = iPhone_files;
+ framework_iPhone->_properties["files"] = iOS_files;
_frameworksBuildPhase.add(framework_iPhone);
-#endif
+
//////////////////////////////////////////////////////////////////////////
// ScummVM-OS X
Object *framework_OSX = new Object(this, "PBXFrameworksBuildPhase_" + _targets[OSX_TARGET], "PBXFrameworksBuildPhase", "PBXFrameworksBuildPhase", "", "Frameworks");
@@ -451,48 +578,12 @@ void XcodeProvider::setupFrameworksBuildPhase() {
ADD_SETTING_ORDER_NOVALUE(osx_files, getHash(id), comment, order++);
ADD_BUILD_FILE(id, *framework, getHash(*framework), comment);
- addFileReference(*framework, *framework, properties[*framework]);
+ ADD_FILE_REFERENCE(*framework, *framework, properties[*framework]);
}
framework_OSX->_properties["files"] = osx_files;
_frameworksBuildPhase.add(framework_OSX);
-#ifdef ENABLE_IOS
- //////////////////////////////////////////////////////////////////////////
- // Simulator
- Object *framework_simulator = new Object(this, "PBXFrameworksBuildPhase_" + _targets[SIM_TARGET], "PBXFrameworksBuildPhase", "PBXFrameworksBuildPhase", "", "Frameworks");
-
- framework_simulator->addProperty("buildActionMask", "2147483647", "", kSettingsNoValue);
- framework_simulator->addProperty("runOnlyForDeploymentPostprocessing", "0", "", kSettingsNoValue);
-
- // List of frameworks
- Property simulator_files;
- simulator_files._hasOrder = true;
- simulator_files._flags = kSettingsAsList;
-
- ValueList frameworks_simulator;
- frameworks_simulator.push_back("CoreAudio.framework");
- frameworks_simulator.push_back("CoreFoundation.framework");
- frameworks_simulator.push_back("Foundation.framework");
- frameworks_simulator.push_back("UIKit.framework");
- frameworks_simulator.push_back("AudioToolbox.framework");
- frameworks_simulator.push_back("QuartzCore.framework");
- frameworks_simulator.push_back("OpenGLES.framework");
-
- order = 0;
- for (ValueList::iterator framework = frameworks_simulator.begin(); framework != frameworks_simulator.end(); framework++) {
- std::string id = "Frameworks_" + *framework + "_simulator";
- std::string comment = *framework + " in Frameworks";
-
- ADD_SETTING_ORDER_NOVALUE(simulator_files, getHash(id), comment, order++);
- ADD_BUILD_FILE(id, *framework, getHash(*framework), comment);
- addFileReference(*framework, *framework, properties[*framework]);
- }
-
- framework_simulator->_properties["files"] = simulator_files;
-
- _frameworksBuildPhase.add(framework_simulator);
-#endif
}
void XcodeProvider::setupNativeTarget() {
@@ -502,11 +593,6 @@ void XcodeProvider::setupNativeTarget() {
Group *productsGroup = new Group(this, "Products", "PBXGroup_CustomTemplate_Products_" , "");
// Output native target section
for (unsigned int i = 0; i < _targets.size(); i++) {
-#ifndef ENABLE_IOS
- if (i != OSX_TARGET) { // TODO: Fix iOS-targets, for now just disable them.
- continue;
- }
-#endif
Object *target = new Object(this, "PBXNativeTarget_" + _targets[i], "PBXNativeTarget", "PBXNativeTarget", "", _targets[i]);
target->addProperty("buildConfigurationList", getHash("XCConfigurationList_" + _targets[i]), "Build configuration list for PBXNativeTarget \"" + _targets[i] + "\"", kSettingsNoValue);
@@ -556,49 +642,51 @@ void XcodeProvider::setupProject() {
project->_properties["knownRegions"] = regions;
project->addProperty("mainGroup", _rootSourceGroup->getHashRef(), "CustomTemplate", kSettingsNoValue);
+ project->addProperty("productRefGroup", getHash("PBXGroup_CustomTemplate_Products_"), "" , kSettingsNoValue);
project->addProperty("projectDirPath", _projectRoot, "", kSettingsNoValue | kSettingsQuoteVariable);
project->addProperty("projectRoot", "", "", kSettingsNoValue | kSettingsQuoteVariable);
// List of targets
Property targets;
targets._flags = kSettingsAsList;
-#ifdef ENABLE_IOS
targets._settings[getHash("PBXNativeTarget_" + _targets[IOS_TARGET])] = Setting("", _targets[IOS_TARGET], kSettingsNoValue, 0, 0);
-#endif
targets._settings[getHash("PBXNativeTarget_" + _targets[OSX_TARGET])] = Setting("", _targets[OSX_TARGET], kSettingsNoValue, 0, 1);
-#ifdef ENABLE_IOS
- targets._settings[getHash("PBXNativeTarget_" + _targets[SIM_TARGET])] = Setting("", _targets[SIM_TARGET], kSettingsNoValue, 0, 2);
-#endif
project->_properties["targets"] = targets;
-#ifndef ENABLE_IOS
+
// Force list even when there is only a single target
project->_properties["targets"]._flags |= kSettingsSingleItem;
-#endif
_project.add(project);
}
+XcodeProvider::ValueList& XcodeProvider::getResourceFiles() const {
+ static ValueList files;
+ if (files.empty()) {
+ files.push_back("gui/themes/scummclassic.zip");
+ files.push_back("gui/themes/scummmodern.zip");
+ files.push_back("gui/themes/translations.dat");
+ files.push_back("dists/engine-data/drascula.dat");
+ files.push_back("dists/engine-data/hugo.dat");
+ files.push_back("dists/engine-data/kyra.dat");
+ files.push_back("dists/engine-data/lure.dat");
+ files.push_back("dists/engine-data/mort.dat");
+ files.push_back("dists/engine-data/neverhood.dat");
+ files.push_back("dists/engine-data/queen.tbl");
+ files.push_back("dists/engine-data/sky.cpt");
+ files.push_back("dists/engine-data/teenagent.dat");
+ files.push_back("dists/engine-data/tony.dat");
+ files.push_back("dists/engine-data/toon.dat");
+ files.push_back("dists/engine-data/wintermute.zip");
+ files.push_back("dists/pred.dic");
+ files.push_back("icons/scummvm.icns");
+ }
+ return files;
+}
+
void XcodeProvider::setupResourcesBuildPhase() {
_resourcesBuildPhase._comment = "PBXResourcesBuildPhase";
- // Setup resource file properties
- std::map<std::string, FileProperty> properties;
- properties["scummclassic.zip"] = FileProperty("archive.zip", "", "scummclassic.zip", "\"<group>\"");
- properties["scummmodern.zip"] = FileProperty("archive.zip", "", "scummmodern.zip", "\"<group>\"");
-
- properties["kyra.dat"] = FileProperty("file", "", "kyra.dat", "\"<group>\"");
- properties["lure.dat"] = FileProperty("file", "", "lure.dat", "\"<group>\"");
- properties["queen.tbl"] = FileProperty("file", "", "queen.tbl", "\"<group>\"");
- properties["sky.cpt"] = FileProperty("file", "", "sky.cpt", "\"<group>\"");
- properties["drascula.dat"] = FileProperty("file", "", "drascula.dat", "\"<group>\"");
- properties["hugo.dat"] = FileProperty("file", "", "hugo.dat", "\"<group>\"");
- properties["teenagent.dat"] = FileProperty("file", "", "teenagent.dat", "\"<group>\"");
- properties["toon.dat"] = FileProperty("file", "", "toon.dat", "\"<group>\"");
-
- properties["Default.png"] = FileProperty("image.png", "", "Default.png", "\"<group>\"");
- properties["icon.png"] = FileProperty("image.png", "", "icon.png", "\"<group>\"");
- properties["icon-72.png"] = FileProperty("image.png", "", "icon-72.png", "\"<group>\"");
- properties["icon4.png"] = FileProperty("image.png", "", "icon4.png", "\"<group>\"");
+ ValueList &files_list = getResourceFiles();
// Same as for containers: a rule for each native target
for (unsigned int i = 0; i < _targets.size(); i++) {
@@ -611,40 +699,17 @@ void XcodeProvider::setupResourcesBuildPhase() {
files._hasOrder = true;
files._flags = kSettingsAsList;
- ValueList files_list;
- files_list.push_back("scummclassic.zip");
- files_list.push_back("scummmodern.zip");
- files_list.push_back("kyra.dat");
- files_list.push_back("lure.dat");
- files_list.push_back("queen.tbl");
- files_list.push_back("sky.cpt");
- files_list.push_back("Default.png");
- files_list.push_back("icon.png");
- files_list.push_back("icon-72.png");
- files_list.push_back("icon4.png");
- files_list.push_back("drascula.dat");
- files_list.push_back("hugo.dat");
- files_list.push_back("teenagent.dat");
- files_list.push_back("toon.dat");
-
int order = 0;
for (ValueList::iterator file = files_list.begin(); file != files_list.end(); file++) {
- std::string id = "PBXResources_" + *file;
- std::string comment = *file + " in Resources";
-
- ADD_SETTING_ORDER_NOVALUE(files, getHash(id), comment, order++);
- // TODO Fix crash when adding build file for data
- //ADD_BUILD_FILE(id, *file, comment);
- addFileReference(*file, *file, properties[*file]);
- }
-
- // Add custom files depending on the target
- if (_targets[i] == PROJECT_DESCRIPTION "-OS X") {
- files._settings[getHash("PBXResources_" PROJECT_NAME ".icns")] = Setting("", PROJECT_NAME ".icns in Resources", kSettingsNoValue, 0, 6);
-
- // Remove 2 iphone icon files
- files._settings.erase(getHash("PBXResources_Default.png"));
- files._settings.erase(getHash("PBXResources_icon.png"));
+ if (shouldSkipFileForTarget(*file, _targets[i], *file)) {
+ continue;
+ }
+ std::string resourceAbsolutePath = _projectRoot + "/" + *file;
+ std::string file_id = "FileReference_" + resourceAbsolutePath;
+ std::string base = basename(*file);
+ std::string comment = base + " in Resources";
+ addBuildFile(resourceAbsolutePath, base, getHash(file_id), comment);
+ ADD_SETTING_ORDER_NOVALUE(files, getHash(resourceAbsolutePath), comment, order++);
}
resource->_properties["files"] = files;
@@ -658,11 +723,9 @@ void XcodeProvider::setupResourcesBuildPhase() {
void XcodeProvider::setupSourcesBuildPhase() {
_sourcesBuildPhase._comment = "PBXSourcesBuildPhase";
- // Setup source file properties
- std::map<std::string, FileProperty> properties;
-
// Same as for containers: a rule for each native target
for (unsigned int i = 0; i < _targets.size(); i++) {
+ const std::string &targetName = _targets[i];
Object *source = new Object(this, "PBXSourcesBuildPhase_" + _targets[i], "PBXSourcesBuildPhase", "PBXSourcesBuildPhase", "", "Sources");
source->addProperty("buildActionMask", "2147483647", "", kSettingsNoValue);
@@ -673,13 +736,19 @@ void XcodeProvider::setupSourcesBuildPhase() {
int order = 0;
for (std::vector<Object *>::iterator file = _buildFile._objects.begin(); file != _buildFile._objects.end(); ++file) {
- if (!producesObjectFileOnOSX((*file)->_name)) {
+ const std::string &fileName = (*file)->_name;
+ if (shouldSkipFileForTarget((*file)->_id, targetName, fileName)) {
+ continue;
+ }
+ if (!producesObjectFileOnOSX(fileName)) {
continue;
}
- std::string comment = (*file)->_name + " in Sources";
+ std::string comment = fileName + " in Sources";
ADD_SETTING_ORDER_NOVALUE(files, getHash((*file)->_id), comment, order++);
}
+ setupAdditionalSources(targetName, files, order);
+
source->_properties["files"] = files;
source->addProperty("runOnlyForDeploymentPostprocessing", "0", "", kSettingsNoValue);
@@ -689,73 +758,20 @@ void XcodeProvider::setupSourcesBuildPhase() {
}
// Setup all build configurations
-void XcodeProvider::setupBuildConfiguration() {
+void XcodeProvider::setupBuildConfiguration(const BuildSetup &setup) {
_buildConfiguration._comment = "XCBuildConfiguration";
_buildConfiguration._flags = kSettingsAsList;
- ///****************************************
- // * iPhone
- // ****************************************/
-#ifdef ENABLE_IOS
- // Debug
- Object *iPhone_Debug_Object = new Object(this, "XCBuildConfiguration_" PROJECT_DESCRIPTION "-iPhone_Debug", _targets[IOS_TARGET] /* ScummVM-iPhone */, "XCBuildConfiguration", "PBXNativeTarget", "Debug");
- Property iPhone_Debug;
- ADD_SETTING_QUOTE(iPhone_Debug, "ARCHS", "$(ARCHS_UNIVERSAL_IPHONE_OS)");
- ADD_SETTING_QUOTE(iPhone_Debug, "CODE_SIGN_IDENTITY", "iPhone Developer");
- ADD_SETTING_QUOTE_VAR(iPhone_Debug, "CODE_SIGN_IDENTITY[sdk=iphoneos*]", "iPhone Developer");
- ADD_SETTING(iPhone_Debug, "COMPRESS_PNG_FILES", "NO");
- ADD_SETTING(iPhone_Debug, "COPY_PHASE_STRIP", "NO");
- ADD_SETTING_QUOTE(iPhone_Debug, "DEBUG_INFORMATION_FORMAT", "dwarf-with-dsym");
- ValueList iPhone_FrameworkSearchPaths;
- iPhone_FrameworkSearchPaths.push_back("$(inherited)");
- iPhone_FrameworkSearchPaths.push_back("\"$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks\"");
- ADD_SETTING_LIST(iPhone_Debug, "FRAMEWORK_SEARCH_PATHS", iPhone_FrameworkSearchPaths, kSettingsAsList, 5);
- ADD_SETTING(iPhone_Debug, "GCC_DYNAMIC_NO_PIC", "NO");
- ADD_SETTING(iPhone_Debug, "GCC_ENABLE_CPP_EXCEPTIONS", "NO");
- ADD_SETTING(iPhone_Debug, "GCC_ENABLE_FIX_AND_CONTINUE", "NO");
- ADD_SETTING(iPhone_Debug, "GCC_OPTIMIZATION_LEVEL", "0");
- ADD_SETTING(iPhone_Debug, "GCC_PRECOMPILE_PREFIX_HEADER", "NO");
- ADD_SETTING_QUOTE(iPhone_Debug, "GCC_PREFIX_HEADER", "");
- ADD_SETTING(iPhone_Debug, "GCC_THUMB_SUPPORT", "NO");
- ADD_SETTING(iPhone_Debug, "GCC_UNROLL_LOOPS", "YES");
- ValueList iPhone_HeaderSearchPaths;
- iPhone_HeaderSearchPaths.push_back("$(SRCROOT)/engines/");
- iPhone_HeaderSearchPaths.push_back("$(SRCROOT)");
- iPhone_HeaderSearchPaths.push_back("include/");
- ADD_SETTING_LIST(iPhone_Debug, "HEADER_SEARCH_PATHS", iPhone_HeaderSearchPaths, kSettingsAsList | kSettingsQuoteVariable, 5);
- ADD_SETTING(iPhone_Debug, "INFOPLIST_FILE", "Info.plist");
- ValueList iPhone_LibPaths;
- iPhone_LibPaths.push_back("$(inherited)");
- iPhone_LibPaths.push_back("\"$(SRCROOT)/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, "PREBINDING", "NO");
- ADD_SETTING(iPhone_Debug, "PRODUCT_NAME", PROJECT_DESCRIPTION);
- ADD_SETTING_QUOTE(iPhone_Debug, "PROVISIONING_PROFILE", "EF590570-5FAC-4346-9071-D609DE2B28D8");
- ADD_SETTING_QUOTE_VAR(iPhone_Debug, "PROVISIONING_PROFILE[sdk=iphoneos*]", "");
- ADD_SETTING(iPhone_Debug, "SDKROOT", "iphoneos4.0");
- ADD_SETTING_QUOTE(iPhone_Debug, "TARGETED_DEVICE_FAMILY", "1,2");
-
- iPhone_Debug_Object->addProperty("name", "Debug", "", kSettingsNoValue);
- iPhone_Debug_Object->_properties["buildSettings"] = iPhone_Debug;
-
- // Release
- Object *iPhone_Release_Object = new Object(this, "XCBuildConfiguration_" PROJECT_DESCRIPTION "-iPhone_Release", _targets[IOS_TARGET] /* ScummVM-iPhone */, "XCBuildConfiguration", "PBXNativeTarget", "Release");
- Property iPhone_Release(iPhone_Debug);
- ADD_SETTING(iPhone_Release, "GCC_OPTIMIZATION_LEVEL", "3");
- ADD_SETTING(iPhone_Release, "COPY_PHASE_STRIP", "YES");
- REMOVE_SETTING(iPhone_Release, "GCC_DYNAMIC_NO_PIC");
- ADD_SETTING(iPhone_Release, "WRAPPER_EXTENSION", "app");
-
- iPhone_Release_Object->addProperty("name", "Release", "", kSettingsNoValue);
- iPhone_Release_Object->_properties["buildSettings"] = iPhone_Release;
-
- _buildConfiguration.add(iPhone_Debug_Object);
- _buildConfiguration.add(iPhone_Release_Object);
+ std::string projectOutputDirectory;
+#ifdef POSIX
+ char *rp = realpath(setup.outputDir.c_str(), NULL);
+ projectOutputDirectory = rp;
+ free(rp);
#endif
+
/****************************************
- * scummvm
+ * ScummVM - Project Level
****************************************/
// Debug
@@ -763,7 +779,6 @@ void XcodeProvider::setupBuildConfiguration() {
Property scummvm_Debug;
ADD_SETTING(scummvm_Debug, "ALWAYS_SEARCH_USER_PATHS", "NO");
ADD_SETTING_QUOTE(scummvm_Debug, "USER_HEADER_SEARCH_PATHS", "$(SRCROOT) $(SRCROOT)/engines");
- ADD_SETTING_QUOTE(scummvm_Debug, "ARCHS", "$(ARCHS_STANDARD_32_BIT)");
ADD_SETTING_QUOTE(scummvm_Debug, "CODE_SIGN_IDENTITY", "Don't Code Sign");
ADD_SETTING_QUOTE_VAR(scummvm_Debug, "CODE_SIGN_IDENTITY[sdk=iphoneos*]", "Don't Code Sign");
ADD_SETTING_QUOTE(scummvm_Debug, "FRAMEWORK_SEARCH_PATHS", "");
@@ -773,9 +788,11 @@ void XcodeProvider::setupBuildConfiguration() {
ADD_SETTING(scummvm_Debug, "GCC_INPUT_FILETYPE", "automatic");
ADD_SETTING(scummvm_Debug, "GCC_OPTIMIZATION_LEVEL", "0");
ValueList scummvm_defines(_defines);
- ADD_DEFINE(scummvm_defines, "IPHONE");
- ADD_DEFINE(scummvm_defines, "XCODE");
- ADD_DEFINE(scummvm_defines, "IPHONE_OFFICIAL");
+ 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_THUMB_SUPPORT", "NO");
ADD_SETTING(scummvm_Debug, "GCC_USE_GCC3_PFE_SUPPORT", "NO");
@@ -791,7 +808,7 @@ void XcodeProvider::setupBuildConfiguration() {
ADD_SETTING_QUOTE(scummvm_Debug, "OTHER_CFLAGS", "");
ADD_SETTING_QUOTE(scummvm_Debug, "OTHER_LDFLAGS", "-lz");
ADD_SETTING(scummvm_Debug, "PREBINDING", "NO");
- ADD_SETTING(scummvm_Debug, "SDKROOT", "macosx");
+ ADD_SETTING(scummvm_Debug, "ENABLE_TESTABILITY", "YES");
scummvm_Debug_Object->addProperty("name", "Debug", "", kSettingsNoValue);
scummvm_Debug_Object->_properties["buildSettings"] = scummvm_Debug;
@@ -803,6 +820,7 @@ void XcodeProvider::setupBuildConfiguration() {
REMOVE_SETTING(scummvm_Release, "GCC_WARN_ABOUT_RETURN_TYPE");
REMOVE_SETTING(scummvm_Release, "GCC_WARN_UNUSED_VARIABLE");
REMOVE_SETTING(scummvm_Release, "ONLY_ACTIVE_ARCH");
+ REMOVE_SETTING(scummvm_Release, "ENABLE_TESTABILITY");
scummvm_Release_Object->addProperty("name", "Release", "", kSettingsNoValue);
scummvm_Release_Object->_properties["buildSettings"] = scummvm_Release;
@@ -810,17 +828,92 @@ void XcodeProvider::setupBuildConfiguration() {
_buildConfiguration.add(scummvm_Debug_Object);
_buildConfiguration.add(scummvm_Release_Object);
+ ///****************************************
+ // * ScummVM - iOS Target
+ // ****************************************/
+
+ // Debug
+ Object *iPhone_Debug_Object = new Object(this, "XCBuildConfiguration_" PROJECT_DESCRIPTION "-iPhone_Debug", _targets[IOS_TARGET] /* ScummVM-iPhone */, "XCBuildConfiguration", "PBXNativeTarget", "Debug");
+ Property iPhone_Debug;
+ ADD_SETTING_QUOTE(iPhone_Debug, "CODE_SIGN_IDENTITY", "iPhone Developer");
+ ADD_SETTING_QUOTE_VAR(iPhone_Debug, "CODE_SIGN_IDENTITY[sdk=iphoneos*]", "iPhone Developer");
+ ADD_SETTING(iPhone_Debug, "COMPRESS_PNG_FILES", "NO");
+ ADD_SETTING(iPhone_Debug, "COPY_PHASE_STRIP", "NO");
+ ADD_SETTING_QUOTE(iPhone_Debug, "DEBUG_INFORMATION_FORMAT", "dwarf");
+ ValueList iPhone_FrameworkSearchPaths;
+ iPhone_FrameworkSearchPaths.push_back("$(inherited)");
+ iPhone_FrameworkSearchPaths.push_back("\"$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks\"");
+ ADD_SETTING_LIST(iPhone_Debug, "FRAMEWORK_SEARCH_PATHS", iPhone_FrameworkSearchPaths, kSettingsAsList, 5);
+ ADD_SETTING(iPhone_Debug, "GCC_DYNAMIC_NO_PIC", "NO");
+ ADD_SETTING(iPhone_Debug, "GCC_ENABLE_CPP_EXCEPTIONS", "NO");
+ ADD_SETTING(iPhone_Debug, "GCC_ENABLE_FIX_AND_CONTINUE", "NO");
+ ADD_SETTING(iPhone_Debug, "GCC_OPTIMIZATION_LEVEL", "0");
+ ADD_SETTING(iPhone_Debug, "GCC_PRECOMPILE_PREFIX_HEADER", "NO");
+ ADD_SETTING(iPhone_Debug, "GCC_WARN_64_TO_32_BIT_CONVERSION", "NO");
+ ADD_SETTING(iPhone_Debug, "WARNING_CFLAGS", "-Wno-multichar");
+ ADD_SETTING_QUOTE(iPhone_Debug, "GCC_PREFIX_HEADER", "");
+ ADD_SETTING(iPhone_Debug, "GCC_THUMB_SUPPORT", "NO");
+ ADD_SETTING(iPhone_Debug, "GCC_UNROLL_LOOPS", "YES");
+ ValueList iPhone_HeaderSearchPaths;
+ iPhone_HeaderSearchPaths.push_back("$(SRCROOT)/engines/");
+ iPhone_HeaderSearchPaths.push_back("$(SRCROOT)");
+ iPhone_HeaderSearchPaths.push_back("\"" + projectOutputDirectory + "\"");
+ iPhone_HeaderSearchPaths.push_back("\"" + projectOutputDirectory + "/include\"");
+ 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");
+ ValueList iPhone_LibPaths;
+ iPhone_LibPaths.push_back("$(inherited)");
+ 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, "PREBINDING", "NO");
+ ADD_SETTING(iPhone_Debug, "PRODUCT_NAME", PROJECT_NAME);
+ ADD_SETTING(iPhone_Debug, "PRODUCT_BUNDLE_IDENTIFIER", "\"org.scummvm.${PRODUCT_NAME}\"");
+ ADD_SETTING(iPhone_Debug, "IPHONEOS_DEPLOYMENT_TARGET", "7.1");
+ //ADD_SETTING_QUOTE(iPhone_Debug, "PROVISIONING_PROFILE", "EF590570-5FAC-4346-9071-D609DE2B28D8");
+ ADD_SETTING_QUOTE_VAR(iPhone_Debug, "PROVISIONING_PROFILE[sdk=iphoneos*]", "");
+ ADD_SETTING(iPhone_Debug, "SDKROOT", "iphoneos");
+ ADD_SETTING_QUOTE(iPhone_Debug, "TARGETED_DEVICE_FAMILY", "1,2");
+ ValueList scummvmIOS_defines;
+ ADD_DEFINE(scummvmIOS_defines, "\"$(inherited)\"");
+ ADD_DEFINE(scummvmIOS_defines, "IPHONE");
+ ADD_DEFINE(scummvmIOS_defines, "IPHONE_IOS7");
+ ADD_DEFINE(scummvmIOS_defines, "IPHONE_SANDBOXED");
+ ADD_SETTING_LIST(iPhone_Debug, "GCC_PREPROCESSOR_DEFINITIONS", scummvmIOS_defines, kSettingsNoQuote | kSettingsAsList, 5);
+ ADD_SETTING(iPhone_Debug, "ASSETCATALOG_COMPILER_APPICON_NAME", "AppIcon");
+ ADD_SETTING(iPhone_Debug, "ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME", "LaunchImage");
+
+ iPhone_Debug_Object->addProperty("name", "Debug", "", kSettingsNoValue);
+ iPhone_Debug_Object->_properties["buildSettings"] = iPhone_Debug;
+
+ // Release
+ Object *iPhone_Release_Object = new Object(this, "XCBuildConfiguration_" PROJECT_DESCRIPTION "-iPhone_Release", _targets[IOS_TARGET] /* ScummVM-iPhone */, "XCBuildConfiguration", "PBXNativeTarget", "Release");
+ Property iPhone_Release(iPhone_Debug);
+ ADD_SETTING(iPhone_Release, "GCC_OPTIMIZATION_LEVEL", "3");
+ ADD_SETTING(iPhone_Release, "COPY_PHASE_STRIP", "YES");
+ REMOVE_SETTING(iPhone_Release, "GCC_DYNAMIC_NO_PIC");
+ ADD_SETTING(iPhone_Release, "WRAPPER_EXTENSION", "app");
+ REMOVE_SETTING(iPhone_Release, "DEBUG_INFORMATION_FORMAT");
+ ADD_SETTING_QUOTE(iPhone_Release, "DEBUG_INFORMATION_FORMAT", "dwarf-with-dsym");
+
+ iPhone_Release_Object->addProperty("name", "Release", "", kSettingsNoValue);
+ iPhone_Release_Object->_properties["buildSettings"] = iPhone_Release;
+
+ _buildConfiguration.add(iPhone_Debug_Object);
+ _buildConfiguration.add(iPhone_Release_Object);
+
/****************************************
- * ScummVM-OS X
+ * ScummVM - OS X Target
****************************************/
// Debug
Object *scummvmOSX_Debug_Object = new Object(this, "XCBuildConfiguration_" PROJECT_DESCRIPTION "-OSX_Debug", _targets[OSX_TARGET] /* ScummVM-OS X */, "XCBuildConfiguration", "PBXNativeTarget", "Debug");
Property scummvmOSX_Debug;
- ADD_SETTING_QUOTE(scummvmOSX_Debug, "ARCHS", "$(NATIVE_ARCH)");
+ ADD_SETTING(scummvmOSX_Debug, "COMBINE_HIDPI_IMAGES", "YES");
+ ADD_SETTING(scummvmOSX_Debug, "SDKROOT", "macosx");
ADD_SETTING(scummvmOSX_Debug, "COMPRESS_PNG_FILES", "NO");
ADD_SETTING(scummvmOSX_Debug, "COPY_PHASE_STRIP", "NO");
- ADD_SETTING_QUOTE(scummvmOSX_Debug, "DEBUG_INFORMATION_FORMAT", "dwarf-with-dsym");
+ ADD_SETTING_QUOTE(scummvmOSX_Debug, "DEBUG_INFORMATION_FORMAT", "dwarf");
ADD_SETTING_QUOTE(scummvmOSX_Debug, "FRAMEWORK_SEARCH_PATHS", "");
ADD_SETTING(scummvmOSX_Debug, "GCC_C_LANGUAGE_STANDARD", "c99");
ADD_SETTING(scummvmOSX_Debug, "GCC_ENABLE_CPP_EXCEPTIONS", "NO");
@@ -830,7 +923,8 @@ void XcodeProvider::setupBuildConfiguration() {
ADD_SETTING(scummvmOSX_Debug, "GCC_OPTIMIZATION_LEVEL", "0");
ADD_SETTING(scummvmOSX_Debug, "GCC_PRECOMPILE_PREFIX_HEADER", "NO");
ADD_SETTING_QUOTE(scummvmOSX_Debug, "GCC_PREFIX_HEADER", "");
- ValueList scummvmOSX_defines(_defines);
+ ValueList scummvmOSX_defines;
+ ADD_DEFINE(scummvmOSX_defines, "\"$(inherited)\"");
ADD_DEFINE(scummvmOSX_defines, "SDL_BACKEND");
ADD_DEFINE(scummvmOSX_defines, "MACOSX");
ADD_SETTING_LIST(scummvmOSX_Debug, "GCC_PREPROCESSOR_DEFINITIONS", scummvmOSX_defines, kSettingsNoQuote | kSettingsAsList, 5);
@@ -866,7 +960,7 @@ void XcodeProvider::setupBuildConfiguration() {
scummvmOSX_LdFlags.push_back("-lz");
ADD_SETTING_LIST(scummvmOSX_Debug, "OTHER_LDFLAGS", scummvmOSX_LdFlags, kSettingsAsList, 5);
ADD_SETTING(scummvmOSX_Debug, "PREBINDING", "NO");
- ADD_SETTING(scummvmOSX_Debug, "PRODUCT_NAME", PROJECT_DESCRIPTION);
+ ADD_SETTING(scummvmOSX_Debug, "PRODUCT_NAME", PROJECT_NAME);
scummvmOSX_Debug_Object->addProperty("name", "Debug", "", kSettingsNoValue);
scummvmOSX_Debug_Object->_properties["buildSettings"] = scummvmOSX_Debug;
@@ -878,48 +972,15 @@ void XcodeProvider::setupBuildConfiguration() {
REMOVE_SETTING(scummvmOSX_Release, "GCC_DYNAMIC_NO_PIC");
REMOVE_SETTING(scummvmOSX_Release, "GCC_OPTIMIZATION_LEVEL");
ADD_SETTING(scummvmOSX_Release, "WRAPPER_EXTENSION", "app");
+ REMOVE_SETTING(scummvmOSX_Release, "DEBUG_INFORMATION_FORMAT");
+ ADD_SETTING_QUOTE(scummvmOSX_Release, "DEBUG_INFORMATION_FORMAT", "dwarf-with-dsym");
scummvmOSX_Release_Object->addProperty("name", "Release", "", kSettingsNoValue);
scummvmOSX_Release_Object->_properties["buildSettings"] = scummvmOSX_Release;
_buildConfiguration.add(scummvmOSX_Debug_Object);
_buildConfiguration.add(scummvmOSX_Release_Object);
-#ifdef ENABLE_IOS
- /****************************************
- * ScummVM-Simulator
- ****************************************/
- // Debug
- Object *scummvmSimulator_Debug_Object = new Object(this, "XCBuildConfiguration_" PROJECT_DESCRIPTION "-Simulator_Debug", _targets[SIM_TARGET] /* ScummVM-Simulator */, "XCBuildConfiguration", "PBXNativeTarget", "Debug");
- Property scummvmSimulator_Debug(iPhone_Debug);
- ADD_SETTING_QUOTE(scummvmSimulator_Debug, "FRAMEWORK_SEARCH_PATHS", "$(inherited)");
- ADD_SETTING_LIST(scummvmSimulator_Debug, "GCC_PREPROCESSOR_DEFINITIONS", scummvm_defines, kSettingsNoQuote | kSettingsAsList, 5);
- ADD_SETTING(scummvmSimulator_Debug, "SDKROOT", "iphonesimulator3.2");
- ADD_SETTING_QUOTE(scummvmSimulator_Debug, "VALID_ARCHS", "i386 x86_64");
- REMOVE_SETTING(scummvmSimulator_Debug, "TARGETED_DEVICE_FAMILY");
-
- scummvmSimulator_Debug_Object->addProperty("name", "Debug", "", kSettingsNoValue);
- scummvmSimulator_Debug_Object->_properties["buildSettings"] = scummvmSimulator_Debug;
-
- // Release
- Object *scummvmSimulator_Release_Object = new Object(this, "XCBuildConfiguration_" PROJECT_DESCRIPTION "-Simulator_Release", _targets[SIM_TARGET] /* ScummVM-Simulator */, "XCBuildConfiguration", "PBXNativeTarget", "Release");
- Property scummvmSimulator_Release(scummvmSimulator_Debug);
- ADD_SETTING(scummvmSimulator_Release, "COPY_PHASE_STRIP", "YES");
- ADD_SETTING(scummvmSimulator_Release, "GCC_OPTIMIZATION_LEVEL", "3");
- REMOVE_SETTING(scummvmSimulator_Release, "GCC_DYNAMIC_NO_PIC");
- ADD_SETTING(scummvmSimulator_Release, "WRAPPER_EXTENSION", "app");
-
- scummvmSimulator_Release_Object->addProperty("name", "Release", "", kSettingsNoValue);
- scummvmSimulator_Release_Object->_properties["buildSettings"] = scummvmSimulator_Release;
-
- _buildConfiguration.add(scummvmSimulator_Debug_Object);
- _buildConfiguration.add(scummvmSimulator_Release_Object);
-
- //////////////////////////////////////////////////////////////////////////
- // Configuration List
- _configurationList._comment = "XCConfigurationList";
- _configurationList._flags = kSettingsAsList;
-#endif
// 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++) {
@@ -940,6 +1001,22 @@ void XcodeProvider::setupBuildConfiguration() {
}
}
+void XcodeProvider::setupImageAssetCatalog(const BuildSetup &setup) {
+ const std::string filename = "Images.xcassets";
+ const std::string absoluteCatalogPath = _projectRoot + "/dists/ios7/" + filename;
+ const std::string id = "FileReference_" + absoluteCatalogPath;
+ Group *group = touchGroupsForPath(absoluteCatalogPath);
+ group->addChildFile(filename);
+ addBuildFile(absoluteCatalogPath, filename, getHash(id), "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++);
+ }
+}
+
//////////////////////////////////////////////////////////////////////////
// Misc
//////////////////////////////////////////////////////////////////////////
@@ -954,9 +1031,12 @@ void XcodeProvider::setupDefines(const BuildSetup &setup) {
ADD_DEFINE(_defines, *i);
}
// Add special defines for Mac support
+ 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, "SCUMM_NEED_ALIGNMENT");
- ADD_DEFINE(_defines, "SCUMM_LITTLE_ENDIAN");
ADD_DEFINE(_defines, "UNIX");
ADD_DEFINE(_defines, "SCUMMVM");
}
@@ -965,7 +1045,6 @@ void XcodeProvider::setupDefines(const BuildSetup &setup) {
// Object hash
//////////////////////////////////////////////////////////////////////////
-// TODO use md5 to compute a file hash (and fall back to standard key generation if not passed a file)
std::string XcodeProvider::getHash(std::string key) {
#if DEBUG_XCODE_HASH
@@ -977,7 +1056,12 @@ std::string XcodeProvider::getHash(std::string key) {
return hashIterator->second;
// Generate a new key from the file hash and insert it into the dictionary
+#ifdef MACOSX
+ std::string hash = md5(key);
+#else
std::string hash = newHash();
+#endif
+
_hashDictionnary[key] = hash;
return hash;
@@ -986,6 +1070,19 @@ std::string XcodeProvider::getHash(std::string key) {
bool isSeparator(char s) { return (s == '-'); }
+#ifdef MACOSX
+std::string XcodeProvider::md5(std::string key) {
+ unsigned char md[CC_MD5_DIGEST_LENGTH];
+ CC_MD5(key.c_str(), (CC_LONG) key.length(), md);
+ std::stringstream stream;
+ stream << std::hex << std::setfill('0') << std::setw(2);
+ for (int i=0; i<CC_MD5_DIGEST_LENGTH; i++) {
+ stream << (unsigned int) md[i];
+ }
+ return stream.str();
+}
+#endif
+
std::string XcodeProvider::newHash() const {
std::string hash = createUUID();
@@ -1070,7 +1167,6 @@ std::string XcodeProvider::writeSetting(const std::string &variable, const Setti
// Output a list
if (setting._flags & kSettingsAsList) {
-
output += var + ((setting._flags & kSettingsNoValue) ? "(" : " = (") + newline;
for (unsigned int i = 0, count = 0; i < setting._entries.size(); ++i) {
diff --git a/devtools/create_project/xcode.h b/devtools/create_project/xcode.h
index d48f11cb19..d495dd0dfd 100644
--- a/devtools/create_project/xcode.h
+++ b/devtools/create_project/xcode.h
@@ -40,6 +40,8 @@ protected:
void createOtherBuildFiles(const BuildSetup &setup);
+ void addResourceFiles(const BuildSetup &setup, StringList &includeList, StringList &excludeList);
+
void createProjectFile(const std::string &name, const std::string &uuid, const BuildSetup &setup, const std::string &moduleDir,
const StringList &includeList, const StringList &excludeList);
@@ -63,7 +65,7 @@ private:
std::string _sourceTree;
FileProperty(std::string fileType = "", std::string name = "", std::string path = "", std::string source = "")
- : _fileEncoding(""), _lastKnownFileType(fileType), _fileName(name), _filePath(path), _sourceTree(source) {
+ : _fileEncoding(""), _lastKnownFileType(fileType), _fileName(name), _filePath(path), _sourceTree(source) {
}
};
@@ -208,6 +210,7 @@ private:
assert(!_properties["isa"]._settings.empty());
SettingList::iterator it = _properties["isa"]._settings.begin();
+
return it->first;
}
};
@@ -230,6 +233,15 @@ private:
_objectMap[obj->_id] = true;
}
+ Object *find(std::string id) {
+ for (std::vector<Object *>::iterator it = _objects.begin(); it != _objects.end(); ++it) {
+ if ((*it)->_id == id) {
+ return *it;
+ }
+ }
+ return NULL;
+ }
+
std::string toString() {
std::string output;
@@ -300,18 +312,26 @@ private:
// Setup objects
void setupCopyFilesBuildPhase();
- void setupFrameworksBuildPhase();
+ void setupFrameworksBuildPhase(const BuildSetup &setup);
void setupNativeTarget();
void setupProject();
void setupResourcesBuildPhase();
void setupSourcesBuildPhase();
- void setupBuildConfiguration();
+ void setupBuildConfiguration(const BuildSetup &setup);
+ void setupImageAssetCatalog(const BuildSetup &setup);
+ void setupAdditionalSources(std::string targetName, Property &files, int &order);
// Misc
void setupDefines(const BuildSetup &setup); // Setup the list of defines to be used on build configurations
+ // Retrieve information
+ ValueList& getResourceFiles() const;
+
// Hash generation
std::string getHash(std::string key);
+#ifdef MACOSX
+ std::string md5(std::string key);
+#endif
std::string newHash() const;
// Output
diff --git a/devtools/create_project/xcode/create_project.xcodeproj/project.pbxproj b/devtools/create_project/xcode/create_project.xcodeproj/project.pbxproj
index f13bcf6969..4f06a5e469 100644
--- a/devtools/create_project/xcode/create_project.xcodeproj/project.pbxproj
+++ b/devtools/create_project/xcode/create_project.xcodeproj/project.pbxproj
@@ -140,6 +140,9 @@
/* Begin PBXProject section */
F9A66C1E1396D36100CEE494 /* Project object */ = {
isa = PBXProject;
+ attributes = {
+ LastUpgradeCheck = 0720;
+ };
buildConfigurationList = F9A66C211396D36100CEE494 /* Build configuration list for PBXProject "create_project" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
@@ -177,12 +180,14 @@
F9A66C2E1396D36100CEE494 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
- ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
+ ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_OPTIMIZATION_LEVEL = 0;
- GCC_PREPROCESSOR_DEFINITIONS = DEBUG;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ POSIX,
+ MACOSX,
+ );
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
- GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
@@ -195,9 +200,11 @@
F9A66C2F1396D36100CEE494 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
- ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
GCC_C_LANGUAGE_STANDARD = gnu99;
- GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ POSIX,
+ MACOSX,
+ );
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
@@ -213,6 +220,10 @@
COPY_PHASE_STRIP = NO;
GCC_DYNAMIC_NO_PIC = NO;
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "$(inherited)",
+ DEBUG,
+ );
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Debug;
@@ -224,6 +235,7 @@
COPY_PHASE_STRIP = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
+ GCC_PREPROCESSOR_DEFINITIONS = "$(inherited)";
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Release;
diff --git a/devtools/credits.pl b/devtools/credits.pl
index 1a038c7dee..6201fc1052 100755
--- a/devtools/credits.pl
+++ b/devtools/credits.pl
@@ -826,8 +826,9 @@ begin_credits("Credits");
add_person("John Willis", "DJWillis", "");
end_section();
- begin_section("iPhone");
+ begin_section("iPhone / iPad");
add_person("Oystein Eftevaag", "vinterstum", "");
+ add_person("Vincent B&eacute;nony", "bSr43", "");
end_section();
begin_section("LinuxMoto");
diff --git a/devtools/update-version.pl b/devtools/update-version.pl
index b313846ab3..3e44198d31 100755
--- a/devtools/update-version.pl
+++ b/devtools/update-version.pl
@@ -38,6 +38,7 @@ my @subs_files = qw(
dists/slackware/scummvm.SlackBuild
dists/macosx/Info.plist
dists/iphone/Info.plist
+ dists/ios7/Info.plist
dists/irix/scummvm.spec
dists/win32/scummvm.nsi
dists/wii/meta.xml
diff --git a/dists/ios7/Images.xcassets/AppIcon.appiconset/Contents.json b/dists/ios7/Images.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644
index 0000000000..c37df59806
--- /dev/null
+++ b/dists/ios7/Images.xcassets/AppIcon.appiconset/Contents.json
@@ -0,0 +1,86 @@
+{
+ "images" : [
+ {
+ "size" : "29x29",
+ "idiom" : "iphone",
+ "filename" : "icon4-29@2x.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "29x29",
+ "idiom" : "iphone",
+ "filename" : "icon4-29@3x.png",
+ "scale" : "3x"
+ },
+ {
+ "size" : "40x40",
+ "idiom" : "iphone",
+ "filename" : "icon4-40@2x.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "40x40",
+ "idiom" : "iphone",
+ "filename" : "icon4-40@3x.png",
+ "scale" : "3x"
+ },
+ {
+ "size" : "60x60",
+ "idiom" : "iphone",
+ "filename" : "icon4-60@2x.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "60x60",
+ "idiom" : "iphone",
+ "filename" : "icon4-60@3x.png",
+ "scale" : "3x"
+ },
+ {
+ "size" : "29x29",
+ "idiom" : "ipad",
+ "filename" : "icon4-29.png",
+ "scale" : "1x"
+ },
+ {
+ "size" : "29x29",
+ "idiom" : "ipad",
+ "filename" : "icon4-29@2x.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "40x40",
+ "idiom" : "ipad",
+ "filename" : "icon4-40.png",
+ "scale" : "1x"
+ },
+ {
+ "size" : "40x40",
+ "idiom" : "ipad",
+ "filename" : "icon4-40@2x.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "76x76",
+ "idiom" : "ipad",
+ "filename" : "icon4-76.png",
+ "scale" : "1x"
+ },
+ {
+ "size" : "76x76",
+ "idiom" : "ipad",
+ "filename" : "icon4-76@2x.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "83.5x83.5",
+ "idiom" : "ipad",
+ "filename" : "icon4-83.5@2x.png",
+ "scale" : "2x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+} \ No newline at end of file
diff --git a/dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-29.png b/dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-29.png
new file mode 100644
index 0000000000..9b89d07046
--- /dev/null
+++ b/dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-29.png
Binary files differ
diff --git a/dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-29@2x.png b/dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-29@2x.png
new file mode 100644
index 0000000000..0de0984ed7
--- /dev/null
+++ b/dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-29@2x.png
Binary files differ
diff --git a/dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-29@3x.png b/dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-29@3x.png
new file mode 100644
index 0000000000..db6089dcf6
--- /dev/null
+++ b/dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-29@3x.png
Binary files differ
diff --git a/dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-40.png b/dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-40.png
new file mode 100644
index 0000000000..9a7575b404
--- /dev/null
+++ b/dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-40.png
Binary files differ
diff --git a/dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-40@2x.png b/dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-40@2x.png
new file mode 100644
index 0000000000..5cd982d0e1
--- /dev/null
+++ b/dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-40@2x.png
Binary files differ
diff --git a/dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-40@3x.png b/dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-40@3x.png
new file mode 100644
index 0000000000..22580b0ac6
--- /dev/null
+++ b/dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-40@3x.png
Binary files differ
diff --git a/dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-60@2x.png b/dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-60@2x.png
new file mode 100644
index 0000000000..22580b0ac6
--- /dev/null
+++ b/dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-60@2x.png
Binary files differ
diff --git a/dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-60@3x.png b/dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-60@3x.png
new file mode 100644
index 0000000000..c5f39976bb
--- /dev/null
+++ b/dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-60@3x.png
Binary files differ
diff --git a/dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-76.png b/dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-76.png
new file mode 100644
index 0000000000..0609594553
--- /dev/null
+++ b/dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-76.png
Binary files differ
diff --git a/dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-76@2x.png b/dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-76@2x.png
new file mode 100644
index 0000000000..7bc1ae1de1
--- /dev/null
+++ b/dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-76@2x.png
Binary files differ
diff --git a/dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-83.5@2x.png b/dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-83.5@2x.png
new file mode 100644
index 0000000000..acaf12f435
--- /dev/null
+++ b/dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-83.5@2x.png
Binary files differ
diff --git a/dists/ios7/Images.xcassets/Contents.json b/dists/ios7/Images.xcassets/Contents.json
new file mode 100644
index 0000000000..da4a164c91
--- /dev/null
+++ b/dists/ios7/Images.xcassets/Contents.json
@@ -0,0 +1,6 @@
+{
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+} \ No newline at end of file
diff --git a/dists/ios7/Images.xcassets/LaunchImage.launchimage/Contents.json b/dists/ios7/Images.xcassets/LaunchImage.launchimage/Contents.json
new file mode 100644
index 0000000000..40e3b1e3dd
--- /dev/null
+++ b/dists/ios7/Images.xcassets/LaunchImage.launchimage/Contents.json
@@ -0,0 +1,150 @@
+{
+ "images" : [
+ {
+ "extent" : "full-screen",
+ "idiom" : "iphone",
+ "subtype" : "736h",
+ "filename" : "ScummVM-splash-1242x2208.png",
+ "minimum-system-version" : "8.0",
+ "orientation" : "portrait",
+ "scale" : "3x"
+ },
+ {
+ "extent" : "full-screen",
+ "idiom" : "iphone",
+ "subtype" : "736h",
+ "filename" : "ScummVM-splash-2208x1242.png",
+ "minimum-system-version" : "8.0",
+ "orientation" : "landscape",
+ "scale" : "3x"
+ },
+ {
+ "extent" : "full-screen",
+ "idiom" : "iphone",
+ "subtype" : "667h",
+ "filename" : "ScummVM-splash-750x1334.png",
+ "minimum-system-version" : "8.0",
+ "orientation" : "portrait",
+ "scale" : "2x"
+ },
+ {
+ "orientation" : "portrait",
+ "idiom" : "iphone",
+ "extent" : "full-screen",
+ "minimum-system-version" : "7.0",
+ "scale" : "2x"
+ },
+ {
+ "extent" : "full-screen",
+ "idiom" : "iphone",
+ "subtype" : "retina4",
+ "filename" : "ScummVM-splash-640x1136-1.png",
+ "minimum-system-version" : "7.0",
+ "orientation" : "portrait",
+ "scale" : "2x"
+ },
+ {
+ "orientation" : "portrait",
+ "idiom" : "ipad",
+ "filename" : "ScummVM-splash-768x1024.png",
+ "extent" : "full-screen",
+ "minimum-system-version" : "7.0",
+ "scale" : "1x"
+ },
+ {
+ "orientation" : "landscape",
+ "idiom" : "ipad",
+ "filename" : "ScummVM-splash-1024x768.png",
+ "extent" : "full-screen",
+ "minimum-system-version" : "7.0",
+ "scale" : "1x"
+ },
+ {
+ "orientation" : "portrait",
+ "idiom" : "ipad",
+ "filename" : "ScummVM-splash-1536x2048.png",
+ "extent" : "full-screen",
+ "minimum-system-version" : "7.0",
+ "scale" : "2x"
+ },
+ {
+ "orientation" : "landscape",
+ "idiom" : "ipad",
+ "filename" : "ScummVM-splash-2048x1536.png",
+ "extent" : "full-screen",
+ "minimum-system-version" : "7.0",
+ "scale" : "2x"
+ },
+ {
+ "orientation" : "portrait",
+ "idiom" : "iphone",
+ "extent" : "full-screen",
+ "scale" : "1x"
+ },
+ {
+ "orientation" : "portrait",
+ "idiom" : "iphone",
+ "extent" : "full-screen",
+ "scale" : "2x"
+ },
+ {
+ "orientation" : "portrait",
+ "idiom" : "iphone",
+ "extent" : "full-screen",
+ "subtype" : "retina4",
+ "scale" : "2x"
+ },
+ {
+ "orientation" : "portrait",
+ "idiom" : "ipad",
+ "extent" : "to-status-bar",
+ "scale" : "1x"
+ },
+ {
+ "orientation" : "portrait",
+ "idiom" : "ipad",
+ "extent" : "full-screen",
+ "scale" : "1x"
+ },
+ {
+ "orientation" : "landscape",
+ "idiom" : "ipad",
+ "extent" : "to-status-bar",
+ "scale" : "1x"
+ },
+ {
+ "orientation" : "landscape",
+ "idiom" : "ipad",
+ "extent" : "full-screen",
+ "scale" : "1x"
+ },
+ {
+ "orientation" : "portrait",
+ "idiom" : "ipad",
+ "extent" : "to-status-bar",
+ "scale" : "2x"
+ },
+ {
+ "orientation" : "portrait",
+ "idiom" : "ipad",
+ "extent" : "full-screen",
+ "scale" : "2x"
+ },
+ {
+ "orientation" : "landscape",
+ "idiom" : "ipad",
+ "extent" : "to-status-bar",
+ "scale" : "2x"
+ },
+ {
+ "orientation" : "landscape",
+ "idiom" : "ipad",
+ "extent" : "full-screen",
+ "scale" : "2x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+} \ No newline at end of file
diff --git a/dists/ios7/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-1024x768.png b/dists/ios7/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-1024x768.png
new file mode 100644
index 0000000000..6fb6c9bf4b
--- /dev/null
+++ b/dists/ios7/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-1024x768.png
Binary files differ
diff --git a/dists/ios7/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-1242x2208.png b/dists/ios7/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-1242x2208.png
new file mode 100644
index 0000000000..c70153b1f7
--- /dev/null
+++ b/dists/ios7/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-1242x2208.png
Binary files differ
diff --git a/dists/ios7/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-1536x2048.png b/dists/ios7/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-1536x2048.png
new file mode 100644
index 0000000000..8d6e588226
--- /dev/null
+++ b/dists/ios7/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-1536x2048.png
Binary files differ
diff --git a/dists/ios7/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-2048x1536.png b/dists/ios7/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-2048x1536.png
new file mode 100644
index 0000000000..988122bce8
--- /dev/null
+++ b/dists/ios7/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-2048x1536.png
Binary files differ
diff --git a/dists/ios7/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-2208x1242.png b/dists/ios7/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-2208x1242.png
new file mode 100644
index 0000000000..33b3740092
--- /dev/null
+++ b/dists/ios7/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-2208x1242.png
Binary files differ
diff --git a/dists/ios7/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-640x1136-1.png b/dists/ios7/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-640x1136-1.png
new file mode 100644
index 0000000000..91641cf91f
--- /dev/null
+++ b/dists/ios7/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-640x1136-1.png
Binary files differ
diff --git a/dists/ios7/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-750x1334.png b/dists/ios7/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-750x1334.png
new file mode 100644
index 0000000000..630502974a
--- /dev/null
+++ b/dists/ios7/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-750x1334.png
Binary files differ
diff --git a/dists/ios7/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-768x1024.png b/dists/ios7/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-768x1024.png
new file mode 100644
index 0000000000..6a33b63110
--- /dev/null
+++ b/dists/ios7/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-768x1024.png
Binary files differ
diff --git a/dists/ios7/Info.plist b/dists/ios7/Info.plist
new file mode 100644
index 0000000000..84885d9232
--- /dev/null
+++ b/dists/ios7/Info.plist
@@ -0,0 +1,52 @@
+<?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>ScummVM</string>
+ <key>CFBundleIcons</key>
+ <dict/>
+ <key>CFBundleIcons~ipad</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>1.8.0git</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>1.8.0git</string>
+ <key>UIApplicationExitsOnSuspend</key>
+ <false/>
+ <key>UIFileSharingEnabled</key>
+ <true/>
+ <key>UILaunchImages</key>
+ <array/>
+ <key>UIPrerenderedIcon</key>
+ <true/>
+ <key>UIRequiresFullScreen</key>
+ <true/>
+ <key>UIStatusBarHidden</key>
+ <true/>
+ <key>UISupportedInterfaceOrientations</key>
+ <array>
+ <string>UIInterfaceOrientationLandscapeLeft</string>
+ <string>UIInterfaceOrientationLandscapeRight</string>
+ <string>UIInterfaceOrientationPortrait</string>
+ </array>
+ <key>UISupportedInterfaceOrientations~ipad</key>
+ <array>
+ <string>UIInterfaceOrientationLandscapeLeft</string>
+ <string>UIInterfaceOrientationLandscapeRight</string>
+ <string>UIInterfaceOrientationPortrait</string>
+ </array>
+</dict>
+</plist>
diff --git a/dists/ios7/Info.plist.in b/dists/ios7/Info.plist.in
new file mode 100644
index 0000000000..33094f4df9
--- /dev/null
+++ b/dists/ios7/Info.plist.in
@@ -0,0 +1,52 @@
+<?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>ScummVM</string>
+ <key>CFBundleIcons</key>
+ <dict/>
+ <key>CFBundleIcons~ipad</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>@VERSION@</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>@VERSION@</string>
+ <key>UIApplicationExitsOnSuspend</key>
+ <false/>
+ <key>UIFileSharingEnabled</key>
+ <true/>
+ <key>UILaunchImages</key>
+ <array/>
+ <key>UIPrerenderedIcon</key>
+ <true/>
+ <key>UIRequiresFullScreen</key>
+ <true/>
+ <key>UIStatusBarHidden</key>
+ <true/>
+ <key>UISupportedInterfaceOrientations</key>
+ <array>
+ <string>UIInterfaceOrientationLandscapeLeft</string>
+ <string>UIInterfaceOrientationLandscapeRight</string>
+ <string>UIInterfaceOrientationPortrait</string>
+ </array>
+ <key>UISupportedInterfaceOrientations~ipad</key>
+ <array>
+ <string>UIInterfaceOrientationLandscapeLeft</string>
+ <string>UIInterfaceOrientationLandscapeRight</string>
+ <string>UIInterfaceOrientationPortrait</string>
+ </array>
+</dict>
+</plist>
diff --git a/dists/macosx/Info.plist b/dists/macosx/Info.plist
index b872febd60..ef504751a7 100644
--- a/dists/macosx/Info.plist
+++ b/dists/macosx/Info.plist
@@ -4,6 +4,18 @@
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
+ <key>CFBundleDisplayName</key>
+ <string>ScummVM</string>
+ <key>CFBundleExecutable</key>
+ <string>scummvm</string>
+ <key>CFBundleGetInfoString</key>
+ <string>1.8.0git, Copyright 2001-2016 The ScummVM Team</string>
+ <key>CFBundleIconFile</key>
+ <string>scummvm.icns</string>
+ <key>CFBundleIdentifier</key>
+ <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
<key>CFBundleLocalizations</key>
<array>
<string>en</string>
@@ -28,18 +40,6 @@
<string>se</string>
<string>uk</string>
</array>
- <key>CFBundleDisplayName</key>
- <string>ScummVM</string>
- <key>CFBundleExecutable</key>
- <string>scummvm</string>
- <key>CFBundleGetInfoString</key>
- <string>1.8.0git, Copyright 2001-2016 The ScummVM Team</string>
- <key>CFBundleIconFile</key>
- <string>scummvm.icns</string>
- <key>CFBundleIdentifier</key>
- <string>org.scummvm.scummvm</string>
- <key>CFBundleInfoDictionaryVersion</key>
- <string>6.0</string>
<key>CFBundleName</key>
<string>ScummVM</string>
<key>CFBundlePackageType</key>
@@ -48,10 +48,10 @@
<string>1.8.0git</string>
<key>CFBundleVersion</key>
<string>1.8.0git</string>
- <key>NSPrincipalClass</key>
- <string>NSApplication</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright 2001-2016 The ScummVM Team</string>
+ <key>NSPrincipalClass</key>
+ <string>NSApplication</string>
<key>SUFeedURL</key>
<string>http://www.scummvm.org/appcasts/macosx/release.xml</string>
<key>SUPublicDSAKeyFile</key>
diff --git a/dists/macosx/Info.plist.in b/dists/macosx/Info.plist.in
index 1a83447e26..55be27d77b 100644
--- a/dists/macosx/Info.plist.in
+++ b/dists/macosx/Info.plist.in
@@ -4,6 +4,18 @@
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
+ <key>CFBundleDisplayName</key>
+ <string>ScummVM</string>
+ <key>CFBundleExecutable</key>
+ <string>scummvm</string>
+ <key>CFBundleGetInfoString</key>
+ <string>@VERSION@, Copyright 2001-2016 The ScummVM Team</string>
+ <key>CFBundleIconFile</key>
+ <string>scummvm.icns</string>
+ <key>CFBundleIdentifier</key>
+ <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
<key>CFBundleLocalizations</key>
<array>
<string>en</string>
@@ -28,18 +40,6 @@
<string>se</string>
<string>uk</string>
</array>
- <key>CFBundleDisplayName</key>
- <string>ScummVM</string>
- <key>CFBundleExecutable</key>
- <string>scummvm</string>
- <key>CFBundleGetInfoString</key>
- <string>@VERSION@, Copyright 2001-2016 The ScummVM Team</string>
- <key>CFBundleIconFile</key>
- <string>scummvm.icns</string>
- <key>CFBundleIdentifier</key>
- <string>org.scummvm.scummvm</string>
- <key>CFBundleInfoDictionaryVersion</key>
- <string>6.0</string>
<key>CFBundleName</key>
<string>ScummVM</string>
<key>CFBundlePackageType</key>
@@ -48,10 +48,10 @@
<string>@VERSION@</string>
<key>CFBundleVersion</key>
<string>@VERSION@</string>
- <key>NSPrincipalClass</key>
- <string>NSApplication</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright 2001-2016 The ScummVM Team</string>
+ <key>NSPrincipalClass</key>
+ <string>NSApplication</string>
<key>SUFeedURL</key>
<string>http://www.scummvm.org/appcasts/macosx/release.xml</string>
<key>SUPublicDSAKeyFile</key>
diff --git a/gui/credits.h b/gui/credits.h
index 72fe3fa951..b084935cbb 100644
--- a/gui/credits.h
+++ b/gui/credits.h
@@ -351,8 +351,10 @@ static const char *credits[] = {
"C1""GPH Devices (GP2X, GP2XWiz & Caanoo)",
"C0""John Willis",
"",
-"C1""iPhone",
+"C1""iPhone / iPad",
"C0""Oystein Eftevaag",
+"A0""Vincent Benony",
+"C0""Vincent B\351nony",
"",
"C1""LinuxMoto",
"C0""Lubomyr Lisen",
diff --git a/gui/module.mk b/gui/module.mk
index e355212620..fb7c968c34 100644
--- a/gui/module.mk
+++ b/gui/module.mk
@@ -32,6 +32,15 @@ MODULE_OBJS := \
widgets/scrollbar.o \
widgets/tab.o
+# HACK: Even if it seems redundant, please keep these directives in that order!
+# This is needed by the "create_project" tool, for the OS X / iOS Xcode project.
+# The main problem is that the create_project tool scans the files for both OS X, and iOS targets.
+# It must be able to collect all the files for both targets, so that the backend can later filter
+# them for its own targets (in the Xcode terminology)
+ifdef IPHONE
+MODULE_OBJS += \
+ browser.o
+else
ifdef MACOSX
MODULE_OBJS += \
browser_osx.o
@@ -39,6 +48,7 @@ else
MODULE_OBJS += \
browser.o
endif
+endif
ifdef ENABLE_EVENTRECORDER
MODULE_OBJS += \
diff --git a/ports.mk b/ports.mk
index adc28d4fd4..17baee80dd 100644
--- a/ports.mk
+++ b/ports.mk
@@ -58,7 +58,7 @@ bundle: scummvm-static
mkdir -p $(bundle_name)/Contents/MacOS
mkdir -p $(bundle_name)/Contents/Resources
echo "APPL????" > $(bundle_name)/Contents/PkgInfo
- cp $(srcdir)/dists/macosx/Info.plist $(bundle_name)/Contents/
+ sed -e 's/$$(PRODUCT_BUNDLE_IDENTIFIER)/org.scummvm.scummvm/' $(srcdir)/dists/macosx/Info.plist >$(bundle_name)/Contents/Info.plist
ifdef USE_SPARKLE
mkdir -p $(bundle_name)/Contents/Frameworks
cp $(srcdir)/dists/macosx/dsa_pub.pem $(bundle_name)/Contents/Resources/
@@ -92,11 +92,139 @@ endif
cp $(srcdir)/dists/iphone/icon-72.png $(bundle_name)/
cp $(srcdir)/dists/iphone/Default.png $(bundle_name)/
+ios7bundle: ios7
+ 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<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</array>";\
+ 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>";\
+ print "\t\t<dict>";\
+ print "\t\t\t<key>UILaunchImageMinimumOSVersion</key>";\
+ print "\t\t\t<string>8.0</string>";\
+ print "\t\t\t<key>UILaunchImageName</key>";\
+ print "\t\t\t<string>LaunchImage-800-Portrait-736h</string>";\
+ print "\t\t\t<key>UILaunchImageOrientation</key>";\
+ print "\t\t\t<string>Portrait</string>";\
+ print "\t\t\t<key>UILaunchImageSize</key>";\
+ print "\t\t\t<string>{414, 736}</string>";\
+ print "\t\t\t<key>UILaunchImageMinimumOSVersion</key>";\
+ print "\t\t\t<string>8.0</string>";\
+ print "\t\t\t<key>UILaunchImageName</key>";\
+ print "\t\t\t<string>LaunchImage-800-Landscape-736h</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>{414, 736}</string>";\
+ print "\t\t\t<key>UILaunchImageMinimumOSVersion</key>";\
+ print "\t\t\t<string>8.0</string>";\
+ print "\t\t\t<key>UILaunchImageName</key>";\
+ print "\t\t\t<string>LaunchImage-800-667h</string>";\
+ print "\t\t\t<key>UILaunchImageOrientation</key>";\
+ print "\t\t\t<string>Portrait</string>";\
+ print "\t\t\t<key>UILaunchImageSize</key>";\
+ print "\t\t\t<string>{375, 667}</string>";\
+ print "\t\t\t<key>UILaunchImageMinimumOSVersion</key>";\
+ print "\t\t\t<string>7.0</string>";\
+ print "\t\t\t<key>UILaunchImageName</key>";\
+ print "\t\t\t<string>LaunchImage-700-568h</string>";\
+ print "\t\t\t<key>UILaunchImageOrientation</key>";\
+ print "\t\t\t<string>Portrait</string>";\
+ print "\t\t\t<key>UILaunchImageSize</key>";\
+ print "\t\t\t<string>{320, 568}</string>";\
+ print "\t\t</dict>";\
+ print "\t\t<dict>";\
+ print "\t\t\t<key>UILaunchImageMinimumOSVersion</key>";\
+ print "\t\t\t<string>7.0</string>";\
+ print "\t\t\t<key>UILaunchImageName</key>";\
+ print "\t\t\t<string>LaunchImage-700-Portrait</string>";\
+ print "\t\t\t<key>UILaunchImageOrientation</key>";\
+ print "\t\t\t<string>Portrait</string>";\
+ print "\t\t\t<key>UILaunchImageSize</key>";\
+ print "\t\t\t<string>{768, 1024}</string>";\
+ print "\t\t</dict>";\
+ print "\t\t<dict>";\
+ print "\t\t\t<key>UILaunchImageMinimumOSVersion</key>";\
+ print "\t\t\t<string>7.0</string>";\
+ print "\t\t\t<key>UILaunchImageName</key>";\
+ print "\t\t\t<string>LaunchImage-700-Landscape</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>{768, 1024}</string>";\
+ print "\t\t</dict>";\
+ print "\t</array>";\
+ s=2}\
+ s==0 {print $$0}\
+ s > 0 { s-- }' $(srcdir)/dists/ios7/Info.plist >$(bundle_name)/Info.plist
+ sed -i'' -e 's/$$(PRODUCT_BUNDLE_IDENTIFIER)/org.scummvm.scummvm/' $(bundle_name)/Info.plist
+ cp $(DIST_FILES_DOCS) $(bundle_name)/
+ cp $(DIST_FILES_THEMES) $(bundle_name)/
+ifdef DIST_FILES_ENGINEDATA
+ cp $(DIST_FILES_ENGINEDATA) $(bundle_name)/
+endif
+ $(STRIP) scummvm
+ ldid -S scummvm
+ chmod 755 scummvm
+ cp scummvm $(bundle_name)/ScummVM
+ cp $(srcdir)/dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-29@2x.png $(bundle_name)/AppIcon29x29@2x.png
+ cp $(srcdir)/dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-29@2x.png $(bundle_name)/AppIcon29x29@2x~ipad.png
+ cp $(srcdir)/dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-29@3x.png $(bundle_name)/AppIcon29x29@3x.png
+ cp $(srcdir)/dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-29.png $(bundle_name)/AppIcon29x29~ipad.png
+ cp $(srcdir)/dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-40@2x.png $(bundle_name)/AppIcon40x40@2x.png
+ cp $(srcdir)/dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-40@2x.png $(bundle_name)/AppIcon40x40@2x~ipad.png
+ cp $(srcdir)/dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-40@3x.png $(bundle_name)/AppIcon40x40@3x.png
+ cp $(srcdir)/dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-40.png $(bundle_name)/AppIcon40x40~ipad.png
+ cp $(srcdir)/dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-60@2x.png $(bundle_name)/AppIcon60x60@2x.png
+ cp $(srcdir)/dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-60@3x.png $(bundle_name)/AppIcon60x60@3x.png
+ cp $(srcdir)/dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-76@2x.png $(bundle_name)/AppIcon76x76@2x~ipad.png
+ cp $(srcdir)/dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-76.png $(bundle_name)/AppIcon76x76~ipad.png
+ cp $(srcdir)/dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-83.5@2x.png $(bundle_name)/AppIcon83.5x83.5@2x~ipad.png
+ cp $(srcdir)/dists/ios7/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-640x1136-1.png $(bundle_name)/LaunchImage-700-568h@2x.png
+ cp $(srcdir)/dists/ios7/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-2048x1536.png $(bundle_name)/LaunchImage-700-Landscape@2x~ipad.png
+ cp $(srcdir)/dists/ios7/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-1024x768.png $(bundle_name)/LaunchImage-700-Landscape~ipad.png
+ cp $(srcdir)/dists/ios7/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-1536x2048.png $(bundle_name)/LaunchImage-700-Portrait@2x~ipad.png
+ cp $(srcdir)/dists/ios7/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-768x1024.png $(bundle_name)/LaunchImage-700-Portrait~ipad.png
+ cp $(srcdir)/dists/ios7/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-1242x2208.png $(bundle_name)/LaunchImage-800-Portrait-736h@3x.png
+ cp $(srcdir)/dists/ios7/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-2208x1242.png $(bundle_name)/LaunchImage-800-Landscape-736h@3x.png
+ cp $(srcdir)/dists/ios7/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-750x1334.png $(bundle_name)/LaunchImage-800-667h@2x.png
+
# Location of static libs for the iPhone
ifneq ($(BACKEND), iphone)
+ifneq ($(BACKEND), ios7)
# Static libaries, used for the scummvm-static and iphone targets
OSX_STATIC_LIBS := `$(SDLCONFIG) --static-libs`
endif
+endif
ifdef USE_FREETYPE2
OSX_STATIC_LIBS += $(STATICLIBPATH)/lib/libfreetype.a $(STATICLIBPATH)/lib/libbz2.a
@@ -164,7 +292,7 @@ scummvm-static: $(OBJS)
$(OSX_STATIC_LIBS) \
$(OSX_ZLIB)
-# Special target to create a static linked binary for the iPhone
+# Special target to create a static linked binary for the iPhone (legacy, and iOS 7+)
iphone: $(OBJS)
$(CXX) $(LDFLAGS) -o scummvm $(OBJS) \
$(OSX_STATIC_LIBS) \